简体   繁体   English

OpenGL和GLSL中的凹凸贴图

[英]Bump Mapping in OpenGL and GLSL

I'm trying to implement bump mapping on a cube using OpenGL and GLSL. 我正在尝试使用OpenGL和GLSL在多维数据集上实现凹凸贴图。 However, when I rotate my cube around, only the left-facing square and right-facing square appear (that is, in the negative x and positive x direction), the other four faces of the cube (top, bottom, front, back) are black. 但是,当我旋转多维数据集时,只有左向正方形和右向正方形出现(即,在负x和正x方向上),立方体的其他四个面(上,下,前,后) )是黑色的。 Here is an example: 这是一个例子:

在此处输入图片说明

My mesh class consists of an indexList and vertexList (the Vertex class contains x, y, z, etc). 我的网格类由indexList和vertexList组成(Vertex类包含x,y,z等)。 I'm using this simple cube.ply model, which contains s,t texture coordinates. 我正在使用这个简单的cube.ply模型,其中包含s,t纹理坐标。 Borrowing from this example , I calculate the tangent vectors as follows: 从此示例中借用,我计算出切向量如下:

void Mesh::computeTangents() {

        for (size_t i = 0; i < m_indexList.size(); i += 3) {

            Vertex v1 = m_vertexList[m_indexList[i]];
            Vertex v2 = m_vertexList[m_indexList[i+1]];
            Vertex v3 = m_vertexList[m_indexList[i+2]];

            glm::vec3 pos1 = glm::vec3(v1.getX(), v1.getY(), v1.getZ());
            glm::vec3 pos2 = glm::vec3(v2.getX(), v2.getY(), v2.getZ());
            glm::vec3 pos3 = glm::vec3(v3.getX(), v3.getY(), v3.getZ());
            glm::vec2 tex1 = glm::vec2(v1.getS(), v1.getT());
            glm::vec2 tex2 = glm::vec2(v2.getS(), v2.getT());
            glm::vec2 tex3 = glm::vec2(v3.getS(), v3.getT());

            glm::vec3 edge1 = glm::normalize(pos2 - pos1);
            glm::vec3 edge2 = glm::normalize(pos3 - pos1);

            glm::vec2 texEdge1 = glm::normalize(tex2 - tex1);
            glm::vec2 texEdge2 = glm::normalize(tex3 - tex1);

            float det = (texEdge1.x * texEdge2.y) - (texEdge1.y * texEdge2.x);

            glm::vec3 tangent;

            if(fabsf(det) < 1e-6f) {
                tangent.x = 1.0;
                tangent.y = 0.0;
                tangent.z = 0.0;
            }
            else {
                det = 1.0 / det;

                tangent.x = (texEdge2.y * edge1.x - texEdge1.y * edge2.x) * det;
                tangent.y = (texEdge2.y * edge1.y - texEdge1.y * edge2.y) * det;
                tangent.z = (texEdge2.y * edge1.z - texEdge1.y * edge2.z) * det;

                glm::normalize(tangent);
            }

            m_vertexList[m_indexList[i]].setTanX(tangent.x);
            m_vertexList[m_indexList[i]].setTanY(tangent.y);
            m_vertexList[m_indexList[i]].setTanZ(tangent.z);
            m_vertexList[m_indexList[i+1]].setTanX(tangent.x);
            m_vertexList[m_indexList[i+1]].setTanY(tangent.y);
            m_vertexList[m_indexList[i+1]].setTanZ(tangent.z);
            m_vertexList[m_indexList[i+2]].setTanX(tangent.x);
            m_vertexList[m_indexList[i+2]].setTanY(tangent.y);
            m_vertexList[m_indexList[i+2]].setTanZ(tangent.z);
        }
    }

If I output the values of the tangent vector for each triangle, I get these values: 如果输出每个三角形的切向量的值,则会得到以下值:
1, 0, 0 1 0 0
1, 0, 0 1 0 0
0, 0, -1 0、0,-1
0, 0, -1 0、0,-1
0, 0, 1 0、0、1
0, 0, 1 0、0、1
-1, 0, 0 -1,0,0
-1, 0, 0, -1,0,0,
1, 0, 0 1 0 0
1, 0, 0 1 0 0
1, 0, 0 1 0 0
1, 0, 0 1 0 0

If these are correct, then the problem is likely in the shader. 如果这些是正确的,则问题可能出在着色器中。 My shader is as follows (mostly taken from a book): 我的着色器如下(大部分取自一本书):

vert: VERT:

attribute vec4 vertexPosition;
attribute vec3 vertexNormal;
attribute vec2 vertexTexture;
attribute vec3 vertexTangent;

varying vec2 texCoord;
varying vec3 viewDirection;
varying vec3 lightDirection;

uniform vec3 diffuseColor;
uniform float shininess;
uniform vec4 lightPosition;

uniform mat4 modelViewMatrix;
uniform mat4 normalMatrix;
uniform mat4 MVP; // modelview projection

