【问题标题】:C++ / OpenGL 3.3+: No vertices are being renderedC++ / OpenGL 3.3+:没有顶点被渲染
【发布时间】:2017-05-14 12:15:48
【问题描述】:

我猜这是同类型的第 100 万个问题。我正在使用带有 C++ 的 OpenGL 3.3 Core Profile 并尝试渲染一个三角形。

我已经阅读了以下两页,包括键入和复制粘贴正在讨论的代码。下面我发布了重要的位。我已经渲染了一个三角形,但显然我改变了一些小细节并把它搞砸了。 GLFW 和 GLEW 正在初始化并使用 glClearColor 清除工作正常。

正在使用的框架:用于窗口化、GLEW 和 GLM 的 GLFW。

问题:我的代码有什么错误,为什么什么都没有呈现?

期望:应该可以看到一个白色三角形。

结果:没有渲染任何内容。窗口充满了 glClearColor

游戏.cpp

const float vertex_data[9] = {
    -1.0f, -1.0f, 0.0f,
     1.0f, -1.0f, 0.0f,
     0.0f,  1.0f, 0.0f,
};

void Game::init()
{
    shader = ShaderProgram();
    shader.attachShader(readTextFromFile("data/shaders/main.vs"), GL_VERTEX_SHADER);
    shader.attachShader(readTextFromFile("data/shaders/main.fs"), GL_FRAGMENT_SHADER);
    shader.linkProgram();

    mesh = Mesh(vertex_data);
}

void Game::render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    shader.bind();
    {
        mesh.render();
    }
    shader.unbind();
}

Mesh.cpp

uint32_t vao;
uint32_t vertex_buffer;

Mesh::Mesh(const float vertex_data[])
{
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    glGenBuffers(1, &vertex_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
}

void Mesh::render()
{
    glBindVertexArray(vao);
    glEnableVertexAttribArray(0);
    {
        // Is this actually necessary for every draw-call?
        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); 
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }
    glDisableVertexAttribArray(0);
}

ShaderProgram.cpp

uint32 id = 0;
bool linked = false;

uint32 vertex_shader = 0;
uint32 fragment_shader = 0;

ShaderProgram::~ShaderProgram()
{
    unbind();

    if (vertex_shader > 0)
    {
        glDetachShader(id, vertex_shader);
        glDeleteShader(vertex_shader);
    }

    if (fragment_shader > 0)
    {
        glDetachShader(id, fragment_shader);
        glDeleteShader(fragment_shader);
    }

    if (id > 0 && linked)
    {
        glDeleteProgram(id);
    }
}

void ShaderProgram::attachShader(std::string source, int32 type)
{
    assert(type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER);
    assert(id == 0);

    const char* code = source.c_str();

    switch (type)
    {
        case GL_VERTEX_SHADER:
            assert(vertex_shader == 0);

            vertex_shader = glCreateShader(GL_VERTEX_SHADER);
            glShaderSource(vertex_shader, 1, &code, NULL);
            glCompileShader(vertex_shader);

            int32 vresult;
            glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &vresult);

            if (vresult != GL_TRUE)
            {
                int32 infolength;
                glGetShaderiv(vertex_shader, GL_INFO_LOG_LENGTH, &infolength);

                GLchar* infolog = new GLchar[infolength + 1];
                glGetShaderInfoLog(vertex_shader, infolength + 1, NULL, infolog);

                std::stringstream ss;
                ss << "Shader compilation failed for Vertex Shader: " << infolog << std::endl;

                std::cout << ss.str() << std::endl;

                throw std::runtime_error(ss.str());
            }
            break;
        case GL_FRAGMENT_SHADER:
            assert(fragment_shader == 0);

            fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
            glShaderSource(fragment_shader, 1, &code, NULL);
            glCompileShader(fragment_shader);

            int32 fresult;
            glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &fresult);

            if (fresult != GL_TRUE)
            {
                int32 infolength;
                glGetShaderiv(fragment_shader, GL_INFO_LOG_LENGTH, &infolength);

                int32 infosize = infolength + 1;
                GLchar* infolog = new GLchar[infosize];
                glGetShaderInfoLog(fragment_shader, infosize, NULL, infolog);

                std::stringstream ss;
                ss << "Shader compilation failed for Fragment Shader: " << infolog << std::endl;

                std::cout << ss.str() << std::endl;

                throw std::runtime_error(ss.str());
            }
            break;
        default:
            throw std::invalid_argument("Unknown Shader-Type specified");
    }
}

void ShaderProgram::linkProgram()
{
    assert(id == 0);
    assert(vertex_shader > 0);
    assert(fragment_shader > 0);

    id = glCreateProgram();

    glAttachShader(id, vertex_shader);
    glAttachShader(id, fragment_shader);

    glLinkProgram(id);

    int32 result;
    glGetProgramiv(id, GL_LINK_STATUS, &result);

    if (result != GL_TRUE)
    {
        int32 infolength;
        glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infolength);

        int32 infosize = infolength + 1;
        GLchar* infolog = new GLchar[infosize];
        glGetProgramInfoLog(id, infosize, NULL, infolog);

        std::stringstream ss;
        ss << "Shader Program Linking failed: " << infolog << std::endl;

        throw std::runtime_error(ss.str());
    }

    linked = true;
}

void ShaderProgram::bind()
{
    assert(id > 0);
    assert(linked);

    glUseProgram(id);
}

void ShaderProgram::unbind()
{
    int32 current;
    glGetIntegerv(GL_CURRENT_PROGRAM, &current);

    if (current == id)
    {
        glUseProgram(0);
    }
}

bool ShaderProgram::isLinked()
{
    return linked;
}

顶点着色器:“main.vs”

#version 330

layout(location = 0) in vec3 VertexPosition;

void main()
{
    gl_Position = vec4(VertexPosition.xyz, 1.0);
}

片段着色器“main.fs”:

#version 330

out vec4 FinalColor;

void main()
{
    FinalColor = vec4(1.0, 1.0, 1.0, 1.0);
}

【问题讨论】:

  • 您使用的是什么窗口框架(例如glfw)?
  • @BenSteffan 添加到主帖。用于窗口化、GLEW 和 GLM 的 GLFW。
  • 我喜欢你提出问题的方式、应该发生的事情以及你使用的一切。更多问题应使用此格式。

标签: c++ opengl glsl shader


【解决方案1】:

这行有错误:

glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);

第二个参数需要数组的大小,但您传递的是指针的大小。要修复它,请使用vertex count * sizeof( float )

【讨论】:

  • 这很快!这是正确的答案。修复此问题会使三角形出现。我会尽快接受你的回答。关于如何自动检索正确大小而不是手动输入 sizeof(float) * (vertexcount * 3) 的任何建议?
  • @j8a2b0e7 您可以将顶点存储到std::vector 以获取数组大小而不是使用C 样式数组,但是您仍然必须乘以sizeof( float )
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多