opengl - 片段漫反射值随相机位置/旋转而变化

标签 opengl glsl lighting fragment-shader geometry-shader

我正在尝试让一些简单的漫射照明在 GLSL 中工作。我有一个立方体作为点数组传入,我正在计算几何着色器内的面法线(因为我打算在运行时使网格变形,所以我需要新的面法线。)

我的问题是,当我在世界各地移动相机时,漫反射值正在发生变化。所以立方体表面的阴影随着相机的移动而变化。我无法弄清楚我错过了什么导致了这个问题。我的着色器如下:

顶点:

#version 330 core

layout(location = 0) in vec3 vertexPosition_modelspace;

uniform mat4 MVP;

void main(){     
    gl_Position =  MVP * vec4(vertexPosition_modelspace,1);
}

几何:

#version 330

precision highp float;

layout (triangles) in;
layout (triangle_strip) out;
layout (max_vertices = 3) out;

out vec3 normal;
uniform mat4 MVP;
uniform mat4 MV;

void main(void)
{
    for (int i = 0; i < gl_in.length(); i++) {
        gl_Position = gl_in[i].gl_Position;


        vec3 U = gl_in[1].gl_Position.xyz - gl_in[0].gl_Position.xyz;
        vec3 V = gl_in[2].gl_Position.xyz - gl_in[0].gl_Position.xyz;

        normal.x = (U.y * V.z) - (U.z * V.y);
        normal.y = (U.z * V.x) - (U.x * V.z);
        normal.z = (U.x * V.y) - (U.y * V.x);

        normal = normalize(transpose(inverse(MV)) * vec4(normal,1)).xyz;

        EmitVertex();
    }
    EndPrimitive();
}

片段:

#version 330 core

in vec3 normal;
out vec4 out_color;
const vec3 lightDir = vec3(-1,-1,1);

uniform mat4 MV;

void main()
{
    vec3 nlightDir = normalize(vec4(lightDir,1)).xyz;
    float diffuse = clamp(dot(nlightDir,normal),0,1);

    out_color = vec4(diffuse*vec3(0,1,0),1.0);
}

谢谢

最佳答案

你的代码中有很多错误的地方。大多数问题都来自于完全忘记了不同向量所在的空间。您无法在不同空间中的向量之间进行有意义的计算。

normal = normalize(transpose(inverse(MV)) * vec4(normal,1)).xyz;

通过使用 1 作为法线的第四个分量,您可以完全打破此计算。它会导致法线被翻译,这是不合适的。

此外,您的正常值是根据gl_Position计算的。并且gl_Position位于剪辑空间,而不是模型空间。因此,您得到的只是剪辑空间法线,这不是您需要、想要或什至可以使用的。

如果您想计算相机空间法线,请从相机空间位置计算它。或者从模型空间位置计算模型空间法线,并使用模型/ View 矩阵将其转换到相机空间。

此外,在CPU上执行逆/转置并将其传递给着色器。哦,并将所有正常计算从循环中取出;您只需每个三角形执行一次(将其存储在局部变量中并将其复制到每个顶点的输出)。并停止手动进行叉积;使用内置的 GLSL cross 函数。

vec3 nlightDir = normalize(vec4(lightDir,1)).xyz;

这并不比之前在转换中使用 1 作为第四个分量更有意义。只需直接标准化 lightDir 即可。

同样重要的是,如果您在相机空间中进行照明,那么光线方向需要随着相机的变化而变化,以使其在世界中保持相同的明显方向。因此,您必须获取世界空间灯光位置并将其转换为相机空间(通常在 CPU 上,作为统一传入)。

关于opengl - 片段漫反射值随相机位置/旋转而变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16602240/

相关文章:

javascript - 用于 MacOs Catalina 的 Electron OpenGL

c++ - glShaderSource崩溃

opengl - 为什么我不能将 int 成员添加到我的 GLSL 着色器输入/输出 block ?

opengl - 如何在 OpenGL 中快速轻松地创建与场景无关的阴影,而无需着色器

java - LWJGL (Java) 中 OpenGL 的奇怪光照行为

opengl - 如何在旋转对象时在OpenGL中固定光源?

java - Qt Jambi 与 JOGL 用于 java OpenGL 开发?

c++ - QOpenGLWidget 的makeCurrent 不起作用?

three.js - 为什么需要在 webgl 着色器中定义精度值?

c++ - GLSL语法问题: unexpected NEW_IDENTIFIER