void main() {
    vec4 eyePosition = modelViewMatrix * vertexPosition;
    vec3 N = normalize(vec3(normalMatrix * vec4(vertexNormal, 1.0)));
    vec3 T = normalize(vec3(normalMatrix * vec4(vertexTangent, 1.0)));
    vec3 B = normalize(cross(N, T));

    vec3 v;
    v.x = dot(lightPosition.xyz, T);
    v.y = dot(lightPosition.xyz, B);
    v.z = dot(lightPosition.xyz, N);
    lightDirection = normalize(v);

    v.x = dot(eyePosition.xyz, T);
    v.y = dot(eyePosition.xyz, B);
    v.z = dot(eyePosition.xyz, N);
    viewDirection = normalize(v);

    texCoord = vertexTexture;
    gl_Position = MVP * vertexPosition;
}

Frag: 破片:

varying vec2 texCoord;
varying vec3 viewDirection;
varying vec3 lightDirection;

uniform vec3 diffuseColor;
uniform float shininess;

void main() {

    float bumpDensity = 16.0;
    float bumpSize = 0.15;

    vec2 c = bumpDensity * texCoord;
    vec2 p = fract(c) - vec2(0.5);

    float d, f;
    d = dot(p, p);
    f = 1.0 / sqrt(d + 1.0);

    if (d >= bumpSize) {
        p = vec2(0.0);
        f = 1.0;
    }

    vec3 normalDelta = vec3(p.x, p.y, 1.0) * f;
    vec3 litColor = diffuseColor * max(dot(normalDelta, lightDirection), 0.0);
    vec3 reflectDir = reflect(lightDirection, normalDelta);
    float spec = max(dot(viewDirection, reflectDir), 0.0);
    spec *= shininess;
    litColor = min(litColor + spec, vec3(1.0));
    gl_FragColor = vec4(litColor, 1.0);
 } 

Edit: Changed background to more clearly see the black faces. 编辑:更改背景以更清楚地看到黑脸。 Also, I incorrectly noted which faces were actually appearing before. 另外,我错误地指出了之前实际出现过哪些面孔。

Edit 2: I'm finding that the value of max(dot(normalDelta, lightDirection), 0.0) in the fragment shader returns 0 for those faces. 编辑2:我发现片段着色器中的max(dot(normalDelta,lightDirection),0.0)的值对于那些面孔返回0。 However, I still don't know why. 但是,我仍然不知道为什么。

Edit 3: Well, the problem turned out to be that I was passing the wrong index of the tangent vectors in my Vertex class. 编辑3:恩,问题出在我的顶点类中传递了切向量的错误索引。 That is, I had 10 in this line instead of 9: 也就是说,我在这一行中有10个,而不是9个:

glVertexAttribPointer(v3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof( float ) * 9));  

Okay, so the problem is that any face with a normal on the xz-plane isn't rendering properly, ie the ones that are rendering properly are the ones with normals along the y-axis (top and bottom faces). 好,所以问题是,任何面与正常上xz平面不能正常呈现,即正常呈现的是那些具有沿y轴(顶面和底面)法线的那些。

And your list of tangents: 和您的切线列表:

 1, 0,  0
 1, 0,  0
 0, 0, -1
 0, 0, -1
 0, 0,  1
 0, 0,  1
-1, 0,  0
-1, 0,  0
 1, 0,  0
 1, 0,  0
 1, 0,  0
 1, 0,  0

Are all either along the x or z axes. 全部沿x轴或z轴。 So what I'm guessing might be happening is that your normals and tangents are pointing in the same (or opposite) directions, in which case this line in your vertex shader: 因此,我猜测可能正在发生的事情是法线和切线指向相同(或相反)的方向,在这种情况下,顶点着色器中的该行:

vec3 B = normalize(cross(N, T));

is going to result in vec3(0.0, 0.0, 0.0), which can't be normalized. 将导致无法标准化的vec3(0.0,0.0,0.0)。

My recommendation is to try manually giving the x and z faces tangents along the y-axis, see if that makes a difference. 我的建议是尝试手动沿y轴给x和z面切线,看看是否有区别。 If it helps, then you know that the problem is with your computation of the tangents. 如果有帮助,则说明问题出在切线的计算上。

If it doesn't help, you can troubleshoot by outputting values from the fragment shader as on-screen colours. 如果没有帮助,则可以通过将片段着色器的值输出为屏幕上的颜色来进行故障排除。 Try displaying the viewDirection, lightDirection, normalDelta, reflectDir, and anything else you can think of to see which variable is causing the blackness. 尝试显示viewDirection,lightDirection,normalDelta,reflectDir以及您可以想到的其他任何东西,以查看哪个变量导致了黑色。

Bonus: Switch the glClear color to something other than black? 奖励:将glClear颜色切换为黑色以外的颜色? So that it doesn't look like a face floating in space. 因此它看起来不像是在太空中漂浮的面孔。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM