OpenGL定向照明+定位

时间:2012-02-28 23:48:02

标签: opengl game-engine lighting

我正在编写引擎并使用Light 0作为场景的“太阳”。太阳是定向光。

我设置场景的正交视点,然后将灯光设置在屏幕的“东”侧(和角色)(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 );
    }

2 个答案:

答案 0 :(得分: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足以控制一系列凸形的照明,因此您必须弄清楚是否应该将光(例如太阳)应用于面部。在某些情况下,这只是采取面部所属的实体,并在到达“天空”之前看到太阳光的矢量是否与另一个实体相交。

查看光照贴图上的内容以及阴影贴图。

答案 1 :(得分:2)

可以绊倒许多人的一件事是发送到glLightFv的位置由当前矩阵堆栈转换。因此,如果您希望将灯光设置为世界坐标中的特定位置,则必须在glLightFv调用时在矩阵堆栈上设置并激活相机和投影矩阵。