3D正交投影

时间:2015-01-08 22:56:10

标签: opengl orthographic

我想构建一个正交投影,使我的太阳阴影贴图看起来正确。不幸的是,代码没有像使用常规透视投影那样实现期望的结果。这是我设置投影矩阵的代码:

glViewport (0, 0, (GLsizei)shadowMap.x, (GLsizei)shadowMap.y);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();

//suns use this
glOrtho(0, shadowMap.x, 0, shadowMap.y, 0.1,1000.0);

glMatrixMode (GL_MODELVIEW);
glLoadIdentity();

据我所知,这应该是正确的。但是,经过快速调试渲染后,我注意到场景在屏幕的一小部分呈现。经过一些实验,我发现改变glOrtho中的shadowMap值使它覆盖整个纹理,但它确实放大了。在我的视角投影中,我使用0.1和1000.0来近距离和远距离,我已经尝试了这些和它确实会改变结果,但仍然无法获得理想的结果。我得到正确结果的唯一时间是使用shadowMap.x和shadowMap.y保存值,但就像我说的那样,它的渲染非常小。

我在这里做错了什么?我读过的所有内容都说初始代码是正确的。

编辑: 显然不清楚这是用于阴影贴图传递,常规传递是用透视渲染的,并且很好。

2 个答案:

答案 0 :(得分:0)

阴影映射是多遍算法。 你正在考虑第一次通过(第1点)。

  1. 将场景窗体光源视图渲染为深度纹理

  2. 从相机视图渲染场景并启用深度纹理投影映射。

    • 然后将当前片段xy +深度转换为光投影坐标,并与深度纹理上存储的深度进行比较

    • 如果两个深度相等(或几乎相等),则应将当前片段视为亮起,否则视为阴影。

  3. 所以对你的代码来说一切都很好,从这个传递到深度纹理存储深度值,然后进入第2点。

    你应该考虑的一件事是你的光线应该覆盖多大的区域(在世界空间中)。通过模型视图上的loadidentity,您将尝试覆盖1个世界单位x 1世界单位区域,仅为您点亮。

    • 考虑我们的球体位于0,0,0,半径为5.0
    • 深度纹理为256,256度。
    • 我们希望将它沿Z投影到球体上。

      glVieport(0,0,256,256); glMatrixMode(GL_PROJECTION); glLoadidentity(); glOrtho(-2.5,2.5,-2.5,2.5,-1000,1000); glMatrixMode(GL_MODELVIEW); glLoadidentity(); //翻转z,我们从obove投射光 glRotate(1,0,0,180);

答案 1 :(得分:0)

我不知道你在哪里设置了光模型视图矩阵。您可以使用以下代码渲染阴影贴图:

double* getOrthoMVPmatrix(vector3 position,vector3 lookat,
                          GLdouble  left,  GLdouble  right,
                          GLdouble  bottom,  GLdouble  top,
                          GLdouble  nearVal,  GLdouble  farVal)
{

 glPushMatrix();

 double projection[16];
 double modelView[16];
 double *matrix = new double [16];

 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 glOrtho(  left, right, bottom, top, nearVal,  farVal) ;
 glMatrixMode(GL_MODELVIEW);
 glEnable(GL_DEPTH_TEST);
 glLoadIdentity();
 gluLookAt(position.x,position.y,position.z,lookat.x,lookat.y,lookat.z,0,1,0);

 glGetDoublev(GL_MODELVIEW_MATRIX, modelView);
 glGetDoublev(GL_PROJECTION_MATRIX, projection);


 glPopMatrix();

 matrix  = projection*modelView;

 return matrix ;

}


void renderShadowMap(void)
{

 //"Bind your depth framebuffer"

 glViewport(0,0,"Your SM SIZE","Your SM SIZE");
 glEnable(GL_CULL_FACE);
 glCullFace(GL_FRONT);
 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

 double *MVP =  getOrthoMVPmatrix( "your light position","your light position" + "your light direction",
                          -"left","right",
                           "bottom","top",
                           "near","far"
                          ) ;


 //"call glUseProgram to bind your shader"

 // set the uniform MVP we made "

 //"Draw your scene "

 glViewport(0,0,"screen width","screen height");


}



你需要为double [16]数组创建一个乘法运算符。在我的情况下,我做了一个矩阵类,但按照你的方式做。 不要忘记在绘制真实场景之前调用glCullFace(GL_BACK)并在之后免费获得MVP。