【问题标题】:OpenGl 4, GL_ARRAY_BUFFER doesnt send normals data correctlyOpenGL 4,GL_ARRAY_BUFFER 没有正确发送法线数据
【发布时间】:2020-02-10 04:39:53
【问题描述】:

我有一个使用这种方法创建的平原:Heres an image showing my way of thinking

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

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

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

Heres an example how object with same shader works and how my plain behaves, It totally lacks diffuse lighting

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

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

Heres how it looks like when I got to fragment shader and set norm to 0 1 0

【问题讨论】:

  • 这是一个简单的印刷错误。法线向量的属性位置是 2。所以它必须是glEnableVertexAttribArray(2) 而不是glEnableVertexAttribArray(1)
  • 哇,谢谢。从昨天开始,我一直在想它,而且它是如此简单。

标签: c++ opengl glsl


【解决方案1】:
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

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

【讨论】:

  • 已经知道了,但还是谢谢你,下一个程序员可能会从你的回答和我的愚蠢中获得知识
  • 印刷错误是题外话。它不打算回答他们。问题和答案对任何用户都没有用。
猜你喜欢
  • 2017-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多