更新:似乎大部分这些东西现在都不见了。我认为在 OpenGL ES 2.0 中正确进行光照的方法是编写自己的着色器,以任何你希望的方式传递法线,然后在着色器中进行光照。特别是根据OpenGL ES 2.0 docs,不再有glMaterialFv,glLightFv等(更不用说glNormalPointer和朋友了。)我认为这是为我编译的原因是因为这些东西是由GLKit在iOS中提供的,尽管显然它们并不能作为直接替代品开箱即用。但是,GLKit 提供了一些标准着色器来模拟 OpenGL ES 1.1 中的光照功能。
如果有人有任何进一步的信息,我很感激,但我认为这就是答案。
我是 OpenGL 的新手,所以对任何混淆提前表示歉意。我在 iOS 上使用 OpenGL ES 2.0。我在 Internet 上找到的许多示例似乎都已过时。例如,glBegin(GL_POLYGON) 方法似乎已被弃用,所以我认为我不能像大多数较旧的示例那样使用 glNormal3f。
我从 Ray Wenderlich 的精彩教程开始,并将其与我正在构建的游戏集成,成功渲染了一些房间的基本几何图形。现在我只想添加照明。我不确定什么不起作用,但我怀疑它与法线有关。
我做了一个令人困惑的尝试来启用 GL_LIGHT0,主要取自 OpenGL文档。
//* Some attempts at lighting
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 50.0 };
GLfloat light0_position[] = { 0.0, 0.0, 7.99, 0.0 };
GLfloat light0_ambience[] = { 0.2, 0.2, 0.2, 1.0 };
GLfloat light0_specular[] = { 1.0, 1.0, 1.0, 1.0 };
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambience);
glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
//*/
glEnable(GL_DEPTH_TEST);
我正在使用 VBOS 将顶点位置和颜色传递给一对简单的着色器。以下内容来自教程:
_positionSlot = glGetAttribLocation(programHandle, "Position");
_colorSlot = glGetAttribLocation(programHandle, "SourceColor");
然后在 render: 方法中(我已经修改了 Vertex 结构以包括位置和颜色位置之间的法线)。
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE,
sizeof(Vertex), 0);
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (GLvoid*) (sizeof(float) * 6));
除了照明,所有这些都非常有效。我已经计算并重新计算了我的法线。对于平行于 X 和 Y 轴的垂直矩形墙,这是微不足道的。它们是绑定到 GL_ARRAY_BUFFER 的缓冲区的一部分,以及位置和颜色信息。
我曾多次尝试使用 glNormalPointer:
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, sizeof(Vertex), (GLvoid*)(sizeof(float)*3));
教程中的顶点结构现在是:
typedef struct {
float Position[3];
float Normal[3];
float Color[4];
} Vertex;
上面调用成功,但是没有出现灯光效果。一些消息来源建议我也应该将 glVertexAttribPointer 用于法线。为此,我修改了教程的顶点着色器:
attribute vec4 Position;
attribute vec4 SourceColor;
attribute vec3 Normal;
varying vec4 DestinationColor;
uniform mat4 Projection;
uniform mat4 Modelview;
void main(void) {
DestinationColor = SourceColor;
gl_Position = Projection * Modelview * Position;
}
并添加了我认为允许我使用该 Normal 变量的调用(尽管我不确定 OpenGL 如何知道如何处理它):
// just before glLinkProgram()
glBindAttribLocation(programHandle, 1, "Normal");
GLuint _normalSlot = glGetAttribLocation(programHandle, "Normal");
glVertexAttribPointer(_normalSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(float)*3));
我注意到,无论我将 Normal 变量放在 GLSL 文件中的哪个位置,glBindAttribLocation 总是对该属性失败,而 glGetAttribLocation 总是为该属性返回 -1。(我可以使用 glBindAttribLocation 成功更改 SourceColor 属性的位置,但它不会接受 Normal。)在旧版本的 OpenGL/GLSL 中曾经有一个 gl_Normal 变量,但显然现在没有了。
我不知所措,继续尝试发生在我身上的任何事情。我的下一步将是 glInterleavedArrays。有这么多活动部件,很难找到问题所在。可能是我的法线一直很好,而是灯有问题。除了照明,还有什么方法可以确认您的法线是否正确?或者如果法线错误,我应该能够从灯光中看到任何东西吗?
因此,对于这篇文章的篇幅和混乱深表歉意,但任何关于在这种情况下如何指定法线的详细解释都将受到欢迎。我反复提到,现在 OpenGL ES 2.0 中的情况有所不同,但从来没有任何详细的例子。提前致谢。