首页 > 解决方案 > OpenGL 2D 批量渲染:当有多个活动纹理时,纹理一起出现故障

问题描述

在此处输入图像描述 这就是我在一个简单的 for 循环中绘制从黑色纹理切换到浅绿色纹理时发生的情况。它似乎有来自先前绘制的纹理的位。

这是我的渲染器工作原理的简化版本

  1. Init():创建我的 VAO 和属性指针并生成元素缓冲区和索引
  2. Begin():绑定我的顶点缓冲区并映射缓冲区指针
  3. Draw():提交一个可渲染的绘图,它在顶点缓冲区中获得 4 个顶点,每个顶点都有一个位置、颜色、texCoords 和一个纹理槽
  4. End():我删除缓冲区指针,将我的 VAO、IBO 和纹理绑定到它们的活动纹理槽并绘制元素。

我每帧都这样做(初始化除外)。我不明白的是,如果我绘制 PER TEXTURE,只有一个处于活动状态,那么这不会发生。当我有多个活动纹理并且它们被绑定时。

这是我的渲染器

void Renderer2D::Init()
    {
        m_Textures.reserve(32);
        m_VertexBuffer.Create(nullptr, VERTEX_BUFFER_SIZE);

        m_Layout.PushFloat(2); //Position
        m_Layout.PushUChar(4); //Color
        m_Layout.PushFloat(2); //TexCoords
        m_Layout.PushFloat(1); //Texture ID

        //VA is bound and VB is unbound
        m_VertexArray.AddBuffer(m_VertexBuffer, m_Layout);

        unsigned int* indices = new unsigned int[INDEX_COUNT];
        int offset = 0;
        for (int i = 0; i < INDEX_COUNT; i += 6)
        {
            indices[i + 0] = offset + 0;
            indices[i + 1] = offset + 1;
            indices[i + 2] = offset + 2;

            indices[i + 3] = offset + 2;
            indices[i + 4] = offset + 3;
            indices[i + 5] = offset + 0;

            offset += 4;
        }

        m_IndexBuffer.Create(indices, INDEX_COUNT);

        m_VertexArray.Unbind();
    }

    void Renderer2D::Begin()
    {
        m_VertexBuffer.Bind();
        m_Buffer = (VertexData*)m_VertexBuffer.GetBufferPointer();
    }

    void Renderer2D::Draw(Renderable2D& renderable)
    {
        const glm::vec2& position = renderable.GetPosition();
        const glm::vec2& size = renderable.GetSize();
        const Color& color = renderable.GetColor();
        const glm::vec4& texCoords = renderable.GetTextureRect();
        const float tid = AddTexture(renderable.GetTexture());

        DT_CORE_ASSERT(tid != 0, "TID IS EQUAL TO ZERO");
        m_Buffer->position = glm::vec2(position.x, position.y);
        m_Buffer->color = color;
        m_Buffer->texCoord = glm::vec2(texCoords.x, texCoords.y);
        m_Buffer->tid = tid;
        m_Buffer++;

        m_Buffer->position = glm::vec2(position.x + size.x, position.y);
        m_Buffer->color = color;
        m_Buffer->texCoord = glm::vec2(texCoords.z, texCoords.y);
        m_Buffer->tid = tid;
        m_Buffer++;

        m_Buffer->position = glm::vec2(position.x + size.x, position.y + size.y);
        m_Buffer->color = color;
        m_Buffer->texCoord = glm::vec2(texCoords.z, texCoords.w);
        m_Buffer->tid = tid;
        m_Buffer++;

        m_Buffer->position = glm::vec2(position.x, position.y + size.y);
        m_Buffer->color = color;
        m_Buffer->texCoord = glm::vec2(texCoords.x, texCoords.w);
        m_Buffer->tid = tid;
        m_Buffer++;

        m_IndexCount += 6;
    }

    void Renderer2D::End()
    {
        Flush();
    }

    const float Renderer2D::AddTexture(const Texture2D* texture)
    {
        for (int i = 0; i < m_Textures.size(); i++) {
            if (texture == m_Textures[i]) // Compares memory addresses
                return i + 1; // Returns the texture id plus one since 0 is null texture id
        }

        // If the texture count is already at or greater than max textures
        if (m_Textures.size() >= MAX_TEXTURES)
        {
            End();
            Begin();
        }

        m_Textures.push_back((Texture2D*)texture);
        return m_Textures.size();
    }

    void Renderer2D::Flush()
    {
        m_VertexBuffer.DeleteBufferPointer();

        m_VertexArray.Bind();
        m_IndexBuffer.Bind();
        for (int i = 0; i < m_Textures.size(); i++) {
            glActiveTexture(GL_TEXTURE0 + i);
            m_Textures[i]->Bind();
        }

        glDrawElements(GL_TRIANGLES, m_IndexCount, GL_UNSIGNED_INT, NULL);

        m_IndexBuffer.Unbind();
        m_VertexArray.Unbind();

        m_IndexCount = 0;
        m_Textures.clear();
    }



这是我的片段着色器

#version 330 core
out vec4 FragColor;

in vec4 ourColor;
in vec2 ourTexCoord;
in float ourTid;

uniform sampler2D textures[32];

void main()
{
    vec4 texColor = ourColor;
    if(ourTid > 0.0) 
    {
        int tid = int(ourTid - 0.5);
        texColor = ourColor * texture(textures[tid], ourTexCoord);
    }
    FragColor = texColor;
} 

感谢您的帮助,如果您需要查看更多代码,请告诉我

标签: openglgraphicsglsl

解决方案


我不知道你是否需要这个,但记录在案

您的片段代码中有逻辑问题

让我们考虑一下,如果您的“ourTid”大于 0 让我们以 1.0f 为例,您减去 0.5f ,我们将其转换为 int(0.5) 现在肯定是 0 假设我们需要纹理编号 2 并执行相同的过程 2- 0.5 = 1.5 "cast it to int" = 1 肯定你每次都会有以前的纹理现在解决方案很容易你应该添加 0.5 而不是减去它以确保避免数字插值并且你得到正确的纹理。


推荐阅读