Parallax mapping with shadow maps and decals in deferred rendering - opengl

I have a problem with my deferred renderer and parallax mapping. It works fine with the normal geometry -> lighting stages, but I'm not sure how I would apply the parallax depth to the screenspace decals or shadow mapping.
My gbuffer stores two texture attachments.
1) diffuse map (rgb) + specular map (alpha channel).
2) normal map (rgb).
I reconstruct world position with depth buffer and inverse view matrix.
The problem is that the normal mapping calculations that get sent to the gbuffer attachments are done in the geometry (first step) pass (the TBN calculations etc), but I don't know to apply that data to the shadow mapping (done during lighting pass) or the decal step (just before lighting).
I was thinking that I could possibly do something when I reconstruct the world position from the depth map, but am at a loss as to how to do that, or if it is even the right approach.
I could possibly merge the geometry and decal pass together if I pre-rendered the depth from the geometry pass first (decals needs complete depth buffer), so I could calculate them together. I don't like the idea of doing that and it obviously won't work with shadows maps which are applied during lighting.

Related

OpenGL Directional Light Shadow Map; how to lookup the correct shadowmap value?

I'm working on implementing directional light and an associated shadowmap.
I'm successfully rendering the shadowmap texture using an orthographic projection. But this is where I'm stuck; in the final render pass, how do I work out the correct texture coordinate from my shadow map to sample? And then, how do I determine whether this object is behind that depth?
What I've tried to do so far:
Pass the lights View+Projection matrix to the vertex shader for my object
Multiply the objects vertices in the Vertex Shader by this matrix to pass to the fragment shader
This gives my fragment shader the location of the vertex when it was drawn to the shadowmap
So, with this I can sample the shadow map?
And this gives me the depth of whatever was drawn there.
But it doesn't tell me whether I'm behind or in front of this depth.
After executing your second step, you get a 4-vector (x,y,z,w). Lets assume you performed perspective division on it, and w = 1. Then you have x,y,z coordinates of a vertex in light source's space, that you pass to your fragment shader.
x and y you use to sample the shadow map in the next step, but what about the z coordinate? Well, it is the would-be depth value of the fragment from the light source's PoV. It is this value you compare your shadow map sample to. If it is bigger than shadowmaps value(+bias), than your fragment is in the shadow. Otherwise it isn't.

Write to texture GLSL

I want to be able to (in fragment shader) add one texture to another. Right now I have projective texturing and want to expand on that.
Here is what I have so far :
Im also drawing the viewfrustum along which the blue/gray test image is projected onto the geometry that is in constant rotation.
My vertex shader:
ProjTexCoord = ProjectorMatrix * ModelTransform * raw_pos;
My Fragment Shader:
vec4 diffuse = texture(texture1, vs_st);
vec4 projTexColor = textureProj(texture2, ProjTexCoord);
vec4 shaded = diffuse; // max(intensity * diffuse, ambient); -- no shadows for now
if (ProjTexCoord[0] > 0.0 ||
ProjTexCoord[1] > 0.0 ||
ProjTexCoord[0] < ProjTexCoord[2] ||
ProjTexCoord[1] < ProjTexCoord[2]){
diffuse = shaded;
}else if(dot(n, projector_aim) < 0 ){
diffuse = projTexColor;
}else{
diffuse = shaded;
}
What I want to achieve:
When for example - the user presses a button, I want the blue/gray texture to be written to the gray texture on the sphere and rotate with it. Imagine it as sort of "taking a picture" or painting on top of the sphere so that the blue/gray texture spins with the sphere after a button is pressed.
As the fragment shader operates on each pixel it should be possible to copy pixel-by-pixel from one texture to the other, but I have no clue how, I might be googling for the wrong stuff.
How can I achieve this technically? What method is most versatile? Suggestions are very much appreciated, please let me know If more code is necessary.
Just to be clear, you'd like to bake decals into your sphere's grey texture.
The trouble with writing to the grey texture while drawing another object is it's not one to one. You may be writing twice or more to the same texel, or a single fragment may need to write to many texels in your grey texture. It may sound attractive as you already have the coordinates of everything in the one place, but I wouldn't do this.
I'd start by creating a texture containing the object space position of each texel in your grey texture. This is key, so that when you click you can render to your grey texture (using an FBO) and know where each texel is in your current view or your projective texture's view. There may be edge cases where the same bit of texture appears on multiple triangles. You could do this by rendering your sphere to the grey texture using the texture coordinates as your vertex positions. You probably need a floating point texture for this, and the following image probably isn't the sphere's texture mapping, but it'll do for demonstration :P.
So when you click, you render a full screen quad to your grey texture with alpha blending enabled. Using the grey texture object space positions, each fragment computes the image space position within the blue texture's projection. Discard the fragments that are outside the texture and sample/blend in those that are inside.
I think you are overcomplicating things.
Writes to textures inside classic shaders (i.e. not compute shader) are only implemented for latest hardware and very latest OpenGL versions and extensions.
It could be terribly slow if used wrong. It's so easy to introduce pipeline stalls and CPU-GPU sync points
Pixel shader could become a terribly slow unmaintainable mess of branches and texture fetches.
And all this mess will be done for every single pixel every single frame
Solution: KISS
Just update your texture on CPU side.
Write to texture, replacing parts of it with desired content
Update is only need to be done once and only when you need this. Data persists until you rewrite it (not even once per frame, but only once per change request)
Pixel shader is dead brain simple: no branching, one texture
To get target pixels, implement ray-picking (you will need it anyway for any non-trivial interactive 3D-graphics program)
P.S. "Everything should be made as simple as possible, but not simpler." Albert Einstein.

