Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl 为什么当相机离我很远时,我的物体会失去照明?_Opengl_Shader_Lighting - Fatal编程技术网

Opengl 为什么当相机离我很远时,我的物体会失去照明?

Opengl 为什么当相机离我很远时,我的物体会失去照明?,opengl,shader,lighting,Opengl,Shader,Lighting,我正在OpenGL2.1中构建一个3D场景,并使用带有Phong照明模型的平行光对其进行照明 近距离观察,一切似乎都很好,但当相机离开模型时,它们会失去所有照明(环境光除外) 是什么让这一切发生的 以下是顶点着色器: uniform mat4 viewMatrix; uniform mat4 modelMatrix; uniform mat4 projectionMatrix; uniform mat3 normalMatrix; uniform vec3 lightDir; out vec3

我正在OpenGL2.1中构建一个3D场景,并使用带有Phong照明模型的平行光对其进行照明

近距离观察,一切似乎都很好,但当相机离开模型时,它们会失去所有照明(环境光除外)

是什么让这一切发生的

以下是顶点着色器:

uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
uniform vec3 lightDir;

out vec3 normal;
out vec3 lightDir_viewSpace;
out vec3 vertexPos_viewSpace;

void main(){
    normal = normalize( normalMatrix * gl_Normal );
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * gl_Vertex;

    vertexPos_viewSpace = - ( viewMatrix * modelMatrix * gl_Vertex ).xyz;;
    lightDir_viewSpace = normalize( viewMatrix * vec4(lightDir, 1) ).xyz;
}
下面是片段着色器:

uniform vec3 Ka;
uniform vec3 Kd;
uniform vec3 Ks;
uniform float Shininess;

in vec3 normal;
in vec3 lightDir_viewSpace;
in vec3 vertexPos_viewSpace;

float getdiffuseIntensity( vec3 N, vec3 L ){
    float intensity = clamp(dot(L , N), 0.0, 1.0);
    return intensity;
}

float getSpecularIntensity( vec3 N, vec3 L, vec3 vertexPos, float shine ){
    vec3 R = normalize( reflect( -L, N ) );
    vec3 V = normalize( vertexPos );
    float intensity = 0.0;
    if ( dot(N, L) > 0.0 ){
        float cosVR = clamp( dot(V, R), 0.0, 1.0 );
        intensity = pow( cosVR, shine );
    }
    return intensity;
}

void main(){
    vec3 normalNorm = normalize( normal );
    vec3 lightDirNorm = normalize( lightDir_viewSpace );
    vec3 vertexDirNorm = normalize( vertexPos_viewSpace );

    vec3 ilumAmbi = Ka;
    vec3 ilumDiff = Kd * getdiffuseIntensity( normalNorm, lightDirNorm );
    vec3 ilumEspec = Ks * getSpecularIntensity( normalNorm, lightDirNorm, vertexDirNorm, Shininess );

    gl_FragColor = vec4( ilumAmbi + ilumDiff + ilumEspec , 1.0 );
}
万一有人问;是的,这是一个学校项目

我做错了什么吗?

始终确保向量都在相同的空间(模型空间、世界空间或视图空间)中

法线在世界空间中,而lightDir在视图空间中,因此您应该将lightDir更改为世界空间,这更容易作为您的输入(
uniform vec3 lightDir;
) 已经在世界空间了

第二个错误是你的镜面反射计算。在Phong模型中,镜面反射高光是通过使用理想反射向量(
vec3 R=normalize(reflect(-L,N));
和观察者方向之间的角度(这就是点(V,R)所做的)来计算的

因此,最终的代码是:

uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
uniform vec3 viewPos; // the Position of your view in world coordinates

out vec3 normal;
out vec3 viewDir;

void main(){
    normal = normalize( normalMatrix * gl_Normal );
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * gl_Vertex;
    vec4 worldPos = modelMatrix * gl_Vertex;

    viewDir = worldPos.xyz - viewPos; // maybe you have to change the ordering, i'm not sure
}
以及:

但是我没有测试它。

问题在于:

lightDir_viewSpace = normalize( viewMatrix * vec4(lightDir, 1) ).xyz
这样做的目的是将
lightDir
解释为点(x,y,z,1),而不是向量(x,y,z,0)。您的代码执行某种类型的点光源,这就是为什么光源会随摄影机距离而变化。所以正确的代码是

lightDir_viewSpace = normalize( viewMatrix * vec4(lightDir, 0) ).xyz
但是,请注意,对于每个顶点和每个片段,此表达式的计算结果总是相同的向量。因此,实际上最好在CPU上进行计算,并在片段着色器中使用
uniform vec3 lightDir_viewSpace

这也意味着您不再需要单独的
viewMatrix
modelMatrix
制服。相反,在CPU上计算
modelViewMatrix=viewMatrix*modelMatrix
,然后在顶点着色器中使用
uniform mat4 modelViewMatrix


这也是原因,没有必要在世界空间中这样做。

vec3 normalNorm=normal;//不需要规格化
这是不正确的,
normal
是在三角形上插值的,因此需要规格化<代码>视图目录=worldPos.xyz-视图位置1。相反,2。你做的和OP完全一样,只是在世界空间。请注意,OP的
vertexPos_viewSpace=-(viewMatrix*modelMatrix*gl_Vertex)。xyz
实际上不是顶点位置,而是视图空间中从顶点到摄影机(0,0,0)的向量,因此规范化是您的
viewDir
。我不知道点和向量之间有什么区别,谢谢!
lightDir_viewSpace = normalize( viewMatrix * vec4(lightDir, 0) ).xyz