Почему атрибут вершины для нормального вектора не работает?

Я пытаюсь реализовать рассеянное освещение с OpenGL. Я отладил фрагментный шейдер для куба и обнаружил, что вектор нормали всегда (0,0,0), хотя я указываю нормали в моих данных вершин и включаю атрибут вершин.

Соответствующий код OpenGL:

GLfloat vertices[] = {
-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
-0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,

-0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
-0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
-0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,

-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
-0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
-0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,

0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,

-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
-0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,

-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
-0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f
};

GLuint VBO, boxVAO;
glGenVertexArrays(1, &boxVAO);
glGenBuffers(1, &VBO);

glBindVertexArray(boxVAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);

Вершинный шейдер:

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
out vec3 FragPos;
out vec3 outNormal;

uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;

void main()
{
    gl_Position = proj * view * model * vec4(position, 1.0);
    FragPos = vec3(model * vec4(position, 1.0f));
    outNormal = vec3(normal);
}

Фрагмент шейдера:

#version 330 core
in vec3 FragPos;
in vec3 outNormal;
out vec4 color;

uniform vec3 objectColor;
uniform vec3 lightColor;
uniform vec3 lightPos;

void main()
{
    float ambientIntensity = 0.5f;
    vec3 ambientColor = ambientIntensity * lightColor;

    vec3 norm = normalize(outNormal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float diffuse = max(dot(norm, lightDir), 0.0);
    vec3 diffuseColor = diffuse * lightColor;

    vec3 resultColor = (ambientColor + diffuseColor) * objectColor;
    color = vec4(resultColor, 1.0f);
}

Вывод: (показывает только внешнее освещение, рассеянное)

Кроме того, не уверен, помогает ли это вообще, но делает что-то странное, например, устанавливает нормаль, поскольку позиция фрагментов дает такой результат:

Таким образом, кажется, что нормали должны давать рассеянный свет, но каким-то образом неправильно загружаются в шейдер. Есть идеи?

Вот код, который я использовал для отладки шейдера:

// debug testing
vec3 test = vec3(outNormal.xyz);
bvec3 ln = lessThan(test, vec3(0,0,0));
if (ln[2]){
    color = vec4(1.0, 0.0, 0.0, 1.0);
}else{
    color = vec4(0.0, 1.0, 0.0, 1.0);
}

1 ответ

Решение

К сожалению! Оказывается, когда я создал источник света VAO, я использовал те же вершины, но использовал только первые три значения каждой вершины для положения (что правильно для источника света). Но я случайно использовал этот VAO для рисования куба вместо VAO, показанного в коде выше. Не могу поверить, что я не уловил это.. Во всяком случае, код здесь правильный.

Мир.

Другие вопросы по тегам