シェーダーが何をしているかについてかなり混乱しています。シェーディングの 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
または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 は空です。ターミナルから実行すると、コンパイルとリンクのステータスが成功し、検証も成功し、シェーダーが機能します。また、ターミナルから実行すると、警告などで情報ログがいっぱいになります。
この質問は、ここから来る問題を調査した後に形成されました: Linux での GLSL シェーダーのコンパイル
シェーダー クラスのソースは次のとおりです。
#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 つの均一な場所にバインドしようとし、いくつかのブレンドを行いましたが、正常に機能しました。