Color Cookie
Color Cookie

Reputation: 9

OpenGL Showing Blank White Screen

I'm trying to abstract openGL function into their own classes. VertexBuffer and IndexBuffer Class Worked. But after trying to abstract VertexArray class. It isn't working, and I can't seem to workout what's the problem. I'm providing 3 files main Application file, Buffer class file and VertexArray Class file. I've left out some functions and one file, which i think isn't necessary

I've tried debugging with VS-2019. I created this project in VS-2017 but upgraded. everything till glEnableVertexAttribArray works and I've checked the values of _Elem and they seem correct. but I'm unable to see the triangle. But when I try to do it in raw functions, it works

Main.cpp:

#include "Buffer.h"
#include "VertexArray.h"

int main(void)
{
    GLFWwindow* window;

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    if (glewInit() != GLEW_OK)
    {
        glfwTerminate();
        return -1;
    }

    glEnable(GL_DEBUG_CALLBACK_FUNCTION);
    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
    glDebugMessageCallback(GLErrLogger, nullptr);

    {
        float pos[] = {
             0.0f,  0.5f,
             0.5f, -0.5f,
            -0.5f, -0.5f
        };

        unsigned int indices[] = {
            0, 1, 2
        };

        // Some Shader stuff

        VertexBuffer vb(_BufferDataParams(pos));
        BufferLayout bLayout;
        bLayout.Push<GL_FLOAT, sizeof(GLfloat)>(2);
        //RefID va;
        //glGenVertexArrays(1, &va);
        //vb.BindSelf();
        //glBindVertexArray(va);
        VertexArray va(vb, bLayout);
        //glEnableVertexAttribArray(0);
        //glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);

        IndexBuffer ib(_BufferDataParams(indices));
        glUseProgram(shader);

        GLint location = glGetUniformLocation(shader, "u_Color");
        if (location != -1)
                    glUniform4f(location, 0.2f, 0.3f, 0.8f, 1.0f);
        else
                    std::cerr << "u_Color doesn't exists.\n";

        /* Loop until the user closes the window */
        while (!glfwWindowShouldClose(window))
        {
            /* Render here */
            glClear(GL_COLOR_BUFFER_BIT);

            glDrawElements(GL_TRIANGLES, ib.GetCount(), ib.GetDataType(), nullptr);

            /* Swap front and back buffers */
            glfwSwapBuffers(window);

            /* Poll for and process events */
            glfwPollEvents();
        }
        glDeleteProgram(shader);
    }
    glfwTerminate();
    return 0;
}

Buffer.h:

#pragma once

#define _LenArr(_Arr) std::extent<decltype(_Arr)>::value
#define _BufferDataParams(_Arr) _Arr, sizeof(_Arr), _LenArr(_Arr)

using GLTYPE = unsigned int;
using Countable = unsigned int;
using LayoutElem = struct {
    GLTYPE Type;
    unsigned int Count;
    size_t ElemSize;
    GLTYPE Normalized;
};

struct BufferLayout
{
private:
    std::vector<LayoutElem> Layout;
    Countable Stride;
public:
    BufferLayout() : Stride(0)  {}

    template<GLTYPE _GL_Ty, size_t _ElemSize>
    void Push(Countable Count, GLTYPE normalized = GL_FALSE)
    {
        Layout.push_back({ _GL_Ty, Count, _ElemSize, normalized });
        Stride += Count * _ElemSize;
    }

    inline const std::vector<LayoutElem>& GetElements() const { return Layout; }
    inline Countable GetStride() const { return Stride; }
};

template <unsigned int TYPE, GLTYPE _DataType>
class Buffer
{
private:
    unsigned int mRefID;
    size_t m_Count;
    GLTYPE mDataType;
public:
    Buffer(const void* data, size_t size, size_t count,
        GLTYPE dataType = _DataType, unsigned int usage = GL_STATIC_DRAW)
        : mRefID(0), m_Count(count), mDataType(dataType)
    {
        glGenBuffers(1, &mRefID);
        glBindBuffer(TYPE, mRefID);
        glBufferData(TYPE, size, data, usage);
    }

