OpenGL Направленное освещение + Позиционирование - PullRequest
2 голосов
/ 29 февраля 2012

Я пишу движок и использую Light 0 как «солнце» для сцены. Солнце - это направленный свет.

Я устанавливаю точку обзора Орто сцены, затем настраиваю свет на «восточную» сторону экрана (и на символ) (x / y - координаты плоскости местности, положительный z направлен на камеру и указывает на «высоту» на местности - сцена также поворачивается для изометрического вида по оси х).

Свет, кажется, светит отлично "Восток" 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. 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 ]

3 голосов
/ 29 марта 2012

Вам нужно будет предоставить нормали для каждой поверхности.То, что происходит (без нормалей), это то, что направленный свет по существу светит на все к востоку от нуля, позиционно, в то время как все, что там есть, имеет норму 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 достаточно для управляемого освещения серии выпуклых форм, поэтому вам придется выяснить, следует ли применять свет (например, солнце) к лицу.В некоторых случаях это просто получение твердого тела, которому принадлежит лицо, и определение, пересекается ли вектор солнечного света с другим телом, прежде чем достигнуть «неба».

Ищите материал на картах света, а также карты теней для этого,

2 голосов
/ 29 марта 2012

Одна вещь, которая может сбить с толку многих людей, состоит в том, что позиция, отправленная на glLightFv, переводится текущим стеком матрицы. Таким образом, если вы хотите, чтобы ваш источник света был установлен на определенную позицию в мировых координатах, ваша камера и матрицы проекции должны быть установлены и активированы в стеке матриц во время вызова glLightFv.

...