OpenGL - 用纹理绘制正方形的最简单方法

Posted

技术标签:

【中文标题】OpenGL - 用纹理绘制正方形的最简单方法【英文标题】:OpenGL - Easiest way to draw a square with a texture 【发布时间】:2015-07-10 18:28:16 【问题描述】:

通常我用这样的纹理画一个正方形:

创建一个具有 4 个坐标(正方形的 A、B、C、D)的 VBO 创建一个包含 4 个索引(A、C、D 和 B、C、D)的 EBO,表明我想从 2 个三角形中绘制一个正方形。 使用纹理绘制此元素

没有 EBO 阵列就没有最简单的方法吗?

因为用起来不是很方便……如果我想这样使用:

VAO = [-0.8f, 0.5f, 0.0f, ...]

EBO = [0, 1, 3, 1, 2, 3, ...]

然后我需要从我的 VAO 中删除一个正方形...然后我还需要从我的 EBO 数组中删除索引并重新排列它。 有没有更好的方法来做到这一点?

【问题讨论】:

您没有指定目标的 GL 版本。使用可编程流水线,您可以做到这一点attribute-less,因此可能会完全跳过 VBO 和 EBO。不过,您仍然需要将顶点数据获取到着色器(除非它是常量),但现在还有其他可能性。 【参考方案1】:

如果你真的只想画一个有纹理的正方形,你应该考虑新建一个空的VAO,然后调用glDrawArrays(GL_TRIANGLE_STRIP, 0,3);

顶点着色器如下所示:

out vec2 mapping;

void main()

    float size = 1.0f;

    vec2 offset;
    switch(gl_VertexID)
    
    case 0:
        //Bottom-left
        mapping = vec2(0.0f, 0.0f);
        offset = vec2(-size, -size);
        break;
    case 1:
        //Top-left
        mapping = vec2(0.0f, 1.0f);
        offset = vec2(-size, size);
        break;
    case 2:
        //Bottom-right
        mapping = vec2(1.0, 0.0);
        offset = vec2(size, -size);
        break;
    case 3:
        //Top-right
        mapping = vec2(1.0, 1.0);
        offset = vec2(size, size);
        break;
    

     gl_Position = vec4(offset, 0.0f, 1.0f);

映射变量告诉片段着色器纹理坐标是什么。

【讨论】:

这是我渲染全屏四边形的首选方式。但我想补充一点,如果您想绘制大量四边形,这可能会成为一个巨大的性能问题。顶点着色器为每个顶点做了很多工作,它甚至可能包括分支,这取决于编译器的聪明程度。不过,当然可以满足问题的“简单”部分。【参考方案2】:

没有 EBO 数组就没有最简单的方法吗?

复制您的顶点并使用glDrawArrays()

【讨论】:

但这会给顶点带来 50% 的开销,对吧? 这是权衡,是的。【参考方案3】:

您可以使用 DrawArray 绘制索引。

类似这样的:

Vertex2D* vertex = (Vertex2D*) vbo->lock();
        vertex[0].x = x[0]; vertex[0].y = y[0]; vertex[0].u = u[0]; vertex[0].v = v[0]; vertex[0].color = color;
        vertex[1].x = x[0]; vertex[1].y = y[1]; vertex[1].u = u[0]; vertex[1].v = v[1]; vertex[1].color = color;
        vertex[2].x = x[1]; vertex[2].y = y[1]; vertex[2].u = u[1]; vertex[2].v = v[1]; vertex[2].color = color;
        vertex[3].x = x[1]; vertex[3].y = y[0]; vertex[3].u = u[1]; vertex[3].v = v[0]; vertex[3].color = color;
vbo->unlock();

shader->bind();
vbo->bind();
vao->bind();
tex->bind();
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
tex->unbind();
vao->unbind();
vbo->unbind();
shader->unbind();

【讨论】:

以上是关于OpenGL - 用纹理绘制正方形的最简单方法的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL ES 1.1 clearColor 绘图

OpenGL - 004通过简单案例介绍绘制渲染流程

OpenGL 绘制纹理

在 OpenGL 中绘制 3d 图形的最有效方法是啥?

iOS OpenGL ES简单绘制纹理

纹理不适合正方形 - OpenGL