为什么使用OpenGL编译顶点着色器时出现着色器编译器错误#143,#160和#216?

时间:2018-12-08 09:00:39

标签: c++ opengl graphics glsl shader

我刚刚开始学习C ++中的Grpahics以及着色器和精灵。我写了一个小的顶点着色器和一个片段着色器。

顶点着色器:

#version 130

in vec2 vertexPosition;

void main() {
    gl_Position.xy = vertexPosition;
    gl_Position.z = 0.0;
    gl_Position.w = 1.0;
}

片段着色器:

#version 130

out vec3 color;

void main() {
    color = vec3(0.94, 0.37, 0.36);
}

在编译时,我收到以下错误消息:

Fragment shader failed to compile with the following errors:
ERROR: 0:6: error(#143) Undeclared identifier: gl_Position
ERROR: 0:6: error(#216) Vector field selection out of range "xy"
ERROR: 0:6: error(#160) Cannot convert from: "default in highp 2-component vector of vec2" to: "float"
ERROR: 0:7: error(#216) Vector field selection out of range "z"
ERROR: 0:8: error(#216) Vector field selection out of range "w"
ERROR: error(#273) 5 compilation errors.  No code generated

如何解决这些错误?

PS:我使用的是AMD A10 8700P Radeon R6处理器内置图形。 在阅读其他问题时,我注意到使用AMD图形卡是导致多个问题的根本原因,因此,如果就我而言,这是问题所在,那么我该如何解决?

我为所有GLSL操作使用了单独的类。

GLSLProgram.h:

#pragma once

#include <GL/glew.h>

#include <string>

class GLSLProgram
{
public:
    GLSLProgram();
    ~GLSLProgram();

    void compileShaders(const std::string &vertexShaderFilePath, const std::string &fragmentShaderFilePath);

    void linkShaders();

    void addAttribute(const std::string& attributeName);

    void use();
    void unuse();
private:
    int _numAttributes;

    void compileShader(const std::string &filePath, GLuint id);

    GLuint _programID;

    GLuint _vertexShaderID;
    GLuint _fragmentShaderID;
};

GLSLProgram.cpp:

#include "GLSLProgram.h"
#include "Errors.h"

#include <fstream>
#include <vector>

GLSLProgram::GLSLProgram() : 
_numAttributes(0), _programID(0), _vertexShaderID(0), _fragmentShaderID(0) 
{
}


GLSLProgram::~GLSLProgram() {
}

void GLSLProgram::compileShaders(const std::string &vertexShaderFilePath, const std::string &fragmentShaderFilePath) {
    _vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    if (!_vertexShaderID) {
        fatalError("Vertex Shader failed to be created!");
    }

    _fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
    if (!_fragmentShaderID) {
        fatalError("Fragment Shader failed to be created!");
    }

    compileShader(vertexShaderFilePath, _vertexShaderID);
    compileShader(vertexShaderFilePath, _fragmentShaderID);
}

void GLSLProgram::linkShaders() {
    // Vertex and fragment shaders are successfully compiled.
    // Now time to link them together into a program.
    // Get a program object.
    _programID = glCreateProgram();

    // Attach our shaders to our program
    glAttachShader(_programID, _vertexShaderID);
    glAttachShader(_programID, _fragmentShaderID);

    // Link our program
    glLinkProgram(_programID);

    // Note the different functions here: glGetProgram* instead of glGetShader*.
    GLint isLinked = 0;
    glGetProgramiv(_programID, GL_LINK_STATUS, (int *)&isLinked);
    if (isLinked == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetProgramiv(_programID, GL_INFO_LOG_LENGTH, &maxLength);

        // The maxLength includes the NULL character
        std::vector<char> errorLog(maxLength);
        glGetProgramInfoLog(_programID, maxLength, &maxLength, &errorLog[0]);

        // We don't need the program anymore.
        glDeleteProgram(_programID);
        // Don't leak shaders either.
        glDeleteShader(_vertexShaderID);
        glDeleteShader(_fragmentShaderID);

        std::printf("%s\n", &(errorLog[0]));
        fatalError("Shaders failed to link!");
    }

    // Always detach shaders after a successful link.
    glDetachShader(_programID, _vertexShaderID);
    glDetachShader(_programID, _fragmentShaderID);
    glDeleteShader(_vertexShaderID);
    glDeleteShader(_fragmentShaderID);
}

void GLSLProgram::addAttribute(const std::string &attributeName) {
    glBindAttribLocation(_programID, _numAttributes++, attributeName.c_str());

}

void GLSLProgram::use() {
    glUseProgram(_programID);
    for(int i = 0; i < _numAttributes; ++i) {
        glEnableVertexAttribArray(i);
    }
}

void GLSLProgram::unuse() {
    glUseProgram(0);
    for(int i = 0; i < _numAttributes; ++i) {
        glDisableVertexAttribArray(i);
    }
}


void GLSLProgram::compileShader(const std::string &filePath, GLuint id)
{
    std::ifstream shaderFile(filePath);
    if (shaderFile.fail())
    {
        perror(filePath.c_str());
        fatalError("Failed to open " + filePath);
    }

    std::string fileContents = "";
    std::string line;

    while (std::getline(shaderFile, line))
    {
        fileContents += line + "\n";
    }

    shaderFile.close();

    const char *contentsPtr = fileContents.c_str();
    glShaderSource(id, 1, &contentsPtr, nullptr);

    glCompileShader(id);

    GLint success = 0;
    glGetShaderiv(id, GL_COMPILE_STATUS, &success);

    if (success == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, &maxLength);

        //The maxLength includes the NULL character
        std::vector<char> errorLog(maxLength);
        glGetShaderInfoLog(id, maxLength, &maxLength, &errorLog[0]);

        glDeleteShader(id);

        std::printf("%s\n", &(errorLog[0]));
        fatalError("Shader " + filePath + " Failed to compile");
    }
}

致命错误仅显示提供的字符串并退出。

1 个答案:

答案 0 :(得分:4)

gl_Position仅在顶点着色器中有效。

您两次编译了顶点着色器,但是没有在compileShaders中编译片段着色器:

必须是

compileShader(vertexShaderFilePath, _vertexShaderID);
compileShader(fragmentShaderFilePath, _fragmentShaderID);

代替

compileShader(vertexShaderFilePath, _vertexShaderID);
compileShader(vertexShaderFilePath, _fragmentShaderID);