OpenGL中的视差映射毛刺

时间:2011-01-20 17:56:41

标签: c++ opengl glsl

alt text alt text

这是在将切线向量转移到顶点着色器后立即反转切线向量时的结果:

alt text alt text

“影子”位置错误。

(只有当我通过Y轴旋转它才有效,所以最后一个图像似乎呈现出一个好的视差映射立方体)

我确定它不是一个切入的矢量或纹理坐标问题

由于

我在工作演示中使用了完全相同的切线计算函数完全相同的立方体位置,法线和纹理坐标数据。 毕竟,我将带有位置/ texcoord / normal / tangent数据的数组导出到.txt文件中,我看到了我的预期(我期望的是与工作演示相同的pos / tex / norm数据,包括计算的切线,我设法从工作演示中导出。

下一个论点是,我将着色器代码复制到一个正在运行的演示中,它仍然有效。 另一个是,我尝试了多种方法来渲染这个立方体。 我尝试使用glVertexAttribPointer进行VBO,我尝试使用保存切线作为其他纹理坐标的VBO(如在演示中),我尝试使用glVertexAttrib4f进行DisplayList。结果是...... 完全相同。

高度贴图正确加载,我尝试将其设置为漫反射贴图,看起来没问题。 glGetError()给了我无错误,着色器编译日志就这么说了。

可能是相机或初始状态。

也许发布初始化代码会有所帮助。

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);
}

顺便说一句,我正在使用GL Extension Wrangler和扩展。

着色器代码& log(此导出的文件包含直接传递给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_FrontLightProduct[0].specular * power * atten;
 vec4 color = gl_FrontLightModelProduct.sceneColor + ambient + diffuse + specular;color *= texture2D(diffuseMap,TexCoord);
 gl_FragColor = color ;
 } 

制服工作正常,因为如果我用常量值切换它们,结果是一样的。 编译着色器:

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;
}

在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);  
    }

和一个小笔记

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

告诉我你关于这些糟糕结果可能是什么原因的其他想法。

1 个答案:

答案 0 :(得分:5)

Wheew ......已经解决了。问题是加载纹理文件,即使我没有看到漫反射贴图或漫反射+法线贴图的任何障碍。我正在使用SDL的IMG_Load,也许我用错了方法,但它对我不起作用。这可能是正常的地图搞砸了。

错误的纹理导入代码:

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);

    }

当心!

我现在正在使用基于HBITMAP的纹理加载来自我正在讨论的dhpoware demo。它工作正常。

<强>和平

经过2-3天的艰苦调试后,让我感到一丝欣喜。

哦,我会忘记,最后的结果: alt text