如何让我的灯光相对于我的场景(在立方体中)保持固定?

Posted

技术标签:

【中文标题】如何让我的灯光相对于我的场景(在立方体中)保持固定?【英文标题】:How can I make my light stay fixed relative to my scene (in the cube)? 【发布时间】:2018-11-03 07:36:16 【问题描述】:

我一直在画康奈尔盒子。我想在我的灯里放灯(灯是一个放在右边墙上的白色立方体)。它会产生一种灯在发光的错觉。但是我不能把我的灯放到立方体里。我尝试设置视图变换,然后设置灯光位置,但它不起作用。 这是我的简单代码:(灯立方已移动glTranslatef(0.63, 0.3, 0.0)

 void display(void)


    glEnable(GL_DEPTH_TEST);
    glViewport(0, 0, 600, 600);
    glClearColor(0.32, 0.32, 0.32, 1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    // draw cube
    glPushMatrix();
    glTranslatef(0.2, -0.3, 0.4);
    glColor3d(1.0, 0.38, 0.0);
    glutSolidCube(0.2);
    glPopMatrix();
    // draw sphere
    glPushMatrix();
    glTranslatef(0.2, -0.1, 0.4);
    glColor3d(0.71, 0.0, 0.59);
    glutSolidSphere(0.1,100,100);
    glPopMatrix();
    // draw parallelepiped
    glPushMatrix();
    glTranslatef(-0.2, -0.2, 0.25);
    glRotatef(20, 0.0, 1.0, 0.0);
    glColor3d(1.0, 0.38, 0.0);
    glScalef(1, 1.8, 1);
    glutSolidCube(0.2);
    glPopMatrix();
    // draw lamp
    glPushMatrix();
    glTranslatef(0.63, 0.3, 0.0);
    glScalef(1.5, 0.3, 1);
    glColor3d(1.0, 1.0, 1.0);
    glutSolidCube(0.2);
    glPopMatrix();

    glBegin(GL_QUADS);
    glNormal3f(0, 1.0, 0);
    glColor3d(0.69, 0.69, 0.69); // bottom
    glVertex3d(-0.5, -0.5, 0.5);
    glVertex3d(-0.5, -0.5, -0.5);
    glVertex3d(0.5, -0.5, -0.5);
    glVertex3d(0.5, -0.5, 0.5);
    glEnd();
    glBegin(GL_QUADS);
    glNormal3f(0, -1.0, 0);
    glColor3d(0.69, 0.69, 0.69); // top
    glVertex3d(-0.5, 0.5, 0.5);
    glVertex3d(-0.5, 0.5, -0.5);
    glVertex3d(0.5, 0.5, -0.5);
    glVertex3d(0.5, 0.5, 0.5);
    glEnd();
    glBegin(GL_QUADS);
    glNormal3f(-1.0, 0.0, 0.0);
    glColor3d(0.0, 0.79, 0.05); // right
    glVertex3d(0.5, -0.5, 0.5);
    glVertex3d(0.5, 0.5, 0.5);
    glVertex3d(0.5, 0.5, -0.5);
    glVertex3d(0.5, -0.5, -0.5);
    glEnd();
    glBegin(GL_QUADS);
    glNormal3f(1.0, 0.0, 0.0);
    glColor3d(1.0, 0.16, 0.0); // left
    glVertex3d(-0.5, -0.5, 0.5);
    glVertex3d(-0.5, 0.5, 0.5);
    glVertex3d(-0.5, 0.5, -0.5);
    glVertex3d(-0.5, -0.5, -0.5);
    glEnd();
    glBegin(GL_QUADS);
    glNormal3f(0.0, 0.0, 1.0);
    glColor3d(0.69, 0.69, 0.69); // back
    glVertex3d(-0.5, -0.5, -0.5);
    glVertex3d(-0.5, 0.5, -0.5);
    glVertex3d(0.5, 0.5, -0.5);
    glVertex3d(0.5, -0.5, -0.5);
    glEnd();
    glFlush();
    glPopMatrix();
    glutSwapBuffers();



void Initialize() 
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    GLfloat global_ambient[] =  0.1, 0.1, 0.1, 1.0 ;
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
    GLfloat ambient[] =  0.0,0.0,0.0,1.0 ;
    GLfloat diffuse[] =  1.0,1.0,1.0,1.0 ;
    GLfloat spec[] =  1,1,1,1 ;
    GLfloat specref[] =  1,1,1,1 ;
    GLfloat lpos[] =  0.0, 0.0, 0.0, 1.0 ;
    glLightfv(GL_LIGHT0, GL_POSITION, lpos);
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, spec);

    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specref);
    glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 64);
    glEnable(GL_COLOR_MATERIAL);
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);


void exitFunc(unsigned char key, int x, int y) 
    switch (key) 
    case 27:
        exit(0);
        break;
    


void reshape(int w, int h)

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-0.35, 0.35, -0.35, 0.35, 1.2, 400.0);
    glMatrixMode(GL_MODELVIEW);
    glTranslatef(0, 0, -2);


