OpenGL 定向照明 + 定位

标签 opengl game-engine lighting

我正在编写一个引擎并使用 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/

相关文章:

c++ - 使聚光灯静止

C++ Directx 11 环境光

c++ - C++ OpenGL 中定位光和直射光的区别?

c++ - 如何使用 OpenGL C++ 绘制双曲面?

opengl - 在 OpenGL 中绘制对象 X 秒

java - 使用纹理时 libgdx 不加载文件

c# - 移动跨平台游戏开发的最佳编程语言

c++ - ECS框架如何更新组件数据并通知系统?

c++ - C++ 中的 OpenGl VBO 技术

c++ - 引起问题的纹理