Parallax mapping error in OpenGL

alt textalt text

And this is the result when I invert the tangent vector immediately after it is passed to the vertex shader:

alt textalt text

The "shadow" is in the wrong place.

(And it only works when I rotate it along the Y axis, so the last image seems to be a nice cube with parallax display)

IM SURE THIS IS NOT A PROBLEM OF TANGENT VECTOR OR TEXTURE COORDINATES

Because the

I used exactly the same touch calculation functions and exactly the same cube position, normal and texture coordinates , as in the working demo. In the end, I exported arrays with position data / texcoord / normal / tangent to a .txt file, and I saw what I was exactly expecting (and I expected that this is the same pos / tex / norm data as in the working demos, including calculated tangents, which I managed to export from a working demo).

Next argument: I copied my shader code into a working demo and it still works . Another, I tried several ways to make this cube. I tried VBO with glVertexAttribPointer, I tried VBO while saving the tangent as another texture coordinate (as in the demo), I tried DisplayList with glVertexAttrib4f. The result ... EXACTLY VERY.

The height map loads correctly, I tried to install it as a diffuse map, and it looked fine. glGetError () gives me No Errors and shader compilation files say so.

This is probably something with cameras or init states.

Perhaps the initialization code will be published.

void CDepthBase::OpenGLSet() { glEnable( GL_TEXTURE_2D ); glShadeModel( GL_SMOOTH ); glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); glClearDepth( 1.0f ); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glDepthFunc( GL_LEQUAL ); glEnable(GL_DEPTH_TEST); glBlendFunc( GL_ONE, GL_ONE ); GLfloat ratio; glViewport(0, 0, ResolutionWidth, ResolutionHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, ResolutionWidth / (float)ResolutionHeight, 0.1f, 900.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if (GLEW_OK != glewInit()) { MBX("Failed to init GLEW.", "Error"); } if (glewIsSupported("GL_ARB_vertex_buffer_object")) { VBO_supported = true; } else VBO_supported = false; glHint( GL_FOG_HINT, GL_DONT_CARE ); glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); glShadeModel(GL_SMOOTH); glAlphaFunc(GL_ALWAYS, 0); } 

By the way, I am using GL Extension Wrangler with extensions.

Shader code and log (this exported file contains code that was directly passed to the glShaderSource file):

 Vertex shader was successfully compiled to run on hardware. Fragment shader was successfully compiled to run on hardware. Fragment shader(s) linked, vertex shader(s) linked. ------------------------------------------------------------------------------------------ varying vec3 lightDir; varying vec3 viewDir; attribute vec4 tangent; void main() { gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; gl_TexCoord[0] = gl_MultiTexCoord0; vec3 vertexPos = vec3(gl_ModelViewMatrix * gl_Vertex); vec3 tn = tangent.xyz; vec3 n = normalize(gl_NormalMatrix * gl_Normal); vec3 t = normalize(gl_NormalMatrix * tangent.xyz); vec3 b = cross(t, n) * -tangent.w; mat3 tbnMatrix = mat3(tx, bx, nx, ty, by, ny, tz, bz, nz); lightDir = (gl_LightSource[0].position.xyz - vertexPos) / 100.0; lightDir = tbnMatrix * lightDir; viewDir = -vertexPos; viewDir = tbnMatrix * viewDir; } ----------------------------------------------------------------------------------------- varying vec3 lightDir; varying vec3 viewDir; uniform sampler2D diffuseMap; uniform sampler2D normalMap; uniform sampler2D heightMap; uniform float scale; uniform float bias; void main() { vec3 v = normalize(viewDir); vec2 TexCoord = gl_TexCoord[0].st; { float height = texture2D(heightMap, gl_TexCoord[0].st).r; height = height * scale + bias; TexCoord = gl_TexCoord[0].st + (height * v.xy); } vec3 l = lightDir; float atten = max(0.0, 1.0 - dot(l, l)); l = normalize(l); vec3 n = normalize(texture2D(normalMap, TexCoord).rgb * 2.0 - 1.0); vec3 h = normalize(l + v); float nDotL = max(0.0, dot(n, l)); float nDotH = max(0.0, dot(n, h)); float power = (nDotL == 0.0) ? 0.0 : pow(nDotH, gl_FrontMaterial.shininess); vec4 ambient = gl_FrontLightProduct[0].ambient * atten; vec4 diffuse = gl_FrontLightProduct[0].diffuse * nDotL * atten; vec4 specular = gl_FrontLightProduct[0].specular * power * atten; vec4 color = gl_FrontLightModelProduct.sceneColor + ambient + diffuse + specular;color *= texture2D(diffuseMap,TexCoord); gl_FragColor = color ; } 

The uniform works correctly because the results are the same if I switch them with constant values. Shader Compilation:

 void __Shader::import(){ if(imported) __Shader::~__Shader(); v = glCreateShader(GL_VERTEX_SHADER); f = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(v, 1, (const GLchar **)&vsrc.cstr,NULL); glShaderSource(f, 1, (const GLchar **)&fsrc.cstr,NULL); glCompileShader(v); glCompileShader(f); p = glCreateProgram(); glAttachShader(p,v); glAttachShader(p,f); if(_flags & NORMAL_MAPPING) glBindAttribLocation(p, ATTRIB_TANGENT, "tangent"); glLinkProgram(p); if(_flags & DIFFUSE_MAPPING) diffuseUni.loc = glGetUniformLocation(p, "diffuseMap"); if(_flags & NORMAL_MAPPING) normalUni.loc = glGetUniformLocation(p, "normalMap"); if(_flags & PARALLAX_MAPPING) heightUni.loc = glGetUniformLocation(p, "heightMap"); if(_flags & SPECULAR_MAPPING) specularUni.loc = glGetUniformLocation(p, "specularMap"); imported = true; } 

Setting Attribute in VBO:

  if(tangents.size() > 0){ buffered |= 3; glGenBuffers(1, &VBO_tangent); glBindBuffer(GL_ARRAY_BUFFER, VBO_tangent); glBufferData(GL_ARRAY_BUFFER, tangents.size()*sizeof(tangent), tangents.get_ptr(), GL_STATIC_DRAW); } // and in draw: if(buffered & 3) { glBindBuffer(GL_ARRAY_BUFFER, VBO_tangent); glVertexAttribPointer(__Shader::ATTRIB_TANGENT, 4, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(__Shader::ATTRIB_TANGENT); } 

and a small note

 for(int i = 0; i < responders.size(); ++i) if(strstr(responders[i].idea, "tangent problem")) responders[i].please_dont_talk(); 

Just tell me your other ideas about what might be causing these bad results.

+4
source share
1 answer

Wheew ... already decided this. The problem was loading texture files, although I did not see any violations with diffuse display or even diffuse + normal display. I used IMG_Load from the SDL, maybe I used it incorrectly, but for me it did not work. It was probably a normal map.

Bad texture error code:

 if(imported || filenamez.length() < 1) return; SDL_Surface* surface = 0; surface = IMG_Load(filenamez.c_str()); if (surface) { glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); bool endianess = filenamez.substr(filenamez.length()-4) == ".jpg"; glTexImage2D(GL_TEXTURE_2D, 0, 3, surface->w, surface->h, 0, (endianess ? GL_RGB : GL_BGR), GL_UNSIGNED_BYTE, surface->pixels); } 

CAUTION!

Now I am using HBITMAP-based texture loading, taken from the dhpoware demo that I talked about. And it works great.

peace.

After 2-3 days of hard debugging, let me feel a little euphoric.

Oh, I would forget the final result: alt text

+5
source

Source: https://habr.com/ru/post/1336353/


All Articles