我对我的着色器在做什么感到很困惑。我有一个着色器类,它为我包装了阴影的 opengl 部分。我在 code::blocks 中构建我的应用程序并运行它,编译失败,链接阶段失败,但验证GL_VALIDATE_STATUS
成功并且着色器实际工作。
当我在代码块 IDE 之外运行它时,编译和链接阶段成功,验证也成功。在 IDE 中运行时,ProgramLog 和 InfoLog 为空,甚至没有警告,但在 IDE 之外运行时,编译和链接成功时,InfoLog 会显示警告。
我对此感到非常困惑,这是我的编译阶段:
GLuint handle = glCreateShader(a_Type);
glShaderSource(handle, 1, &a_Source, NULL);
glCompileShader(handle);
a_Type 可以是GL_VERTEX_SHADER
,GL_FRAGMENT_SHADER
或者是 a GL_GEOMETRY_SHADER
,我的着色器代码是从文件加载的。a_Source
const char*
然后我继续检查编译状态:
glGetShaderiv(handle, GL_COMPILE_STATUS, &success); OGLCHECK
if(success != GL_TRUE)
{
这是一个逻辑检查,将GL_TRUE
在从终端GL_FALSE
运行但从 IDE 运行时进行。
链接检查如下
glGetProgramiv(m_ProgramHandle, GL_LINK_STATUS, &success); OGLCHECK
if(success != GL_TRUE)
{
和验证
glValidateProgram(m_ProgramHandle); OGLCHECK
glGetProgramiv(m_ProgramHandle, GL_VALIDATE_STATUS, &success); OGLCHECK
if(success != GL_TRUE)
{
总而言之,从使用 IDE 开始,着色器编译和链接状态失败,但验证通过,着色器工作,但 InfoLog 为空。从终端运行时,编译和链接状态成功,验证和着色器也正常工作。当从终端运行时,我还有一个填充的 InfoLog,例如警告。
这个问题是在我对来自这里的问题进行一些调查后形成的: GLSL shader compilation on linux
这是着色器类的源代码
#include "Shader.h"
Shader::Shader():m_FragmentHandle(0),m_GeometryHandle(0),m_VertexHandle(0),m_ProgramHandle(0),m_CurrentTexture(0)
{
}
Shader::~Shader()
{
if(m_GeometryHandle != 0)
{
glDeleteShader(m_GeometryHandle);
m_GeometryHandle = 0;
}
if(m_VertexHandle != 0)
{
glDeleteShader(m_VertexHandle);
m_VertexHandle = 0;
}
if(m_FragmentHandle != 0)
{
glDeleteShader(m_FragmentHandle);
m_FragmentHandle = 0;
}
}
bool Shader::Load(const char* a_FileName)
{
printf( "Loading shader: %s\n", a_FileName );
char* shaderFile = new char[strlen(a_FileName) + 6]; //(char*)calloc(custom::strlen(a_FileName) + 6, sizeof(char));
char* source = NULL;
strcpy(shaderFile, a_FileName);
strcat(shaderFile, ".geom");
source = GetShaderSource(shaderFile);
if(source != NULL)
{
printf( "Compiling geometry shader...\n" );
m_GeometryHandle = Compile(GL_GEOMETRY_SHADER, source);
free(source);
source = 0;
if(m_GeometryHandle == 0)
{
printf( "Geometry shader compiling failed.\n" );
delete[] shaderFile;
shaderFile = 0;
return false;
}
}
strcpy(shaderFile, a_FileName);
strcat(shaderFile, ".vert");
source = GetShaderSource(shaderFile);
if(source != NULL)
{
printf( "Compiling vertex shader...\n" );
m_VertexHandle = Compile(GL_VERTEX_SHADER, source);
free(source);
source = 0;
if(m_VertexHandle == 0)
{
printf( "Vertex shader compiling failed.\n" );
delete[] shaderFile;
shaderFile = 0;
return false;
}
}
else
{
printf("No vertex shader found. A vertex and fragment shader are required!\n");
}
strcpy(shaderFile, a_FileName);
strcat(shaderFile, ".frag");
source = GetShaderSource(shaderFile);
if(source != NULL)
{
printf( "Compiling fragment shader...\n" );
m_FragmentHandle = Compile(GL_FRAGMENT_SHADER, source);
free(source);
source = 0;
if(m_FragmentHandle == 0)
{
printf( "Fragment shader compiling failed.\n" );
delete[] shaderFile;
shaderFile = 0;
return false;
}
}
else
{
printf("No fragment shader found. A vertex and fragment shader are required!\n");
}
delete[] shaderFile;
shaderFile = 0;
CreateProgram();
if(!Link())
{
printf( "Linking of shader \"%s\" failed!\n", a_FileName );
return false;
}
printf( "Shader build succesfully!\n" );
return true;
}
// WARNING: YOU NEED TO FREE THE RETURNED SOURCE YOURSELF!! free(buffer);
char* Shader::GetShaderSource(const char* a_FileName)
{
FILE* f;
f = fopen(a_FileName, "rb");
if(f != NULL)
{
// Shader is available
char* buffer;
long size;
fseek(f, 0L, SEEK_END);
size = ftell(f);
rewind(f);
buffer = (char*)calloc(1, size+1);
if(!buffer)
{
fclose(f);
return NULL;
}
if(fread(buffer, size, 1, f) != 1)
{
fclose(f);
return NULL;
}
fclose(f);
return buffer;
}
return NULL;
}
GLuint Shader::Compile(const GLuint a_Type, const char* a_Source)
{
if(a_Source == NULL)
return 0;
GLuint handle = glCreateShader(a_Type); OGLCHECK
glShaderSource(handle, 1, &a_Source, NULL); OGLCHECK
glCompileShader(handle); OGLCHECK
int bufflen = 0;
GLint success = GL_FALSE;
glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &bufflen); OGLCHECK
if(bufflen > 1)
{
GLchar* logString = new GLchar[bufflen + 1];
glGetShaderInfoLog(handle, bufflen, 0, logString); OGLCHECK
printf( "Shader compile output:\n%s\n", logString );
delete logString;
logString = 0;
} else {
glGetShaderiv(handle, GL_PROGRAM_LOG_LENGTH, &bufflen); OGLCHECK
}
glGetShaderiv(handle, GL_COMPILE_STATUS, &success); OGLCHECK
if(success != GL_TRUE)
{
printf( "Failed to compile shader!\n" );
glDeleteShader(handle); OGLCHECK
//handle = 0;
}
return handle;
}
void Shader::CreateProgram()
{
m_ProgramHandle = glCreateProgram(); OGLCHECK
if(m_GeometryHandle != 0)
{
glAttachShader(m_ProgramHandle, m_GeometryHandle); OGLCHECK
printf( "Attaching geometry shader...\n" );
}
if(m_VertexHandle != 0)
{
glAttachShader(m_ProgramHandle, m_VertexHandle); OGLCHECK
printf( "Attaching vertex shader...\n" );
}
if(m_FragmentHandle != 0)
{
glAttachShader(m_ProgramHandle, m_FragmentHandle); OGLCHECK
printf( "Attaching fragment shader...\n" );
}
}
bool Shader::Link()
{
glLinkProgram(m_ProgramHandle);
GLint bufflen = 0;
glGetProgramiv(m_ProgramHandle, GL_INFO_LOG_LENGTH, &bufflen); OGLCHECK
if(bufflen > 1)
{
GLchar *logString = new GLchar[bufflen + 1];
glGetProgramInfoLog(m_ProgramHandle, bufflen, 0, logString);
printf( "Shader linking output:\n%s\n", logString );
delete logString;
logString = 0;
}
GLint success = GL_FALSE;
glGetProgramiv(m_ProgramHandle, GL_LINK_STATUS, &success); OGLCHECK
if(success != GL_TRUE)
{
printf( "Shader failed to link!\n" );
return false;
}
glValidateProgram(m_ProgramHandle); OGLCHECK
glGetProgramiv(m_ProgramHandle, GL_VALIDATE_STATUS, &success); OGLCHECK
if(success != GL_TRUE)
{
printf( "Shader program was not validated.!\n" );
}
GLint activeCount = 0;
GLint maxNameLength = 0;
glGetProgramiv(m_ProgramHandle, GL_ACTIVE_UNIFORMS, &activeCount); OGLCHECK
glGetProgramiv(m_ProgramHandle, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength); OGLCHECK
GLchar* name = new GLchar[maxNameLength];
GLsizei length = 100;
GLenum type = GL_INVALID_ENUM;
GLint size = 0;
for(int i=0; i<activeCount; ++i)
{
glGetActiveUniform(m_ProgramHandle, i, maxNameLength, &length, &size, &type, name); OGLCHECK
GLint handle = glGetUniformLocation(m_ProgramHandle, name); OGLCHECK
m_Parameters.insert(ParameterPair(name, handle));
}
glGetProgramiv(m_ProgramHandle, GL_ACTIVE_ATTRIBUTES, &activeCount); OGLCHECK
glGetProgramiv(m_ProgramHandle, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLength); OGLCHECK
delete name;
name = new GLchar[maxNameLength];
for(int i=0; i<activeCount; ++i)
{
glGetActiveAttrib(m_ProgramHandle, i, maxNameLength, &length, &size, &type, name); OGLCHECK
GLint handle = glGetAttribLocation(m_ProgramHandle, name); OGLCHECK
m_Attributes.insert(ParameterPair(name, handle));
}
delete name;
name = 0;
return true;
}
当我创建着色器时,我会:
Shader gShader;
gShader.load("data/shaders/myshader");
加载程序加载 data/shaders/myshader.frag data/shaders/myshader.vert 等。您可以在 Load 函数中看到这一点。
更新 1:我发现尽管着色器似乎可以在 IDE 中工作,但我无法绑定到属性位置。但我可以更改片段着色器中的颜色,这会显示出来。从终端属性工作正常,我尝试在 2 个统一位置绑定 2 个纹理并进行了一些混合,工作正常。