开发者

Parallax mapping glitch in OpenGL

开发者 https://www.devze.com 2023-02-06 00:48 出处:网络
And this is result when I invert the tangent vector right after transferring it to vertex shader: The \"shadow\" is in the wrong place.

Parallax mapping glitch in OpenGL

Parallax mapping glitch in OpenGL

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

Parallax mapping glitch in OpenGL

Parallax mapping glitch in OpenGL

The "shadow" is in the wrong place.

(And it works only when I rotate it through Y axis so the last image seem to present a good parallax mapped cube)

IM SURE IT IS NOT A TANGENT VECTOR OR TEXTURE COORDINATES PROBLEM

Because

I used exactly the same tangent calculation functions and exactly the same cube position, normal and texture coordinate data as in working demo. After all, I exported arrays with position/texcoord/normal/tangent data into a .txt file and I saw what I exactly expected (and what I expected is the same pos/tex/norm data as in working demo, including calculated tangents which I managed to export from working demo).

The next argument is, I copied my shader code to a working demo and it still works. Other one is, I tried multiple ways to render this cube. I tried VBO with glVertexAttribPointer, I tried VBO with saving tangent as other texture coordinate (as in the demo), I tried DisplayList with glVertexAttrib4f. Result is... EXACTLY THE SAME.

Height map is loading correctly, I tried to set it as a diffuse map and it looked OK. glGetError() gives me No Errors and shader compile logs says so.

It is probably something with camera or init states.

Maybe posting an init code will help.

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'm using GL Extension Wrangler with extensions.

Shader code & log (this exported file contains code which was directly passed to glShaderSource):

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(t.x, b.x, n.x,
                       t.y, b.y, n.y,
                       t.z, b.z, n.z);
 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_FrontLightPro开发者_高级运维duct[0].specular * power * atten;
 vec4 color = gl_FrontLightModelProduct.sceneColor + ambient + diffuse + specular;color *= texture2D(diffuseMap,TexCoord);
 gl_FragColor = color ;
 } 

Uniforms are working correctly because results are the same if I switch them with constant values. Compiling shader:

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 can be the reason of those bad results.


Wheew... already solved it. The problem was with loading texture files even though I did not see any disorders with diffuse mapping or even with diffuse+normal mapping. I was using IMG_Load from SDL, maybe I used it wrong way but it did not work for me. It was probably normal map messed up.

bad texture import 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);

    }

BEWARE !

I'm now using HBITMAP-based texture loading taken from dhpoware demo which I was talking about. And it works fine.

peace.

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

Oh, I'd forget, the final result:

Parallax mapping glitch in OpenGL

0

精彩评论

暂无评论...
验证码 换一张
取 消