Accessing the Depth Buffer from a fragment shader

I had an idea for fog that I would like to implement in OpenGl: After the scene is rendered, a quad is rendered over the entire viewport. In the fragment shader, this quad samples the depth buffer at that location and changes its color/alpha in order to make that pixel as foggy as needs be.
Now I know I can render the scene with the depth buffer linked to a texture, render the scene normally and then render the fog, passing it that texture, but this is one rendering too many. I wish to be able to either
Directly access the current depth buffer from the fragment shader
Be able to render the scene once, both to the normal depth buffer/screen and to the texture for fog.
Is this possible?
What you're thinking of (accessing the target framebuffer for input) would result in a feedback loop which is forbidden.
(…), but this is one rendering too many.
Why do you think that? You don't have to render the whole scene a new, just the fog overlay on top of it.
I wish to be able to either
Directly access the current depth buffer from the fragment shader
If you want to access only the depth of the newly rendered fragment, just use gl_FragCoord.z, this variable (that should only be read to keep performance) holds the depth buffer value the new fragment will have.
See the GLSL Specification:
The variable gl_FragCoord is available as an input variable from within fragment shaders
and it holds the window relative coordinates (x, y, z, 1/w) values for the fragment.
If multi-sampling, this value can be for any location within the pixel, or one of the
fragment samples. The use of centroid in does not further restrict this value to be
inside the current primitive. This value is the result of the fixed functionality that
interpolates primitives after vertex processing to generate fragments. The z component
is the depth value that would be used for the fragment’s depth if no shader contained
any writes to gl_FragDepth. This is useful for invariance if a shader conditionally
computes gl_FragDepth but otherwise wants the fixed functionality fragment depth.
Be able to render the scene once, both to the normal depth buffer/screen and to the texture for fog.
What's so wrong with first rendering the scene normally, with depth going into a separate depth texture attachment, then render the fog, finally compositing them. The computational complexity does not increase by this. Just because it's more steps, it's not doing more work that in your imagined solution, since the individual steps become simpler.
distance camera-pixel:
float z = gl_FragCoord.z / gl_FragCoord.w;
the solution you think to is a common solution, but no need of a supplementary sampling with a quad, everything is already there to compute fog in one pass if depth buffer is enable:
here is a an implementation
const float LOG2 = 1.442695;
float z = gl_FragCoord.z / gl_FragCoord.w;
float fogFactor = exp2( -gl_Fog.density *
gl_Fog.density *
z *
z *
LOG2 );
fogFactor = clamp(fogFactor, 0.0, 1.0);
gl_FragColor = mix(gl_Fog.color, finalColor, fogFactor );

opengl using depth buffer for shadows- any reason not to just render z to tex rather than use depth buffer?

