OpenGL 显示空白屏幕

Posted

技术标签:

【中文标题】OpenGL 显示空白屏幕【英文标题】:OpenGL Showing Blank White Screen 【发布时间】:2019-07-07 15:46:22 【问题描述】:

我正在尝试将 openGL 函数抽象到他们自己的类中。 VertexBuffer 和 IndexBuffer 类工作。但是在尝试抽象 VertexArray 类之后。它不起作用,我似乎无法锻炼出什么问题。我提供了 3 个文件主应用程序文件、缓冲区类文件和 VertexArray 类文件。我遗漏了一些函数和一个文件,我认为这不是必需的

我已尝试使用 VS-2019 进行调试。我在 VS-2017 中创建了这个项目,但升级了。 glEnableVertexAttribArray 之前的一切都有效,我检查了 _Elem 的值,它们看起来是正确的。但我看不到三角形。但是当我尝试在原始函数中执行此操作时,它可以工作

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;

缓冲区.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(); 

我希望看到一个蓝色的三角形。并让抽象工作。

【问题讨论】:

【参考方案1】:

问题是线

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

由于命名缓冲区对象绑定到目标GL_ARRAY_BUFFERglVertexAttribPointer 的最后一个参数被视为缓冲区的字节偏移量。

您尝试将 0 传递给最后一个参数并将其强制转换为 void*,但值

(const void*)&offset

是局部变量offset的地址。就做(const void*)offset:

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

进一步注意glewExperimental = GL_TRUE 似乎在您的代码中丢失。见GLEW documentation:

glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)

    glfwTerminate();
    return -1;

【讨论】:

以上是关于OpenGL 显示空白屏幕的主要内容,如果未能解决你的问题,请参考以下文章

opengl 显示形状和绘制文本

具有独特着色器的 OpenGL 多次绘制调用会产生空白屏幕

SDL 3d OpenGL:立方体上的纹理产生空白屏幕

OpenGL程序没有显示三角形

VC++ 中是不是有某种空白的 openGL 和 freeglut 项目?

用 D 语言用 OpenGL 3 渲染一个简单的矩形