我正在从本教程中学习 OpenGL:http: //openglbook.com/the-book/。我有着色器的问题。我在编译/链接着色器时遇到错误,但我不知道我做错了什么。
错误:
符号 ex_Color 在顶点和片段着色器中使用 2 种不同类型定义。
着色器(由于 GLSL 版本,我对其进行了一些修改):
const GLchar* VertexShader =
{
    "#version 130\n"\
    "in vec4 in_Position;\n"\
    "in vec4 in_Color;\n"\
    "out vec4 ex_Color;\n"\
    "void main(void)\n"\
    "{\n"\
    "       gl_Position = in_Position;\n"\
    "       ex_Color = in_Color;\n"\
    "}\n"
};
const GLchar* FragmentShader =
{
    "#version 130\n"\
    "precision mediump float;\n"\
    "in vec4 ex_Color;\n"\
    "out vec4 out_Color;\n"\
    "void main(void)\n"\
    "{\n"\
    "       out_Color = ex_Color;\n"\
    "}\n"
};
源代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#define WINDOW_TITLE_PREFIX "Chapter 2"
int CurrentWidth = 800,
    CurrentHeight = 600,
    WindowHandle = 0;
unsigned FrameCount = 0;
GLuint
    VertexShaderId,
    FragmentShaderId,
    ProgramId,
    VaoId,
    VboId,
    ColorBufferId;
    const GLchar* VertexShader =
    {
            "#version 130\n"\
            "in vec4 in_Position;\n"\
            "in vec4 in_Color;\n"\
            "out vec4 ex_Color;\n"\
            "void main(void)\n"\
            "{\n"\
            "       gl_Position = in_Position;\n"\
            "       ex_Color = in_Color;\n"\
            "}\n"
    };
    const GLchar* FragmentShader =
    {
            "#version 130\n"\
            "precision mediump float;\n"\
            "in vec4 ex_Color;\n"\
            "out vec4 out_Color;\n"\
            "void main(void)\n"\
            "{\n"\
            "       out_Color = ex_Color;\n"\
            "}\n"
    };
