OpenGL Mesh不会绘制

时间:2017-03-26 10:35:13

标签: c++ opengl game-engine renderer

我必须忽略一些非常简单的事情,尽管我不确定它是什么。这段代码可以与我之前编写的其他变体相媲美。但由于某种原因,我无法在屏幕上呈现任何内容。我甚至将代码简化为“hello triangle”,但仍无法显示任何内容。

我想知道是否有人能够查看我的代码并提供任何有关其失败原因的见解。我非常感谢提供任何帮助。

三角形状数据的定义

ShapeData ShapeFactory::MakeTriangle() {

    ShapeData result;

    Vertex t1Verts[] = {
        Vector3(-1.0f,-1.0f, 0.0f),         //0
        Vector3(1.0f,0.0f,0.0f),            //colour
        Vector3(+0.0f, +0.0f, +1.0f),       //normal
        Vector2(0.0f,0.0f),                 //uvCoord
        Vector3(0.0f,1.0f, 0.0f),           //1
        Vector3(0.0f,1.0f,0.0f),            //colour
        Vector3(+0.0f, +0.0f, +1.0f),       //normal
        Vector2(0.0f,0.0f),                 //uvCoord
        Vector3(1.0f, -1.0f, 0),            //2
        Vector3(0.0f,0.0f,1.0f),            //colour
        Vector3(+0.0f, +0.0f, +1.0f),       //normal
        Vector2(0.0f,0.0f)                  //uvCoord
    };

    GLushort  iArr[]{ 0,1,2 };

    result.numVertices = GET_ARRAY_SIZE(t1Verts);
    result.numIndices = GET_ARRAY_SIZE(iArr);

    result.vertices = new Vertex[result.numVertices];
    result.indices = new GLushort[result.numIndices];
    memcpy(result.vertices, t1Verts, sizeof(t1Verts));
    memcpy(result.indices, iArr, sizeof(iArr));

    return result;
}

将形状数据复制到网格对象中并加载到OpenGL

void Mesh::Load(const ShapeData data)
{
    m_shapeData = data;
    m_drawCount = data.numIndices;
    BufferGeometry();
}

void Mesh::BufferGeometry()
{
    glGenVertexArrays(1, &m_vertexBufferId); // Create a VAO, and assign it's Id
    glBindVertexArray(m_vertexBufferId); //Bind the newly created VAO

    glGenBuffers(BUFFER_COUNT, m_arrayBuffers); //Create Buffers

    //Bind the vertex buffer Id and create buffers within OpenGL
    glBindBuffer(GL_ARRAY_BUFFER, m_arrayBuffers[VERTEX_BUFFER]);
    glBufferData(GL_ARRAY_BUFFER, m_shapeData.GetVertexBufferSize(), &m_shapeData.vertices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);   //Attrib pointer for Vertex Position
    glEnableVertexAttribArray(1);   //Attrib pointer for Vertex Colour
    glEnableVertexAttribArray(2);   //Attrib pointer for Vertex Normal
    glEnableVertexAttribArray(3);   //Attrib pointer for Vertex Texture Coord

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, 0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, (char*)(sizeof(float) * 3));
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, (char*)(sizeof(float) * 6));
    glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, (char*)(sizeof(float) * 9));

    //Bind the index buffer Id and create buffers within OpenGL
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_arrayBuffers[VERTEX_BUFFER]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_shapeData.GetIndexBufferSize(), &m_shapeData.indices, GL_STATIC_DRAW);

    glBindVertexArray(0); //Unbind VAO once we're done.
}

使用的常数

static const GLuint NUM_FLOAT_PER_VERT = 11;
static const GLuint VERTEX_BYTE_SIZE = NUM_FLOAT_PER_VERT * sizeof(float);

绘制方法 Shader绑定和解除绑定分别调用glUseProgram(shaderId / 0)。 渲染器绘制除了清除屏幕颜色为黑色外什么都不做。

void Game::Draw()
{
    m_display->SwapBuffer();
    m_renderer.Draw();
    m_shader.Bind();
    //m_shader.SetSharderMatrixUniform("transform", m_transform.GetTranslation());
    m_renderer.DrawMesh(m_mesh);
    m_shader.UnBind();
    assert(glGetError() == GL_NO_ERROR);
}

