GLFW triangle will not change color

2019-07-20 16:51发布

问题:

I've been following a short youtube tutorial on how to make basic graphics with glfw. I cannot get my triangle to change color help me.

main code:

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <fstream>

#include <GL/glew.h>
#include <GLFW/glfw3.h>

std::string LoadFileToString(const char* filepath)
{
    std::string fileData;
    std::ifstream stream(filepath, std::ios::in);

    if (stream.is_open())
    {
        std::string line = "";

        while (getline(stream, line))
        {
            fileData += "\n" + line;
        }

        stream.close();
    }

    return fileData;
}

GLuint LoadShaders(const char* vertShaderPath, const char* fragShaderPath)
{
    GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
    GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);

    std::string vertShaderSource = LoadFileToString(vertShaderPath);
    std::string fragShaderSource = LoadFileToString(vertShaderPath);

    const char* rawVertShaderSource = vertShaderSource.c_str();
    const char* rawFragShaderSource = fragShaderSource.c_str();

    glShaderSource(vertShader, 1, &rawVertShaderSource, NULL);
    glShaderSource(fragShader, 1, &rawFragShaderSource, NULL);

    glCompileShader(vertShader);
    glCompileShader(fragShader);

    GLuint program = glCreateProgram();
    glAttachShader(program, vertShader);
    glAttachShader(program, fragShader);
    glLinkProgram(program);

    return program;
}

int main()
{
    if (glfwInit() == false)
    {
        //did not succeed
        fprintf(stderr, "GLFW failed to initialise.");
        return -1;
    }

    //4 AA
    glfwWindowHint(GLFW_SAMPLES, 4);
    //tells glfw to set opengl to 3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    GLFWwindow* window;
    window = glfwCreateWindow(640, 480, "DJ KELLER KEEMSTAR", NULL, NULL);

    if (!window)
    {
        fprintf(stderr, "Window failed to create");
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);
    glewExperimental = true;

    if (glewInit() != GLEW_OK)
    {
        fprintf(stderr, "Glew failed to initialise");
        glfwTerminate();
        return -1;
    }

    //generate VAO
    GLuint vaoID;
    glGenVertexArrays(1, &vaoID);
    glBindVertexArray(vaoID);

    static const GLfloat verts[] =
    {
        //X, Y, Z
        -1.0f, -1.0f, 0.0f,
        1.0f, -1.0f, 0.0f,
        0.0f, 1.0f, 0.0f
    };

    GLuint program = LoadShaders("shader.vertshader", "shader.fragshader");

    //generate VBO
    GLuint vboID;
    glGenBuffers(1, &vboID);
    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);

    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
    do
    {
        glClear(GL_COLOR_BUFFER_BIT);
        glEnableVertexAttribArray(0);

        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

        glUseProgram(program);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        glDisableVertexAttribArray(0);

        glfwSwapBuffers(window);
        glfwPollEvents();

    } while (glfwWindowShouldClose(window) == false);

    return 0;
}

fragshader:

#version 330 core
out vec3 color;

void main()
{
    color = vec3(1,0,0);
}

vertshader:

#version 330 core
layout(location = 0) in vec3 in_pos;

void main()
{
    gl_Position.xyz = in_pos;
    gl_Position.w = 1;
}

The triangle is supposed to be red:

回答1:

std::string vertShaderSource = LoadFileToString(vertShaderPath);
std::string fragShaderSource = LoadFileToString(vertShaderPath);
                                                ^^^^^^^^^^^^^^ wat

Don't try to use a vertex shader as a fragment shader.

Recommend querying the compilation and link status/logs while assembling the shader:

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <cstdarg>

struct Program
{
    static GLuint Load( const char* shader, ... )
    {
        GLuint prog = glCreateProgram();
        va_list args;
        va_start( args, shader );
        while( shader )
        {
            const GLenum type = va_arg( args, GLenum );
            AttachShader( prog, type, shader );
            shader = va_arg( args, const char* );
        }
        va_end( args );
        glLinkProgram( prog );
        CheckStatus( prog );
        return prog;
    }

private:
    static void CheckStatus( GLuint obj )
    {
        GLint status = GL_FALSE;
        if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
        if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
        if( status == GL_TRUE ) return;
        GLchar log[ 1 << 15 ] = { 0 };
        if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
        if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
        std::cerr << log << std::endl;
        exit( EXIT_FAILURE );
    }

    static void AttachShader( GLuint program, GLenum type, const char* src )
    {
        GLuint shader = glCreateShader( type );
        glShaderSource( shader, 1, &src, NULL );
        glCompileShader( shader );
        CheckStatus( shader );
        glAttachShader( program, shader );
        glDeleteShader( shader );
    }
};

#define GLSL(version, shader) "#version " #version "\n" #shader

const char* vert = GLSL
(
    330 core,
    layout( location = 0 ) in vec3 in_pos;
    void main()
    {
        gl_Position.xyz = in_pos;
        gl_Position.w = 1;
    }
);

const char* frag = GLSL
(
    330 core,
    out vec3 color;
    void main()
    {
        color = vec3(1,0,0);
    }
);

int main()
{
    if (glfwInit() == false)
    {
        //did not succeed
        fprintf(stderr, "GLFW failed to initialise.");
        return -1;
    }

    //4 AA
    glfwWindowHint(GLFW_SAMPLES, 4);
    //tells glfw to set opengl to 3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    GLFWwindow* window = glfwCreateWindow(640, 480, "DJ KELLER KEEMSTAR", NULL, NULL);
    if (!window)
    {
        fprintf(stderr, "Window failed to create");
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);

    glewExperimental = true;
    if (glewInit() != GLEW_OK)
    {
        fprintf(stderr, "Glew failed to initialise");
        glfwTerminate();
        return -1;
    }

    //generate VAO
    GLuint vaoID;
    glGenVertexArrays(1, &vaoID);
    glBindVertexArray(vaoID);

    static const GLfloat verts[] =
    {
        //X, Y, Z
        -1.0f, -1.0f, 0.0f,
        1.0f, -1.0f, 0.0f,
        0.0f, 1.0f, 0.0f
    };

    GLuint program = Program::Load
        (
        vert, GL_VERTEX_SHADER,
        frag, GL_FRAGMENT_SHADER,
        NULL
        );

    //generate VBO
    GLuint vboID;
    glGenBuffers(1, &vboID);
    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);

    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
    do
    {
        glClear(GL_COLOR_BUFFER_BIT);
        glEnableVertexAttribArray(0);

        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

        glUseProgram(program);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        glDisableVertexAttribArray(0);

        glfwSwapBuffers(window);
        glfwPollEvents();

    } while (glfwWindowShouldClose(window) == false);

    return 0;
}

That way if you try something like:

GLuint program = Program::Load
    (
    vert, GL_VERTEX_SHADER,
    vert, GL_VERTEX_SHADER,
    NULL
    );

...it will bail out early and give you a better indication of what went wrong:

Vertex shader(s) failed to link.
Vertex link error: INVALID_OPERATION.
ERROR: 0:2: error(#248) Function already has a body: main
ERROR: error(#273) 1 compilation errors.  No code generated


标签: c++ opengl glfw