0
votes

enter image description here This is what happens when I draw switching from the black texture to the lime green one in a simple for loop. It seems to have bits from the previously drawn texture.

Here's a simplified version of how my renderer works

  1. Init(): Create my VAO and attrib pointers and generate element buffer and indicies
  2. Begin(): Bind my vertex buffer and map the buffer pointer
  3. Draw(): Submit a renderable to draw which gets 4 vertecies in the vertex buffer each get a position, color, texCoords, and a Texture Slot
  4. End(): I delete the buffer pointer, bind my VAO, IBO, and textures to their active texture slots and draw the elements.

I do this every frame (except init). What I don't understand is if I draw PER TEXTURE, only having one active then this doesn't happen. It's when I have multiple active textures and they are bound.

Here's my renderer

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



Here's my fragment shader

#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;
} 

I appreciate any help, let me know if you need to see more code

1
An array of textures can only be indexed with a dynamically uniform integral expression, otherwise the results is undefined. An input variable is not dynamically uniform - of course. I recommend to use a single GL_TEXTURE_2D_ARRAY rather than an array of GL_TEXTURE_2D. Read about Core Language (GLSL) - Dynamically uniform expression - Rabbid76

1 Answers

0
votes

i don't know if you need this anymore but for the the record

you have a logical problem in your fragment code

let's think if your "ourTid" bigger than 0 let's take 1.0f for example you subtract 0.5f , we cast it to int(0.5) it's 0 for sure now let's say that we need the texture number 2 and do the same process 2-0.5 = 1.5 "cast it to int" = 1 definitely you will have the previous texture every time now the solution is easy you should add 0.5 instead of subtract it to be sure that the numbers interpolation is avoided and you got the correct texture.