首页 > 解决方案 > OpenGL 4,GL_ARRAY_BUFFER 没有正确发送法线数据

问题描述

我有一个使用这种方法创建的平原:这是一张显示我的思维方式的图像

我将这些三角形条纹分开,这样每个条纹都可以有唯一的颜色,而且我仍然可以使用顶点索引。

我的问题是法线缓冲区。我像这样创建法线(这是在计算顶点的算法中):

//Calculating Vertices
    for (unsigned int z = 0; z < m_size; z++)
    {
        for (unsigned int x = 0; x <= m_size; x++)
        {
            Vertices.push_back(glm::vec3(m_startingPos.x + x * m_sqrWidth, m_startingPos.y, m_startingPos.z + z * m_sqrWidth));
            Vertices.push_back(glm::vec3(m_startingPos.x + x * m_sqrWidth, m_startingPos.y, m_startingPos.z + (z + 1) * m_sqrWidth));


            glm::vec3 TL = glm::vec3(m_startingPos.x + x * m_sqrWidth, m_startingPos.y, m_startingPos.z + z * m_sqrWidth);
            glm::vec3 TR = glm::vec3(m_startingPos.x + (x + 1) * m_sqrWidth, m_startingPos.y, m_startingPos.z + z * m_sqrWidth);
            glm::vec3 BL = glm::vec3(m_startingPos.x + x * m_sqrWidth, m_startingPos.y, m_startingPos.z + (z + 1) * m_sqrWidth);
            glm::vec3 BR = glm::vec3(m_startingPos.x + (x + 1) * m_sqrWidth, m_startingPos.y, m_startingPos.z + (z + 1) * m_sqrWidth);

            //Normals:
            Normals.push_back(glm::normalize(glm::cross(TL - BR, BL - BR)));
            Normals.push_back(glm::normalize(glm::cross(TR - BR, TL - BR))); 

            //Color:
            colors.push_back(0.0f); colors.push_back(0.0f); colors.push_back(0.5f);
            colors.push_back(0.0f); colors.push_back(0.5f); colors.push_back(0.0f);
        }
    }

所以每个法线都是 0 1 0,我知道这一点。

在这里,我为法线创建了一个缓冲区和 attribPointer(它全部在一个类中,因此 unsigned int normalsBuffer 在 .h 文件中声明并初始化为 NULL):

glGenBuffers(1, &normalsBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, normalsBuffer);
    glBufferData(GL_ARRAY_BUFFER, Normals.size() * sizeof(float) * 3, &Normals[0].x, GL_STATIC_DRAW);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); 

在 glVertexAttribPointer 中,inedex 设置为 2,因为顶点取 0,颜色取 1。

所以现在继承我的着色器:

#shader vertex
#version 330 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 color_in;
layout(location = 2) in vec3 normals_in;

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

out vec3 FragPos;
out vec3 Normal;
out vec3 color_f;

void main()
{
    color_f = color_in;
    FragPos = vec3(model * vec4(position, 1.0));
    Normal = normals_in;
    Normal = mat3(transpose(inverse(model))) * normals_in;

    gl_Position = projection * view * vec4(FragPos, 1.0);
};

#shader fragment
#version 330 core
out vec4 color;

in flat vec3 Normal;
in vec3 FragPos;

in flat vec3 color_f;

uniform vec4 u_Color;

uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 lightColor;


void main()
{
    vec3 objectColor = color_f;

    // ambient
    float ambientStrength = 0.1;
    vec3 ambient = ambientStrength * lightColor;

    // diffuse 
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = diff * lightColor;

    // specular
    float specularStrength = 0.5;
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
    vec3 specular = specularStrength * spec * lightColor;

    vec3 result = (ambient + diffuse + specular) * objectColor;
    color = vec4(result, 1.0);
}

这是一个示例,具有相同着色器的对象如何工作以及我的普通行为如何,它完全没有漫射照明

如果我转到片段着色器并设置 vec3 norm = vec3(0.0, 1.0, 0.0) 一切正常,但这不是我想要的方式。

所以我以同样的方式发送颜色数据,它很好,但发送法线数据似乎不起作用。

下面是我片段着色器并将 norm 设置为 0 1 0 时的样子

标签: c++openglglsl

解决方案


glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

因此,您为颜色(1)启用 VertexAttribArray,您应该为法线(2)激活 VertexAttribArray,并且(void*)0如果您使用结构,请确保您得到正确的确保使用 offsetof 它更可靠,特别是如果您使用编译器有优化


推荐阅读