【问题标题】:3D Orthographic Projection3D 正交投影
【发布时间】:2015-03-07 05:07:19
【问题描述】:

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

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 一起保存,但就像我说的,它的渲染非常小。

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

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

【问题讨论】:

    标签: opengl orthographic


    【解决方案1】:

    阴影映射是多通道算法。 您指的是第一遍(第 1 点)。

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

    2. 在启用深度纹理投影映射的情况下从相机视图渲染场景。

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

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

    因此,您的代码一切正常,将此次传递的深度值存储到深度纹理并继续执行第 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,我们从上方投射光 glRotate(1,0,0,180);

    【讨论】:

    • 我知道阴影映射是如何工作的,这是光源投影的代码。我想问题中没有明确说明,已更新。另外,你错了,这段代码是正确的,因为无论通过,场景仍然会在错误的投影上渲染,所以从技术上讲,这是独立于阴影贴图的。
    • 更新了最后的注释:)
    • 我不知道您的最终结果是否是正交的,因为我从未研究过它,但在渲染中,几何图形被转换为相机空间。因为正交投影不使用变换,我应该从模型视图中省略相机平移吗?
    • Ortho 将根据您的深度纹理缩放 -1 +1 平方,这没关系。但是您需要缩放模型视图矩阵以使您的世界适合此投影。如果你不这样做,你的纹理将只包含 -1 +1 正方形。
    【解决方案2】:

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

    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");
    
    
    }
    



    您需要为双 [16] 数组创建一个乘法运算符。就我而言,我做了一个矩阵类,但按照你的方式去做。 不要忘记在绘制真实场景之前调用 glCullFace(GL_BACK) 并在之后调用 MVP。

    【讨论】:

    • 问题不在于我如何渲染阴影贴图,而在于我如何进行正射投影。
    猜你喜欢
    • 2011-11-25
    • 2014-06-09
    • 2013-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多