我对着色器的作用感到困惑。
我有一个着色器类,它为我包装着色的opengl部分。我在code :: blocks中构建我的应用程序并运行它,编译fase失败,链接阶段失败但GL_VALIDATE_STATUS
验证成功,着色器实际工作。
当我在codeblocks 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
或GL_GEOMETRY_SHADER
,a_Source
是const char*
,我的着色器代码是从文件加载的。
然后我继续检查编译状态:
glGetShaderiv(handle, GL_COMPILE_STATUS, &success); OGLCHECK
if(success != GL_TRUE)
{
这是一个逻辑检查,从终端运行时为GL_TRUE
,而从IDE运行时为GL_FALSE
。
链接检查如下
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个纹理,并做了一些混合,工作正常。