又一个“OpenGL不绘图”问题

时间:2014-04-24 12:16:22

标签: c++ opengl rendering sdl

好吧,我想我会发疯了。

我一直在OpenGL中开发一款3D游戏 - 一切运作良好。

然后我决定从头开始重新设计它,因为它转向奶油冻。所以我建立了一个用OpenGL渲染的基本框架,我不能为我的生活得到渲染三角形的东西。

我已经遍历了每一行代码大约60次,浏览了我可以在互联网上找到的每个清单,检查了我的旧项目是否有效,但仍然看不出有什么问题。

所以这就是一切开始的地方(主要方法):

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* cmdLine, int cmdShow)
{
    try
    {    
        GLContext gl(WINDOW_TITLE, 800, 600);
        TestRenderable test;

        while(true)
        {
            glClearColor(0.0f, 0.15f, 0.3f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);
            test.draw();
            gl.swapBuffers();
        }

    }
    catch(const std::string& err)
    {
        std::string msg = "Error: ";
        msg += err;

        MessageBox(NULL, msg.c_str(), WINDOW_TITLE, MB_OK | MB_ICONERROR);
    }
    catch(...)
    {
        MessageBox(NULL, "Unknown Error", WINDOW_TITLE, MB_OK | MB_ICONERROR);
    }

}

所有课程方法如下:

GLContext::GLContext(const std::string& title, int width, int height)
{
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    m_pWindow = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
    m_glContext = SDL_GL_CreateContext(m_pWindow);

    if(glewInit() != GLEW_OK)
        throw(std::string("Failed to initialize GLEW"));
}

GLContext::~GLContext()
{
    SDL_GL_DeleteContext(m_glContext);
    SDL_DestroyWindow(m_pWindow);
}

void GLContext::swapBuffers()
{
    SDL_GL_SwapWindow(m_pWindow);
}


TestRenderable::TestRenderable() : m_pShader(nullptr), m_pMesh(nullptr)
{
    std::vector<std::string> attributes;
    attributes.push_back("position");
    attributes.push_back("color");

    m_pShader = new Shader("shaders\\shader", attributes);
    m_pShader->addUniform("transform");

    glm::vec3 positions[] =
    {
        { 10.0f, 10.0f, 0.0f },
        { 200.0f, 10.0f, 0.0f },
        { 10.0f, 100.0f, 0.0f }
    };

    glm::vec4 colors[] =
    {
        { 0.0f, 1.0f, 0.0f, 1.0f },
        { 1.0f, 0.0f, 0.0f, 1.0f },
        { 0.0f, 0.0f, 1.0f, 1.0f }
    };

    m_pMesh = new Mesh_PC(positions, colors, 3);

    m_projection = glm::ortho<float>(0.0f, 800.0f, 600.0f, 0.0f, 0.0f, 1.0f);
}

TestRenderable::~TestRenderable()
{
    if(m_pShader != nullptr)
        delete m_pShader;

    if(m_pMesh != nullptr)
        delete m_pMesh;
}

void TestRenderable::draw()
{
    m_pShader->bind();
    m_pShader->setUniformMatrix("transform", m_projection);

    m_pMesh->draw();
}


Mesh_PC::Mesh_PC(glm::vec3 positions[], glm::vec4 colors[], unsigned numVertices) : m_vertexCount(numVertices)
{
    glGenVertexArrays(1, m_vertexArray);

    glBindVertexArray(m_vertexArray[0]);

    glGenBuffers(NUM_BUFFERS, m_buffers);

    glBindBuffer(GL_ARRAY_BUFFER, m_buffers[POSITIONS_BUFFER]);
    glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(positions[0]), positions, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, m_buffers[COLORS_BUFFER]);
    glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(colors[0]), colors, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);

    glBindVertexArray(0);
}

Mesh_PC::~Mesh_PC()
{
    glDeleteBuffers(NUM_BUFFERS, m_buffers);
    glDeleteVertexArrays(1, m_vertexArray);
}

void Mesh_PC::draw()
{
    glBindVertexArray(m_vertexArray[0]);
    glDrawArrays(GL_TRIANGLES, 0, m_vertexCount);
    glBindVertexArray(0);
}



