From fbd2e5d9a802db4fb5e056705ec599ac423e09be Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 27 Oct 2019 01:30:34 +0200 Subject: Create Shader class as a base for vertex and pixel shader --- src/RenderBackend/OpenGL/DeviceFrame.cpp | 2 + src/RenderBackend/OpenGL/PixelShader.cpp | 130 ++--------------------- src/RenderBackend/OpenGL/Shader.cpp | 169 ++++++++++++++++++++++++++++++ src/RenderBackend/OpenGL/ShaderVec.cpp | 20 ++-- src/RenderBackend/OpenGL/VertexShader.cpp | 111 ++------------------ src/main.cpp | 9 ++ 6 files changed, 212 insertions(+), 229 deletions(-) create mode 100644 src/RenderBackend/OpenGL/Shader.cpp (limited to 'src') diff --git a/src/RenderBackend/OpenGL/DeviceFrame.cpp b/src/RenderBackend/OpenGL/DeviceFrame.cpp index 9d60597..e79dfa1 100644 --- a/src/RenderBackend/OpenGL/DeviceFrame.cpp +++ b/src/RenderBackend/OpenGL/DeviceFrame.cpp @@ -28,9 +28,11 @@ namespace amalgine void DeviceFrame::draw() { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); for(DeviceMemory *deviceMemory : buffers) { deviceMemory->draw(); } + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } } diff --git a/src/RenderBackend/OpenGL/PixelShader.cpp b/src/RenderBackend/OpenGL/PixelShader.cpp index f263513..e6006f2 100644 --- a/src/RenderBackend/OpenGL/PixelShader.cpp +++ b/src/RenderBackend/OpenGL/PixelShader.cpp @@ -1,103 +1,18 @@ #include "../../../include/RenderBackend/OpenGL/PixelShader.hpp" #include "../../../include/RenderBackend/OpenGL/opengl.hpp" #include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp" -#include - -using namespace std; namespace amalgine { - PixelShaderTooManyAttributes::PixelShaderTooManyAttributes(i32 maxPixelAttributes) : - runtime_error(string("Attempting to define more than ") + to_string(maxPixelAttributes) + " pixel attributes") - { - - } - - PixelShaderAttributeAlreadyDefined::PixelShaderAttributeAlreadyDefined(const std::string &attributeName) : - runtime_error(string("A pixel attribute with the name ") + attributeName + " has already been defined") - { - - } - - PixelShaderInvalidAttributeName::PixelShaderInvalidAttributeName(const std::string &attributeName) : - runtime_error(string("Pixel attribute name ") + attributeName + " is invalid") - { - - } - - PixelShaderFunctionAlreadyDefined::PixelShaderFunctionAlreadyDefined(const std::string &funcName) : - runtime_error(string("Pixel shader function already defined: ") + funcName) + PixelShader::PixelShader() { - - } - - PixelShader::PixelShader() : locationCounter(0), mainFuncDefined(false) - { - glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxPixelAttribs); - writeHeader("#version 330 core\n\n"); - } - - const string& PixelShader::getOutputAttributeName(i32 attributeIndex) - { - assert(attributeIndex < pixelAttributeNames.size()); - return pixelAttributeNames[attributeIndex].name; + glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxAttribs); } - - ShaderOutputVec4 PixelShader::defineOutputVec4(const std::string &name) - { - i32 attributeIndex = defineOutputVariable(name, "vec4"); - return ShaderOutputVec4(this, attributeIndex); - } - - // TODO: Generate warning if global variable is defined but not assigned to? - ShaderGlobalVec3 PixelShader::defineGlobalVec3(const std::string &name) - { - if(!isShaderVariableNameValid(name.c_str())) - throw PixelShaderInvalidAttributeName(name); - - if(globalAttributes.find(name) != globalAttributes.end()) - throw PixelShaderAttributeAlreadyDefined(name); - - writeHeader("uniform vec3 "); - writeHeader(name); - writeHeader(";\n"); - - ShaderGlobalVec3 globalVec(name); - globalAttributes[name] = globalVec.getVecObject(); - return ShaderGlobalVec3(globalVec); - } - - i32 PixelShader::defineOutputVariable(const string &variableName, const char *typeName) - { - if(!isShaderVariableNameValid(variableName.c_str())) - throw PixelShaderInvalidAttributeName(variableName); - - if(locationCounter + 1 > maxPixelAttribs) - throw PixelShaderTooManyAttributes(maxPixelAttribs); - - if(pixelAttributes.find(variableName) != pixelAttributes.end()) - throw PixelShaderAttributeAlreadyDefined(variableName); - - i32 attributeIndex = locationCounter; - pixelAttributes[variableName] = locationCounter; - writeHeader("out "); - writeHeader(typeName); - writeHeader(" "); - writeHeader(variableName); - writeHeader(";\n"); - - ShaderAttribute shaderAttribute; - shaderAttribute.name = variableName; - shaderAttribute.typeName = typeName; - pixelAttributeNames.push_back(shaderAttribute); - ++locationCounter; - return attributeIndex; - } - + void PixelShader::defineMain(PixelShaderMainFunc mainFunc) { if(mainFuncDefined) - throw PixelShaderFunctionAlreadyDefined("main"); + throw ShaderFunctionAlreadyDefined("main"); writeBody("void main() {\n"); mainFunc(); @@ -105,38 +20,13 @@ namespace amalgine writeBody("}\n\n"); } - void PixelShader::assign(const ShaderOutputVec4 &lhsVariable, const ShaderVec4 &rhsVariable) - { - writeBody(lhsVariable.getName()); - writeBody(" = "); - writeBody(rhsVariable.getOutput()); - writeBody(";\n"); - } - - string PixelShader::build() const - { - std::string result; - result.reserve(header.size() + 2 + body.size()); - result += header; - result += "\n"; - result += body; - return result; - } - - void PixelShader::writeHeader(const string &code) - { - header += code; - } - - void PixelShader::writeBody(const string &code) - { - body += code; - } - Result PixelShader::compile() { + if(!mainFuncDefined) + return Result::Err("main function not defined (defineMain not called)"); + GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); - string verterShaderSource = build(); + std::string verterShaderSource = build(); const char *verterShaderSourcePtr = verterShaderSource.c_str(); printf("Vertex shader:\n%s\n", verterShaderSourcePtr); glShaderSource(fragmentShaderId, 1, &verterShaderSourcePtr, NULL); @@ -144,12 +34,12 @@ namespace amalgine GLint status; glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &status); - string compileLog = getShaderCompileLog((u32)fragmentShaderId); + std::string compileLog = getShaderCompileLog((u32)fragmentShaderId); if(status == GL_TRUE) { if(!compileLog.empty()) printf("Pixel shader compile log:\n%s", compileLog.c_str()); - return Result::Ok(new CompiledPixelShader(fragmentShaderId, move(pixelAttributes))); + return Result::Ok(new CompiledPixelShader(fragmentShaderId, move(inputAttributes))); } else return Result::Err(compileLog); diff --git a/src/RenderBackend/OpenGL/Shader.cpp b/src/RenderBackend/OpenGL/Shader.cpp new file mode 100644 index 0000000..fad1702 --- /dev/null +++ b/src/RenderBackend/OpenGL/Shader.cpp @@ -0,0 +1,169 @@ +#include "../../../include/RenderBackend/OpenGL/Shader.hpp" +#include "../../../include/RenderBackend/OpenGL/opengl.hpp" +#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp" +#include + +using namespace std; + +namespace amalgine { + ShaderTooManyAttributes::ShaderTooManyAttributes(i32 maxAttributes) : + runtime_error(string("Attempting to define more than ") + to_string(maxAttributes) + " attributes") + { + + } + + ShaderAttributeAlreadyDefined::ShaderAttributeAlreadyDefined(const std::string &attributeName) : + runtime_error(string("An attribute with the name ") + attributeName + " has already been defined") + { + + } + + ShaderInvalidAttributeName::ShaderInvalidAttributeName(const std::string &attributeName) : + runtime_error(string("Attribute name ") + attributeName + " is invalid") + { + + } + + ShaderFunctionAlreadyDefined::ShaderFunctionAlreadyDefined(const std::string &funcName) : + runtime_error(string("Shader function already defined: ") + funcName) + { + + } + + Shader::Shader() : inputLocationCounter(0), outputLocationCounter(0), mainFuncDefined(false) + { + writeHeader("#version 330 core\n\n"); + } + + const string& Shader::getOutputAttributeName(i32 attributeIndex) + { + assert(attributeIndex < (i32)outputAttributeNames.size()); + return outputAttributeNames[attributeIndex].name; + } + + const string& Shader::getInputAttributeName(i32 attributeIndex) const + { + assert(attributeIndex < (i32)inputAttributeNames.size()); + return inputAttributeNames[attributeIndex].name; + } + + AttributeType Shader::getInputAttributeType(i32 attributeIndex) const + { + assert(attributeIndex < (i32)inputAttributeNames.size()); + return getAttributeTypeByName(inputAttributeNames[attributeIndex].typeName); + } + + ShaderOutputVec4 Shader::defineOutputVec4(const std::string &name) + { + i32 attributeIndex = defineOutputVariable(name, "vec4"); + return ShaderOutputVec4(this, attributeIndex); + } + + // TODO: Generate warning if global variable is defined but not assigned to? + ShaderGlobalVec3 Shader::defineGlobalVec3(const std::string &name) + { + if(!isShaderVariableNameValid(name.c_str())) + throw ShaderInvalidAttributeName(name); + + if(uniforms.find(name) != uniforms.end()) + throw ShaderAttributeAlreadyDefined(name); + + writeHeader("uniform vec3 "); + writeHeader(name); + writeHeader(";\n"); + + ShaderGlobalVec3 globalVec(name); + uniforms[name] = globalVec.getVecObject(); + return ShaderGlobalVec3(globalVec); + } + + i32 Shader::defineOutputVariable(const string &variableName, const char *typeName) + { + if(!isShaderVariableNameValid(variableName.c_str())) + throw ShaderInvalidAttributeName(variableName); + + if(outputLocationCounter + 1 > maxAttribs) + throw ShaderTooManyAttributes(maxAttribs); + + if(outputAttributes.find(variableName) != outputAttributes.end()) + throw ShaderAttributeAlreadyDefined(variableName); + + i32 attributeIndex = outputLocationCounter; + outputAttributes[variableName] = outputLocationCounter; + writeHeader("out "); + writeHeader(typeName); + writeHeader(" "); + writeHeader(variableName); + writeHeader(";\n"); + + ShaderAttribute shaderAttribute; + shaderAttribute.name = variableName; + shaderAttribute.typeName = typeName; + outputAttributeNames.push_back(shaderAttribute); + ++outputLocationCounter; + return attributeIndex; + } + + ShaderInputVec2 Shader::defineInputVec2(const std::string &name) + { + i32 attributeIndex = defineInputVariable(name, "vec2"); + return ShaderInputVec2(this, attributeIndex); + } + + i32 Shader::defineInputVariable(const string &variableName, const char *typeName) + { + if(!isShaderVariableNameValid(variableName.c_str())) + throw ShaderInvalidAttributeName(variableName); + + if(inputLocationCounter + 1 > maxAttribs) + throw ShaderTooManyAttributes(maxAttribs); + + if(inputAttributes.find(variableName) != inputAttributes.end()) + throw ShaderAttributeAlreadyDefined(variableName); + + i32 attributeIndex = inputLocationCounter; + inputAttributes[variableName] = inputLocationCounter; + ShaderAttribute shaderAttribute; + shaderAttribute.name = variableName; + shaderAttribute.typeName = typeName; + inputAttributeNames.push_back(shaderAttribute); + + writeHeader("layout(location = "); + writeHeader(to_string(inputLocationCounter)); + ++inputLocationCounter; + writeHeader(") in "); + writeHeader(typeName); + writeHeader(" "); + writeHeader(variableName); + writeHeader(";\n"); + return attributeIndex; + } + + void Shader::assign(const ShaderOutputVec4 &lhsVariable, const ShaderVec4 &rhsVariable) + { + writeBody(lhsVariable.getName()); + writeBody(" = "); + writeBody(rhsVariable.getOutput()); + writeBody(";\n"); + } + + string Shader::build() const + { + std::string result; + result.reserve(header.size() + 2 + body.size()); + result += header; + result += "\n"; + result += body; + return result; + } + + void Shader::writeHeader(const string &code) + { + header += code; + } + + void Shader::writeBody(const string &code) + { + body += code; + } +} diff --git a/src/RenderBackend/OpenGL/ShaderVec.cpp b/src/RenderBackend/OpenGL/ShaderVec.cpp index dd3bbe5..8897b84 100644 --- a/src/RenderBackend/OpenGL/ShaderVec.cpp +++ b/src/RenderBackend/OpenGL/ShaderVec.cpp @@ -1,6 +1,5 @@ #include "../../../include/RenderBackend/OpenGL/ShaderVec.hpp" -#include "../../../include/RenderBackend/OpenGL/VertexShader.hpp" -#include "../../../include/RenderBackend/OpenGL/PixelShader.hpp" +#include "../../../include/RenderBackend/OpenGL/Shader.hpp" #include "../../../include/RenderBackend/OpenGL/ShaderProgram.hpp" #include "../../../include/RenderBackend/OpenGL/opengl.hpp" #include @@ -16,7 +15,16 @@ namespace amalgine { return AttributeType::VEC2; } + else if(strncmp(attributeName, "vec3", 4) == 0) + { + return AttributeType::VEC3; + } + else if(strncmp(attributeName, "vec4", 4) == 0) + { + return AttributeType::VEC4; + } + assert(false); return AttributeType::NONE; } @@ -28,13 +36,13 @@ namespace amalgine const string& ShaderInputVec2::getName() const { - return vertexShader->getInputAttributeName(attributeIndex); + return shader->getInputAttributeName(attributeIndex); } void ShaderInputVec2::setData(const DeviceMemory &data) { data.use(); - AttributeType attributeType = vertexShader->getInputAttributeType(attributeIndex); + AttributeType attributeType = shader->getInputAttributeType(attributeIndex); switch(attributeType) { case AttributeType::VEC2: @@ -51,11 +59,11 @@ namespace amalgine const string& ShaderOutputVec4::getName() const { - return pixelShader->getOutputAttributeName(attributeIndex); + return shader->getOutputAttributeName(attributeIndex); } void ShaderOutputVec4::operator=(const ShaderVec4 &shaderVec4) { - pixelShader->assign(*this, shaderVec4); + shader->assign(*this, shaderVec4); } } diff --git a/src/RenderBackend/OpenGL/VertexShader.cpp b/src/RenderBackend/OpenGL/VertexShader.cpp index ac9a159..19705b6 100644 --- a/src/RenderBackend/OpenGL/VertexShader.cpp +++ b/src/RenderBackend/OpenGL/VertexShader.cpp @@ -2,62 +2,16 @@ #include "../../../include/RenderBackend/OpenGL/opengl.hpp" #include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp" -using namespace std; - -namespace amalgine -{ - VertexShaderTooManyAttributes::VertexShaderTooManyAttributes(i32 maxVertexAttributes) : - runtime_error(string("Attempting to define more than ") + to_string(maxVertexAttributes) + " vertex attributes") - { - - } - - VertexShaderAttributeAlreadyDefined::VertexShaderAttributeAlreadyDefined(const std::string &attributeName) : - runtime_error(string("A vertex attribute with the name ") + attributeName + " has already been defined") - { - - } - - VertexShaderInvalidAttributeName::VertexShaderInvalidAttributeName(const std::string &attributeName) : - runtime_error(string("Vertex attribute name ") + attributeName + " is invalid") - { - - } - - VertexShaderFunctionAlreadyDefined::VertexShaderFunctionAlreadyDefined(const std::string &funcName) : - runtime_error(string("Vertex shader function already defined: ") + funcName) - { - - } - - VertexShader::VertexShader() : locationCounter(0), mainFuncDefined(false) - { - glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs); - writeHeader("#version 330 core\n\n"); - } - - const string& VertexShader::getInputAttributeName(i32 attributeIndex) const - { - assert(attributeIndex < vertexAttributeNames.size()); - return vertexAttributeNames[attributeIndex].name; - } - - AttributeType VertexShader::getInputAttributeType(i32 attributeIndex) const +namespace amalgine { + VertexShader::VertexShader() { - assert(attributeIndex < vertexAttributeNames.size()); - return getAttributeTypeByName(vertexAttributeNames[attributeIndex].typeName); + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs); } - - ShaderInputVec2 VertexShader::defineInputVec2(const std::string &name) - { - i32 attributeIndex = defineInputVariable(name, "vec2"); - return ShaderInputVec2(this, attributeIndex); - } - + void VertexShader::defineMain(VertexShaderMainFunc mainFunc) { if(mainFuncDefined) - throw VertexShaderFunctionAlreadyDefined("main"); + throw ShaderFunctionAlreadyDefined("main"); writeBody("void main() {\n"); ShaderVec4 glPosition = mainFunc(); @@ -66,60 +20,11 @@ namespace amalgine writeBody(glPosition.getOutput()); writeBody(";\n}\n\n"); } - - i32 VertexShader::defineInputVariable(const string &variableName, const char *typeName) - { - if(!isShaderVariableNameValid(variableName.c_str())) - throw VertexShaderInvalidAttributeName(variableName); - - if(locationCounter + 1 > maxVertexAttribs) - throw VertexShaderTooManyAttributes(maxVertexAttribs); - - if(vertexAttributes.find(variableName) != vertexAttributes.end()) - throw VertexShaderAttributeAlreadyDefined(variableName); - - i32 attributeIndex = locationCounter; - vertexAttributes[variableName] = locationCounter; - ShaderAttribute shaderAttribute; - shaderAttribute.name = variableName; - shaderAttribute.typeName = typeName; - vertexAttributeNames.push_back(shaderAttribute); - - writeHeader("layout(location = "); - writeHeader(to_string(locationCounter)); - ++locationCounter; - writeHeader(") in "); - writeHeader(typeName); - writeHeader(" "); - writeHeader(variableName); - writeHeader(";\n"); - return attributeIndex; - } - - string VertexShader::build() const - { - std::string result; - result.reserve(header.size() + 2 + body.size()); - result += header; - result += "\n"; - result += body; - return result; - } - - void VertexShader::writeHeader(const string &code) - { - header += code; - } - - void VertexShader::writeBody(const string &code) - { - body += code; - } - + Result VertexShader::compile() { GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); - string verterShaderSource = build(); + std::string verterShaderSource = build(); const char *verterShaderSourcePtr = verterShaderSource.c_str(); printf("Vertex shader:\n%s\n", verterShaderSourcePtr); glShaderSource(vertexShaderId, 1, &verterShaderSourcePtr, NULL); @@ -127,7 +32,7 @@ namespace amalgine GLint status; glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &status); - string compileLog = getShaderCompileLog((u32)vertexShaderId); + std::string compileLog = getShaderCompileLog((u32)vertexShaderId); if(status == GL_TRUE) { if(!compileLog.empty()) diff --git a/src/main.cpp b/src/main.cpp index ada75e2..24ef4f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -133,7 +133,16 @@ CompiledVertexShader* createVertexShader(const DeviceMemory &inputData) VertexShader vertexShader; ShaderInputVec2 inputPosition = vertexShader.defineInputVec2("position"); inputPosition.setData(inputData); + #if 0 + ShaderGlobalMat4x4 model = vertexShader.defineGlobalMat4x4("model"); + ShaderGlobalMat4x4 view = vertexShader.defineGlobalMat4x4("view"); + ShaderGlobalMat4x4 proj = vertexShader.defineGlobalMat4x4("proj"); + vertexShader.defineMain([&inputPosition, &model, &view, &proj]() + { + return proj * view * model * ShaderVec4(inputPosition, 0.0f, 1.0f); + }); + #endif vertexShader.defineMain([&inputPosition]() { return ShaderVec4(inputPosition, 0.0f, 1.0f); -- cgit v1.2.3