我正在编写一个引擎并使用 Light 0 作为场景的“太阳”。太阳是定向光。
我设置了场景的正交视点,然后将灯光设置在屏幕的“东”侧(以及角色)(x/y 是平面地形的坐标,正 z 面向相机,指示地形上的“高度”——场景也会旋转以获得 x 轴上的等距 View 。
光线似乎很好地照在 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 = 正交投影和场景旋转/缩放 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 );
}
最佳答案
您需要为每个表面提供法线。发生的情况(没有法线)是定向光本质上照射在位置上零以东的所有物体上,而那里的所有物体的法线都是 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 足以控制一系列凸面形状的照明,因此您必须确定是否应将光线(例如太阳)应用于脸部。在某些情况下,这只是获取脸部所属的实体,并查看太阳光的矢量在到达“天空”之前是否与另一个实体相交。
为此寻找有关光照贴图和阴影贴图的内容。
关于OpenGL 定向照明 + 定位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9491617/