#pragma once //DGL #include "DGL_FundamentalTypes.hpp" #include "DGL_MiscTypes.hpp" #include "DGL_Enum.hpp" #include "DGL_Space.hpp" namespace GL { // Some Raw Source Defaults: RawString RawVertextShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "void main()\n" "{\n" " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" "}\0"; RawString RawFragmentShaderSource = "#version 400\n" "out vec4 frag_colour;" "void main() {" " frag_colour = vec4(0.5, 0.0, 0.5, 1.0);" "}"; // Default Shaders ID RawShader , SimpleShader , SimpleShader_Transformed ; ID ScreenSpaceVarID; // Forward Declarations sfn GetShaderInfo(ID _shader , gSize _logLength , ptr _infoLengthRef , RawString _infoLogRef) -> void; sfn QueryShader (ID _shaderToQuery, EShaderInfo _shaderInfoDesired, ptr _requestedInfoObject ) -> void; sfn MakeShader(Ref(ID) _shaderIDHolder, EShaderType _typeOfShader, uInt64 _numberOfStringElements, ptr> _sourceCode, ptr _lengthsOfStrings) -> void; sfn MakeShaderProgram(Ref(ID) _shaderProgramIDHolder, const ID _vertexShader, const ID _fragShader) -> void; // Functions sfn ActiveUniforms(ID _shaderToQueryForUniforms) -> GLint { GLint uniforms; glGetProgramiv(_shaderToQueryForUniforms, GL_ACTIVE_UNIFORMS, &uniforms); for (int i = 0; i < uniforms; i++) { int name_len = -1, num = -1; GLenum type = GL_ZERO; char name[100]; glGetActiveUniform(_shaderToQueryForUniforms, GLuint(i), sizeof(name) - 1, &name_len, &num, &type, name); name[name_len] = 0; } return uniforms; } sfn AttachShader(ID _shaderProgram, ID _shaderToAttach) { glAttachShader(_shaderProgram, _shaderToAttach); return; } sfn BindShaderSource(ID _shader, uInt64 _numberOfStringElements, ptr< RawString> _sourceCode, ptr _lengthsOfStrings) { glShaderSource(_shader, _numberOfStringElements, _sourceCode, _lengthsOfStrings); return; } sfn CompileShader(const ID _shaderToCompile) { glCompileShader(_shaderToCompile); gInt Result = gInt(EBool::False); gSize InfoLogLength; QueryShader(_shaderToCompile, EShaderInfo::CompileStatus, Address(Result)); if (!Result) { QueryShader(_shaderToCompile, EShaderInfo::InfoLogLength, Address(InfoLogLength)); if (InfoLogLength > 0) { std::vector ErrorMessage(InfoLogLength + 1); GetShaderInfo(_shaderToCompile, InfoLogLength, nullptr, Address(ErrorMessage.at(0))); throw std::runtime_error(Address(ErrorMessage.at(0))); } else { throw std::runtime_error("Shader compilation failed and did not get a proper info log."); } } return; } sfn CreateShader(EShaderType _typeOfShader) -> ID { return glCreateShader(GLenum(_typeOfShader)); } sfn CreateShaderProgram() -> ID { return glCreateProgram(); } sfn DeleteShader(ID _shaderToDelete) { glDeleteShader(_shaderToDelete); return; } sfn DetachShader(ID _shaderProgram, ID _shaderToDetach) { glDetachShader(_shaderProgram, _shaderToDetach); return; } sfn GetShaderInfo(ID _shader, gSize _logLength, ptr _infoLengthRef, RawString _infoLogRef) -> void { glGetShaderInfoLog(_shader, _logLength, _infoLengthRef, _infoLogRef); return; } sfn GetShaderProgramInfo(ID _shaderProgram, gSize _logLength, ptr _infoLengthRef, RawString _infoLogRef) -> void { glGetProgramInfoLog(_shaderProgram, _logLength, _infoLengthRef, _infoLogRef); } sfn GetUniformVariable(const ID _programID, RawString _nameOfVariable) -> ID { return glGetUniformLocation(_programID, _nameOfVariable); } sfn LinkProgramShader(ID _shaderProgramToLink) { glLinkProgram(_shaderProgramToLink); return; } sfn QueryShader(ID _shaderToQuery, EShaderInfo _shaderInfoDesired, ptr _requestedInfoObject) -> void { glGetShaderiv(_shaderToQuery, GLenum(_shaderInfoDesired), _requestedInfoObject); } sfn QueryShaderProgram(ID _shaderToQuery, EShaderProgramInfo _shaderProgramInfoDesired, ptr _requestedInfoObject) -> void { glGetProgramiv(_shaderToQuery, GLenum(_shaderProgramInfoDesired), _requestedInfoObject); } sfn LoadShaders(RawString _vertexShaderFilePath, RawString _fragmentShaderFilePath) -> ID { using std::cout ; using std::endl ; using std::ifstream ; using std::ios ; using std::string ; using std::stringstream; using std::vector ; string vertexShaderCode ; string fragmentShaderCode ; ifstream vertexShaderFileStream ; ifstream fragmentShaderFileStream; vertexShaderFileStream .open(_vertexShaderFilePath); fragmentShaderFileStream.open(_fragmentShaderFilePath); try { if (vertexShaderFileStream.is_open() and fragmentShaderFileStream.is_open()) { stringstream vertSourceStrStream; stringstream fragSourceStrStream; vertSourceStrStream << vertexShaderFileStream .rdbuf(); fragSourceStrStream << fragmentShaderFileStream.rdbuf(); vertexShaderFileStream .close(); fragmentShaderFileStream.close(); vertexShaderCode = vertSourceStrStream.str(); fragmentShaderCode = fragSourceStrStream.str(); } else { throw std::runtime_error("Impossible to open% s.Are you in the right directory ? Don't forget to read the FAQ !"); } RawString vertexSourcePtr = vertexShaderCode .c_str(); RawString fragmentSourcePtr = fragmentShaderCode.c_str(); cout << "Compiling shader: " << _vertexShaderFilePath << endl; ID vertexShader = CreateShader(EShaderType::Vertex); BindShaderSource(vertexShader, 1, Address(vertexSourcePtr), NULL); CompileShader (vertexShader ); cout << "Compiling shader: " << _fragmentShaderFilePath << endl; ID fragmentShader = CreateShader(EShaderType::Fragment); BindShaderSource(fragmentShader, 1, Address(fragmentSourcePtr), NULL); CompileShader (fragmentShader ); cout << "Making Shader Program and Linking..." << endl; ID generatedProgram; MakeShaderProgram(generatedProgram, vertexShader, fragmentShader); DeleteShader(vertexShader ); DeleteShader(fragmentShader); return generatedProgram; } catch (const std::runtime_error _error) { ErrorRuntime(_error); Exit(ExitCode::Failed); } } sfn LoadRawShader() { ID VertexShader ; ID FragmentShader; MakeShader(VertexShader , EShaderType::Vertex , 1, Address(GL::RawVertextShaderSource ), NULL); MakeShader(FragmentShader, EShaderType::Fragment, 1, Address(GL::RawFragmentShaderSource), NULL); GL::MakeShaderProgram(RawShader, VertexShader, FragmentShader); GL::DeleteShader(VertexShader ); GL::DeleteShader(FragmentShader); } sfn LoadSimpleShader() { SimpleShader = LoadShaders("SimpleVertexShader.vert", "SimpleFragmentShader.frag"); } sfn LoadSimpleShader_Transformed() { SimpleShader_Transformed = LoadShaders("SimpleTransform.vert", "SingleColor.frag"); ScreenSpaceVarID = GL::GetUniformVariable(GL::SimpleShader_Transformed, "modelViewProjection"); } sfn LoadDefaultShaders() { LoadRawShader (); LoadSimpleShader (); LoadSimpleShader_Transformed(); } sfn MakeShader ( Ref(ID) _shaderIDHolder , EShaderType _typeOfShader , uInt64 _numberOfStringElements, ptr> _sourceCode , ptr< const gInt > _lengthsOfStrings ) -> void { _shaderIDHolder = CreateShader(_typeOfShader); BindShaderSource(_shaderIDHolder, _numberOfStringElements, _sourceCode, _lengthsOfStrings); CompileShader(_shaderIDHolder); } sfn MakeShaderProgram(Ref(ID) _shaderProgramIDHolder, const ID _vertexShader, const ID _fragShader) -> void { _shaderProgramIDHolder = CreateShaderProgram(); AttachShader(_shaderProgramIDHolder, _vertexShader); AttachShader(_shaderProgramIDHolder, _fragShader ); LinkProgramShader(_shaderProgramIDHolder); gInt Result = false; QueryShaderProgram(_shaderProgramIDHolder, EShaderProgramInfo::LinkStatus, Address(Result)); if (!Result) { gInt infoLogLength; QueryShaderProgram(_shaderProgramIDHolder, EShaderProgramInfo::InfoLogLength, Address(infoLogLength)); if (infoLogLength > 0) { std::vector ErrorMessage(infoLogLength + 1); GetShaderProgramInfo(_shaderProgramIDHolder, infoLogLength, NULL, Address(ErrorMessage.at(0))); throw std::runtime_error(Address(ErrorMessage.at(0))); } else { throw std::runtime_error("ShaderProgram compilation failed and did not get a proper info log."); } } DetachShader(_shaderProgramIDHolder, _vertexShader); DetachShader(_shaderProgramIDHolder, _fragShader ); return; } sfn SetUniformVariable_MatrixVariableArray(const ID _matrixID, const gSize _numMatricies, const EBool _shouldTransposeValues, ptr _dataPtr) { glUniformMatrix4fv(_matrixID, _numMatricies, GLenum(_shouldTransposeValues), _dataPtr); } sfn UseProgramShader(ID _shaderProgramToUse) { glUseProgram(_shaderProgramToUse); return; } }