void Shader::link() { try { GLint success; // Link program. glLinkProgram(_shaderProgram); glGetProgramiv(_shaderProgram, GL_LINK_STATUS, &success); // Error check for linking if ( success == GL_FALSE ) { GLchar errorLog[1024]; glGetProgramInfoLog(_shaderProgram, sizeof(errorLog), NULL, errorLog); throw(ShaderException("Error linking shader program: "+ std::string(errorLog))); } glValidateProgram(_shaderProgram); glGetProgramiv(_shaderProgram, GL_VALIDATE_STATUS, &success); // Error check for validation if ( success == GL_FALSE ) { GLchar errorLog[1024]; glGetProgramInfoLog(_shaderProgram, sizeof(errorLog), NULL, errorLog); throw(ShaderException("Invalid shader program: "+std::string(errorLog))); } _bound = true; unbind(); } catch (ShaderException e) { std::cerr << e.what() << std::endl; exit(1); } }
void Shader::compileShader(const char *fileName, GLSLShader::ShaderType type) { if (fileName == nullptr) return; if (id_ <= 0) { id_ = glCreateProgram(); if (id_ == 0) { throw ShaderException("Unable to create shader program."); } } std::ifstream inFile(fileName, std::ios::in); if (!inFile) { std::string message = std::string("Unable to open: ") + fileName; throw ShaderException(message); } std::stringstream code; code << inFile.rdbuf(); inFile.close(); compileShader(code.str(), type, fileName); }
void Shader::validate() const { if (!isLinked()) { throw ShaderException("Program is not linked"); } GLint success; glValidateProgram(id_); glGetProgramiv(id_, GL_VALIDATE_STATUS, &success); if (!success) { int length = 0; std::string logString; glGetProgramiv(id_, GL_INFO_LOG_LENGTH, &length); if (length > 0) { char *c_log = new char[length]; int written = 0; glGetProgramInfoLog(id_, length, &written, c_log); logString = c_log; delete[] c_log; } throw ShaderException(std::string("Program failed to validate\n") + logString); } }
Shader(GLenum type, const std::string &filename, const std::string &defines) { RefCountedPtr<FileSystem::FileData> code = FileSystem::gameDataFiles.ReadFile(filename); if (!code.Valid()) Error("Could not load %s", filename.c_str()); // Load some common code RefCountedPtr<FileSystem::FileData> attributesCode = FileSystem::gameDataFiles.ReadFile("shaders/opengl/attributes.glsl"); assert(attributesCode.Valid()); RefCountedPtr<FileSystem::FileData> logzCode = FileSystem::gameDataFiles.ReadFile("shaders/opengl/logz.glsl"); assert(logzCode.Valid()); RefCountedPtr<FileSystem::FileData> libsCode = FileSystem::gameDataFiles.ReadFile("shaders/opengl/lib.glsl"); assert(libsCode.Valid()); AppendSource(s_glslVersion); AppendSource(defines.c_str()); if (type == GL_VERTEX_SHADER) { AppendSource("#define VERTEX_SHADER\n"); } else { AppendSource("#define FRAGMENT_SHADER\n"); } AppendSource(attributesCode->AsStringRange().StripUTF8BOM()); AppendSource(logzCode->AsStringRange().StripUTF8BOM()); AppendSource(libsCode->AsStringRange().StripUTF8BOM()); AppendSource(code->AsStringRange().StripUTF8BOM()); #if 0 static bool s_bDumpShaderSource = true; if (s_bDumpShaderSource) { const char SHADER_OUT_DIR_NAME[] = "shaders"; const char SHADER_OGL_OUT_DIR_NAME[] = "shaders/opengl"; FileSystem::userFiles.MakeDirectory(SHADER_OUT_DIR_NAME); FileSystem::userFiles.MakeDirectory(SHADER_OGL_OUT_DIR_NAME); const std::string outFilename(FileSystem::GetUserDir() + "/" + filename); FILE *tmp = fopen(outFilename.c_str(), "wb"); if(tmp) { Output("%s", filename); for( Uint32 i=0; i<blocks.size(); i++ ) { const char *block = blocks[i]; const GLint sizes = block_sizes[i]; if(block && sizes>0) { fprintf(tmp, "%.*s", sizes, block); } } fclose(tmp); } else { Output("Could not open file %s", outFilename.c_str()); } } #endif shader = glCreateShader(type); if(glIsShader(shader)!=GL_TRUE) throw ShaderException(); Compile(shader); // CheckGLSL may use OS::Warning instead of Error so the game may still (attempt to) run if (!check_glsl_errors(filename.c_str(), shader)) throw ShaderException(); };
void Shader::compileShader(const std::string &source, GLSLShader::ShaderType type, const char *fileName) { if (fileName == nullptr) return; if (id_ <= 0) { id_ = glCreateProgram(); if (id_ == 0) { throw ShaderException("Unable to create shader program."); } } GLuint shaderId = glCreateShader(type); const char *c_code = source.c_str(); glShaderSource(shaderId, 1, &c_code, NULL); glCompileShader(shaderId); GLint success; glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success); if (!success) { int length = 0; std::string logString; glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &length); if (length > 0) { char *c_log = new char[length]; int written = 0; glGetShaderInfoLog(shaderId, length, &written, c_log); logString = c_log; delete[] c_log; } std::string msg; if (fileName) { msg = std::string(fileName) + ": shader compilation failed\n"; } else { msg = "Shader compilation failed.\n"; } msg += logString; throw ShaderException(msg); } else { glAttachShader(id_, shaderId); } }
HRESULT Shader::Init( ID3D11Device* device, ID3D11DeviceContext* deviceContext, char* filename, const D3D11_INPUT_ELEMENT_DESC* inputElementDesc, unsigned int numElements ) { this->zDevice = device; this->zDeviceContext = deviceContext; this->zNumElements = numElements; this->zFilename = filename; this->zInputElementDesc = (D3D11_INPUT_ELEMENT_DESC*)inputElementDesc; HRESULT hr = S_OK; ID3DBlob* mBlobEffect = NULL; ID3DBlob* mBlobErrors = NULL; DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS; #if defined(DEBUG) || defined(_DEBUG) dwShaderFlags |= D3D10_SHADER_DEBUG; #endif D3DX11CompileFromFile(filename, NULL, NULL, "", "fx_5_0", dwShaderFlags, NULL, NULL, &mBlobEffect, &mBlobErrors, &hr); if (FAILED(hr)) { throw(ShaderException( __FILE__, __LINE__, __FUNCTION__, "Effect compilation error, file: " + zFilename)); } if (FAILED(hr = D3DX11CreateEffectFromMemory( mBlobEffect->GetBufferPointer(), mBlobEffect->GetBufferSize(), dwShaderFlags, this->zDevice, &this->zEffect))) { throw(ShaderException( __FILE__, __LINE__, __FUNCTION__, "Cannot create effect from memory, file: " + zFilename)); } SAFE_RELEASE(mBlobEffect); SAFE_RELEASE(mBlobErrors); return this->SetTechnique(0); }
void ShaderProgram::setUniform(const char* location, glm::mat4 mat) { if(!active) { throw ShaderException("You need to call ShaderProgram.begin() before assigning uniforms."); } GLuint m = glGetUniformLocation(program, location); glUniformMatrix4fv(m, 1, GL_FALSE, &mat[0][0]); }
HRESULT Shader::SetTechnique(UINT index) { HRESULT hr = S_OK; if (this->zCurrentTechIndex != index) { this->zCurrentTechIndex = index; this->zTechnique = this->zEffect->GetTechniqueByIndex(index); if (this->zInputElementDesc) { D3DX11_PASS_DESC passDesc; this->zTechnique->GetPassByIndex(0)->GetDesc(&passDesc); if (FAILED(hr = this->zDevice->CreateInputLayout( this->zInputElementDesc, this->zNumElements, passDesc.pIAInputSignature, passDesc.IAInputSignatureSize, &this->zInputLayout ))) { throw(ShaderException( __FILE__, __LINE__, __FUNCTION__, "Cannot create input layout")); } return hr; } } return hr; }
Shader::Shader(const std::string &source, Shader::Type type) { GLenum gl_type; switch (type) { case Shader::Vertex: gl_type = GL_VERTEX_SHADER; break; case Shader::Fragment: gl_type = GL_FRAGMENT_SHADER; break; default: throw Exception("Invalid shader type.\n"); } shader = GLSYM(glCreateShader)(gl_type); const char *src = source.c_str(); GLSYM(glShaderSource)(shader, 1, &src, 0); GLSYM(glCompileShader)(shader); GLint status; GLSYM(glGetShaderiv)(shader, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) throw ShaderException(shader); }
void ShaderProgram::setUniform(const char* location, float value) { if(!active) { throw ShaderException("You need to call ShaderProgram.begin() before assigning uniforms."); } GLuint m = glGetUniformLocation(program, location); glUniform1f(m, value); }
void ShaderProgram::setUniform(const char* location, glm::vec3 vec) { if(!active) { throw ShaderException("You need to call ShaderProgram.begin() before assigning uniforms."); } GLuint m = glGetUniformLocation(program, location); glUniform3fv(m, 1, &vec[0]); }
Shader(GLenum type, const std::string &filename, const std::string &defines) { RefCountedPtr<FileSystem::FileData> code = FileSystem::gameDataFiles.ReadFile(filename); if (!code) OS::Error("Could not load %s", filename.c_str()); // Load some common code RefCountedPtr<FileSystem::FileData> logzCode = FileSystem::gameDataFiles.ReadFile("shaders/gl2/logz.glsl"); assert(logzCode); RefCountedPtr<FileSystem::FileData> libsCode = FileSystem::gameDataFiles.ReadFile("shaders/gl2/lib.glsl"); assert(libsCode); AppendSource(s_glslVersion); AppendSource(defines.c_str()); if (type == GL_VERTEX_SHADER) AppendSource("#define VERTEX_SHADER\n"); else AppendSource("#define FRAGMENT_SHADER\n"); AppendSource(logzCode->AsStringRange().StripUTF8BOM()); AppendSource(libsCode->AsStringRange().StripUTF8BOM()); AppendSource(code->AsStringRange().StripUTF8BOM()); shader = glCreateShader(type); Compile(shader); // CheckGLSL may use OS::Warning instead of OS::Error so the game may still (attempt to) run if (!check_glsl_errors(filename.c_str(), shader)) throw ShaderException(); };
void Shader::compileShader(const char *fileName) { if (fileName == nullptr) return; int numExts = sizeof(ShaderInfo::extensions) / sizeof(ShaderInfo::shader_file_extension); std::string ext = getExtension(fileName); GLSLShader::ShaderType type = GLSLShader::VERTEX; bool matchFound = false; for (int i = 0; i < numExts; ++i) { if (ext == ShaderInfo::extensions[i].ext) { matchFound = true; type = ShaderInfo::extensions[i].type; break; } } if (!matchFound) { std::string msg = "Unrecognized extension: " + ext; throw ShaderException(msg); } compileShader(fileName, type); }
GLuint Shader::compileShader( std::string code, GLenum type ) { try { GLuint shader = glCreateShader(type); // Error checking if ( shader == 0 ) throw("Error creating shader type "+type); // Convert string to const char. const GLchar *sStringPtr[1]; sStringPtr[0] = code.c_str(); // Pass code to shader glShaderSource(shader, 1, (const GLchar **)sStringPtr, NULL); glCompileShader(shader); GLint success; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); // Error checking for compilation. if ( success == GL_FALSE ) { GLchar infoLog[1024]; glGetShaderInfoLog(shader, 1024, NULL, infoLog); std::ostringstream ss; ss << "Error compiling shader " << type << ": " << infoLog; ss << " in shader " << _shaderProgram; throw(ShaderException(ss.str())); } return shader; } catch ( ShaderException e ) { std::cerr << e.what() << std::endl; exit(1); } }
const Shader& Shader::use() const { if (id_ <= 0 || (!linked_)) { throw ShaderException("Shader has not been linked"); } glUseProgram(id_); return *this; }
void Shader::link() { if (linked_) return; if (id_ <= 0) { throw ShaderException("Program has not been compiled."); } glLinkProgram(id_); GLint success; glGetProgramiv(id_, GL_LINK_STATUS, &success); if (!success) { int length = 0; std::string logString; glGetProgramiv(id_, GL_INFO_LOG_LENGTH, &length); if (length > 0) { char *c_log = new char[length]; int written = 0; glGetProgramInfoLog(id_, length, &written, c_log); logString = c_log; delete[] c_log; } throw ShaderException(std::string("Program link failed:\n") + logString); } else { linked_ = true; } }
std::string ShaderProgram::readShaderFile(const char *path) { std::string shaderCode; std::ifstream shaderStream(path, std::ios::in); if(shaderStream.is_open()) { std::string line = ""; while(getline(shaderStream, line)) { shaderCode += "\n" + line; } shaderStream.close(); } else { throw ShaderException(std::string("Could not open file ") + path); } return shaderCode; }
void ShaderProgram::compileShader(GLuint shader, std::string shaderCode) { GLint compileResult = GL_FALSE; int infoLogLength; char const *sourcePointer = shaderCode.c_str(); glShaderSource(shader, 1, &sourcePointer, NULL); glCompileShader(shader); glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); if(compileResult == GL_FALSE) { glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); std::vector<char> shaderErrorMessage(infoLogLength); glGetShaderInfoLog(shader, infoLogLength, NULL, &shaderErrorMessage[0]); throw ShaderException(std::string("Error compiling shader: ") + &shaderErrorMessage[0]); } }
void Program::link() { for (auto shader = std::begin(shaders); shader != std::end(shaders); ++shader) GLSYM(glAttachShader)(program, (*shader)->object()); GLSYM(glLinkProgram)(program); GLint status; GLSYM(glGetProgramiv)(program, GL_LINK_STATUS, &status); if (status != GL_TRUE) throw ShaderException(program); //GLSYM(glValidateProgram)(program); //GLSYM(glGetProgramiv)(program, GL_VALIDATE_STATUS, &status); //if (status != GL_TRUE) // throw ShaderException(program); m_linked = true; }
GLuint ShaderProgram::linkProgram(GLuint vertShader, GLuint fragShader) { GLint compileResult = GL_FALSE; int infoLogLength; GLuint program = glCreateProgram(); glAttachShader(program, vertShader); glAttachShader(program, fragShader); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &compileResult); if(compileResult == GL_FALSE) { glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); std::vector<char> programErrorMessage(std::max(infoLogLength, int(1))); glGetProgramInfoLog(program, infoLogLength, NULL, &programErrorMessage[0]); throw ShaderException(std::string("Error linking shader program: ") + &programErrorMessage[0]); } return program; }
void Shader::loadFromParser(const ShaderParser& parser) { std::size_t count = static_cast<std::size_t>(tyr::ShaderType::Count); for(std::size_t index = static_cast<std::size_t>(tyr::ShaderType::Vertex); index < count; index++) { tyr::ShaderType type = static_cast<tyr::ShaderType>(index); if(parser.hasShader(type)) { std::unique_ptr<ShaderObject> object(new ShaderObject()); object->loadFromString(parser.getShaderSource(type), type); myObjects.push_back(std::move(object)); } } myShaderProgram = glCreateProgram(); for(std::size_t index = 0; index < myObjects.size(); index++) glAttachShader(myShaderProgram, myObjects[index]->getGLIdentifier()); glLinkProgram(myShaderProgram); GLint status; glGetProgramiv (myShaderProgram, GL_LINK_STATUS, &status); if(status == GL_FALSE) { GLint infoLogLength; glGetProgramiv(myShaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength); GLchar *strInfoLog = new GLchar[infoLogLength + 1]; glGetProgramInfoLog(myShaderProgram, infoLogLength, NULL, strInfoLog); throw ShaderException(std::string("Shader linker failure: ") + strInfoLog); delete[] strInfoLog; } for(std::size_t index = 0; index < myObjects.size(); index++) glDetachShader(myShaderProgram, myObjects[index]->getGLIdentifier()); myDepthSettings = parser.getDepthSettings(); myBlendSettings = parser.getBlendSettings(); }
void Shader::add( std::string fileName, GLenum type ) { try { if ( _shaderProgram == 0 ) _shaderProgram = glCreateProgram(); if (_shaderProgram == 0) throw (ShaderException("can't create shader program")); std::string code = addCode(fileName); GLuint object = compileShader(code, type); _shaderObjects.insert(std::pair<GLenum, GLuint>(type, object)); // Bind the shader to the program. glAttachShader(_shaderProgram, object); } catch (ShaderException e) { std::cerr << e.what() << std::endl; exit(1); } catch (std::exception & e) { std::cout << e.what() << std::endl; } catch (...) { std::cerr << "WTF" << std::endl; } }
void ShaderObject::loadFromString(const std::string& source, ShaderType type) { myType = type; myShaderID = glCreateShader(GetGLShaderType(type)); const char* sourcePointer = source.c_str(); glShaderSource(myShaderID, 1, &sourcePointer, NULL); glCompileShader(myShaderID); GLint status = GL_FALSE; glGetShaderiv(myShaderID, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { GLint infoLogLength; glGetShaderiv(myShaderID, GL_INFO_LOG_LENGTH, &infoLogLength); GLchar *strInfoLog = new GLchar[infoLogLength + 1]; glGetShaderInfoLog(myShaderID, infoLogLength, NULL, strInfoLog); throw ShaderException(myType, strInfoLog); delete[] strInfoLog; } }
Shader(GLenum type, const std::string &filename, const std::string &defines) { RefCountedPtr<FileSystem::FileData> filecode = FileSystem::gameDataFiles.ReadFile(filename); if (!filecode.Valid()) Error("Could not load %s", filename.c_str()); std::string strCode(filecode->AsStringRange().ToString()); size_t found = strCode.find("#include"); while (found != std::string::npos) { // find the name of the file to include const size_t begFilename = strCode.find_first_of("\"", found + 8) + 1; const size_t endFilename = strCode.find_first_of("\"", begFilename + 1); const std::string incFilename = strCode.substr(begFilename, endFilename - begFilename); // check we haven't it already included it (avoids circular dependencies) const std::set<std::string>::const_iterator foundIt = previousIncludes.find(incFilename); if (foundIt != previousIncludes.end()) { Error("Circular, or multiple, include of %s\n", incFilename.c_str()); } else { previousIncludes.insert(incFilename); } // build path for include const std::string incPathBuffer = stringf("shaders/opengl/%0", incFilename); // read included file RefCountedPtr<FileSystem::FileData> incCode = FileSystem::gameDataFiles.ReadFile(incPathBuffer); assert(incCode.Valid()); if (incCode.Valid()) { // replace the #include and filename with the included files text strCode.replace(found, (endFilename + 1) - found, incCode->GetData(), incCode->GetSize()); found = strCode.find("#include"); } else { Error("Could not load %s", incPathBuffer.c_str()); } } // Store the modified text with the included files (if any) const StringRange code(strCode.c_str(), strCode.size()); // Build the final shader text to be compiled AppendSource(s_glslVersion); AppendSource(defines.c_str()); if (type == GL_VERTEX_SHADER) { AppendSource("#define VERTEX_SHADER\n"); } else { AppendSource("#define FRAGMENT_SHADER\n"); } AppendSource(code.StripUTF8BOM()); #if 0 static bool s_bDumpShaderSource = true; if (s_bDumpShaderSource) { const char SHADER_OUT_DIR_NAME[] = "shaders"; const char SHADER_OGL_OUT_DIR_NAME[] = "shaders/opengl"; FileSystem::userFiles.MakeDirectory(SHADER_OUT_DIR_NAME); FileSystem::userFiles.MakeDirectory(SHADER_OGL_OUT_DIR_NAME); const std::string outFilename(FileSystem::GetUserDir() + "/" + filename); FILE *tmp = fopen(outFilename.c_str(), "wb"); if(tmp) { Output("%s", filename); for( Uint32 i=0; i<blocks.size(); i++ ) { const char *block = blocks[i]; const GLint sizes = block_sizes[i]; if(block && sizes>0) { fprintf(tmp, "%.*s", sizes, block); } } fclose(tmp); } else { Output("Could not open file %s", outFilename.c_str()); } } #endif shader = glCreateShader(type); if(glIsShader(shader)!=GL_TRUE) throw ShaderException(); Compile(shader); // CheckGLSL may use OS::Warning instead of Error so the game may still (attempt to) run if (!check_glsl_errors(filename.c_str(), shader)) throw ShaderException(); };