我正在创建太阳能系统并且我一直遇到照明问题。第一个问题是月球在地球上没有投射阴影,地球上没有投射阴影。 另一个问题是,照在地球和月球上的光不是来自我的太阳,而是来自轨道的中心点。我在下面的图片中添加了红线以显示我的意思。
下面的图片应说明我的两个问题。
以下是处理灯光和行星的代码。
glDisable(GL_LIGHTING);
drawCircle(800, 720, 1, 50);
//SUN
//Picture location, major radius, minor radius, major orbit, minor orbit, angle
Planet Sun ("/home/rodrtu/Desktop/SolarSystem/images/Sun.png",
100, 99, 200.0, 0.0, 0.0);
double sunOrbS = 0;
double sunRotS = rotatSpeed/10;
cout << sunRotS << " Sun Rotation" << endl;
//orbit speed, rotation speed, moon reference coordinates (Parent planet's major and minor Axis)
Sun.displayPlanet(sunOrbS, sunRotS, 0.0, 0.0);
//Orbit path
//EARTH
GLfloat light_diffuse[] = { 1.5, 1.5, 1.5, 1.5 };
GLfloat pos[] = { 0.0, 0.0, 0.0, 200.0 };
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, pos);
Planet Earth ("/home/rodrtu/Desktop/SolarSystem/images/EarthTopography.png",
50, 49, 500.0, 450.0, 23.5);
double eaOrbS = orbitSpeed;
double eaRotS = rotatSpeed*3;
Earth.displayPlanet(eaOrbS, eaRotS, 0.0, 0.0);
//EARTH'S MOON
Planet Moon ("/home/rodrtu/Desktop/SolarSystem/images/moonTest.png",
25, 23, 100.0, 100.0, 15);
double moOrbS = rotatSpeed*4;
double moRotS = eaOrbS;
Moon.displayPlanet(moOrbS, moRotS, Earth.getMajorAxis(), Earth.getMinorAxis());
orbitSpeed+=.9;
if (orbitSpeed > 359.0)
orbitSpeed = 0.0;
rotatSpeed+=2.0;
if (rotatSpeed > 7190.0)
rotatSpeed = 0.0;
下一个函数用于确定每个行星的轨道坐标和位置
void Planet::setOrbit(double orbitSpeed, double rotationSpeed,
double moonOrbitX, double moonOrbitY)
{
majorAxis = orbitSemiMajor * cos(orbitSpeed / 180.0 * Math::Constants<double>::pi);
minorAxis = orbitSemiMinor * sin(orbitSpeed / 180.0 * Math::Constants<double>::pi);
glTranslate(majorAxis+moonOrbitX, minorAxis+moonOrbitY, 0.0);
glRotatef(orbitAngle, 0.0, 1.0, 1.0);
glRotatef(rotationSpeed, 0.0, 0.0, 1.0);
}
void Planet::displayPlanet(double orbitSpeed,double rotationSpeed,
double moonOrbitX, double moonOrbitY)
{
GLuint surf;
Images::RGBImage surfaceImage;
surfaceImage=Images::readImageFile(texture);
glEnable(GL_TEXTURE_2D);
glGenTextures(0, &surf);
glBindTexture(GL_TEXTURE_2D, surf);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
surfaceImage.glTexImage2D(GL_TEXTURE_2D,0,GL_RGB);
glPushMatrix();
setOrbit(orbitSpeed,rotationSpeed, moonOrbitX, moonOrbitY);
drawSolidPlanet(equatRadius, polarRadius, 1, 40, 40);
glPopMatrix();
}
我做错了什么?我读到了GL_POSITION的w分量,我将我的位置改为200(太阳位于中心),但光源仍然来自轨道中心。
答案 0 :(得分:2)
如果OpenGL没有“投射阴影”功能,我怎么能这样做呢?
你必须明白的是,OpenGL没有“场景”的概念。所有OpenGL都是在屏幕上绘制点,线或三角形,一次一个。绘制后,它对以下绘图操作没有影响。
所以要做一些像阴影一样的事情,你必须得到,好吧,艺术。我的意思是,就像一个画了一幅塑料画面的艺术家,画面的深度只有“画笔”和颜色调色板,你必须以艺术的方式使用OpenGL来重新创造你想要的效果。绘制阴影可以通过各种方式完成。但最流行的一个是术语阴影映射。
Shadow Mapping是一个两步过程。在第一步中,场景被渲染成从光的视点“看到”的“灰度”图像,其中距光的距离被绘制为“灰色”值。这称为阴影深度图。
在第二步中,场景像往常一样被绘制,其中灯光的阴影深度图被投射到场景中,好像灯光是幻灯片投影仪(所有东西都接收到该图像,因为OpenGL没有阴影)。在着色器中,将阴影深度图中的深度值与每个处理过的片段与光源的实际距离进行比较;如果到光的距离比阴影贴图中的相应像素更远,这意味着在渲染阴影贴图时,某些东西位于当前处理的几何体片段前面,因此它位于阴影中,因此它以阴影颜色绘制(通常是环境照明颜色);您可能希望将其与 Ambient Occlusion 效果结合使用,以模拟柔和的自阴影环境照明。
答案 1 :(得分:2)
对灯光位置问题做出正确回复..
[X, Y, Z, W]
称为同质坐标
同质空间中的坐标[X, Y, Z, W]
在3D空间中将为[X/W, Y/W, Z/W]
。
现在,考虑以下W值:
W=1.0
:[1.0, 1.0, 1.0, 1.0]
在3D地方为[1.0, 1.0, 1.0]
。W=0.1
:[1.0, 1.0, 1.0, 0.1]
在3D地方为[10.0, 10.0, 10.0]
。W=0.001
:[1.0, 1.0, 1.0, 0.001]
在3D地方为[1000.0, 1000.0, 1000.0]
。当我们继续向W=0
移动时,[X/W, Y/W, Z/W]
值接近无限远点。它实际上不再是一个点,而是从[0,0,0]
到[X,Y,Z]
的方向。
因此,在定义灯光位置时,我们需要确保正确。
W=0
定义了一个方向光,因此x,y,z是一个方向向量W=1
定义了位置光,因此x,y,z是3D空间中的位置一旦你深入研究矩阵数学,你就可以解决这个问题。例如,如果您尝试使用转换矩阵转换方向(W=0)
,则不会产生任何影响。这也非常重要,因为灯光位置会受到模型视图矩阵的影响。
这里有一些易于理解的信息可供进一步阅读: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/