【问题标题】:Wildly inconsistent and incorrect lighting in openglopengl 中严重不一致和不正确的照明
【发布时间】:2022-12-17 12:46:37
【问题描述】:

我按照教程添加了简单的漫射照明,但照明非常糟糕:

除了不一致之外,所有漫反射分量在某些摄像机角度完全消失(摄像机位置似乎对此没有影响)

顶点着色器:

#version 450 core

layout (location = 0) in vec4 vPosition;
layout (location = 1) in vec4 vNormal;
layout (location = 2) out vec4 fNormal;
layout (location = 3) out vec4 fPos;

uniform mat4 MVMatrix;
uniform mat4 PMatrix;

void main()
{
    gl_Position = PMatrix * (MVMatrix * vPosition);
    fNormal = normalize(inverse(transpose(MVMatrix))*vNormal);
    fPos = MVMatrix * vPosition;
}

片段着色器:

#version 450 core

layout (location = 0) out vec4 fColor;
layout (location = 2) in vec4 fNormal;
layout (location = 3) in vec4 fPos;
uniform vec4 objColour;

void main()
{
    vec3 lightColour = vec3(0.5, 0.0, 0.8);
    vec3 lightPos = vec3(10, 20, 30);
    float ambientStrength = 0.4;
    vec3 ambient = ambientStrength * lightColour;

    vec3 diffLightDir = normalize(lightPos - vec3(fPos));
    float diff = max(dot(vec3(fNormal), diffLightDir), 0.0);
    vec3 diffuse = diff * lightColour;
    
    vec3 rgb = (ambient + diffuse) * objColour.rgb;
    fColor = vec4(rgb, objColour.a);
}

正常计算(由于 pythonnic 的性质,我没有遵循教程,这可能是问题所在)

self.vertices = np.array([], dtype=np.float32)
self.normals = np.array([], dtype=np.float32)
data = Wavefront(r"C:\Users\cwinm\AppData\Local\Programs\Python\Python311\holder.obj", collect_faces=True)
all_vertices = data.vertices
for mesh in data.mesh_list:
    for face in mesh.faces:
        face_vertices = np.array([all_vertices[face[i]] for i in range(3)])
        
        normal = np.cross(face_vertices[0]-face_vertices[1], face_vertices[2] - face_vertices[1])
        normal /= np.linalg.norm(normal)

        self.vertices = np.append(self.vertices, face_vertices)
        for i in range(3): self.normals = np.append(self.normals, normal)
self.index = index_getter(len(self.vertices))
self.vertices.resize((len(self.vertices)//3, 3))
self.vertices = np.array(self.vertices * [0.5, 0.5, 0.5], dtype=np.float32)

(然后将局部顶点和法线附加到全局顶点和法线缓冲区,在初始化后将其推送到 OpenGL)

VBO 创建(也可能是一个问题)

vPositionLoc = glGetAttribLocation(self.program, "vPosition")
vNormalLoc = glGetAttribLocation(self.program, "vNormal")

self.Buffers[self.PositionBuffer] = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.Buffers[self.PositionBuffer])
glBufferStorage(GL_ARRAY_BUFFER, self.vertices.nbytes, self.vertices, 0)
glVertexAttribPointer(vPositionLoc, 3, GL_FLOAT, False, 0, None)
glEnableVertexAttribArray(vPositionLoc)

self.Buffers[self.NormalBuffer] = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.Buffers[self.NormalBuffer])
glBufferStorage(GL_ARRAY_BUFFER, self.normals.nbytes, self.normals, 0)
glVertexAttribPointer(vNormalLoc, 3, GL_FLOAT, False, 0, None)
glEnableVertexAttribArray(vNormalLoc)

环境光照、矩阵和顶点处理都是正常的,只有当我添加法线和(尝试)漫反射光照时才会出现问题

【问题讨论】:

    标签: python opengl pyopengl lighting


    【解决方案1】:

    vNormal 是一个包含 3 个分量的向量。您必须使用法线矩阵转换法线向量。法线矩阵是模型视图矩阵左上角 3x3 分量的逆转置(无平移):

    vec3 normal = normalize(inverse(transpose(mat3(MVMatrix))) * vNormal.xyz);
    

    这与:

    fNormal = normalize(inverse(transpose(MVMatrix)) * vec4(vNormal.xyz, 0.0));
    

    如果未指定或仅部分指定属性,则 x、y 和 z 组件默认为 0.0,但 w 组件默认为 1.0。所以你实际上在做的是
    fNormal = normalize(inverse(transpose(MVMatrix)) * vec4(vNormal.xyz, 1.0));,这是错误的,因为您将模型视图矩阵的平移应用于法向量

    另外 fNormal 必须在片段着色器中归一化,因为通过插值,长度不会保持 1.0。

    【讨论】:

    • 我试过这样做,甚至直接复制粘贴你的代码,也出现同样的问题,但不一致发生在不同的地方
    • 碎片着色器中的规范化消除了一些不一致
    • @User12692182 所以还有一个我还没有发现的问题。您确定所有法向量都指向相同的逻辑方向吗?
    • @User12692182 出于调试原因,请尝试:vec3 normal = vec3(fNormal) * sign(fNormal.z);(片段着色器)。然后使用normal代替fNormal
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    相关资源
    最近更新 更多