0
\$\begingroup\$

I'm attempting to implement parallax mapping using the following shader pair in a deferred renderer, but as you can see in the attached image, the vertical shifting of uv coordinates for sampling is in the wrong direction.

enter image description here

The vertex shader is as follows:

#version 430 core
// Some drivers require the following
precision highp float;
// Model space data
layout (location = 0)in vec3 MSVertex;
layout (location = 1)in vec3 MSNormal;
layout (location = 2)in vec3 MSTangent;
layout (location = 3)in vec3 MSBiTangent;
layout (location = 4)in vec2 MSTexCoord;

uniform mat4 ModelTransform;
uniform mat4 ViewTransform;
uniform mat4 ProjTransform;
uniform vec3 camPos;
out xferBlock
{
    // Tangent space data
    vec3 TSViewPos;
    vec3 TSVertex;
    // World space data
    vec3 WSVertex;
    vec3 WSNormal;
    vec2 TexCoord;
    mat3 TBN;
} outdata;


void main()
{
    //mat3 normalMat = transpose(inverse(mat3(ModelTransform)));
    vec3 T = normalize(vec3(mat3(ModelTransform) * MSTangent));
    vec3 B = normalize(vec3(mat3(ModelTransform) * MSBiTangent));
    vec3 N = normalize(vec3(mat3(ModelTransform) * MSNormal));
    mat3 tbn = mat3(T, B, N);
    outdata.TBN = tbn;
    vec4 vert = ModelTransform * vec4(MSVertex,1.0);
    outdata.WSVertex = vert.xyz;
    outdata.WSNormal = normalize(mat3(ModelTransform) * MSNormal);
    outdata.TexCoord = MSTexCoord;
    outdata.TSViewPos = tbn * camPos;
    outdata.TSVertex = tbn * vert.xyz;
    gl_Position = ProjTransform * ViewTransform * vert;
}

and the fragment shader:

#version 430 core
// Some drivers require the following
precision highp float;
uniform sampler2D colourMap;
uniform sampler2D specularMap;
uniform sampler2D normalMap;
uniform sampler2D heightMap;
uniform sampler2D glowMap;
uniform vec4 incolour;
layout (location = 0) out vec4 position;
layout (location = 1) out vec4 nColour;
layout (location = 2) out vec4 colour;
layout (location = 3) out vec4 specular;
layout (location = 4) out vec4 glow;

uniform int hasMaterial;

in xferBlock
{
    vec3 TSViewPos; 
    vec3 TSVertex;
    vec3 WSVertex;
    vec3 WSNormal;
    vec2 TexCoord;
    mat3 TBN;
}indata;

vec2 parallaxMapping(vec2 texCoords, vec3 viewDir)
{
    const float minLayers = 8.0;
    const float maxLayers = 32.0;
    float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0.0, 0.0, 1.0), viewDir))); 
    // calculate the size of each layer
    float layerDepth = 1.0 / numLayers;
    // depth of current layer
    float currentLayerDepth = 0.0;
    float height =  texture(heightMap, texCoords).r;    
    vec2 P = viewDir.xy / viewDir.z * 0.05;
//  P.y *= -1.0;
    vec2 deltaTexCoords = P / numLayers;
    vec2 currentTexCoords = texCoords;
    float currentDepthMapValue = height;
    while(currentLayerDepth < currentDepthMapValue)
    {
        // shift texture coordinates along direction of P
        currentTexCoords -= deltaTexCoords;
        // get depthmap value at current texture coordinates
        currentDepthMapValue = texture(heightMap, currentTexCoords).r;  
        // get depth of next layer
        currentLayerDepth += layerDepth;  
    }

    // get texture coordinates before collision (reverse operations)
    vec2 prevTexCoords = currentTexCoords + deltaTexCoords;

    // get depth after and before collision for linear interpolation
    float afterDepth  = currentDepthMapValue - currentLayerDepth;
    float beforeDepth = texture(heightMap, prevTexCoords).r - currentLayerDepth + layerDepth;

    // interpolation of texture coordinates
    float weight = afterDepth / (afterDepth - beforeDepth);
    vec2 finalTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight);

    return finalTexCoords;
}

void main()
{


    vec2 txc = indata.TexCoord;
    position = vec4(indata.WSVertex,1.0);
    if (hasMaterial == 1)
    {
        vec2 txc = parallaxMapping(indata.TexCoord,normalize(indata.TSViewPos - indata.TSVertex));
//      if(txc.x > 1.0 || txc.y > 1.0 || txc.x < 0.0 || txc.y < 0.0)
//          discard;
        colour = vec4(texture(colourMap,txc).rgb,1.0);
        vec3 normal_rgb = texture(normalMap,txc).rgb;
        normal_rgb = normalize(normal_rgb * 2.0 - 1.0);
        normal_rgb = normalize(indata.TBN * normal_rgb);
        specular = vec4(texture(specularMap,txc).rgb,1.0);
        nColour = vec4(normal_rgb,1.0);
        glow = vec4(texture(glowMap,txc).rgb,1.0);
    }
    else
    {
        colour = incolour;
        nColour = vec4(indata.WSNormal,1.0);
        specular = incolour;
    }
}

I can fix the issue by uncommenting P.y *= -1.0; in the parallaxMapping function, but this feels like a hack. As you can see in the image, the normals are correct (lighting is from above), so I'm at a loss to explain what is happening.

I've checked(and flipped) the v component in the obj model, and the tangent/bitangent vectors are generated by assimp on load.

I've also tried multiplying by the transpose of the TBN matrix, all with no effect.

I'm working from the tutorial found here.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.