Проблеми с осветлението на OpenGL в Java/lwjgl

Създадох сцена с въртящ се куб в Java/lwjgl. Ако активирам осветлението, получавам реалистично поведение, сякаш източникът на светлина е в позицията на камерата, независимо къде поставям своя източник на светлина.

Ето моя метод за инициализиране на openGL:

private void initGL() throws LWJGLException {
    Display.create();
    Display.setFullscreen(true);
    Display.setVSyncEnabled(true);

    GL11.glViewport(0, 0, WIDTH, HEIGHT);
    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GLU.gluPerspective(70, 4f / 3f, 1, 10000);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);

    GL11.glEnable(GL11.GL_DEPTH_TEST);
    GL11.glDepthMask(true);

    GL11.glEnable(GL11.GL_CULL_FACE);

    // ----IMPORTANT PART----
    GL11.glEnable(GL11.GL_LIGHTING);
    GL11.glEnable(GL11.GL_LIGHT0);

    FloatBuffer position = ByteBuffer.allocateDirect(16).asFloatBuffer();
    position.mark();
    position.put(new float[] { -5f, 5f, 10f, 0f }); // even values about 10e3 for the first three parameters aren't changing anything
    position.reset();

    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, position);

    FloatBuffer ambient = ByteBuffer.allocateDirect(16).asFloatBuffer();
    ambient.mark();
    ambient.put(new float[] { 0.5f, 0.5f, 0.5f, 1f });
    ambient.reset();

    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, ambient);

    // Textures...
}

С тази част от кода се извиква, когато започна да изобразявам:

private void renderGL() {
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

    for (RenderObject ro : renderObjects) {
        ro.render();
    }
}

И това рисува куба. Нормалните стойности са правилни, мисля, обръщането им би попречило да се изчертае лицето, поне в моите тестове.

public void render() {
    GL11.glEnable(GL11.GL_TEXTURE_2D);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID);
    GL11.glColor3f(1f, 1f, 1f);

    GL11.glPushMatrix();

    GL11.glTranslatef(x, y, z);
    GL11.glRotatef(rotation, 1, 1, 1);
    GL11.glTranslatef(-x, -y, -z);

    GL11.glBegin(GL11.GL_QUADS);

    GL11.glNormal3f(0, 0, -1f);
    GL11.glTexCoord2f(0, 0);
    GL11.glVertex3f(x - dx, y - dy, z - dz);
    GL11.glTexCoord2f(0, 1);
    GL11.glVertex3f(x - dx, y + dy, z - dz);
    GL11.glTexCoord2f(1, 1);
    GL11.glVertex3f(x + dx, y + dy, z - dz);
    GL11.glTexCoord2f(1, 0);
    GL11.glVertex3f(x + dx, y - dy, z - dz);

    // the other five faces

    GL11.glEnd();

    GL11.glPopMatrix();
}

Какво бъркам с нещата с осветлението?

РЕДАКТИРАНЕ: Допълнителна информация за грешката

Когато задам последната стойност на масива за позиция на светлината на 0, цялата сцена е черна. Ако го зададете на всяка друга стойност, светлината излиза от прозореца за изглед, както е описано. Околната светлина не променя нищо, кубът, който искам да нарисувам, остава тъмен, когато източникът на светлина не работи. Опитах се да поставя осветителните неща на други позиции в кода, напр. директно след реда GLU.gluPerspective(70, 4f / 3f, 1, 10000); или в цикъла, без да променя никой от описаните ефекти.


person Sibbo    schedule 01.01.2012    source източник


Отговори (1)


Какво бъркам с нещата с осветлението?

Позицията на осветяване се умножава с матрицата на изгледа на модела. Така че трябва да извикате glLightfv(GL_LIGHT_, GL_POSITION, …); точно когато вашата матрица на изглед на модел съдържа трансформацията за гледане.

Технически всичко, което сте написали в тази initGL функция, принадлежи към функцията за рисуване. OpenGL не е графика на сцена, която инициализирате.

Актуализация:

Променете кода си по този начин:

