PDA

View Full Version : Parallax Occlusion Mapping



hbuel
08-22-2006, 05:40 AM
Hello,

I'm looking for a way to implement a Parallax Occlusion shader in GLSL. Which has been very troublesome so far. First I tried to implement according to the guide on GameDev (http://www.gamedev.net/reference/articles/article2325.asp) . Although the description was very good, the shaders were written in HLSL. I tried to convert it to GLSL but stumpled about a part where that doesn't seems to be possible.
float2 dx, dy;
dx = ddx( IN.texcoord );
dy = ddy( IN.texcoord );
while ( nCurrSample < nNumSamples )
{
vCurrSample = tex2Dgrad( Sampler, IN.texcoord + vCurrOffset, dx, dy );
if ( vCurrSample.a > stepHeight )
{
//...
}
}I've read there is no counterpart in GLSL for the tex2Dgrad() function (yet) - although there is one for ddx/ddy(dFdx/dFdy). A counterpart will arise with the proposed extension GL_ARB_shader_texture_lod. So it is not possible to read a texture inside of a flow control part in GLSL? That was the conlusion drawn out of this. I find this irritating cause I was quite sure there were Parallax Occlusion Mapping implementations out there... I've found Steep Parallax Mapping (http://graphics.cs.brown.edu/games/SteepParallax/index.html) which uses GLSL; but I was not able to implement this yet cause the vertex shaders are missing and the description're not as detailed as above. Although further material was announced on this but hasn't arrived till now. But the interesting thing is it uses texture2D inside of flow control

while (NB.a < height) {
height -= step;
offsetCoord += delta;
NB = texture2D(normalBumpMap, offsetCoord);
}but in the abstract PDF this changed to
vec4 nb = texture2DLod(NB, t, LOD);
while (nb.a < height) {
height -= step; t += dt;
nb = texture2DLod(NB, t, LOD);
}Does the texture2DLod usage somehow change the situation in that way tex2Dgrad might not be needed. Why is this working here and not in the above algorithm? I've found one ATi paper ( Dynamic Parallax Occlusion Mapping with Approximate Soft Shadows (http://www.ati.com/developer/techreports/2006/I3D2006/Tatarchuk-POM-SI3D06.pdf) ) to be very interessing (cause it looked most promising) but this wasn't hepling in the implementation and a bit to abstract.

I've implemented the first one except for the tex2Dgrad part (using texture2D insted) but all I got was a lot of distortions and very bad peformance on my 6800GT. The latter two approaches are taking a soft shadow part into account which I always found to be a key feature (but I've not really understood how the soft shadows are computed (yet)).

Can anyone help me in clearing that gradient calculation part? Or know of additional material/guides to implement the latter two-like algorithms which use (maybe well documented) GLSL shaders for this.

thank you very much (and please excuse all the errors - I'm better in reading English that writing it) :)

Humus
08-22-2006, 02:11 PM
On ATI cards you have GL_ATI_shader_texture_lod already, which is what the ARB extension will be based on. As for using texture2D() in a loop, GLSL is a bit more liberal than HLSL here, so you can do it, however, if you have mipmaps the results are undefined if the shader takes different branches.
Using texture2DLod() inside a branch works equally well as tex2Dgrad() since it specifies the LOD explicitly. However, this function is incapable of providing anisotropic filtering since it only gets the LOD and not the gradients.

hbuel
08-24-2006, 11:31 AM
Thank you.

The extension viewer reports I need a Radeon X1600/1900/RV530; only have a 6800GT and a 9700mobile. :(

But I'm afraid I havn't fully understood the gradient part yet or how I have to utilise the texture2DLod() function to get the functionality of tex2Dgrad()? How do I calculate a lod that would be required here? Similar like the gradients with dFdx/dFdy()?

thank you!

Humus
08-24-2006, 05:32 PM
Do you need anisotropic? In that case, texture2DLod() can't help you. If you only require trilinear, you can compute the lod as follows:

vec2 lodTexCoord = texCoord * textureSize;
vec2 dx = dFdx(lodTexCoord);
vec2 dy = dFdy(lodTexCoord);
float lod = log(inversesqrt(min(dot(dx, dx), dot(dy, dy))));