2012-02-28 89 views
2

我正在编写一个引擎,并使用Light 0作为场景的“太阳”。太阳是定向光。OpenGL定向照明+定位

我设置了场景的正交视点,然后将光线设置在屏幕的“东侧”(和字符)(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 =正交投影与场景旋转/放大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

它可能有助于发布您的代码,显示您设置灯光的位置。 – kappamaki 2012-02-29 00:17:37

+0

编辑原件以包含照明代码。 – Locke 2012-03-01 00:21:00

+0

您是否计算并发送每个顶点的法线? – 2012-03-27 20:45:19

回答

3

你将需要为每个表面提供法线。发生了什么(没有法线)是指向的光基本上在零以东的所有东西上都有所发光,而所有东西都有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对于一系列凸起形状的受控照明是足够的,因此您必须弄清楚是否应该将光(例如太阳)应用于脸部。在某些情况下,这只是将脸部所属的实体取出来,看看太阳光线的矢量在到达“天空”之前是否与另一个固体相交。

寻找lightmaps上的东西以及shadowmapping。

2

有一件事可以让很多人发现,发送到glLightFv的位置由当前的矩阵堆栈翻译。因此,如果要将灯光设置为世界坐标中的特定位置,则必须在调用glLightFv时在矩阵堆叠上设置和激活相机和投影矩阵。