Shader::Shader(const std::string& filename, const std::vector<std::string>& attributes)
{
    m_program = glCreateProgram();
    m_shaders[0] = createShader(loadShader(filename + ".vs"), GL_VERTEX_SHADER);
    m_shaders[1] = createShader(loadShader(filename + ".fs"), GL_FRAGMENT_SHADER);

    for(unsigned int i = 0; i < NUM_SHADERS; ++i)
        glAttachShader(m_program, m_shaders[i]);

    for(unsigned int i = 0; i < attributes.size(); ++i)
        glBindAttribLocation(m_program, i, attributes[i].c_str());

    glLinkProgram(m_program);
    checkShaderError(m_program, GL_LINK_STATUS, true, "Program linking failed");

    glValidateProgram(m_program);
    checkShaderError(m_program, GL_VALIDATE_STATUS, true, "Program is invalid");
}

Shader::~Shader()
{
    for(unsigned int i = 0; i < NUM_SHADERS; ++i)
    {
        glDetachShader(m_program, m_shaders[i]);
        glDeleteShader(m_shaders[i]);
    }

    glDeleteProgram(m_program);
}

void Shader::addUniform(const std::string& name)
{
    m_uniforms.insert(std::make_pair(name, glGetUniformLocation(m_program, name.c_str())));
}

void Shader::bind()
{
    glUseProgram(m_program);
}

void Shader::setUniformMatrix(const std::string& name, const glm::mat4& value)
{
    bind();

    auto it = m_uniforms.find(name);

    if(it != m_uniforms.end())
    {
        glUniformMatrix4fv(it->second, 1, GL_FALSE, &value[0][0]);
    }
}

void Shader::setUniformVec4(const std::string& name, const glm::vec4& value)
{
    bind();

    auto it = m_uniforms.find(name);

    if(it != m_uniforms.end())
    {
        glUniform4fv(it->second, 1, &value[0]);
    }
}

std::string Shader::loadShader(const std::string& filename)
{
    std::ifstream file;
    file.open(filename.c_str());

    std::string output;
    std::string line;

    if(file.is_open())
    {
        while(file.good())
        {
            getline(file, line);
            output.append(line + "\n");
        }

        file.close();
    }
    else
    {
        std::string err("Unable to load shader: ");
        err.append(filename);
        throw(err);
    }

    return output;
}

void Shader::checkShaderError(GLuint shader, GLuint flag, bool isProgram, const char* errorMessage)
{
    GLint success = 0;
    GLchar error[1024] = { 0 };

    if(isProgram)
        glGetProgramiv(shader, flag, &success);
    else
        glGetShaderiv(shader, flag, &success);

    if(success == GL_FALSE)
    {
        if(isProgram)
            glGetProgramInfoLog(shader, sizeof(error), NULL, error);
        else
            glGetShaderInfoLog(shader, sizeof(error), NULL, error);

        std::string err(errorMessage);
        err.append(": '");
        err.append(error);
        err.append("'");
        throw(err);
    }
}

GLuint Shader::createShader(const std::string& text, GLenum shaderType)
{
    GLuint shader = glCreateShader(shaderType);

    if(shader == 0)
        throw("Shader creation failed");

    const GLchar *shaderSourceStrings[1];
    GLint shaderSourceStringLengths[1];

    shaderSourceStrings[0] = text.c_str();
    shaderSourceStringLengths[0] = static_cast<GLint>(text.length());

    glShaderSource(shader, 1, shaderSourceStrings, shaderSourceStringLengths);
    glCompileShader(shader);

    checkShaderError(shader, GL_COMPILE_STATUS, false, "Shader compilation failed");

    return shader;
}

顺便说一句,我正在开发SDL - 我在GLContext类中有一个以下类型的对象:

class SDL
{
public:
    SDL() { SDL_Init(SDL_INIT_VIDEO); }
    ~SDL() { SDL_Quit(); }
};

我的着色器:

顶点着色器:

#version 120

attribute vec3 position;
attribute vec4 color;

varying vec4 color0;

uniform mat4 transform;

void main(void)
{
    gl_Position = transform * vec4(position, 1.0);
    color0 = color;
}

Fragment Shader:

#version 120

varying vec4 color0;

void main(void)
{   
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

我知道着色器等中有未使用的东西,但这仅用于测试目的。

有人可以帮我吗?

1 个答案:

答案 0 :(得分:4)

在致电glBindBuffer之前,您需要致电glVertexAttribPointer。目前,两个属性都将使用最后一个缓冲区(带有颜色值的缓冲区)。