public void render() {
    GL11.glEnable(GL11.GL_TEXTURE_2D);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID);
    GL11.glColor3f(1f, 1f, 1f);

    GL11.glPushMatrix();

    // this is where you set up your view:
    GL11.glTranslatef(x, y, z);
    GL11.glRotatef(rotation, 1, 1, 1);
    GL11.glTranslatef(-x, -y, -z);

    // and now it's time to set the light position:
    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, position);

    GL11.glBegin(GL11.GL_QUADS);

    GL11.glNormal3f(0, 0, -1f);
    GL11.glTexCoord2f(0, 0);
    GL11.glVertex3f(x - dx, y - dy, z - dz);
    GL11.glTexCoord2f(0, 1);
    GL11.glVertex3f(x - dx, y + dy, z - dz);
    GL11.glTexCoord2f(1, 1);
    GL11.glVertex3f(x + dx, y + dy, z - dz);
    GL11.glTexCoord2f(1, 0);
    GL11.glVertex3f(x + dx, y - dy, z - dz);

    // the other five faces

    GL11.glEnd();

    GL11.glPopMatrix();
}

След това трябва да премахнете initGL напълно, да преместите неговия код във функцията за рисуване, превръщайки го в:

public void render() {

    GL11.glViewport(0, 0, WIDTH, HEIGHT);

    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GLU.gluPerspective(70, 4f / 3f, 1, 10000);

    GL11.glMatrixMode(GL11.GL_MODELVIEW);   
    glLoadIdentity();
    GL11.glPushMatrix();

    // this is where you set up your view:
    GL11.glTranslatef(x, y, z);
    GL11.glRotatef(rotation, 1, 1, 1);
    GL11.glTranslatef(-x, -y, -z);

    // and now it's time to set the light position:
    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, position);

    // we do the rest of the light here as well
    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, ambient);

    GL11.glEnable(GL11.GL_DEPTH_TEST);
    GL11.glDepthMask(true);
    GL11.glEnable(GL11.GL_CULL_FACE);

    // we enable lighting right before rendering
    GL11.glEnable(GL11.GL_LIGHTING);
    GL11.glEnable(GL11.GL_LIGHT0);    

    GL11.glEnable(GL11.GL_TEXTURE_2D);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID);

    GL11.glColor3f(1f, 1f, 1f);

    GL11.glBegin(GL11.GL_QUADS);

    GL11.glNormal3f(0, 0, -1f);
    GL11.glTexCoord2f(0, 0);
    GL11.glVertex3f(x - dx, y - dy, z - dz);
    GL11.glTexCoord2f(0, 1);
    GL11.glVertex3f(x - dx, y + dy, z - dz);
    GL11.glTexCoord2f(1, 1);
    GL11.glVertex3f(x + dx, y + dy, z - dz);
    GL11.glTexCoord2f(1, 0);
    GL11.glVertex3f(x + dx, y - dy, z - dz);

    // the other five faces

    GL11.glEnd();

    GL11.glPopMatrix();
}
person datenwolf    schedule 01.01.2012
comment
Благодаря за вашият отговор! Методът GL11.glLight() е lwjgl версията на метода glLightfv() в C. Моля, вижте моята редакция, мисля, че не описах проблема си правилно преди. - person Sibbo; 01.01.2012
comment
@Sibbo: Трябва да поставите позиционирането на светлината веднага след настройката на матрицата view. Това не е проекцията. Вижте моята редакция на отговора. - person datenwolf; 01.01.2012
comment
Така че матрицата, която използвах с glRotation, завърта изгледа около куба, а не куба около изгледа? Тъй като променливите x, y и z са координатите на куба и въртенето трябва да завърти куба около оста 1/1/1. - person Sibbo; 02.01.2012
comment
@Sibbo: Е, технически вие местите само куба. OpenGL няма такова нещо като камера. Но ако се замислите, преместването на камера е същото като преместването на света в обратната посока. Матрицата modelview съчетава трансформация на модел и трансформация на изглед, следователно modelview. Проекционната матрица може да се мисли като лещата на OpenGL. - person datenwolf; 02.01.2012
comment
А, благодаря :) Но току-що открих проблема си, където на друго място в кода, нищо, ако е копирано тук... Създадох FloatBuffers погрешно, без да използвам flip() и order(). Сега работи, но източникът на светлина се върти заедно с куба :), но сега мога да работя сам, благодаря досега. - person Sibbo; 02.01.2012
comment
@Sibbo: За източника на светлина, който не се върти с куба, задайте позицията на светлината, преди да зададете въртенето на куба. Досега си мислех, че си завъртял камерата около куба. - person datenwolf; 02.01.2012
comment
Вчера работих малко повече върху него, сега мога ефективно да използвам метода push и popMatrix() :) Сега съм заседнал в оптимизирането, но това би било OT. Благодаря за вашата помощ :) - person Sibbo; 02.01.2012