OpenGL Parallax Displacement Mapping Not Working

I am attempting to implement parallax displacement mapping into my OpenGL code but it is not working as it should.

https://imgur.com/a/9yIQL

As I move around, double-lines moves around and if I am looking and positioned at just the right angle, the extra lines disappears and it looks like a normal texture, but without any displacement mapping.

I have tried various texture/displacement mapping combos and all of them have the same issue, so it is not my textures.

VS Code:

#version 330 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 uvCoordinates;
layout (location = 2) in vec3 normal;
layout (location = 3) in vec3 tangent;

out Vertex
{

vec3 position;
vec2 uvCoordinates;
vec3 normal;
mat3 tbnMatrix;

} vertex;

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

void main()
{

gl_Position = projection * view * model * vec4(position, 1.0);

vertex.position = (model * vec4(position, 1.0)).xyz;
vertex.uvCoordinates = uvCoordinates;
vertex.normal = normalize((model * vec4(normal, 0.0)).xyz);

vec3 n = normalize((model * vec4(normal, 0.0)).xyz);
vec3 t = normalize((model * vec4(tangent, 0.0)).xyz);

t = normalize(t - dot(t, n) * n);

vec3 b = cross(t, n);

vertex.tbnMatrix = mat3(t, b, n);

}


FS Code:

#version 330 core

layout (location = 0) out vec4 color;

in Vertex
{

vec3 position;
vec2 uvCoordinates;
vec3 normal;
mat3 tbnMatrix;

} vertex;

struct Material
{

vec3 ambientLight;
vec3 diffuseLight;
vec3 specularLight;
float transparency;
float shininess;
int useDiffuse;
int useSpecular;
int useNormal;
int useDisplacement;
sampler2D diffuse;
sampler2D specular;
sampler2D normal;
sampler2D displacement;

};

uniform vec3 ambientLight;

uniform vec3 eyePosition;

uniform Material material;

uniform float displacementScale;
uniform float displacementBias;

vec2 calculateTextureCoordinates(vec3 eyeDirection, vec2 uvCoordinates, mat3 tbnMatrix, sampler2D displacement)
{

return uvCoordinates + (eyeDirection * tbnMatrix).xy * (texture(displacement, uvCoordinates).r * displacementScale + displacementBias);

}

void main()
{

color = vec4(ambientLight * material.ambientLight, material.transparency);

if(material.useDiffuse == 1)
{

vec2 uvCoordinates;

if(material.useDisplacement == 1)
{

uvCoordinates = calculateTextureCoordinates(normalize(eyePosition - vertex.position), vertex.uvCoordinates, vertex.tbnMatrix, material.displacement);

}
else
{

uvCoordinates = vertex.uvCoordinates;

}

color *= texture(material.diffuse, uvCoordinates);

}

}


I also have other lighting shaders that use the exact same tbn matrix to calculate normal mapping, which works just fine. This leads me to believe that both my tangent calculations and tbn matrix are working just fine. This scene is using no lighting, so lighting should have no impact on this code.

The displacementScale uniform is set to 0.04 and my displacementBias is set to -0.02. Increasing the scale causes the lines to become even more and more disoriented and decreasing it causes less of the disoriented effect but does not provide any displacement whatsoever.

I've also checked to make sure I have binded all my textures to the correct sampler2D and they are correct. I've been working on this for awhile now and I am completely stuck. Any help would be immensely appreciated.

In order to properly implement this, you have to understand which "space" you are working in. In computer graphics, you have five discrete spaces to work in:

1. Object space. This is the un-transformed vertex coordinates.
2. Model, or World space, this is the position of a vertex when transformed into it's world position.
3. View space. This is the world, relative to the camera, or eye.
4. Projection, or screen space. This is when fragments get rasterised.
5. Tangent space. This is space relative to the texture coordinates. Call it UV space if you like.

In your example, we will ignore lighting, as it complicates matters.

In order to correctly displace the UV coordinates according to the view vector, you have to take your view vector, and transform it into tangent space, like so:

view_dir = eyePosition - (model * position).xyz;
TS_View = normalize(tbn * view_dir);


In doing so, when you perform your view direction calculations with uv coordinates, they are using the same coordinate system, and the displacement will be correct regardless of the orientation of the model.

You may find that it's still not quite right. If so, try flipping the sign of the y or x component of the view direction, by multiplying it by -1.