渲染::绘制

void Renderer::DrawMesh(Mesh& model)
{
    glBindVertexArray(model.GetVertexBufferId());
    glDrawElements(GL_TRIANGLES, model.GetDrawCount(), GL_UNSIGNED_SHORT, 0);
    glBindVertexArray(0);
    assert(glGetError() == GL_NO_ERROR);
}

我相信Shader正在加载&正确编译。但是,我也会包含相应的代码。

void Shader::LoadFileData(const string& fileName) {
    const GLchar* charArr[1];
    string filePath = fileName;
    string vertexShader = File::LoadFile("res\\Shaders\\" + filePath + ".vert");
    string fragmentShader = File::LoadFile("res\\Shaders\\" + filePath + ".frag");

    m_shaders[VERTEX_SHADER] = glCreateShader(GL_VERTEX_SHADER);
    m_shaders[FRAGMENT_SHADER] = glCreateShader(GL_FRAGMENT_SHADER);

    charArr[0] = vertexShader.c_str();
    glShaderSource(m_shaders[VERTEX_SHADER], 1, charArr, 0);
    charArr[0] = fragmentShader.c_str();
    glShaderSource(m_shaders[FRAGMENT_SHADER], 1, charArr, 0);

    glCompileShader(m_shaders[VERTEX_SHADER]);
    glCompileShader(m_shaders[FRAGMENT_SHADER]);

    bool bSuccess = (CheckShaderCompileStatus(m_shaders[VERTEX_SHADER]) && CheckShaderCompileStatus(m_shaders[FRAGMENT_SHADER]));

    if (bSuccess) {
        m_programId = glCreateProgram();
        glAttachShader(m_programId, m_shaders[VERTEX_SHADER]);
        glAttachShader(m_programId, m_shaders[FRAGMENT_SHADER]);
        glLinkProgram(m_programId);

        if (!CheckProgramLinkStatus(m_programId))
            return;

        glDeleteShader(m_shaders[VERTEX_SHADER]);
        glDeleteShader(m_shaders[FRAGMENT_SHADER]);
    }
#if DEBUG
    assert(glGetError() == GL_NO_ERROR);
#endif
}

我认为问题可能在于BufferGeometry方法,因为glVertexAttribPointer调用在某种程度上是错误的,但我没有看到它。

struct Vector3 
{
    float x;
    float y;
    float z;
}

struct Vector2 {
    float x;
    float y;
}

@Vallentin - 这是着色器代码。它或多或少的管道位置和颜色数据直接来自顶点属性。 着色器代码:.frag

#version 430

in vec4 vertColour;
out vec4 fragColour;

void main()
{
    fragColour = vertColour;
}

.vert

#version 430

layout (location=0) in vec3 position;
layout (location=1) in vec3 colour;

out vec4 vertColour;

uniform mat4 transform;

void main(){
    vertColour = vec4(colour,1.0f);
    gl_Position = vec4(position,1.0);
}

2 个答案:

答案 0 :(得分:0)

如果你的缓冲区几何形状是"位置,颜色,正常,紫外"然后对每个顶点重复四次调用,如

glVertexAttribPointer(L, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, (char*)(sizeof(float) * K));

错了。

查看glVertexAttribPointer docs

你所谓的VERTEX_BYTE_SIZE必须是步幅 :( 3 + 3 + 3 + 2)* sizeof(float)= 44

要从头开始读取缓冲区,最后一个参数必须是0

答案 1 :(得分:0)

感谢所有帮助人员。

事实证明,这是令人头脑麻木的愚蠢行为。

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_arrayBuffers[VERTEX_BUFFER]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_shapeData.GetIndexBufferSize(), &m_shapeData.indices[0], GL_STATIC_DRAW);

应该是

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_arrayBuffers[INDEX_BUFFER]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_shapeData.GetIndexBufferSize(), &m_shapeData.indices[0], GL_STATIC_DRAW);

我必须看过那种方法一千次,而不是看到它。

非常感谢:)