c - 如何让我的灯光相对于我的场景(在立方体中)保持固定?
问题描述
我一直在画康奈尔盒子。我想在我的灯里放灯(灯是一个放在右边墙上的白色立方体)。它会产生一种灯在发光的错觉。但是我不能把我的灯放到立方体里。我试图设置视图变换,然后设置灯光位置,但它不起作用。这是我的简单代码:(灯立方体已移动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;
}
解决方案
请注意,按glBegin
/glEnd
序列绘制,固定函数管道矩阵堆栈和每个顶点光模型的固定函数管道,几十年来已被弃用。阅读Fixed Function Pipeline并查看Vertex Specification and 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 着色。
如果光矢量以相对于表面平面的锐角撞击顶点坐标,这可能会导致您无法“看到”光。
在您的情况下,绿色墙壁几乎没有点亮,因为光源几乎直接在墙上。灯本身不亮,因为光源在灯内部,是从背面发出的光。
稍微改变灯光的位置,把它放在墙的前面,把右边的墙镶嵌成 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();
推荐阅读
- javascript - 更改 Blob 文件名
- c++ - 在 c/c++ 中,二进制补码整数将 +1 转换为 -1 并将 0 转换为 1 的按位运算是什么?
- python - Django TemplateSyntaxError - 'staticfiles' 不是注册的标签库
- excel - 为许多连续行自动填充文本中的连续数字
- php - 如果元素的所有值在整个数组 PHP 中都是空白,则完全删除元素
- c - 使用c语言获取数组元素的升序
- javascript - 使用复选框交换 div 内所有内容的位置
- r - 整洁的 eval vs base 或 get() vs sym() vs as.symbol()
- docker - 使用内部网络 docker 的 Traefik 404 错误
- flutter - Flutter Text Field:如何在边框内添加图标