2

我正在编写一个引擎并使用 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 = 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 );
    }
4

2 回答 2

3

您需要为每个表面提供法线。正在发生的事情(没有法线)是定向光基本上照在零以东的所有位置上,而那里的所有东西都具有 0,0,1 的法线(它面向西)。

据我所知,您不需要发送每个顶点的法线,而是因为 GL 是一个状态机,所以您需要确保每当法线发生变化时都会更改它。所以如果你在一个立方体上渲染一个面,“西”面应该有一个调用

glNormal3i(0,0,1);
glTexCoord..
glVertex3f...
glTexCoord..
etc.

在 xyz 对齐的矩形棱镜的情况下,“整数”就足够了。对于不面向六个基本方向之一的面,您需要对其进行归一化。根据我的经验,除非四边形不平坦,否则您只需要标准化前三个点。这是通过找到由四边形中的前三个边形成的三角形的法线来完成的。

我发现有一些关于“计算法线”的简单教程很有启发性。

第二部分是因为它是一个定向光,(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 足以用于一系列凸形的受控照明,因此您必须确定是否应将光(例如太阳)应用于面部。在某些情况下,这只是获取面所属的实体,并查看太阳光的矢量在到达“天空”之前是否与另一个实体相交。

寻找光照贴图和阴影贴图的东西。

于 2012-03-29T14:42:40.677 回答
2

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

于 2012-03-29T16:50:12.197 回答