1

我正在创建太阳系,但我一直遇到照明问题。第一个问题是月球在地球上没有影子,地球在月球上也没有影子。另一个问题是,照在地球和月球上的光不是来自我的太阳,而是来自轨道的中心点。我在下图中添加了红线以显示我的意思。

下面的图片应该说明我的两个问题是什么。

在此处输入图像描述

这是处理灯光和行星的代码。

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(太阳居中的位置),但光源仍然来自轨道的中心。

4

2 回答 2

3

对灯位问题做出适当的答复..

[X, Y, Z, W]称为齐次坐标

同质空间中的坐标[X, Y, Z, W][X/W, Y/W, Z/W]在 3D 空间中。

现在,考虑以下 W 值:

  • W=1.0:[1.0, 1.0, 1.0, 1.0][1.0, 1.0, 1.0]在 3D 的地方。
  • W=0.1:[1.0, 1.0, 1.0, 0.1][10.0, 10.0, 10.0]在 3D 的地方。
  • W=0.001:[1.0, 1.0, 1.0, 0.001][1000.0, 1000.0, 1000.0]在 3D 的地方。

当我们继续朝着价值观前进时W=0,就会[X/W, Y/W, Z/W]接近无穷大。它实际上不再是一个点,而是一个从[0,0,0]to的方向[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/

于 2013-05-24T22:55:37.227 回答
2

如果 OpenGL 没有“投射阴影”功能,那我该如何完成呢?

您必须了解的是,OpenGL 没有“场景”的概念。OpenGL 所做的只是在屏幕上一次绘制一个点、线或三角形。绘制完成后,对后面的绘制操作没有影响。

所以要做一些像阴影这样花哨的东西,你必须要有,好吧,艺术。我的意思是,就像艺术家用“仅”一支画笔和调色板来绘制具有深度的塑料图片一样,您必须以艺术的方式使用 OpenGL 来重新创建您想要的效果。可以通过多种方式绘制阴影。但最流行的是阴影映射这个术语。

阴影映射是一个两步过程。在第一步中,场景被渲染为从灯光的角度“看到”的“灰度”图片,其中与灯光的距离被绘制为“灰度”值。这称为阴影深度图

在第二步中,照常绘制场景,将灯光的阴影深度图投影到场景中,就好像灯光是幻灯机一样(所有东西都接收该图像,因为 OpenGL 没有阴影)。在着色器中,阴影深度图中的深度值与每个已处理片段到光源的实际距离进行比较;如果到灯光的距离比阴影贴图中的相应像素更远,这意味着在渲染阴影贴图时,当前处理的几何片段前面有一些东西,因此它位于阴影中,所以它以阴影颜色绘制(通常是环境照明颜色);您可能希望将其与环境光遮蔽效果相结合,以模拟柔和的自阴影环境照明。

于 2013-05-23T23:15:54.053 回答