1
\$\begingroup\$

I have a sprite class that is supposed to make a 2D rectangle based on the location, colour and size of the rectangle. I have created a renderer class that uses this sprite class to create buffers and finally render things on the screen.

Currently, I have 2 sprites.

/**
 * RSprite sprite(x coordinate of the lower left corner of the rectangle,
 *                y coordinate of the lower left corner of the rectangle,
 *                horizontal length of the rectangle,
 *                vertical length of the rectangle,
 *                Vector 4D consisting of 4 floats representing a colour(RGBA)) for the rectangle
 */
RSprite sprite1(0, 0, 4, 4, Vector4D(0.75f, 0.047f, 0.9f, 1.0f)
                         /* ^Normalised form of (193, 12, 232, 255)rgba */);

RSprite sprite2(0.5, 0.5, 0.5, 0.5, Vector4D(0.6f, 0.0f, 1.0f, 1.0f));
                                 /* ^Normalised form of (153, 0, 255, 255)rgba */);

Now I add these sprites to a group, which is just a structure maintaining a vector array of these sprites.

Group * g = new Group();
g->addRenderable(&sprite2).addRenderable(&sprite1);

Finally, I add this group to a layer object I had made earlier.

layer0.addGroup("group1", *g);

Now my problem is the colour specified for sprite1 i.e. (193, 12, 232, 255)rgba is appearing completely white(which is not what I intended it to be). However, the other sprite2 has the colours appearing just fine.

Concludingly, the problem is boiled down to, why is OpenGL not displaying 193, 12, 232, 255rgba incorrectly but at the same time it is correctly displaying 153, 0, 255, 255rgba?

EDIT: Adding code samples. Implementation of the layer class I am using:

RStaticLayer::RStaticLayer(RShaderComponent& shader)
        : m_Renderer(new RGuerrillaRendererComponent()), m_Shader(shader)
    {
        m_Shader.enableShader();
        m_Shader.setUniformMat4("proj_matrix", (const RML::Matrix4) RML::Matrix4::orthographic(0.0f, 16.0f, 0.0f, 9.0f, -1.0f, 1.0f));
        m_Shader.disableShader();
    }

    RStaticLayer::~RStaticLayer()
    {
        delete m_Renderer;
    }

    RLayer & RStaticLayer::addGroup(std::string name, Group & group)
    {
        m_Groups[name] = &group;

        return *this;
    }

    void RStaticLayer::draw()
    {
        m_Shader.enableShader();

        m_Renderer->begin();
        for(auto group = m_Groups.begin(); group != m_Groups.end(); group++)
        {
            for(auto renderable = group->second->renderables.begin(); renderable != group->second->renderables.end(); ++renderable)
            {
                m_Renderer->submit(*renderable);
            }
        }
        m_Renderer->end();
        m_Renderer->flush();

        m_Shader.disableShader();
    }

    void RStaticLayer::removeGroup(std::string name)
    {
        m_Groups.erase(name);
    }

What the m_Renderer.submit(), begin(), end() and flush() do:

void RGuerrillaRendererComponent::begin()
    {
        GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_VBO));
        GLCall(m_Buffer = (VertexData *) glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
        m_IndexCount = 0;
    }

    void RGuerrillaRendererComponent::submit(const RRenderableObject * renderable)
    {
        const RML::Vector3D & position = renderable->getPosition();
        const RML::Vector2D & size = renderable->getSize();
        const RML::Vector4D & color = renderable->getColor();

        m_Buffer->vertex = position;
        m_Buffer->color = color;
        m_Buffer++;

        m_Buffer->vertex = RML::Vector3D(position.x, position.y + size.y, position.z);
        m_Buffer->color = color;
        m_Buffer++;

        m_Buffer->vertex = RML::Vector3D(position.x + size.x, position.y + size.y, position.z);
        m_Buffer->color = color;
        m_Buffer++;

        m_Buffer->vertex = RML::Vector3D(position.x + size.x, position.y, position.z);
        m_Buffer->color = color;
        m_Buffer++;

        m_IndexCount += 6;
    }

    void RGuerrillaRendererComponent::end()
    {
        GLCall(glUnmapBuffer(GL_ARRAY_BUFFER));
        GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_VBO));
    }

    void RGuerrillaRendererComponent::flush()
    {
        GLCall(glBindVertexArray(m_VAO));
        m_IBO->bindIndexBuffer();

        GLCall(glDrawElements(GL_TRIANGLES, m_IndexCount, GL_UNSIGNED_SHORT, NULL));

        m_IBO->unbindIndexBuffer();
        GLCall(glBindVertexArray(0));

        m_IndexCount = 0;
    }

