opengl 球体照明错误结果

8ftvxx2r  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(93)

我有一个简单的逐像素光照着色器,但是我想要绘制的球体看起来有点像逐顶点着色。我从昨天开始调查,但没有发现任何问题。球体的法线与标准化顶点位置相同,或者我错了?
顶点着色器:

#version 330 core

uniform mat4 ModelViewProjectionMatrix;
uniform mat4 ModelViewMatrix;
uniform mat3 NormalMatrix;

in vec3 Position;
in vec3 Normal;

out vec3 VertexEyePosition;
out vec3 NormalEyePosition;

void main()
{
    gl_Position = ModelViewProjectionMatrix * vec4(Position, 1.0f);
    VertexEyePosition = vec3(ModelViewMatrix * vec4(Position, 1.0f));
    NormalEyePosition = NormalMatrix * normalize(Normal);
}

字符串
片段着色器:

#version 330 core

uniform vec4 EyeLightPosition;

in vec3 VertexEyePosition;
in vec3 NormalEyePosition;

out vec4 FinalColor;

void main()
{
    vec3 L = normalize(vec3(EyeLightPosition) - VertexEyePosition);
    vec3 N = NormalEyePosition;
    vec3 R = reflect(-L, N);
    vec3 V = normalize(-VertexEyePosition);

    vec3 Ambient = 0.1 * vec3(1.0, 0.0, 0.0);
    vec3 Diffuse = 0.8 * vec3(1.0, 0.0, 0.0) * max(0.0, dot(N, L));
    vec3 Specular = vec3(1.0) * pow(max(0.0, dot(R, V)), 8.0);

    FinalColor = vec4(Ambient + Diffuse + Specular, 1.0);
}


对于立方体或平面,着色器工作正常。
球体生成:

void SphereMesh::GenerateGeometry()
{
    vertices.clear();
    uv_coords.clear();
    normals.clear();
    faces.clear();

    vertices.reserve((segments + 1) * (rings + 1));
    uv_coords.reserve((segments + 1) * (rings + 1));

    // Generate vertices and UV coordinates;
    for (unsigned int ring = 0; ring <= rings; ring++)
    {
        const float ring_sin = glm::sin(static_cast<float>(ring) / rings * glm::pi<float>() - 0.5f * glm::pi<float>());
        const float ring_cos = glm::cos(static_cast<float>(ring) / rings * glm::pi<float>() - 0.5f * glm::pi<float>());

        for (unsigned int segment = 0; segment <= segments; segment++)
        {
            if (((ring == 0) || (ring == rings)) && (segment == segments)) continue;

            const float segment_sin = glm::sin(static_cast<float>(segment) / segments * 2.0f * glm::pi<float>());
            const float segment_cos = glm::cos(static_cast<float>(segment) / segments * 2.0f * glm::pi<float>());

            const float x = radius * ring_cos * segment_sin;
            const float y = radius * ring_sin;
            const float z = radius * ring_cos * segment_cos;

            const float u = ((ring == 0) || (ring == rings)) && (segment == segments) ?
                    static_cast<float>(segment) / (segments - 1) + 0.5f * static_cast<float>(segment) / (segments - 1):
                    static_cast<float>(segment) / segments;
            const float v = static_cast<float>(ring) / rings;

            vertices.emplace_back(x, y, z);
            uv_coords.emplace_back(u, v);
            normals.emplace_back(glm::normalize(glm::vec3(x, y, z)));
        }
    }

    // Generate faces
    for (unsigned int ring = 0; ring < rings; ring++)
    {
        for (unsigned int segment = 0; segment < segments; segment++)
        {
            if (ring == 0)  // Lower cap
            {
                Face face;
                face.a = segment;
                face.b = segments + segment + 1;
                face.c = segments + segment;
                faces.push_back(face);
            }
            else if (ring < rings - 1) // Body
            {
                const unsigned int v1 = segments + ((ring - 1) * (segments + 1)) + segment;
                const unsigned int v2 = segments + ((ring - 1) * (segments + 1)) + segment + 1;
                const unsigned int v3 = segments + ((ring - 1 + 1) * (segments + 1)) + segment;
                const unsigned int v4 = segments + ((ring - 1 + 1) * (segments + 1)) + segment + 1;
                Face face1, face2;
                face1.a = v1;
                face1.b = v2;
                face1.c = v3;
                face2.a = v3;
                face2.b = v2;
                face2.c = v4;
                faces.push_back(face1);
                faces.push_back(face2);
            }
            else // Upper cap
            {
                Face face;
                face.a = segments + ((ring - 1) * (segments + 1)) + segment;
                face.b = segments + ((ring - 1) * (segments + 1)) + segment + 1;
                face.c = segments + ((ring - 1 + 1) * (segments + 1)) + segment;
                faces.push_back(face);
            }
        }
    }
}


测试结果:


的数据

pqwbnv8z

pqwbnv8z1#

NormalEyePosition也必须在片段着色器中进行归一化插值向量时,不保留向量的长度。
vec3 N = NormalEyePosition;

vec3 N = normalize(NormalEyePosition);

字符串

相关问题