Несколько прожекторов в OpenGL не работает - PullRequest
0 голосов
/ 08 мая 2019

Я использую opengl в образовательных целях, но у меня возникают проблемы при создании нескольких прожекторов для представления уличных фонарей.Я использую итератор для создания нескольких, но в конце концов только последний прожектор получает свет, я думаю, что проблема в методе addlight, однако я не знаю, что происходит.

На изображении ниже вы можете увидеть, как происходит.

https://imgur.com/Y77eHln

#include "CreateLamps.h"

std::vector<SpotLight> lamp;

CreateLamps::CreateLamps(int number) {

    for (int i = 0; i < number; i++) {
        SpotLight *spot = new SpotLight(-8.0f, 5.f, (i*10) + 30.0f, 1.f);
        lamp.push_back(*spot);
    }

}

void CreateLamps::Add() {

    std::vector<SpotLight>::iterator it = lamp.begin();

    while (it != lamp.end())
    {

        glPushMatrix();
        glTranslatef(1, 0, 30.0);
        glTranslatef(it->position[0], it->position[3] * 3, it->position[2]);
        glRotatef(100.f, -5.0, -10, 0);
        it->addlight();
        it->draw();
        it++;
        glPopMatrix();

    }
}

#include "SpotLight.h"

using namespace std;

GLfloat target[3] = { 0.0f, 0.0f, 0.0f };
GLfloat color[3] = { 1.0f, 1.0f, 1.0f };
GLfloat cutoff(5.0f);
GLfloat exponent(15.0f);

SpotLight::SpotLight(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {

    position[0] = x;
    position[1] = y;
    position[2] = z;
    position[3] = w;

    direction[0] = target[0] - position[0];
    direction[1] = target[1] - position[1];
    direction[2] = (target[2] - position[2]);

}

void SpotLight::addlight() {

    glEnable(GL_LIGHT1);

    glLightfv(GL_LIGHT1, GL_DIFFUSE, color);
    glLightfv(GL_LIGHT1, GL_SPECULAR, color);
    glLightfv(GL_LIGHT1, GL_POSITION, position);

    glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, direction);
    glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, cutoff);
    glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, exponent);

}

void SpotLight::draw() {
    if (!glIsEnabled(GL_LIGHT1)) 
        return;

    glPushMatrix();
    GLfloat up[3] = { 0, 1, 0 };
    lookAt(position, target, up);

    GLfloat ambient[4] = { 0.8f, 0.8f, 0.8f, 1.0f };
    GLfloat diffuse[4] = { 0.01f, 0.01f, 0.01f, 1.0f };
    GLfloat specular[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
    GLfloat shininess = 32.0f;

    glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
    glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
    glMaterialf(GL_FRONT, GL_SHININESS, shininess);

    glutSolidCone(0.3, 0.6, 10, 10);
    glPushMatrix();
    glTranslatef(0, 0, 0.1f);
    glutSolidCylinder(0.2, 0.39, 10, 10);
    glPopMatrix();

    glDisable(GL_LIGHTING);
    glColor3fv(color);
    glutSolidSphere(0.2, 100, 100);
    glEnable(GL_LIGHTING);
    glPopMatrix();
}


void SpotLight::normalize(const GLfloat* vec, GLfloat* output)
{
    GLfloat length = sqrtf(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);
    output[0] /= length;
    output[1] /= length;
    output[2] /= length;
}

void SpotLight::cross(const GLfloat* vec1, const GLfloat* vec2, GLfloat * output) {
    output[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
    output[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
    output[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
}

void SpotLight::lookAt(GLfloat* eye, GLfloat* center, GLfloat* up)
{
    GLfloat f[3] = { center[0] - eye[0],
                     center[1] - eye[1],
                     center[2] - eye[2] };

    normalize(f, f);
    GLfloat u[3];
    normalize(up, u);
    GLfloat s[3];
    cross(f, u, s);
    normalize(s, s);
    cross(s, f, u);
    normalize(u, u);

}

void drawScene() {

    glPushMatrix();
    glTranslatef(pointlight.position[0], pointlight.position[1], pointlight.position[2]);
    pointlight.addLight();
    glPopMatrix();

    // Draw road
    glPushMatrix();
    glScalef(10, 10, 8.5);
    glTranslatef(-0.018f, 0, 0.75);
    glRotatef(180.f, 0, 1, 0);
    models[0]->renderTheModel();
    glPopMatrix();

    //Draw Car Model
    glPushMatrix();
    glMultMatrixf(carros[0]->local);
    carros[0]->draw();
    glPopMatrix();

//Draw spotlights
    glPushMatrix();
    lamps->Add();
    glPopMatrix();
}

Ответы [ 2 ]

3 голосов
/ 08 мая 2019

Вы только когда-либо устанавливали LIGHT1, что означает, что только 1 свет будет включен (последний).Если вы укажете GL_LIGHT0 + index, вы сможете включить больше.

void SpotLight::addlight(int index) {

    glEnable(GL_LIGHT0 + index);

    glLightfv(GL_LIGHT0 + index, GL_DIFFUSE, color);
    glLightfv(GL_LIGHT0 + index, GL_SPECULAR, color);
    glLightfv(GL_LIGHT0 + index, GL_POSITION, position);

    glLightfv(GL_LIGHT0 + index, GL_SPOT_DIRECTION, direction);
    glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, cutoff);
    glLightf(GL_LIGHT0 + index, GL_SPOT_EXPONENT, exponent);
}

И тогда вам просто нужно будет передать индекс при включении

void CreateLamps::Add() {

    std::vector<SpotLight>::iterator it = lamp.begin();

    while (it != lamp.end())
    {

        glPushMatrix();
        glTranslatef(1, 0, 30.0);
        glTranslatef(it->position[0], it->position[3] * 3, it->position[2]);
        glRotatef(100.f, -5.0, -10, 0);
        it->addlight(it - lamp.begin());
        it->draw();
        it++;
        glPopMatrix();

    }
}

Просто знайте, чтоу вас может не хватить света после 8, поэтому вы можете проверить значение GL_MAX_LIGHTS ...

int numLights = 0;
glGetIntegerv(GL_MAX_LIGHTS, &numLights);
std::cout << "GL_MAX_LIGHTS " << numLights << std::endl;
0 голосов
/ 08 мая 2019

Предположительно, вы рисуете дорогу после прорисовки всех источников света.

Ваш код делает это:

  • Для каждого источника света:
    • Установите источник света 1 согласнок параметрам этого источника света
    • Нарисуйте форму самого источника света
  • Нарисуйте дорогу.

Когда дорога будет нарисована, включите свет 1настраивается с параметрами последнего нарисованного источника света.Таким образом, он использует эти параметры освещения, чтобы нарисовать дорогу.Вы уже переписали все параметры других источников света.

Если вы хотите нарисовать дорогу со всеми огнями, тогда все огни должны быть настроены, когда вы рисуете дорогу.Не только последний.

Обратите внимание, что вы можете настроить только 8 источников света одновременно в OpenGL.Если на дороге указано более 8 ламп, вам придется разделить дорогу на несколько участков, чтобы в каждой секции было до 8 ламп.


Стандартный отказ от ответственности, если вы не знаетеуже: вы используете старый стиль (с фиксированной функцией) OpenGL, который был заменен шейдерным OpenGL (версии 3 и 4).Этот API подходит для простых программ, но не позволяет использовать всю гибкость и производительность вашей видеокарты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...