What my shader enable/disable functions look like:

void RShaderComponent::enableShader() const
    {
        GLCall(glUseProgram(m_ShaderID)); // m_ShaderID is acquired successfuly. It has been used in another project too.
    }

    void RShaderComponent::disableShader() const
    {
        GLCall(glUseProgram(0));
    }

Pardon the GLCall() macro. It's just a pre-v4 error checking macro.

\$\endgroup\$
  • \$\begingroup\$ Also, I tried changing the order in which I add the sprites. No dice. Changing the colour for sprite1 to 0, 0, 255, 255rgba displayed the blue colour well. There is something going on when the red and blue channels are mixed. \$\endgroup\$ – Twarit Waikar Jun 27 '18 at 14:11
  • \$\begingroup\$ Please can you add a picture explaining your problem. As they say, a picture paints a thousand words \$\endgroup\$ – user116458 Jun 27 '18 at 14:53
  • \$\begingroup\$ Are your sprite1 and sprite2 going out of scope? You appear to be storing pointers to them in your vector. If you're doing this in a function, and they are declared locally, you could be trying to draw with garbage data once the function in which they're created exits. A more complete code sample would help in diagnosing this. This may sound silly, but swap the order in which sprite1 and sprite2 are declared in your source. (Not just the order in which they're added to the group.) \$\endgroup\$ – 3Dave Jun 27 '18 at 14:57
  • \$\begingroup\$ When I change the order... image \$\endgroup\$ – Twarit Waikar Jun 27 '18 at 15:54
  • \$\begingroup\$ Changing the colour to blue surprisingly applies the colour correctly. imgur.com/a/6kAZyzF \$\endgroup\$ – Twarit Waikar Jun 27 '18 at 15:59
1
\$\begingroup\$

I'm not sure the code samples you've shown have a logic error, but I have a couple observations:

1) it's possible you meant to use Vector4f instead of Vector4D based on the comment // Vector 4D consisting of 4 floats representing a colour(RGBA), and you're actually passing in 2 doubles instead of 4 floats as the parameters. This wouldn't result in a white output though.

2) Is some part of your code passing in the 0-255 byte values instead of floats? I noticed that in your screenshot even the "just fine" (0.6, 0, 1.0) color looks to be completely cyan (0, 1.0, 1.0).

3) related to the above, what is the pixel format for your framebuffer? It looks like some of your channels are mixed up, and possibly a mismatch in the format and bit depth could be causing your issues.

\$\endgroup\$
  • \$\begingroup\$ I am not sure what you meant by "you're actually passing in 2 doubles instead of 4 floats as the parameters". I have a Vector4D class that has 4 floats as its 4D components. How could I have passed 2 doubles instead? Yes, the code is never passing in 0-255 values. But I guess you have pinpointed the problem with that observation. My red and blue channels aren't mixing well. EDIT: I just tested pure red, blue and purple. These colours seem to be rendered correctly, except for the fact that the purple is looking more on the pinkish side. \$\endgroup\$ – Twarit Waikar Jun 27 '18 at 17:56
  • \$\begingroup\$ My vertex buffer has a Vector3D and a Vector4D containing the vertex position and the color \$\endgroup\$ – Twarit Waikar Jun 27 '18 at 17:58
  • \$\begingroup\$ I just found the mistake! You were right, there was a mismatch in the format. \$\endgroup\$ – Twarit Waikar Jun 27 '18 at 18:01
0
\$\begingroup\$

Are you using the correct blending function? For simple 2D games, it's usually the normal blending function:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
\$\endgroup\$
  • \$\begingroup\$ I haven't set any blending function yet. But this seems to be a thing to keep in mind for the future. Thanks for the response but I was having a frame buffer format mismatch. Posted the answer here. \$\endgroup\$ – Twarit Waikar Jun 27 '18 at 18:10
0
\$\begingroup\$

The frame buffer format is not matching the attribute pointer format that the renderer is setting. I had this in my code:

glVertexAttribPointer(SHADER_COLOR_LOCATION, 4, GL_UNSIGNED_INT, GL_FALSE, VERTEX_SIZE, (const GLvoid *) (offsetof(VertexData, VertexData::color)));

Notice the GL_UNSIGNED_INT that I was passing in. Mistook it to be an index buffer for a second I guess. However, I fixed it by replacing it with the correct data type that I was using for my colour buffer i.e. float.

glVertexAttribPointer(SHADER_COLOR_LOCATION, 4, GL_FLOAT, GL_FALSE, VERTEX_SIZE, (const GLvoid *) (offsetof(VertexData, VertexData::color))));
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.