int main(int argc, char** argv)

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(600, 600);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("Cornell Box");
    Initialize();
    glutDisplayFunc(display);
    glutKeyboardFunc(exitFunc);
    glutReshapeFunc(reshape);
    glutIdleFunc(display);

    glutMainLoop();
    return 0;   

【问题讨论】:

【参考方案1】:

请注意,由glBegin/glEnd 序列绘制、固定函数管道矩阵堆栈和每个顶点光照模型的固定函数管道,几十年来已被弃用。 阅读Fixed Function Pipeline 并查看Vertex Specification 和Shader,了解最先进的渲染方式。


无论如何,当灯光位置由glLightfv(GL_LIGHT0, GL_POSITION, pos)设置时,那么 pos 乘以当前模型视图矩阵。 这意味着如果在设置模型视图矩阵之前设置位置,那么灯光位置将放置在世界的绝对坐标中。 如果是在设置模型视图矩阵之后设置,则可以在模型坐标系中设置灯光位置。

在绘制灯时设置灯光位置,到“灯”的中心:

// draw lamp
glPushMatrix();
glTranslatef(0.63, 0.3, 0.0);
glScalef(1.5, 0.3, 1);

GLfloat lpos[] =  0.0, 0.0, 0.0, 1.0 ;
glLightfv(GL_LIGHT0, GL_POSITION, lpos);

glColor3d(1.0, 1.0, 1.0);
glutSolidCube(0.2);
glPopMatrix(); 

OpenGL 固定函数管道计算每个顶点的光:Gouraud shading。 这可能会导致,如果光矢量以相对于表面平面的锐角撞击顶点坐标,则您无法“看到”光。

在您的情况下,绿色墙壁几乎没有点亮,因为光源几乎直接在墙上。灯本身不亮,因为光源在灯内部,是从背面发出的光。

见OpenGL Lighting on texture plane is not working

稍微改变灯光的位置,把它放在墙的前面,把右边的墙镶嵌成4个四边形,“看”我的意思:

 GLfloat lpos[] =  -0.1, 0.0, 0.0, 1.0 ; 

// right
glBegin(GL_QUADS);
glNormal3f(-1.0, 0.0, 0.0);
glColor3d(0.0, 0.79, 0.05); 
glVertex3d(0.5,  0.3,  0.5);
glVertex3d(0.5,  0.5,  0.5);
glVertex3d(0.5,  0.5,  0.0);
glVertex3d(0.5,  0.3,  0.0);

glVertex3d(0.5,  0.3,  0.0);
glVertex3d(0.5,  0.5,  0.0);
glVertex3d(0.5,  0.5, -0.5);
glVertex3d(0.5,  0.3, -0.5);

glVertex3d(0.5, -0.5,  0.5);
glVertex3d(0.5,  0.3,  0.5);
glVertex3d(0.5,  0.3,  0.0);
glVertex3d(0.5, -0.5,  0.0);

glVertex3d(0.5, -0.5,  0.0);
glVertex3d(0.5,  0.3,  0.0);
glVertex3d(0.5,  0.3, -0.5);
glVertex3d(0.5, -0.5, -0.5);

glEnd();

【讨论】:

谢谢!我理解我的坐标错误,但我有一个问题。请看:ibb.co/jxDkk0。我希望那盏灯应该是白色的(因为光线),为此,我应该将四边形分成瓷砖,是吗? 我设置了lpos[] = -0.5, 0.0, 0.0, 1.0 ;,但现在球体上的高光在左侧,看来光源是从左侧发光的。请看:ibb.co/ihXLk0 @V.Jakob 是的,当然,这不是修复,这应该演示行为。 你不能这样修复它。最简单的修复方法是摆脱已弃用的固定功能管道并编写现代光照模型着色器。 我明白了,但我有一个任务是用 GLUT 来完成 :(。谢谢你所有的建议。我试图在现代 OpenGL 中做到这一点,但在现代 opengl 中绘制球体太难了,我不知道怎么做。如果你告诉我怎么做,我将非常感激!!!未来:是否有可能在 Cornell box 中使用阴影贴图(这里,使用 GLUT)制作阴影? @V.Jakob GLUT API 用于创建像GLFW 这样的窗口。当然,您可以将“现代”OpenGL 与 GLUT 一起使用。我建议将GLEW 用于OpenGL 扩展,将GLM - OpenGL Mathematics 用于矩阵运算。请参阅 Sphere Calculations 创建球体。

以上是关于如何让我的灯光相对于我的场景(在立方体中)保持固定?的主要内容,如果未能解决你的问题,请参考以下文章

ThreeJS - 错误的光线旋转

图像处理中关于Blob的阈值的一些概念

如何复制相对于我的活动单元格的一系列单元格?

如何在android中保持地图方向固定在北方

如何让 XSLT 键功能适用于我的场景?

如何让我的子菜单在 jQuery 悬停菜单中保持打开状态?