void ShaderProgram::Link(const std::string& vs, const std::string& ps) { std::string source; const char *src; source = File::ReadFile(vs); src = source.c_str(); GLuint vert_id = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vert_id, 1, &src, nullptr); glCompileShader(vert_id); ShaderLog(vert_id); glAttachShader(_id, vert_id); source = File::ReadFile(ps); src = source.c_str(); GLuint frag_id = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(frag_id, 1, &src, nullptr); glCompileShader(frag_id); ShaderLog(frag_id); glAttachShader(_id, frag_id); glBindFragDataLocation(_id, 0, "fragColor"); glLinkProgram(_id); ProgramLog(_id); }
bool ShaderLogF(const char *strMessage ...) { va_list args; va_start(args, strMessage); StdStrBuf Buf; Buf.FormatV(strMessage, args); return ShaderLog(Buf.getData()); }
void C4Shader::DumpInfoLog(const char *szWhat, GLhandleARB hShader) { // Get length of info line int iLength = 0; glGetObjectParameterivARB(hShader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &iLength); if(iLength <= 1) return; // Allocate buffer, get data char *pBuf = new char [iLength + 1]; int iActualLength = 0; glGetInfoLogARB(hShader, iLength, &iActualLength, pBuf); if(iActualLength > iLength || iActualLength <= 0) return; // Terminate, log pBuf[iActualLength] = '\0'; ShaderLogF(" gl: Compiling %s:", szWhat); ShaderLog(pBuf); delete[] pBuf; }
bool C4Shader::Init(const char *szWhat, const char **szUniforms) { #ifndef USE_CONSOLE // No support? if(!GLEW_ARB_fragment_program) { Log(" gl: no shader support!"); return false; } // Clear old shader first if (hProg) Clear(); #endif StdStrBuf VertexShader = Build(VertexSlices, true), FragmentShader = Build(FragmentSlices, true); // Dump if (C4Shader::IsLogging()) { ShaderLogF("******** Vertex shader for %s:", szWhat); ShaderLog(VertexShader.getData()); ShaderLogF("******** Fragment shader for %s:", szWhat); ShaderLog(FragmentShader.getData()); } #ifndef USE_CONSOLE // Attempt to create shaders hVert = Create(GL_VERTEX_SHADER_ARB, FormatString("%s vertex shader", szWhat).getData(), VertexShader.getData()); hFrag = Create(GL_FRAGMENT_SHADER_ARB, FormatString("%s fragment shader", szWhat).getData(), FragmentShader.getData()); if(!hFrag || !hVert) return false; // Link program hProg = glCreateProgramObjectARB(); #ifdef GL_KHR_debug if (glObjectLabel) glObjectLabel(GL_PROGRAM, hProg, -1, szWhat); #endif glAttachObjectARB(hProg, hVert); glAttachObjectARB(hProg, hFrag); // Bind all input variables for (int i = 0; i <= VAI_BoneWeightsMax - VAI_BoneWeights; ++i) { glBindAttribLocation(hProg, VAI_BoneWeights + i, FormatString("oc_BoneWeights%d", i).getData()); glBindAttribLocation(hProg, VAI_BoneIndices + i, FormatString("oc_BoneIndices%d", i).getData()); } glLinkProgramARB(hProg); // Link successful? DumpInfoLog(FormatString("%s shader program", szWhat).getData(), hProg); if(GetObjectStatus(hProg, GL_OBJECT_LINK_STATUS_ARB) != 1) { Clear(); ShaderLogF(" gl: Failed to link %s shader!", szWhat); return false; } ShaderLogF(" gl: %s shader linked successfully", szWhat); // Okay, allocate uniform array iUniformCount = 0; while (szUniforms[iUniformCount]) iUniformCount++; pUniforms = new GLint[iUniformCount]; // Get uniform locations. Note this is expected to fail for a few of them // because the respective uniforms got optimized out! for (int i = 0; i < iUniformCount; i++) pUniforms[i] = glGetUniformLocationARB(hProg, szUniforms[i]); #endif return true; }