OpenGL着色器链接

OpenGL shader linking

本文关键字:链接 OpenGL      更新时间:2023-10-16

在跟随了一组很棒但没有让我理解基础知识的OpenGL教程之后,我正在尝试用c++编写一些非常基本的OpenGL编码。我的程序应该读取顶点和片段着色器并绘制三角形。

当链接着色器时,我得到一个错误(我怀疑错误可以追溯到编译着色器)。我知道我的着色器被我的程序读取,但对它们的任何更改都不会影响我的错误。通过运行:

glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);

我收到错误:"链接调用没有任何附加的着色器对象"。程序建立,我的三角形显示,但不受着色器的影响。

修复错误后,我不再得到上述错误。我现在得到一个抱怨后glCompileShader():

"Error: 0:3 'location': syntax Error: parse Error "

所以我认为它与我的着色器文件有关(将在下面添加它们)。着色器文件取自教程,所以我认为他们会工作。

材质文件:

顶点着色器:

#version 330                                                            
layout (location = 0) in vec3 Position;                                 
void main()                                                             
{                                                                       
    gl_Position = vec4(0.5*Position.x, 0.5*Position.y, Position.z, 1.0);    
}

片段着色器:

#version 330                                                            
out vec4 FragColor;                                                     
void main()                                                             
{                                                                       
    FragColor = vec4(1.0, 0.0, 0.0, 1.0);                               
}

在我的main函数中,我运行:

compileShader();

附加着色器:

static void AddShader(GLuint ShaderProgram, GLenum ShaderType, std::string filePath){
//create shader object
GLuint ShaderObj = glCreateShader(ShaderType);
//error if no shader
if (ShaderObj == 0){
    fprintf(stderr, "Error creating shader type %dn", ShaderType);
    exit(0);
}
//"specify source code"
//readShaderFile returns the shader file as a string
std::string shaderFile = readShaderFile(filePath);
const char* shaderFilePointer = shaderFile.c_str();
GLint ShaderFileLength[1];  
ShaderFileLength[0] = strlen(shaderFilePointer);
glShaderSource(ShaderObj, 1, &shaderFilePointer, ShaderFileLength);
//compile the shader
glCompileShader(ShaderObj);
//check if compile successful
GLint success;
glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
if (!success){
    GLchar InfoLog[1024];
    glGetShaderInfoLog(ShaderObj, sizeof(InfoLog), NULL, InfoLog);
    fprintf(stderr, "Error compiling shader type %d: '%s'n", ShaderType, InfoLog);
    exit(1);
}
glAttachShader(ShaderProgram, ShaderObj);
}

下面是使用的函数:

static void compileShaders(){
//create program
GLuint ShaderProgram = glCreateProgram();
//check error
if (ShaderProgram == 0){
    fprintf(stderr, "Error creating shader program!n");
    exit(1);
}
//attach compiled shaders
std::string vertexShaderFilePath    = "Shaders/colShading.vert";
std::string fragShaderFilePath      = "Shaders/colShading.frag";
AddShader(ShaderProgram, GL_VERTEX_SHADER, vertexShaderFilePath);
AddShader(ShaderProgram, GL_FRAGMENT_SHADER, fragShaderFilePath);
GLint Success = 0;
GLchar ErrorLog[1024] = { 0 };
//link shader to program
glLinkProgram(ShaderProgram);
//check link error
glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
if (Success == 0) {
    glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
    fprintf(stderr, "Error linking shader program: '%s'n", ErrorLog);
}
//use the linked shader program
glUseProgram(ShaderProgram);
}

我怀疑需要更多的代码才能找到这里的问题,但请告诉我。提前感谢!

<

解决方案/strong>

下面的第一个答案奏效了。我删除了:

layout (location = 0) 

从顶点着色器,然后添加:

glBindAttribLocation(ShaderProgram, 0, "Position");

似乎你的硬件或驱动程序不支持显式着色器位置语法,这需要OpenGL/GLSL> 3.3。

要解决这个问题,如果samgak的答案没有帮助,你仍然有两个选择:

  1. 链接着色器之前显式设置位置:

这是用glBindAttribLocation函数完成的,并且意味着基本上与你在着色器中拥有的相同。例子:

AddShader(ShaderProgram, GL_VERTEX_SHADER, vertexShaderFilePath);
AddShader(ShaderProgram, GL_FRAGMENT_SHADER, fragShaderFilePath);
//...
//Define the location of the attributes
glBindAttribute(ShaderProgram, 0, "Position") //Bind "in Position" to location 0
//link shader to program
glLinkProgram(ShaderProgram);
  • 链接后,在构建VAOs(或绘制几何图形)时,查询属性的位置,并相应地设置缓冲区:
  • 您可以使用glGetAttribLocation函数执行此操作。

    GLuint positionLoc = glGetAttribLocation(ShaderProgram, "Position");// Ask for the location of the attribute "Position
    //Create buffers and transfer data...
    glBindBuffer(gl.ARRAY_BUFFER, ...);
    
    glBufferData(...);
    //Turns on the vertex attribute for "Position" 
    glEnableVertexAttribArray(positionLoc);
    //Set the pointer between buffer and attribute 
    glVertexAttribPointer(positionLoc,...);
    

    出于性能考虑,建议使用第一个选项,因为它不会强制刷新。