【问题标题】:openGL Rotate Sphere with fix lightopenGL Rotate Sphere 带固定光
【发布时间】:2016-11-26 10:34:15
【问题描述】:

我想旋转一个球体。并且灯应该在房间的固定位置。 但似乎光线不是在固定位置,而是随着球体旋转。 我试图把所有东西都放在 push/popmatrix 中。没有帮助。 我读到了 normal 但我也读到 glut 会自动处理球体。

如何固定灯光位置?

#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

所以你可以看到灯光似乎随着物体移动。 但我想要的是将光线留在中间并像太阳一样照亮物体。

【问题讨论】:

  • 您正在使用已弃用超过八年的旧版固定功能 OpenGL 管道。您应该改用现代 OpenGL 的可编程管道。
  • @NicoSchertler 我以前读过这个帖子。但我不太确定在哪里设置模型视图矩阵并且必须编写 glLightfv(GL_LIGHT0, GL_POSITION, light_position);再次。出于沮丧,我试图把它放在任何可能的地方。但没有任何变化。
  • glRotatef()gluSphere() 之间。
  • glPushMatrix(); glColor3f(0, 0, 1); glTranslatef(0.5, 0, 0); glRotatef(angletest, 0, 0, 1); glLightfv(GL_LIGHT0, GL_POSITION, light_position); gluSphere(二次元, 0.2, 50, 50); glPopMatrix();但这并没有这样做

标签: opengl


【解决方案1】:

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

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

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

【讨论】:

  • 感谢您的回答。不幸的是,当我这样写时: glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(40, 1.0, 1.0f, 20.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity();过剩后重新显示();我什么都看不见了
  • 因为您现在有了一个以前没有的透视矩阵(您通过随后在display() 中对glLoadIdentity() 的调用将其删除。删除透视变换,您应该会再次看到一些东西。
  • 谢谢。就是这样。我还需要删除 glLightfv(GL_LIGHT0, GL_POSITION, light_position);两次。但现在它起作用了。谢谢
猜你喜欢
  • 2012-05-25
  • 1970-01-01
  • 1970-01-01
  • 2013-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多