OpenGL透视投影剪切多边形与顶点外部的Frustum =错误的纹理映射?

时间:2017-06-13 04:28:11

标签: c++ opengl-es embedded glm-math

我看到一个问题,即如果所有顶点都保留在透视投影中的屏幕上,我可以正确地绘制纹理多边形,但是如果我将四边形缩放得足够大,使得一个或多个顶点落在“观察体积太远”之后,那么生成的OpenGL绘图不正确(参见截图)。纹理映射变得歪斜,看起来好像屏幕外顶点“移动”并变得扭曲。我在GLES 3.0兼容驱动程序上使用GLES 2.0代码(详情见底部)。我现在将更详细地解释我的测试 -

我正在绘制一个由两个简单多边形组成的GL_TRIANGLE_STRIP'正方形',并在四边形上应用简单的纹理贴图(纹理完美地映射到四边形上一次,没有重复。紫外坐标0-> 1映射为你期待。

单独地,我使用GLM函数为矩阵变换提供帮助,然后使用glm :: PerspectiveFov()来设置查看音量(视锥体)。结果是一个相机略微向下看到四边形,形成一个“地面”状的表面,上面有一个格子图案纹理。

correctly drawn view of quad screenshot

从这里开始,如果我进一步增加四边形上的比例变换因子,或者旋转相机使得屏幕外的顶点顶点从观察区域“向后”,我突然看到极端奇怪的行为,就像纹理一样映射更改,或者多边形的一个顶点移动不正确。见这里:

polygon texture mapping becomes wrong

对于相机旋转我使用glm :: lookAt() - 有效地移动'眼睛'位置,同时将目标保持在场景中的0,0(多边形的中心)。

另请注意,当我越过此阈值时,我看到连接所有顶点的红色调试线突然将其方向从它应该的位置移开。

有谁知道这个问题是如何产生的?有没有办法解决它所以我可以绘制一个巨大的四边形,并在屏幕上有顶点没有这些问题/工件?感谢!!!

GPU信息:

GL供应商:Vivante Corporation

GL渲染器:Vivante GC2000

GL版:OpenGL ES 3.0 V5.0.11.p8.41671

GLSL版本:OpenGL ES GLSL ES 3.00

1 个答案:

答案 0 :(得分:0)

对我原始问题的一些研究和评论使我相信观察到的效果是Vivante GPU GC2000上OpenGL驱动程序实现中的错误的结果。显然这种错误在嵌入式GPU硬件驱动程序中很常见 - 这种ES实现的源代码永远不可用的事实加剧了这个问题。

为了通过解决方法解决这个问题,我能够获取原始正方形的尺寸,而是创建一个纹理正方形的网格阵列,以便所有多边形最终都足够小以适应“#”。足够靠近观察区域(或者完全修剪,避免虫子行为)。 C ++中的代码:

// measurements we will add as we move along the grid
float tile_size = 1.0 / num_grid_subdivisions; // square width 1
float tile_uv_dist = 1.0 / num_grid_subdivisions; // assume 0->1 texture mapping
XY curr_bl = XY(-0.5, -0.5); // quad from -0.5 to 0.5 in x and y (1x1)
float cu = 0; //current texture coordinates in x dimension
float cv = 0; //current texture coordinates in y dimension
for (int row = 0; row < num_grid_subdivisions; ++row)
{
        for (int row_item = 0; row_item < num_grid_subdivisions; ++row_item)
        {
            // GL_TRIANGLES to keep simple, but could use STRIP later
            VertXYUV bl(curr_bl, cu, cv); // bottomleft
            // if we know bottomleft, we know the rest of the points of the square
            VertXYUV tl(XY(curr_bl.x, curr_bl.y + tile_size), cu, cv + tile_uv_dist);
            VertXYUV br(XY(curr_bl.x + tile_size, curr_bl.y), cu+ tile_uv_dist, cv );
            VertXYUV tr(XY(curr_bl.x + tile_size, curr_bl.y + tile_size),
            cu + tile_uv_dist, cv + tile_uv_dist);
            // our square tile is two triangle polygons
            AddVert(bl); AddVert(tl); AddVert(br); // triangle 1
            AddVert(br); AddVert(tl); AddVert(tr); // triangle 2

            // current info should always be tracking 'bl' of current tile
            // increment row item, moving across to the right (+x)
            cu += tile_uv_dist;
            curr_bl.x += tile_size;
        }

        // current info should always be tracking 'bl' of current tile
        // incrementing row, moving up (+y)
        cv += tile_uv_dist;
        cu = 0; // reset x space texture coordinate back to left side (0)
        curr_bl.y += tile_size;
        curr_bl.x = grid_bl.x;
}