GLSL:旋转正常
GLSL: Rotating Normal
有一个场景,里面有一些物体和一个地形。当我尝试旋转对象时,法线保持不变。意味着物体的黑暗面保持物体的黑暗面。我的镜面闪电正在工作。
顶点着色器:
uniform vec3 lightPos;
uniform sampler2D Texture;
varying vec2 TexCoord;
varying vec3 position;
varying vec3 vertex;
varying mat3 nMat;
varying mat3 vMatrix;
varying vec3 normal;
varying vec3 oneNormal;
varying vec3 lightPos2;
void main()
{
gl_Position=gl_ModelViewProjectionMatrix*gl_Vertex;
position=vec3(gl_ModelViewMatrix*gl_Vertex);
vMatrix = mat3(gl_ModelViewMatrix);
lightPos2 = vec3(gl_ModelViewMatrix*vec4(lightPos,1.0));
vertex = vec3(gl_Vertex);
nMat = gl_NormalMatrix;
normal=gl_NormalMatrix*gl_Normal;
oneNormal = gl_Normal;
TexCoord=gl_MultiTexCoord0.xy;
}
片段着色器:
varying vec3 position;
varying vec3 normal;
uniform sampler2D Texture;
varying vec2 TexCoord;
uniform vec3 lightPos;
varying vec3 vertex;
uniform vec3 lambient;
uniform vec3 ldiffuse;
uniform vec3 lspecular;
uniform float shininess;
varying mat3 nMat;
varying mat3 vMatrix;
varying vec3 oneNormal;
varying vec3 lightPos2;
void main()
{
float dist=length(vertex-lightPos);
float att=1.0/(1.0+0.1*dist+0.01*dist*dist);
vec4 TexColor = texture2D(Texture, TexCoord);
vec3 ambient=TexColor.rgb*lambient; //the ambient light
//=== Diffuse ===//
vec3 surf2light=normalize(position-lightPos2);
float dcont=max(0.0,
dot( normalize(nMat*(-normal)), nMat*surf2light) );
vec3 diffuse=dcont*(TexColor.rgb*ldiffuse);
//=== Specular ===//
vec3 surf2view = normalize(lightPos-position);
surf2light=nMat*normalize(-vertex);
vec3 reflection=reflect(-surf2view,normalize(normal));
float scont=pow(max(0.0,dot(surf2light,reflection)),shininess);
vec3 specular=scont*lspecular;
gl_FragColor=vec4((ambient+diffuse+specular)*att,1.0);
}
你正在变换法线。但至少对于部分照明计算,您使用的是光源位置,该位置也会转换为相同的坐标空间。如果同时变换法线和光源,则法线相对于光源的方向将再次相同。
从顶点着色器中提取关键线:
position=vec3(gl_ModelViewMatrix*gl_Vertex);
lightPos2 = vec3(gl_ModelViewMatrix*vec4(lightPos,1.0));
normal=gl_NormalMatrix*gl_Normal;
gl_NormalMatrix
对应于gl_ModelViewMatrix
,并进行了必要的调整以变换方向向量而不是点。因此,模型视图变换已应用于所有position
、lightPos2
和normal
。
然后,所有这三个值(应用插值)都传递到片段着色器中,您可以在其中计算漫射照明项:
vec3 surf2light=normalize(position-lightPos2);
float dcont=max(0.0,
dot( normalize(nMat*(-normal)), nMat*surf2light) );
vec3 diffuse=dcont*(TexColor.rgb*ldiffuse);
现在,这里有几个问题:
- 您再次将
nMat
(法线矩阵)应用于两个向量,即使它们已经变换过。它没有害处,因为如果您对两个向量应用相同的旋转,点积不会改变,但这没有意义。 - 所有使用的值(
position
、lightPos2
、normal
)都由模型视图矩阵转换。因此,它们的相对位置/方向与原始位置/方向完全相同。计算结果将与应用于相应的未变换向量时的结果相同。
您需要确定要用于照明计算的坐标系。至少有几个选择。对您来说最简单的方法可能是使用眼睛坐标空间。为此,可以在将光源位置传递到着色器之前将视图转换应用于光源位置,然后在着色器代码中直接使用此光源位置,而无需任何其他转换。
由于您说镜面反射照明按预期工作,并且您在那里使用均匀lightPos
,因此它可能就像使用该变量而不是在漫反射计算中lightPos2
一样简单。
相关文章:
- 与互斥锁相比,旋转锁可以保证上下文切换
- OpenInventor从9.8升级到10.4.2后,GLSL纹理返回零
- 绘制旋转的三角形
- 旋转模型矩阵时的形状失真
- 四边形的 2D 旋转
- 垂直方向的 Gtk3+ 旋转按钮 (c/c++)
- 发布旋转矩阵(openGL/glm)
- 顺时针迭代旋转 3 位数字
- Opengl 3.1 GLSL 140 在 C++ 年输出白色在片段着色器中
- 形状对象的旋转和缩放不正确C++
- 如何在 OpenSceneGraph 中缩放/旋转/移动资产
- 如何有效地计算将单位立方体映射到自身的反射和旋转?
- 在不使用统一的情况下将纹理传递给 GLSL 着色器?
- 子轴围绕父轴而不是他自己的轴旋转
- 将使用太多的纹理插值器 - 带旋转的着色器
- 在细胞中产生噪声 - CPP 和 GLSL
- 这个SSDO演示的GLSL版本要求是自我冲突的吗
- SFML 向下移动时如何围绕屏幕中心旋转?
- GLSL:旋转正常
- GLSL 2D旋转矩阵不像预期的那样工作