为啥在使用 OpenGL 编译顶点着色器时会出现着色器编译器错误 #143、#160 和 #216?
Posted
技术标签:
【中文标题】为啥在使用 OpenGL 编译顶点着色器时会出现着色器编译器错误 #143、#160 和 #216?【英文标题】:Why am I getting a Shader Compiler Error #143, #160 and #216 when comiling a vertex Shader using OpenGL?为什么在使用 OpenGL 编译顶点着色器时会出现着色器编译器错误 #143、#160 和 #216? 【发布时间】:2018-12-08 09:00:39 【问题描述】:我刚开始学习 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");
致命错误只是打印提供的字符串并退出。
【问题讨论】:
对于顶点着色器,您必须通过glCreateShader( GL_VERTEX_SHADER)
创建着色器对象。
我已经在一个单独的类中完成了该操作,该类处理所有 GLSL 操作。我也将在此处添加该代码。
是的,gl_Position
仅在顶点着色器中可用。
【参考方案1】:
gl_Position
仅在顶点着色器中有效。
你编译了两次顶点着色器,但是你没有编译compileShaders
中的片段着色器:
必须是
compileShader(vertexShaderFilePath, _vertexShaderID);
compileShader(fragmentShaderFilePath, _fragmentShaderID);
而不是
compileShader(vertexShaderFilePath, _vertexShaderID);
compileShader(vertexShaderFilePath, _fragmentShaderID);
【讨论】:
以上是关于为啥在使用 OpenGL 编译顶点着色器时会出现着色器编译器错误 #143、#160 和 #216?的主要内容,如果未能解决你的问题,请参考以下文章