球体照明错误结果

huangapple go评论59阅读模式
英文:

Sphere lighting wrong results

问题

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

顶点着色器:

#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()
{
    // ... (这里省略了其他代码)
}

结果:

球体照明错误结果

英文:

I have a simple per-pixel-lighting shader, but the sphere I want to draw looks a bit like per-vertex shading. I investigated this since yesterday, but didn't find any issues. The normals of a sphere are the same as the normalized vertex positions, or am I wrong?

Vertex shader:


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

Fragment shader:


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

For a cube or plane the shader works fine.

Sphere generation:

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

Result:

球体照明错误结果

答案1

得分: 1

NormalEyePosition 在片元着色器中也必须进行规范化,当插值向量时,向量的长度不会保持不变。

vec3 N = normalize(NormalEyePosition);
英文:

NormalEyePosition must also be normalized in the fragment shader When interpolating vectors, the length of the vector is not maintained.

<s>vec3 N = NormalEyePosition;</s>

vec3 N = normalize(NormalEyePosition);

huangapple
  • 本文由 发表于 2023年7月14日 01:43:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76682013.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定