So I'm working on implementing shadow mapping. So far, I've rendered the geometry (depth, normals, colors) to a framebuffer from the camera's point of view, and rendered the depth of the geometry from the light's point of view. Now, I'm rendering the lighting from the camera's point of view, and for each fragment, I'm to compare its distance to the light, to the depth tex value from the render-from-the-lights-pov pass. If the distance is greater, it's in shadow. (Just recapping here to make sure there isn't anything I don't realize I don't understand).
So, to do this last step, I need to convert the depth value [0-1] to its eye-space value [0.1-100] (my near/far planes). (explanation here- Getting the true z value from the depth buffer).
Is there any reason to not instead just have the render-from-the-lights-pov pass just write to a texture the distance of the fragment to the camera (the z component) directly? Then we won't have to deal with the ridiculous conversion? Or am I missing something?
You can certainly write your own depth value to a texture, and many people do just that. The advantage of doing that is that you can choose whatever representation and mapping you like.
The downside is that you have to either a) still have a "real" depth buffer attached to your FBO (and therefore double up the bandwidth you're using for depth writing), or b) use GL_MIN/GL_MAX blending mode (depending on how you are mapping depth) and possibly miss out on early-z out optimizations.

glsl sampler2DShadow and shadow2D clarification

Quick background of where I'm at (to make sure we're on the same page, and sanity check if I'm missing/assuming something stupid):
Goal: I want to render my scene with shadows, using deferred lighting
and shadowmaps.
Struggle: finding clear and consistent documentation regarding how to use shadow2D and sampler2DShadow.
Here's what I'm currently doing:
In the fragment shader of my final rendering pass (the one that actually calculates final frag values), I have the MVP matrices from the pass from the light's point of view, the depth texture from said pass (aka the "shadow map"), and the position/normal/color textures from my geometry buffer.
From what I understand, I need to find what UV of the shadow map the position of the current fragment corresponds to. I do that by the following:
//Bring position value at fragment (in world space) to screen space from lights POV
vec4 UVinShadowMap = (lightProjMat * lightViewMat * vec4(texture(pos_tex, UV).xyz,1.0)).xy;
//Convert screen space to 'texture space' (from -1to1 to 0to1)
UVinShadowMap = (UVinShadowMap+1)/2;
Now that I have this UV, I can get the percieved 'depth' from the light's pov with
float depFromLightPOV = texture2D(shadowMap, UVinShadowMap).r;
and compare that against the distance between the position at the current fragment and the light:
float actualDistance = distance(texture2D(pos_tex, UV).xyz, lightPos);
The problem comes from that 'depth' is stored in values 0-1, and actual distance is in world coordinates. I've tried to do that conversion manually, but couldn't get it to work. And in searching online, it looks like the way I SHOULD be doing this is with a sampler2DShadow...
So here's my question(s):
What changes do I need to make to instead use shadow2D? What does shadow2D even do? Is it just more-or-less an auto-conversion-from-depth-to-world texture? Can I use the same depth texture? Or do I need to render the depth texture a different way? What do I pass in to shadow2D? The world-space position of the fragment I want to check? Or the same UV as before?
If all these questions can be answered in a simple documentation page, I'd love if someone could just post that. But I swear I've been searching for hours and can't find anything that simply says what the heck is going on with shadow2D!
Thanks!
First of all, what version of GLSL are you using?
Beginning with GLSL 1.30, there is no special texture lookup function (name anyway) for use with sampler2DShadow. GLSL 1.30+ uses a bunch of overloads of texture (...) that are selected based on the type of sampler passed and the dimensions of the coordinates.
Second, if you do use sampler2DShadow you need to do two things differently:
Texture comparison must be enabled or you will get undefined results
GL_TEXTURE_COMPARE_MODE = GL_COMPARE_REF_TO_TEXTURE​
The coordinates you pass to texture (...) are 3D instead of 2D. The new 3rd coordinate is the depth value that you are going to compare.
Last, you should understand what texture (...) returns when using sampler2DShadow:
If this comparison passes, texture (...) will return 1.0, if it fails it will return 0.0. If you use a GL_LINEAR texture filter on your depth texture, then texture (...) will perform 4 depth comparisons using the 4 closest depth values in your depth texture and return a value somewhere in-between 1.0 and 0.0 to give an idea of the number of samples that passed/failed.
That is the proper way to do hardware anti-aliasing of shadow maps. If you tried to use a regular sampler2D with GL_LINEAR and implement the depth test yourself you would get a single averaged depth back and a boolean pass/fail result instead of the behavior described above for sampler2DShadow.
As for getting a depth value to test from a world-space position, you were on the right track (though you forgot perspective division).
There are three things you must do to generate a depth from a world-space position:
Multiply the world-space position by your (light's) projection and view matrices
Divide the resulting coordinate by its W component
Scale and bias the result (which will be in the range [-1,1]) into the range [0,1]
The final step assumes you are using the default depth range... if you have not called glDepthRange (...) then this will work.
The end result of step 3 serves as both a depth value (R) and texture coordinates (ST) for lookup into your depth map. This makes it possible to pass this value directly to texture (...). Recall that the first 2 components of the texture coordinates are the same as always, and that the 3rd is a depth value to test.