openGL使用修复灯旋转球体

时间:2016-11-26 10:34:15

标签: opengl

我想旋转一个球体。并且灯应该在房间的固定位置。 但似乎光线不在固定位置,而是与球体一起旋转。 我试图把所有东西放在push / popmatrix中。没有帮助。 我读到了关于正常情况的内容,但我也读到了过度使用球体的自动过滤。

如何修复灯光位置?

#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glut.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

float angletest = 1;
float winwidth, winheight;

void keyboard(unsigned char key, int x, int y)
{

switch (key)
{
case'\033':
    exit(0);
    break;
}
}

void reshape(w, h)
GLsizei w;
GLsizei h;
{
int size;

winwidth = w;
winheight = h;
size = w>h ? h : w;
glViewport(0, 0, size, size);       
glMatrixMode(GL_PROJECTION);    
glLoadIdentity();
gluPerspective(40, 1.0, 1.0f, 20.0f);
glutPostRedisplay();
}

void display(void)
{
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

glLoadIdentity();

GLUquadricObj *quadric;
quadric = gluNewQuadric();

glPushMatrix();
glColor3f(0, 0, 1);
glTranslatef(0.5, 0, 0);
glRotatef(angletest, 0, 0, 1);
gluSphere(quadric, 0.2, 50, 50);
glPopMatrix();

glPushMatrix();
glColor3f(0, 1, 0);
glRotatef(angletest, 0, 0, 1);
glTranslatef(0, 0.5, 0);
glutSolidSphere(0.2, 50, 50);
glPopMatrix();

glFlush();
glutSwapBuffers();

}

void init()
{
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);

glClearColor(0, 0, 0, 0);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 50.0 };
GLfloat light_position[] = { 0, 0.5, 0, 1.0f };

glShadeModel(GL_SMOOTH);

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);

glEnable(GL_LIGHT0);

}

void idle(void)
{
angletest = angletest + 0.05;

glutPostRedisplay();
}

void main(int argc, char** argv)
{
glutInitWindowSize(400, 400);
glutInitWindowPosition(100, 100);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);

glutCreateWindow("test");

glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutIdleFunc(idle);
init(); 
glutMainLoop();

}

试图像下面提到的那样做,并把

glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glRotatef之间的

(angletest,0,0,1);和gluSphere(quadric,0.2,50,50); 但那并没有这样做。

glPushMatrix(); 
glColor3f(0, 0, 1); 
glTranslatef(0.5, 0, 0); 
glRotatef(angletest, 0, 0, 1); 
glLightfv(GL_LIGHT0, GL_POSITION, light_position); 
gluSphere(quadric, 0.2, 50, 50); 
glPopMatrix();

实际上,我希望光源位于中间位置。但是,如果我把它放在0,0,0的位置,根本就没有光。 为了说明移动光线的意思,我在这里有三张照片。

light is in the right corner

light is in the left down corner

所以你可以看到它似乎与物体一起移动。 但我想要的是光线留在中间并为物体照明,就像它是太阳一样。

1 个答案:

答案 0 :(得分:0)

抱歉,我的评论错了。我刚刚意识到你不使用矩阵堆栈来转换相机(模型视图中的视图部分),而是使用对象空间(模型部分)。在更改视图部件之后和更改模型部件之前,应调用glLightfv()。但是你永远不会改变代码中的视图部分,所以设置一次光就足够了。

您的代码中还有另一个微妙的问题,这会导致此行为。看看你的reshape()功能。您将矩阵模式更改为投影,并且永远不会将其更改回模型视图。因此,您应用的所有矩阵变换都将应用于投影矩阵。照明在视图空间中计算。由于您不更改模型视图矩阵,因此所有光照都在对象的坐标系中完成(假设此系统中的光位置)。然后投影矩阵旋转已经照明的物体,可能远离光线。

所以解决方案很简单:将矩阵模式切换回reshape()函数中的模型视图。