为什么我的 GLSL 着色器光照会随着它所照耀的对象在场景中移动?



我正在遵循关于OpenGL ES 2.0的教程,并将其与我发现的GLSL照明教程相结合,使用developer.apple.com上的一个方便的犹他州茶壶。

经过大量的摆弄和实验,我在屏幕上适度正确地绘制了茶壶,围绕所有三个轴旋转,灯光教程中的"卡通阴影"工作。有一些小故障在几何由于我简单地绘制整个顶点列表作为三角形带(如果你看在茶壶.h文件有'-1'嵌入我应该开始新的三角形带,但这只是测试数据,与我的问题无关)。

我真正困惑的是如何在场景中定位灯光。在我的Objective-C代码中,我有一个float3向量,包含{0,1,0},并将其传递到着色器中,然后计算光的强度。

为什么光线在场景中也会移动?我的意思是,光就像被一根看不见的棍子粘在茶壶上一样,不管茶壶朝哪个方向,它总是指向茶壶的同一边。

这是顶点着色器
attribute vec4 Position;
attribute vec4 SourceColor;
attribute vec3 Normal;
uniform mat4 Projection;
uniform mat4 Modelview;
varying vec3 normal;
void main(void) {
    normal = Normal;
    gl_Position = Projection * Modelview * Position;
}

"位置"是由Obj-C代码设置的,是对象的顶点,"法线"是来自顶点数组(VBO)的法线列表,"投影"one_answers"模型视图"是这样计算的:

(CC3GLMatrix来自Cocos3D库,在上面链接的GLES教程中提到)

CC3GLMatrix *projection = [CC3GLMatrix matrix];
float h = 4.0f * self.frame.size.height / self.frame.size.width;
[projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:1 andFar:100];
glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix);
CC3GLMatrix *modelView = [CC3GLMatrix matrix];
[modelView populateFromTranslation:CC3VectorMake(0, 0, -7)];
[modelView scaleBy:CC3VectorMake(30, 30, 30)];
_currentRotation += displayLink.duration * 90;
[modelView rotateBy:CC3VectorMake(_currentRotation, _currentRotation, _currentRotation)];
glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);

我通过

设置场景中的光线
float lightDir[] = {1,0,1};
glUniform3fv(_lightDirUniform, 1, lightDir);

片段着色器看起来像这样

varying lowp vec4 DestinationColor; // 1
varying highp vec3 normal;
uniform highp vec3 LightDir;

void main(void) {
    highp float intensity;
    highp vec4 color;
    intensity = dot(LightDir,normal);
    if (intensity > 0.95)
        color = vec4(1.0,0.5,0.5,1.0);
    else if (intensity > 0.5)
        color = vec4(0.6,0.3,0.3,1.0);
    else if (intensity > 0.25)
        color = vec4(0.4,0.2,0.2,1.0);
    else
        color = vec4(0.2,0.1,0.1,1.0);
    gl_FragColor = color;
}

在试图解决这个问题时,我遇到了引用(在GLES中不存在)的代码。'gl_LightSource'和'gl_NormalMatrix',但不知道该把什么放入等效物中,我必须从代码中传递到着色器中。引用"眼空间"相机空间"世界空间"等等是令人困惑的,我知道我可能应该在它们之间转换东西,但不明白为什么或如何(以及在哪里-在代码中,还是在着色器中?)

每一帧都需要修改光源吗?我用来设置它的代码看起来太简单了。我并不是真的在移动茶壶,不是吗?相反,我是在移动整个场景——光线和周围的一切?

首先是一些定义:

  • 世界空间:你的整个世界被定义的空间。按照惯例,它是一个永不移动的静态空间。

  • view space/camera space/eye space:相机定义的空间。它通常是相对于世界空间的位置和旋转

  • 模型空间:定义模型的空间。与相机空间一样,它通常是相对于世界空间的位置和旋转

  • 灯光空间:与模型空间相同

在简单的例子(我猜在你的)模型空间和世界空间是相同的。此外,OpenGL本身没有世界空间的概念,这并不意味着你不能使用它。当你想在场景中有多个对象独立移动时,它会派上用场。

现在,在渲染之前,你对对象所做的是创建一个矩阵,将模型的顶点转换为视图空间,因此'modelViewMatrix'。

在这种情况下,光有点不同。着色器中的光照计算是在模型空间中完成的,所以你必须将每帧的光照位置转换到模型空间中。

这可以通过如下计算来完成:

_lightDirUniform = inverseMatrix(model) * inverseMatrix(light) * lightPosition;

光的位置由光转换到世界,再转换到模型空间。如果你没有世界空间,只要省略模型空间变换就可以了。

相关内容

  • 没有找到相关文章

最新更新