c++ - 顶点在 Frustum 外的 OpenGL 透视投影裁剪多边形 = 错误的纹理映射?

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

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

我正在绘制一个由两个简单的多边形组成的 GL_TRIANGLE_STRIP '正方形',并在四边形上应用简单的纹理贴图(纹理仅一次完美地映射到四边形上,没有重复。UV 坐标 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

最佳答案

对我的原始问题的一些研究和评论使我相信观察到的效果是 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;
}

关于c++ - 顶点在 Frustum 外的 OpenGL 透视投影裁剪多边形 = 错误的纹理映射?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44512396/

相关文章:

c++ - 是否可以编写符合标准的随机访问(或至少向前)整数迭代器?

c++ - Cocos2d-x : Convert from CCTime to SEL_SCEDULE error

iphone - iPhone 上的 OpenGL ES 颜色选择

iphone - OpenGL ES 2.0 header 中缺少方法和常量

linux - 如何在Raspbian下设置jackd和guitarix的实时优先级?

embedded - 什么是任务堆栈,它的用途是什么? - uC/OS-II

java - 如何将网络音频流保存到文件(c++/java)

VS2010 中使用 lambda 参数捕获的 C++ 嵌套 lambda 错误?

iphone - 具有透明背景的 OpenGL ES 2.0 GLKit

c - C中的大结构初始化