    inline unsigned int GetRefID() const { return mRefID; }
    inline size_t GetCount() const { return m_Count; }
    inline GLTYPE GetDataType() const { return mDataType; }
    void SetData(const void* data, size_t size, size_t count,
        GLTYPE dataType = _DataType, unsigned int usage = GL_STATIC_DRAW)
    {
        glBindBuffer(TYPE, mRefID);
        glBufferData(TYPE, size, data, usage);
        m_Count = count;
        mDataType = dataType;
    }

    inline static void Bind(const Buffer& buf)
        { glBindBuffer(TYPE, buf.GetRefID()); }

    void BindSelf() const { Bind(*this); }
    inline static void Unbind() { glBindBuffer(TYPE, 0); }

    void Delete() const { glDeleteBuffers(1, &mRefID); }
    ~Buffer() { glDeleteBuffers(1, &mRefID);}
};

using VertexBuffer  = Buffer<GL_ARRAY_BUFFER, GL_FLOAT>;
using IndexBuffer   = Buffer<GL_ELEMENT_ARRAY_BUFFER, GL_UNSIGNED_INT>;

VertexArray.cpp:

#include "stdafx.h"
#include "VertexArray.h"

VertexArray::VertexArray()
    : mRefID(0)
{ glGenVertexArrays(1, &mRefID);}

void VertexArray::Bind(const VertexArray& vArr)
{ glBindVertexArray(vArr.GetRefID()); }

void VertexArray::BindSelf() const { Bind(*this); }

void VertexArray::AddBuffer(const VertexBuffer& vBuf, const BufferLayout& bufLayout)
{
    BindSelf();
    vBuf.BindSelf();

    const auto& Layout = bufLayout.GetElements();
    Countable i = 0;
    size_t offset = 0;
    for (LayoutElem _Elem : Layout)
    {
        std::cout << _Elem.Count << " " << _Elem.Type << " " <<
            _Elem.Normalized << " " << bufLayout.GetStride();
        glEnableVertexAttribArray(i);
        glVertexAttribPointer(i, _Elem.Count, _Elem.Type, _Elem.Normalized,
            bufLayout.GetStride(), (const void*)&offset);
        offset += _Elem.Count * _Elem.ElemSize;
        i++;
    }
}

VertexArray::VertexArray(const VertexBuffer& vBuf, const BufferLayout& bufLayout)
    : mRefID(0)
{
    glGenVertexArrays(1, &mRefID);
    AddBuffer(vBuf, bufLayout);
}

void VertexArray::Unbind() { glBindVertexArray(0); }

inline void VertexArray::Delete() const { glDeleteVertexArrays(1, &mRefID); }

VertexArray::~VertexArray() { Delete(); }

I expect to see a triangle with blueish color. And for the abstraction to work.

Upvotes: 0

Views: 701

Answers (1)

Rabbid76
Rabbid76

Reputation: 211258

The issue is the line

glVertexAttribPointer(i, _Elem.Count, _Elem.Type, _Elem.Normalized,
       bufLayout.GetStride(), (const void*)&offset);

Since a named buffer object is bound to the target GL_ARRAY_BUFFER, the last parameter of glVertexAttribPointer treated as a byte offset into the buffer.

You try to pass 0 to the last parameter and to cast it to void*, but the value of

(const void*)&offset

is the address of the local variable offset. Just do (const void*)offset:

glVertexAttribPointer(i, _Elem.Count, _Elem.Type, GL_FALSE, 
    bufLayout.GetStride(), (const void*)offset);

Further note that glewExperimental = GL_TRUE seems to miss in your code. See the GLEW documentation:

glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
    glfwTerminate();
    return -1;
}

Upvotes: 1

Related Questions