An interesting fix
You may have noticed our deferred decals (presently in beta) tend to shift with distance. Something was wrong with the screen space to world space conversion, but it's a hard problem to describe. I wrote a function based on the work Igor did for his SSLR shader, like this:
vec4 ScreenPositionToWorldPosition(in vec2 texCoord) { float x = (texCoord.s / buffersize.x - 0.5) * 2.0; float y = (texCoord.t / buffersize.y - 0.5) * 2.0; float z = texelFetch(texture5, ivec2(texCoord),gl_SampleID).r; vec4 posProj = vec4(x,y,z,1.0); vec4 posView = inverse(projectioncameramatrix) * posProj; posView /= posView.w; posView+=cameraposition; return posView; }
OpenGL stores depth values in a non-linear manner, which yields more precision closer to the camera. This allows a 24-bit depth buffer to cover a much greater distance than a linear depth buffer would allow with acceptable visual fidelity. The problem with the above equation is that the exponential value isn't being converted back into a linear value before being multiplied by the inverse camera projection matrix.
I found a PDF with a formula I had come across before and started messing around with it: The trick is this:
lineardepth = exponentialdepth / 0.5 - 1.0
This equation can change if you have set glDepthRange to anything other than the defaults. (Coincidentally, calling glDepthRange() was what messed up my deferred renderer for iPad a couple years ago and forced me to use an extra floating-point buffer for storing screen depth at my GDC talk.)
Plugging this into my function and eliminating the camera position add results in the following code:
vec4 ScreenPositionToWorldPosition(in vec2 texCoord) { float x = (texCoord.s / buffersize.x - 0.5) * 2.0; float y = (texCoord.t / buffersize.y - 0.5) * 2.0; float z = texelFetch(texture5, ivec2(texCoord),gl_SampleID).r; z = z / 0.5 - 1.0; vec4 posProj = vec4(x,y,z,1.0); vec4 posView = inverse(projectioncameramatrix) * posProj; posView /= posView.w; return posView; }
This also eliminated a couple of strange divide by twos I had in the texture mapping, which didn't really make sense to me at the time. Below you can see a decal rendered on a surface from a far distance, with no inaccuracies in the texture alignment.
In reality, this was probably about five hours of work with "River Monsters" playing in the background.
- 5
0 Comments
Recommended Comments
There are no comments to display.