EDIT: I have updated the JSFiddle link because it was not displaying correctly in Chrome on Windows 7.
Situation
I am experimenting with particles in THREE.JS and utilizing a frame buffer / render target (double buffered) to write positions to a texture. This texture is manipulated by its own ShaderMaterial, and then read by the PointCloud's ShaderMaterial to position the particles. Everything is working smoothly so far; all functions as anticipated.
My current objective is to utilize my scene's depth texture to determine if any particles are intersecting with my scene's geometry.
Initially, I referenced my depth texture in the PointCloud's fragment shader, utilizing
gl_FragCoord.xy / screenResolution.xy
to create the uv
for the depth texture lookup.
Here is a JSFiddle demonstration. It functions well - when a particle is positioned behind an object in the scene, I change the particle's color to red instead of white.
However, I encounter issues when attempting to perform the same depth comparison in the position texture shader. In the draw fragment shader, I can use the value of gl_FragCoord
to obtain the particle's position in screen space and utilize it for the depth uv
lookup. This is achievable because in the draw vertex shader, I employ the modelViewMatrix
and projectionMatrix
to define the value of gl_Position
.
Despite my efforts in the position fragment shader, I have been unsuccessful. To clarify, my objective is particle collision with the scene on the GPU.
The Question:
- Given a texture where each pixel/texel represents a world-space 3D vector denoting a particle's position, how can I project this vector to screen-space in the fragment shader, ultimately using the
.xy
properties of this vector for auv
lookup in the depth texture?
My Attempts
In the position texture shader, I attempted to transform a particle's position to screen-space using model-view and projection matrices - which is similar to the process in the draw shader:
// Position texture's fragment shader: void main() { vec2 uv = gl_FragCoord.xy / textureResolution.xy; vec4 particlePosition = texture2D( tPosition, uv ); vec2 screenspacePosition = modelViewMatrix * projectionMatrix * vec4( particlePosition, 1.0 ); vec2 depthUV = vec2( screenspacePosition.xy / screenResolution.xy ); float depth = texture2D( tDepth, depthUV ).x; if( depth < screenspacePosition.z ) { // Particle is behind something in the scene, // so do something... } gl_FragColor = vec4( particlePosition.xyz, 1.0 ); }
Other variations I tried include:
- Adjusting the depth's
uv
by0.5 - depthUV
- Utilizing the tPosition texture resolution instead of the screen resolution to scale the depthUV.
- An alternate depth
uv
approach: usingdepthUV = (depthUV - 1.0) * 2.0;
. This improved the situation slightly, but the scaling is incorrect.
- Adjusting the depth's
Assistance would be greatly appreciated! Thank you in advance.