void Initialize(int, char*[]);
void InitWindow(int, char*[]);
void ResizeFunction(int, int);
void RenderFunction(void);
void TimerFunction(int);
void IdleFunction(void);
void Cleanup(void);
void CreateVBO(void);
void DestroyVBO(void);
void CreateShaders(void);
void DestroyShaders(void);
int main(int argc, char* argv[])
{
    Initialize(argc, argv);
    glutMainLoop();
    exit(EXIT_SUCCESS);
}
void Initialize(int argc, char* argv[])
{
    GLenum GlewInitResult;
    InitWindow(argc, argv);
    glewExperimental = GL_TRUE;
    GlewInitResult = glewInit();
    if (GLEW_OK != GlewInitResult) {
        fprintf(
            stderr,
            "ERROR: %s\n",
            glewGetErrorString(GlewInitResult)
        );
        exit(EXIT_FAILURE);
    }
    fprintf(
        stdout,
        "INFO: OpenGL Version: %s (GLSL = %s)\n",
        glGetString(GL_VERSION),
        glGetString(GL_SHADING_LANGUAGE_VERSION) 
    );
    CreateShaders();
    CreateVBO();
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
void InitWindow(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitContextVersion(3, 1);
    glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
    glutInitContextProfile(GLUT_CORE_PROFILE);
    glutSetOption(
        GLUT_ACTION_ON_WINDOW_CLOSE,
        GLUT_ACTION_GLUTMAINLOOP_RETURNS
    );
    glutInitWindowSize(CurrentWidth, CurrentHeight);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX);
    if(WindowHandle < 1) {
        fprintf(
            stderr,
            "ERROR: Could not create a new rendering window.\n"
        );
        exit(EXIT_FAILURE);
    }
    glutReshapeFunc(ResizeFunction);
    glutDisplayFunc(RenderFunction);
    glutIdleFunc(IdleFunction);
    glutTimerFunc(0, TimerFunction, 0);
    glutCloseFunc(Cleanup);
}
void ResizeFunction(int Width, int Height)
{
    CurrentWidth = Width;
    CurrentHeight = Height;
    glViewport(0, 0, CurrentWidth, CurrentHeight);
}
void RenderFunction(void)
{
    ++FrameCount;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glutSwapBuffers();
    glutPostRedisplay();
}
void IdleFunction(void)
{
    glutPostRedisplay();
}
void TimerFunction(int Value)
{
    if (0 != Value) {
        char* TempString = (char*)
            malloc(512 + strlen(WINDOW_TITLE_PREFIX));
        sprintf(
            TempString,
            "%s: %d Frames Per Second @ %d x %d",
            WINDOW_TITLE_PREFIX,
            FrameCount * 4,
            CurrentWidth,
            CurrentHeight
        );
        glutSetWindowTitle(TempString);
        free(TempString);
    }
    FrameCount = 0;
    glutTimerFunc(250, TimerFunction, 1);
}
void Cleanup(void)
{
    DestroyShaders();
    DestroyVBO();
}
void CreateVBO(void)
{
    GLfloat Vertices[] = {
        -0.8f, -0.8f, 0.0f, 1.0f,
         0.0f,  0.8f, 0.0f, 1.0f,
         0.8f, -0.8f, 0.0f, 1.0f
    };
    GLfloat Colors[] = {
        1.0f, 0.0f, 0.0f, 1.0f,
        0.0f, 1.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f, 1.0f
    };
    GLenum ErrorCheckValue = glGetError();
    glGenVertexArrays(1, &VaoId);
    glBindVertexArray(VaoId);
    glGenBuffers(1, &VboId);
    glBindBuffer(GL_ARRAY_BUFFER, VboId);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(0);
    glGenBuffers(1, &ColorBufferId);
    glBindBuffer(GL_ARRAY_BUFFER, ColorBufferId);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Colors), Colors, GL_STATIC_DRAW);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(1);
    ErrorCheckValue = glGetError();
    if (ErrorCheckValue != GL_NO_ERROR)
    {
        fprintf(
            stderr,
            "ERROR: Could not create a VBO: %s \n",
            gluErrorString(ErrorCheckValue)
        );
        exit(-1);
    }
}
void DestroyVBO(void)
{
    GLenum ErrorCheckValue = glGetError();
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glDeleteBuffers(1, &ColorBufferId);
    glDeleteBuffers(1, &VboId);
    glBindVertexArray(0);
    glDeleteVertexArrays(1, &VaoId);
    ErrorCheckValue = glGetError();
    if (ErrorCheckValue != GL_NO_ERROR)
    {
        fprintf(
            stderr,
            "ERROR: Could not destroy the VBO: %s \n",
            gluErrorString(ErrorCheckValue)
        );
        exit(-1);
    }
}
void CreateShaders(void)
{
    GLenum ErrorCheckValue = glGetError();
    VertexShaderId = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(VertexShaderId, 1, &VertexShader, NULL);
    glCompileShader(VertexShaderId);
    GLint vertex_shader_status;
    glGetShaderiv(FragmentShaderId, GL_COMPILE_STATUS, &vertex_shader_status);
    if (vertex_shader_status == 0)
    {
        GLint logLength;
        glGetShaderiv(FragmentShaderId, GL_INFO_LOG_LENGTH, &logLength);
        if (logLength > 0)
        {
            GLchar *log = (GLchar *)malloc(logLength);
            glGetShaderInfoLog(FragmentShaderId, logLength, &logLength, log);
            fprintf(
                stderr,
                "ERROR: Could not create the vertex shader: %s \n",
                log
            );
            free(log);
        }
        glDeleteShader(FragmentShaderId);
    } 
    FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL);
    glCompileShader(FragmentShaderId);
    ProgramId = glCreateProgram();
        glAttachShader(ProgramId, VertexShaderId);
        glAttachShader(ProgramId, FragmentShaderId);
        glBindAttribLocation(ProgramId, 0, "in_Position");
        glBindAttribLocation(ProgramId, 1, "in_Color");
    glLinkProgram(ProgramId);
    glUseProgram(ProgramId);
    GLint logLength, status;
    glValidateProgram(ProgramId);
    glGetProgramiv(ProgramId, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0)
    {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetProgramInfoLog(ProgramId, logLength, &logLength, log);
        fprintf(
                stderr,
                "ERROR: Could not create the program: %s \n",
                log
            );
        free(log);
    }
    glGetProgramiv(ProgramId, GL_VALIDATE_STATUS, &status);
    if (status == 0) {
        fprintf(
                stderr,
                "ERROR: Could not create the program: \n"
            );
    }
    ErrorCheckValue = glGetError();
    if (ErrorCheckValue != GL_NO_ERROR)
    {
        fprintf(
            stderr,
            "ERROR: Could not create the shaders: %s \n",
            gluErrorString(ErrorCheckValue)
        );
        exit(-1);
    }
}
void DestroyShaders(void)
{
    GLenum ErrorCheckValue = glGetError();
    glUseProgram(0);
    glDetachShader(ProgramId, VertexShaderId);
    glDetachShader(ProgramId, FragmentShaderId);
    glDeleteShader(FragmentShaderId);
    glDeleteShader(VertexShaderId);
    glDeleteProgram(ProgramId);
    ErrorCheckValue = glGetError();
    if (ErrorCheckValue != GL_NO_ERROR)
    {
        fprintf(
            stderr,
            "ERROR: Could not destroy the shaders: %s \n",
            gluErrorString(ErrorCheckValue)
        );
        exit(-1);
    }
}
我有 Mobility Radeon HD4570 显卡(OpenGL 3.1、GLSL 1.30)。