【问题标题】:Multiple spotlights in opengl doesn't workopengl中的多个聚光灯不起作用
【发布时间】:2019-09-25 14:56:51
【问题描述】:

我将 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();
}

【问题讨论】:

  • 也许尝试在Add 中打印lamp.size 以查看其中有多少,或者在循环中放置一个断点/cout 语句以查看它迭代了多少次。此外,您正在以一种可怕的方式创建聚光灯,您应该放弃动态内存分配,只使用lamp.emplace_back({-8.0f, 5.f, (i*10) + 30.0f, 1.f});,因为您当前正在泄漏内存
  • 感谢您的警告。关于lamp.size,它打印正确的数字。
  • 当您说“它们不绘制”时,您的意思是圆柱体和圆锥体不绘制,还是说灯光效果不绘制在其他物体上?
  • 我的意思是光只能从圆柱体“出来”,而它也应该来自其他圆柱体。
  • 我添加了一张图片来显示正在发生的事情

标签: c++ opengl opengl-1.x


【解决方案1】:

大概是在画完所有的灯之后再画道路。

您的代码会这样做:

  • 对于每个灯:
    • 根据灯光参数设置灯光 1
    • 画出光本身的形状
  • 画出道路。

绘制道路时,使用最后绘制的灯光的参数设置灯光 1。所以它使用这些灯光参数来绘制道路。你已经覆盖了其他灯的所有参数。

如果你想用所有的灯来绘制道路,那么在你绘制道路时必须设置所有的灯。不只是最后一个。

请注意,您在 OpenGL 中一次只能设置 8 个灯光。如果超过 8 个灯指向道路,则必须将道路分成不同的路段,以便每个路段最多有 8 个灯。


如果您还没有意识到,标准免责声明:您使用的是旧式(固定功能)OpenGL,它已被基于着色器的 OpenGL(版本 3 和 4)取代。此 API 适用于简单程序,但无法让您充分利用显卡的灵活性和性能。

【讨论】:

    【解决方案2】:

    您只设置了 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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多