OpenGL定向照明+定位
Posted
技术标签:
【中文标题】OpenGL定向照明+定位【英文标题】:OpenGL Directional Lighting + Positioning 【发布时间】:2012-02-28 23:48:02 【问题描述】:我正在编写一个引擎并使用 Light 0 作为场景的“太阳”。太阳是定向光。
我设置了场景的 Ortho 视点,然后将灯光设置在屏幕的“东”侧(以及角色)(x/y 是平面地形的坐标,正 z 朝向相机并且指示地形上的“高度”——场景也会旋转以获得 x 轴上的等距视图)。
灯光似乎在 0,0,0 的“东”处闪烁,但随着角色移动,它不会移动(CenterCamera 在提供的值的负值上执行 glTranslate3f,以便可以映射指定世界坐标)。意思是,我越往西走,它总是黑暗的,没有光。
Graphics.BeginRenderingLayer();
Video.MapRenderingMode();
Graphics.BeginLightingLayer( Graphics.AmbientR, Graphics.AmbientG, Graphics.AmbientB, Graphics.DiffuseR, Graphics.DiffuseG, Graphics.DiffuseB, pCenter.X, pCenter.Y, pCenter.Z );
Graphics.BeginRenderingLayer();
Graphics.CenterCamera( pCenter.X, pCenter.Y, pCenter.Z );
RenderMap( pWorld, pCenter, pCoordinate );
Graphics.EndRenderingLayer();
Graphics.BeginRenderingLayer();
Graphics.DrawMan( pCenter );
Graphics.EndRenderingLayer();
Graphics.EndLightingLayer();
Graphics.EndRenderingLayer();
Graphics.BeginRenderingLayer = PushMatrix, EndRenderingLayer = PopMatrix Video.MapRenderingMode = Ortho Projection and Scene Rotation/Zoom CenterCamera 会转换到 X/Y/Z 的反面,这样角色现在就以 X/Y/ 为中心Z 在屏幕中间。
有什么想法吗?也许我在这里有些混淆了我的一些代码?
照明代码如下:
public static void BeginLightingLayer( float pAmbientRed, float pAmbientGreen, float pAmbientBlue, float pDiffuseRed, float pDiffuseGreen, float pDiffuseBlue, float pX, float pY, float pZ )
Gl.glEnable( Gl.GL_LIGHTING );
Gl.glEnable( Gl.GL_NORMALIZE );
Gl.glEnable( Gl.GL_RESCALE_NORMAL );
Gl.glEnable( Gl.GL_LIGHT0 );
Gl.glShadeModel( Gl.GL_SMOOTH );
float[] AmbientLight = new float[4] pAmbientRed, pAmbientGreen, pAmbientBlue, 1.0f ;
float[] DiffuseLight = new float[4] pDiffuseRed, pDiffuseGreen, pDiffuseBlue, 1.0f ;
float[] PositionLight = new float[4] pX + 10.0f, pY, 0, 0.0f ;
//Light position of Direction is 5 to the east of the player.
Gl.glLightfv( Gl.GL_LIGHT0, Gl.GL_AMBIENT, AmbientLight );
Gl.glLightfv( Gl.GL_LIGHT0, Gl.GL_DIFFUSE, DiffuseLight );
Gl.glLightfv( Gl.GL_LIGHT0, Gl.GL_POSITION, PositionLight );
Gl.glEnable( Gl.GL_COLOR_MATERIAL );
Gl.glColorMaterial( Gl.GL_FRONT_AND_BACK, Gl.GL_AMBIENT_AND_DIFFUSE );
【问题讨论】:
发布您的代码以显示您设置灯光的位置可能会有所帮助。 编辑原件以包含照明代码。 您是否正在计算并发送每个顶点的法线? 【参考方案1】:您需要为每个表面提供法线。正在发生的事情(没有法线)是定向光基本上照在零以东的所有位置上,而那里的所有东西的法线都是 0,0,1(它面向西)。
据我所知,您不需要为每个顶点发送法线,而是因为 GL 是一个状态机,所以您需要确保每当法线发生变化时都会对其进行更改。所以如果你在一个立方体上渲染一个面,“西”面应该有一个单独的调用
glNormal3i(0,0,1);
glTexCoord..
glVertex3f...
glTexCoord..
etc.
对于 x-y-z 对齐的直角棱镜,“整数”就足够了。对于不面向六个基本方向之一的面,您需要对其进行归一化。根据我的经验,除非四边形不平坦,否则您只需要标准化前三个点。这是通过找到由四边形中的前三个边形成的三角形的法线来完成的。
我发现一些关于“计算法线”的简单教程很有启发性。
第二部分是,由于它是定向光,因此 (W=0) 根据玩家位置重新定位它是没有意义的。除非光线本身是从相机后面发出的,并且您正在旋转您面前的物体(例如模型),并且您希望始终保持正面照明,否则它的位置可能应该类似于
float[] PositionLight = new float[4] 0.0f, 0.0f, 1.0f, 0.0f ;
或者,如果 GLx 方向被解释为东西方向(即您最初面向北/南)
float[] PositionLight = new float[4] 1.0f, 0.0f, 0.0f, 0.0f ;
这个概念是您正在计算每个面的光,如果光不移动并且场景本身不移动(只是相机在场景中移动),方向计算将始终保持正确。如果法线准确,GL 可以计算出特定面部上显示的光强度。
最后一点是 GL 不会自动为您处理阴影。基本 GL_Light 足以用于一系列凸形的受控照明,因此您必须确定是否应将光(例如太阳)应用于面部。在某些情况下,这只是获取脸部所属的实体,并查看太阳光的矢量在到达“天空”之前是否与另一个实体相交。
在光照贴图和阴影贴图中寻找东西。
【讨论】:
【参考方案2】:可能会绊倒很多人的一件事是发送到glLightFv
的位置是由当前矩阵堆栈转换的。因此,如果您想将灯光设置到世界坐标中的特定位置,则必须在调用glLightFv
时在矩阵堆栈上设置并激活相机和投影矩阵。
【讨论】:
以上是关于OpenGL定向照明+定位的主要内容,如果未能解决你的问题,请参考以下文章