diff --git a/CMakeLists.txt b/CMakeLists.txt index 86711d85b7766c380b260fb969e6acb659f383dc..2ec0a899b7e1632d87bf6515b445aa0b37802d0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,6 +65,9 @@ target_sources( PRIVATE ${SRCDIR}/src/VertexArray.cpp PRIVATE ${SRCDIR}/src/VertexBuffer.cpp PRIVATE ${SRCDIR}/src/Watcher.cpp + + PRIVATE ${SRCDIR}/src/UniformBuffer.cpp + PRIVATE ${SRCDIR}/src/ShaderIntrospector.cpp ) # diff --git a/Notes to self.txt b/Notes to self.txt new file mode 100644 index 0000000000000000000000000000000000000000..9b79d05403aa488f82045708d8a61140239062cf --- /dev/null +++ b/Notes to self.txt @@ -0,0 +1,2 @@ +Use shader introspection find which shaders need to attach to the uniform block points, resulting in sets of shaders where binding point would be the key. +this way we can loop through them \ No newline at end of file diff --git a/assets/materials/brick.yml b/assets/materials/brick.yml index c3da7b67d997986a45d4e0b74b6dd1afc87f7f60..54a753956a8525abade168b20700293ee0b0d5c8 100644 --- a/assets/materials/brick.yml +++ b/assets/materials/brick.yml @@ -1,7 +1,10 @@ -maps: 2 +maps: 3 + mainTex: scifi + bumpTex: scifi_nrm + specTex: scifi_spec - mainTexture: brickwall - specularTex: brickwall-nrm - -values: 1 - test: 0.8 +values: 4 + opacity: 1 + intensity: 1 + bumpiness: 1 + specularity: 0 diff --git a/assets/models/cube.yml b/assets/models/cube.yml index f0cd7325336aa694d033f599bf888333dd315f0f..e8a25b54f8eec50c3f9a77557945a2f878fb1d9b 100644 --- a/assets/models/cube.yml +++ b/assets/models/cube.yml @@ -41,7 +41,6 @@ v: 1.0 1.0 -1.0 0.577 0.577 -0.577 1 0 255 255 255 80 v: -1.0 1.0 1.0 -0.577 0.577 0.577 0 1 255 255 255 80 v: 1.0 1.0 1.0 0.577 0.577 0.577 1 1 255 255 255 80 - meshes: 2 mesh: innercube @@ -68,7 +67,7 @@ mesh: innercube mesh: outercube material: brick - shader: base + shader: edge triangles: 12 t: 14 15 16 t: 16 17 14 diff --git a/assets/shaders/base.glsl b/assets/shaders/base.glsl index 8a98e2b8ba44e9ef3903ab22364662305cd922b1..169e01cd28b3284432de13e3d1fb5e99ce0f64fb 100644 --- a/assets/shaders/base.glsl +++ b/assets/shaders/base.glsl @@ -1,73 +1,143 @@ #shader vertex -#version 410 core +#version 410 layout(location = 0) in vec4 position; layout(location = 1) in vec3 normal; layout(location = 2) in vec2 uv; -layout(location = 3) in vec4 vertex_color_from_program; +layout(location = 3) in vec4 vertex_color; -noperspective out vec2 texCoord; -smooth out vec4 vertex_color_out; +out vec2 texCoord; +out vec4 vertex_color_out; out vec4 pos; -uniform mat4 projection = mat4(1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); +uniform mat4 m2w; +uniform float time = 0; -uniform mat4 view = mat4(1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); +layout(std140) uniform OK_Matrices{ + mat4 projection; + mat4 view; + vec4 view_position; +}; -uniform mat4 model = mat4(1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); -uniform float time = 0; mat4 rotate(float x, float y, float z) { return mat4( - (cos(y + z) + cos(y - z)) / 2, (-sin(y + z) + sin(y - z)) / 2, -sin(y), 0, - (cos(x + y + z) - cos(x - y + z) + cos(x + y - z) - cos(x - y - z) + 2 * sin(x + z) - 2 * sin(x - z)) / 4, (2 * cos(x + z) + 2 * cos(x - z) - sin(x + y + z) + sin(x - y + z) + sin(x + y - z) - sin(x - y - z)) / 4, (-sin(x + y) - sin(x - y)) / 2, 0, - (-2 * cos(x + z) + 2 * cos(x - z) + sin(x + y + z) - sin(x - y + z) + sin(x + y - z) - sin(x - y - z)) / 4, (cos(x + y + z) - cos(x - y + z) - cos(x + y - z) + cos(x - y - z) + 2 * sin(x + z) + 2 * sin(x - z)) / 4, (cos(x + y) + cos(x - y)) / 2, 0, - 0, 0, 0, 1 + (cos(y + z) + cos(y - z)) / 2, (-sin(y + z) + sin(y - z)) / 2, -sin(y), 0, + (cos(x + y + z) - cos(x - y + z) + cos(x + y - z) - cos(x - y - z) + 2 * sin(x + z) - 2 * sin(x - z)) / 4, (2 * cos(x + z) + 2 * cos(x - z) - sin(x + y + z) + sin(x - y + z) + sin(x + y - z) - sin(x - y - z)) / 4, (-sin(x + y) - sin(x - y)) / 2, 0, + (-2 * cos(x + z) + 2 * cos(x - z) + sin(x + y + z) - sin(x - y + z) + sin(x + y - z) - sin(x - y - z)) / 4, (cos(x + y + z) - cos(x - y + z) - cos(x + y - z) + cos(x - y - z) + 2 * sin(x + z) + 2 * sin(x - z)) / 4, (cos(x + y) + cos(x - y)) / 2, 0, + 0, 0, 0, 1 ); } +out vec3 fragVert; +out vec3 fragNormal; + +vec4 MVP(in vec4 position) { + return projection * view * m2w * position; +} + + void main() { -// model to world space transformations = transform -// translation * rotation * scale * vertexPos; + float F = sqrt(position.x*position.x + position.y*position.y + position.z*position.z) * 0.01; + mat4 rot = rotate(0, time*F, 0); - float F = sqrt(position.x*position.x + position.y*position.y + position.z*position.z); - gl_Position = projection * view * model * position; - - vertex_color_out = vertex_color_from_program; - texCoord = uv; - pos = gl_Position; -} + vec4 rotatedNormal = rot * vec4(normal, 1); + // Pass some variables to the fragment shader + //fragNormal = vec3(rotatedNormal); + vertex_color_out = rotatedNormal; + texCoord = uv; + fragNormal = mat3(transpose(inverse(m2w))) * normal; + vec4 out_position = MVP(position); + gl_Position = out_position; + fragVert = vec3(m2w * position); +} #shader fragment -#version 410 +#version 140 + +#define MAX_LIGHTS 8 + in vec4 gl_FragCoord; -// in vec2 gl_PointCoord; // @NOTE Not supported on [macos, openGL 4.1] -noperspective in vec2 texCoord; -smooth in vec4 vertex_color_out; -in vec4 pos; +in vec2 texCoord; +in vec3 fragNormal; +in vec3 fragVert; + out vec4 out_color; uniform float time = 0; -uniform sampler2D mainTexture; - -uniform float test = 1; +uniform sampler2D mainTex; +uniform sampler2D bumpTex; +uniform sampler2D specTex; + +uniform float opacity = 0; +uniform float specularity = 1; +uniform float intensity = 1; +uniform float bumpiness = 1; + +uniform mat4 m2w; + +layout(std140) uniform OK_Matrices{ + mat4 projection; + mat4 view; + vec4 view_position; +}; + +struct OK_Light { + vec4 position; + vec4 intensities; +}; + +layout(std140) uniform OK_Lights{ + OK_Light light[MAX_LIGHTS]; +//float spread; +//float constant; +//float linear; +//float quadratic; +}; + +vec3 OK_PointLight(in vec3 position, in vec3 intensities/*, in float constant, in float linear, in float quadratic*/) { + //Ambience + float ambientStrength = 0.1; + vec3 ambient = ambientStrength * intensities; + + vec3 bump = texture(bumpTex, texCoord).rgb*intensity; + // Diffussion + vec3 norm = normalize(fragNormal*bump); + vec3 lightDir = normalize(position - fragVert); + float diffusion = max(dot(norm, lightDir), 0.0); + vec3 diffuse = diffusion * intensities; + + // Specularity + //float specularStrength = 0.5; + //vec3 viewDir = normalize(view_position.xyz - fragVert); + //vec3 reflectDir = reflect(-lightDir, norm); + //float specPower = pow(max(dot(viewDir, reflectDir), 0.0), 32); + //vec3 specular = specularStrength * specPower * intensities; + + // Attenuation + //float distance = length(position - fragVert); + float attenuation = 1.0; // /(constant + linear * distance + quadratic * (distance * distance)); + + return (ambient*attenuation + diffuse * attenuation /*+ specular*specularity*attenuation*/); +} void main() { - out_color = test*vec4(texture(mainTexture, texCoord).rgb * vertex_color_out.rgb, vertex_color_out.a); + + vec3 diff = texture(mainTex, texCoord).rgb; + vec3 bump = texture(bumpTex, texCoord).rgb; + vec3 spec = texture(specTex, texCoord).rgb; + + vec3 light0 = OK_PointLight(light[0].position.xyz, light[0].intensities.rgb /*,light[0].constant,light[0].linear, light[0].quadratic*/); + vec3 light1 = OK_PointLight(light[1].position.xyz, light[1].intensities.rgb /*,light[1].constant,light[1].linear, light[1].quadratic*/); + vec3 light2 = OK_PointLight(light[2].position.xyz, light[2].intensities.rgb /*,light[1].constant,light[1].linear, light[1].quadratic*/); + + //out_color = vec4(fragNormal, 1)*0.2 + 0.8*vec4(texture(mainTex, texCoord).rgb , vertex_color_out.a); + out_color = vec4((light0+ light1+ light2) * diff, 1); } -//out_color = vec4(texture(mainTexture, texCoord).rgb * vertex_color_out.rgb, vertex_color_out.a); +//out_color = vec4(texture(mainTexture, texCoord).rgb * vertex_color_out.rgb, vertex_color_out.a); \ No newline at end of file diff --git a/assets/shaders/default.glsl b/assets/shaders/default.glsl index 9536132f6f05063c946e6415a67da69a0b1a21c3..a2c599dc67c1cc89d1e800dbaae10bb125ff6fff 100644 --- a/assets/shaders/default.glsl +++ b/assets/shaders/default.glsl @@ -61,4 +61,4 @@ uniform float transparency = 1; void main() { out_color = transparency*vec4(texture(mainTexture, texCoord).rgb, 1); -} +} \ No newline at end of file diff --git a/assets/textures/example.jpg b/assets/textures/example.jpg new file mode 100644 index 0000000000000000000000000000000000000000..80e18a0e645c93427a2e755731659f550496afeb Binary files /dev/null and b/assets/textures/example.jpg differ diff --git a/assets/textures/example_nrm.jpg b/assets/textures/example_nrm.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dfd5e3f6b0943cb9def857668c2daa36971cb6c8 Binary files /dev/null and b/assets/textures/example_nrm.jpg differ diff --git a/assets/textures/nrm_test.jpg b/assets/textures/nrm_test.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e96665c655e42d8ddb438c3a736786648d54b6a7 Binary files /dev/null and b/assets/textures/nrm_test.jpg differ diff --git a/assets/textures/scifi.jpg b/assets/textures/scifi.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ac700da85584e76141fc9b99d9f5737f198abe57 Binary files /dev/null and b/assets/textures/scifi.jpg differ diff --git a/assets/textures/scifi_nrm.jpg b/assets/textures/scifi_nrm.jpg new file mode 100644 index 0000000000000000000000000000000000000000..886fd7fecd9a6054b7020f22a33a577d02c2232d Binary files /dev/null and b/assets/textures/scifi_nrm.jpg differ diff --git a/assets/textures/scifi_spec.jpg b/assets/textures/scifi_spec.jpg new file mode 100644 index 0000000000000000000000000000000000000000..667c04f08d7e43b12eb9a97af73924fe136917ff Binary files /dev/null and b/assets/textures/scifi_spec.jpg differ diff --git a/include/overkill/Config.hpp b/include/overkill/Config.hpp index 436228a574369e7cc72c05911845c3f65354ff34..0bee93ede1f0438839449c818a65a6acd502bf13 100644 --- a/include/overkill/Config.hpp +++ b/include/overkill/Config.hpp @@ -22,7 +22,8 @@ namespace overkill::C constexpr float NearClip = 0.1f; constexpr float FarClip = 100.0f; constexpr float CameraOffset = -70; //How far back the camera is from the center of the scene. - const glm::vec4 ClearColor { 0.05f, 0.06f, 0.075f, 1.0f }; + const glm::vec4 ClearColor { 0.05f, 0.06f, 0.075f, 1.0f }; // Sexy blue + constexpr char PathBaseShader[] = "assets/shaders/base.shader"; constexpr char PathBaseTexture[] = "assets/textures/Checkers.jpg"; constexpr float PI = 3.14159265359f; @@ -33,5 +34,5 @@ namespace overkill::C constexpr char ModelsFolder[] = "assets/models"; constexpr char ScenesFolder[] = "assets/scenes"; - + constexpr unsigned int MAX_LIGHTS = 8; //inject it into shaders } diff --git a/include/overkill/Entity.hpp b/include/overkill/Entity.hpp index 2c77fcb5f2edb30fc08be36c4cbe18508afc748a..55d33a691fe78d3dc97b459d5949f3b068f1d827 100644 --- a/include/overkill/Entity.hpp +++ b/include/overkill/Entity.hpp @@ -1,5 +1,4 @@ #pragma once - #include <string> @@ -34,4 +33,26 @@ public: void update(float dt); }; +struct Transform +{ + + const glm::vec3 right{ 1.0f,0.0f,0.0f }; + const glm::vec3 up{ 0.0f,1.0f,0.0f }; + const glm::vec3 forward{ 0.0f,0.0f,1.0f }; + const glm::vec3 one{ 1.0f, 1.0f, 1.0f }; + const glm::vec3 zero{ 0.0f ,0.0f ,0.0f }; + + glm::vec3 m_position = zero; + glm::vec3 m_rotation = zero; + glm::vec3 m_scale = one; + + auto modelToWorld()->glm::mat4; +}; + + +struct Light : public Transform +{ + glm::vec3 intensities = one; //a.k.a the color of the light +}; + } \ No newline at end of file diff --git a/include/overkill/EntityModel.hpp b/include/overkill/EntityModel.hpp index 0a4f2aae0c8c7c772d1320c1fc315ced65e832ba..e520f58ec928d7beabf1c7986dafeab54890f4db 100644 --- a/include/overkill/EntityModel.hpp +++ b/include/overkill/EntityModel.hpp @@ -10,6 +10,7 @@ namespace overkill { + class Renderer; class EntityModel : public Entity { @@ -17,9 +18,9 @@ private: int m_modelID; // What model with id will be used to draw Entity. glm::vec3 m_scale; +public: glm::mat4 getModelMatrix(); -public: EntityModel(C::Tag modelTag, glm::vec3 pos = glm::vec3(0,0,0), glm::vec3 rot = glm::vec3(0,0,0), glm::vec3 scale = glm::vec3(1,1,1), glm::vec3 vel = glm::vec3(0,0,0), @@ -34,4 +35,4 @@ public: void draw(); }; -} \ No newline at end of file +} diff --git a/include/overkill/Renderer.hpp b/include/overkill/Renderer.hpp index f34f184febcc167422c12fc862a3213fb72a7a58..8542bc2112a5d59895f8fc558a9a8670e561eeee 100644 --- a/include/overkill/Renderer.hpp +++ b/include/overkill/Renderer.hpp @@ -7,24 +7,23 @@ #include <overkill/ElementBuffer.hpp> #include <overkill/ShaderProgram.hpp> #include <overkill/Model.hpp> +#include <overkill/EntityModel.hpp> namespace overkill { +class EntityModel; + class Renderer { public: static void clear(); static void draw(const VertexArray& va, const ElementBuffer& eb, const ShaderProgram& shader); static void draw(const Model& model, glm::mat4 modelMatrix = glm::mat4(1)); // Model matrix is translation rotation and scale of the model. - - + + static void draw( EntityModel& entity, float t ); + //static void draw( EntityModel& entity, float t); }; -class EdgeRenderer : public Renderer -{ -public: - void drawEdged(const VertexArray& va, const ElementBuffer& eb, const ShaderProgram& shader, const ShaderProgram& edgeShader) const; -}; } diff --git a/include/overkill/ShaderIntrospector.hpp b/include/overkill/ShaderIntrospector.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5d0ec846ce46aa455ab86f75753cc4f215e556fe --- /dev/null +++ b/include/overkill/ShaderIntrospector.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include <overkill/gl_caller.hpp> +#include <string> +#include <vector> + +namespace overkill +{ +class ShaderIntrospector +{ +public: + static GLint getActiveBlockCount(const GLuint program); + static const std::vector<GLint> getUniformBlockUniformIndices(const GLuint program, const GLuint uBlockIndex); + static const std::string getUnifromBlockName(const GLuint program, const GLint uBlockIndex); + static GLuint getUniformBlockIndex(const GLuint program, const std::string& name); + static GLuint getUniformBufferMaxSize(const GLuint program); + static GLint getUniformBlockBinding(const GLuint program, GLuint uniformBlockIndex); +}; + +} + +/* + +map: + tag: + program: blockIndex + program: blockIndex + + +*/ \ No newline at end of file diff --git a/include/overkill/ShaderProgram.hpp b/include/overkill/ShaderProgram.hpp index 6b73cee2b68629ce83add8726656ec744fe9a875..a9eb506e962dbd8a16f63a05771711ef6d6e336a 100644 --- a/include/overkill/ShaderProgram.hpp +++ b/include/overkill/ShaderProgram.hpp @@ -11,6 +11,7 @@ #include <overkill/gl_util.hpp> #include <overkill/Texture.hpp> #include <overkill/Material.hpp> +#include <overkill/ShaderIntrospector.hpp> namespace overkill { @@ -33,6 +34,7 @@ class ShaderProgram }; private: std::unordered_map<std::string, GLint> uniforms; + std::unordered_map<std::string, GLint> uniformBlocks; void construct(const std::string& vert, const std::string& frag, const std::string& geom); @@ -58,7 +60,8 @@ public: static ShaderSource ParseProgram(const std::string& file); static GLuint CompileShader(GLuint type, const std::string& source); - + GLuint getUniformBlockIndex(const std::string& blockName) const; + }; // @note unused functions diff --git a/include/overkill/ShaderSystem.hpp b/include/overkill/ShaderSystem.hpp index cd4fe69d6809deae186274eeffaa7f9fd0e5f08d..844500a86c43a544dfe17e4fc92205b058d792dc 100644 --- a/include/overkill/ShaderSystem.hpp +++ b/include/overkill/ShaderSystem.hpp @@ -1,16 +1,30 @@ #pragma once +#include <set> #include <vector> #include <string> #include <unordered_map> #include <overkill/Config.hpp> #include <overkill/ShaderProgram.hpp> +#include <overkill/UniformBuffer.hpp> +#include <overkill/ShaderIntrospector.hpp> #include <overkill/Watcher.hpp> namespace overkill { + struct MVP { + glm::mat4 view; + glm::mat4 projection; + }; + + struct LightData { + glm::vec4 position; + glm::vec4 intensities; + float spread; + }; + class ShaderSystem { @@ -18,17 +32,27 @@ public: using OnUpdate = void (*)(C::ID, C::ID, C::ID); struct UpdateCallback { - C::Tag tag; C::ID modelID; C::ID meshID; OnUpdate callback; }; private: - static std::vector<ShaderProgram> m_shaderPrograms; - static std::unordered_map<C::Tag, C::ID> m_mapShaderProgramID; - static std::vector<UpdateCallback> m_updateCallbacks; + + + static std::unordered_map<C::Tag, std::set<GLuint>> m_mapUniformBufferTargets; + static std::vector<UniformBuffer> m_uniformBuffers; + static std::unordered_map<C::Tag, C::ID> m_mapUniformBuffersID; + + static std::vector<ShaderProgram> m_shaderPrograms; + static std::unordered_map<C::Tag, C::ID> m_mapShaderProgramID; + + static std::vector<UpdateCallback> m_updateCallbacks; + static void push(const C::Tag tag, const std::string& filepath); + static void pushUniformBuffer(const C::Tag&& tag, GLuint size); + static void linkUniformBlocks(); + static void linkUniformBlocksForAll(); public: // <summary> Load all shader data onto GPU memory. @@ -41,7 +65,18 @@ public: static auto copyByTag(const C::Tag& tag) -> ShaderProgram; static auto copyById(C::ID shaderProgramID) -> ShaderProgram; static void bindOnUpdate(const C::Tag& shaderTag, C::ID modelID, C::ID meshID, OnUpdate onUpdate); + static void unbindAll(); + + static auto getUniformBufferIdByTag(const C::Tag& tag)->C::ID; + static auto getUniformBufferByTag(const C::Tag& tag) -> const UniformBuffer&; + static auto getUniformBufferById(C::ID uBufferID) -> const UniformBuffer&; + + + + GLuint getBlockUniformLocation(const C::Tag& uBlock, const C::Tag& uniform); + static auto updateUniformBlock(C::ID uBufferID, C::ID uniformLocation); + //void ShaderProgram::bindUniformBlockToAll(GLuint blockIndex); }; } diff --git a/include/overkill/UniformBuffer.hpp b/include/overkill/UniformBuffer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8a9fddd50bbf2062809d8aef4530c98305bf62a9 --- /dev/null +++ b/include/overkill/UniformBuffer.hpp @@ -0,0 +1,145 @@ +#pragma once + +#include <overkill/gl_caller.hpp> +#include <overkill/ShaderProgram.hpp> +#include <overkill/Config.hpp> +#include <vector> +#include <unordered_map> + +namespace overkill +{ + + +struct BlockLayout +{ +private: + std::unordered_map<C::Tag, GLuint> m_vars; + //std::unordered_map<C::Tag, BlockLayout> m_blocks; + GLuint m_blockSize; //the combined size of this block + C::Tag m_name; +public: + BlockLayout(const char* name = ""); + inline GLsizei size() const { return m_blockSize; } + explicit operator C::Tag() const; + GLuint indexOfUniform(const C::Tag& name) const + { + auto search = m_vars.find(name); //@TODO discuss usage of at() as it works just as well here + if (search != m_vars.end()) + { + return search->second; + } + LOG_WARN("indexOfUniform: \"%s\" cannot be found in buffer!\n has it been added in the layout?", name.c_str()); + return 0; + //return m_vars.at(name); + } + + void pushBlock(const BlockLayout& block, const GLuint count = 1) //allows direct access to the inner-element indices + { + + /* TESTING THE LOGIC BEHIND THIS: + + auto block0 = BlockLayout("b0") + block0.push<16>("position"); + block0.push<16>("color"); + // block0.size = 32 + + block1.push<16>("somevec"); + // block1.size = 16 + block1.pushBlock(block0); + // somevec, 0 + // position, 16 + // color, 32 + // block1.size = 48 + */ + for (GLuint i = 0; i < count; i++) + { + for (const auto& var : block.m_vars) + { + m_vars.emplace(std::make_pair(block.m_name + '[' + std::to_string(i) + "]." + var.first, m_blockSize + var.second)); + } + m_blockSize += block.m_blockSize; + } + } + + void push(const C::Tag& name, GLuint size) + { + m_vars.emplace(std::make_pair(name, m_blockSize)); + m_blockSize += size; + } +}; + + +//struct UniformBufferLayout +//{ +// +//private: +// std::unordered_map<C::Tag, GLuint> m_uniforms; +// GLuint m_blockSize; +// C::Tag m_name; +//public: +// UniformBufferLayout(const char* name = "") : m_blockSize(0), m_name(name) {} +// +// template<GLuint size> +// void push(const C::Tag& name, GLuint count) +// { +// /* m_uniforms.emplace(std::make_pair(name, m_blockSize)); +// m_blockSize += size * componentCount;*/ +// for (GLuint i = 0; i < count; i++) +// { +// push<size>(name + '[' + std::to_string(i) + ']'); +// } +// } +// +// template<GLuint size> +// void push<size>(const C::Tag& name) +// { +// m_uniforms.emplace(std::make_pair(name, m_blockSize)); +// m_blockSize += size; +// } +// +// inline GLsizei size() const { return m_blockSize; } +// +// inline GLuint indexOfUniform(const C::Tag& name) const +// { +// return m_uniforms.at(name); +// +// //auto search = m_uniforms.find(name); //@TODO discuss usage of at() as it works just as well here +// //if (search != m_uniforms.end()) +// //{ +// // return search->second; +// //} +// //LOG_ERROR("indexOfUniform: \"%s\" cannot be found in buffer!\n has it been added in the layout?", name.c_str()); +// //return 0; +// } +// +//}; + +class UniformBuffer +{ + +private: + GLuint m_id; + C::Tag m_name; + BlockLayout m_blockLayout; +public: + + UniformBuffer(const char *name, const BlockLayout& layout, const GLenum drawMode); + + explicit operator C::Tag() const; + explicit operator GLuint() const; + + void clean(); + + void bind() const; + void unbind() const; + + inline GLuint blockSize() + { + return m_blockLayout.size(); + } + + GLuint getUniformIndex(const C::Tag& name) const; + void update(const C::ID index, GLsizeiptr size, const void *data); +}; + +} diff --git a/include/overkill/VertexBufferAttribLayout.hpp b/include/overkill/VertexBufferAttribLayout.hpp index a4b6e33616747f15779a2f34d57a4c74a28691d1..4bbab71ec7e4716eab5e84d818af7dad7bc4ac54 100644 --- a/include/overkill/VertexBufferAttribLayout.hpp +++ b/include/overkill/VertexBufferAttribLayout.hpp @@ -27,17 +27,26 @@ private: public: VertexBufferAttribLayout() : m_stride(0) {} - void push(GLuint count, GLenum type, bool normalized = false) + /// <summary> + /// <param name="count">The number of components the attribute has in the shaderprogram</param> + /// <param name="type">The number of components the attribute has in the shaderprogram</param> + /// <param name="normalized">wether or not the values should be normalized</param> + /// </summary> + + template<GLenum type> + void push(GLuint count, bool normalized = false) { m_attributes.push_back({ count, type, normalized }); - if (type == GL_INT_2_10_10_10_REV) - m_stride += GLTypeSize(type); - else if (type == GL_SHORT) - m_stride += GLTypeSize(type); - else - m_stride += count * GLTypeSize(type); - } - + m_stride += count * GLTypeSize(type); + } +/* + template<> + void push<GL_INT_2_10_10_10_REV>(GLuint count, bool normalized) + { + m_attributes.push_back({ count, GL_INT_2_10_10_10_REV, normalized }); + m_stride += count; //TODO allow for attributes to contain more than one withouth striding errors + } +*/ inline const std::vector<VertexBufferAttrib> getAttributes() const { return m_attributes; } inline GLuint getStride() const { return m_stride; } }; diff --git a/include/overkill/gl_drawSettings.hpp b/include/overkill/gl_drawSettings.hpp new file mode 100644 index 0000000000000000000000000000000000000000..86f2fd5ae8a5ff0c58fe333257e3eaa5eb171813 --- /dev/null +++ b/include/overkill/gl_drawSettings.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include <overkill/gl_caller.hpp> + +/* + + READ ALL THE #pragma lines anc map them + +*/ \ No newline at end of file diff --git a/include/overkill/gl_util.hpp b/include/overkill/gl_util.hpp index ae06578f7b3466d6199a715a4168f47e49a54388..4a21842501a8abd81cb679e25405be6198d33244 100644 --- a/include/overkill/gl_util.hpp +++ b/include/overkill/gl_util.hpp @@ -6,6 +6,6 @@ #include <PMS/logger.h> #include <overkill/gl_caller.hpp> -GLuint GLTypeSize(const GLenum type); -std::string ShaderTypeName(const GLenum typeID); -void GLPrintMaxContants(); +void GLPrintMaxConstants(); +auto GLTypeSize(const GLenum type) -> GLsizei; +auto ShaderTypeName(const GLenum typeID) -> std::string; diff --git a/src/ElementBuffer.cpp b/src/ElementBuffer.cpp index f7ee529bc37e5251e377f429ae884209159ee859..c64abc2c16a5d10d9e8cf645cd8db97bbca9aff9 100644 --- a/src/ElementBuffer.cpp +++ b/src/ElementBuffer.cpp @@ -1,6 +1,5 @@ #include "overkill/ElementBuffer.hpp" - namespace overkill { diff --git a/src/Entity.cpp b/src/Entity.cpp index 910336694f91d213684e5cd9c5b07a7e486261c2..fc133ae0e382f3641aa59e7befcf75f7e58d126f 100644 --- a/src/Entity.cpp +++ b/src/Entity.cpp @@ -47,4 +47,15 @@ namespace overkill dt);*/ } + auto Transform::modelToWorld() -> glm::mat4 + { + auto m2w = glm::scale(glm::mat4(1), m_scale); + + m2w = glm::rotate(m2w, m_rotation.x, right); + m2w = glm::rotate(m2w, m_rotation.y, up); + m2w = glm::rotate(m2w, m_rotation.z, forward); + + m2w = glm::translate(m2w, m_position); + return m2w; + } } \ No newline at end of file diff --git a/src/EntityModel.cpp b/src/EntityModel.cpp index 71f02cc0bebc1137147cf3249d08fb87ad8b4d3f..92ca2f5c9a37d6275b88c3099598c900f678ff0c 100644 --- a/src/EntityModel.cpp +++ b/src/EntityModel.cpp @@ -3,50 +3,51 @@ namespace overkill { - EntityModel::EntityModel(C::Tag modelTag, - glm::vec3 pos, glm::vec3 rot, - glm::vec3 scale, glm::vec3 vel, - glm::vec3 angVel) : Entity(modelTag, pos, rot, vel, angVel) - { - m_modelID = ModelSystem::getIdByTag(modelTag); - m_scale = scale; - } + +EntityModel::EntityModel(C::Tag modelTag, + glm::vec3 pos, glm::vec3 rot, + glm::vec3 scale, glm::vec3 vel, + glm::vec3 angVel) : Entity(modelTag, pos, rot, vel, angVel) +{ + m_modelID = ModelSystem::getIdByTag(modelTag); + m_scale = scale; +} - glm::mat4 EntityModel::getModelMatrix() - { - glm::mat4 model = glm::mat4(1); +glm::mat4 EntityModel::getModelMatrix() +{ + glm::mat4 model = glm::mat4(1); - model = glm::translate(model, m_position); - model = glm::rotate(model, m_rotation.x, glm::vec3(1,0,0)); - model = glm::rotate(model, m_rotation.y, glm::vec3(0,1,0)); - model = glm::rotate(model, m_rotation.z, glm::vec3(0,0,1)); - model = glm::scale(model, m_scale); + model = glm::translate(model, m_position); + model = glm::rotate(model, m_rotation.x, glm::vec3(1,0,0)); + model = glm::rotate(model, m_rotation.y, glm::vec3(0,1,0)); + model = glm::rotate(model, m_rotation.z, glm::vec3(0,0,1)); + model = glm::scale(model, m_scale); - return model; - - } + return model; +} - int EntityModel::getModel() - { return m_modelID; } +int EntityModel::getModel() +{ return m_modelID; } - glm::vec3 EntityModel::getScale() - { return m_scale; } +glm::vec3 EntityModel::getScale() +{ return m_scale; } - void EntityModel::setModelByID(int modelID) - { m_modelID = modelID; } +void EntityModel::setModelByID(int modelID) +{ m_modelID = modelID; } - void EntityModel::setModelByTag(C::Tag tag) - { m_modelID = ModelSystem::getIdByTag(tag); } + void EntityModel::setModelByTag(C::Tag tag) +{ m_modelID = ModelSystem::getIdByTag(tag); } + +void EntityModel::setScale(glm::vec3 scale) +{ m_scale = scale; } - void EntityModel::setScale(glm::vec3 scale) - { m_scale = scale; } +void EntityModel::draw() +{ + Renderer::draw(ModelSystem::getById(m_modelID), getModelMatrix()); +} - void EntityModel::draw() - { - Renderer::draw(ModelSystem::getById(m_modelID), getModelMatrix()); - } -} \ No newline at end of file +} diff --git a/src/Init.cpp b/src/Init.cpp index e5289d567e1783eb4ea82deef2cd86cc3a652955..b2d1f45f5339678a3ec524df6cfabd124fbb9fda 100644 --- a/src/Init.cpp +++ b/src/Init.cpp @@ -61,10 +61,10 @@ void Init::OpenGL(const glm::vec4 background) GLCall(glCullFace(GL_BACK));// the face side to cull away: GL_FRONT | GL_BACK | GL_FRONT_AND_BACK GLCall(glEnable(GL_BLEND)); - //GLCall(glEnable(GL_DEPTH_TEST)); //enabled to avoid ugly artifacts that depend on the angle of view and drawing order + GLCall(glEnable(GL_DEPTH_TEST)); //enabled to avoid ugly artifacts that depend on the angle of view and drawing order GLCall(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - GLPrintMaxContants(); + GLPrintMaxConstants(); } diff --git a/src/ModelSystem.cpp b/src/ModelSystem.cpp index 3d548c9ab7f0d379e262fbcf9196f5e1fba2b151..4a8cf3ff74f1951599f13a56dc294171148f453b 100644 --- a/src/ModelSystem.cpp +++ b/src/ModelSystem.cpp @@ -22,6 +22,38 @@ auto ModelSystem::getById(C::ID modelID) -> const Model& return ModelSystem::m_models[modelID]; } +auto packUV(float u, float v) -> GLshort +{ + const auto MAX = 127; + //const auto MIN = -128; + const auto CLAMPER = 255; + + return (GLint(v * MAX) & CLAMPER) << 8 | (GLint(u * MAX) & CLAMPER); +} + +//TODO move it +auto packNormal(float x, float y, float z) -> GLint +{ + + float magnitude = sqrt(x * x + y * y + z * z); + x /= magnitude; + y /= magnitude; + z /= magnitude; + + + const auto MAX = 511; //01 1111 1111 + const auto MIN = -512; //10 0000 0000 + // -1 * 511 = -511 + GLint ix = (GLint(x * MAX) & 1023); + GLint iy = (GLint(y * MAX) & 1023); + GLint iz = (GLint(z * MAX) & 1023); + //1*511 = 511 + // 01 0000 0000 + //-1*511 = -511 + // 10 0000 0001 + GLint r = (iz << 20) | (iy << 10) | ix; + return r; +} void ModelSystem::reload() { @@ -92,10 +124,12 @@ void ModelSystem::load() newModel.m_vbo = VertexBuffer(vertices.data(), vertices.size() * sizeof(Vertex)); auto vbufLayout = VertexBufferAttribLayout(); - vbufLayout.push(3, GL_FLOAT); //position; - vbufLayout.push(3, GL_FLOAT); //normal - vbufLayout.push(2, GL_FLOAT); //uv - vbufLayout.push(4, GL_UNSIGNED_BYTE, GL_TRUE); //color; + + vbufLayout.push<GL_FLOAT>(3); //position; + vbufLayout.push<GL_FLOAT>(3); //normal + vbufLayout.push<GL_FLOAT>(2); //uv + vbufLayout.push<GL_UNSIGNED_BYTE>(4, GL_TRUE); //color; + newModel.m_vao.addBuffer(newModel.m_vbo, vbufLayout); // diff --git a/src/Renderer.cpp b/src/Renderer.cpp index ce2187393454f2793bbaa04ba2192b56a2d8c9a6..0a1abe41e3c2fa4f25e7a267bd31b4136addc122 100644 --- a/src/Renderer.cpp +++ b/src/Renderer.cpp @@ -1,5 +1,4 @@ #include <overkill/Renderer.hpp> - namespace overkill { @@ -37,17 +36,25 @@ void Renderer::draw(const Model& model, glm::mat4 modelMatrix) // UNBIND [optional]... discuss } -void EdgeRenderer::drawEdged(const VertexArray & va, const ElementBuffer & eb, const ShaderProgram& shader, const ShaderProgram& edgeShader) const +void Renderer::draw( EntityModel& entity, float t) { - va.bind(); - eb.bind(); - shader.bind(); + auto model = ModelSystem::getById( entity.getModel() ); + auto m2w = entity.getModelMatrix(); - GLCall(glDrawElements(GL_TRIANGLES, eb.count(), GL_UNSIGNED_INT, nullptr)); + model.m_vao.bind(); - edgeShader.bind(); - GLCall(glLineWidth(1.0f)) - GLCall(glDrawElements(GL_LINE_STRIP, eb.count(), GL_UNSIGNED_INT, nullptr)); + for (auto mesh : model.m_meshes) + { + mesh.m_ebo.bind(); + + auto& shader = mesh.m_shaderProgram; + shader.bind(); + + GLCall(glUniform1f(shader.getUniformLocation("time"), t)); + GLCall(glUniformMatrix4fv(shader.getUniformLocation("m2w"), 1, GL_FALSE, glm::value_ptr(m2w))); + GLCall(glDrawElements(GL_TRIANGLES, mesh.m_ebo.count(), GL_UNSIGNED_INT, nullptr)); + } } + } diff --git a/src/ShaderIntrospector.cpp b/src/ShaderIntrospector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42fbcaf41e18eb6a2d7f51be71fbf583cdee4110 --- /dev/null +++ b/src/ShaderIntrospector.cpp @@ -0,0 +1,85 @@ +#include <overkill/ShaderIntrospector.hpp> +namespace overkill +{ + +// UNIFORMS +/* +const std::vector<GLint>& ShaderIntrospector::getUniformLocations(const GLuint program) +{ + GLsizei nameMaxLength; + + GLCall(glGetProgramiv(id, GL_ACTIVE_UNIFORM_MAX_LENGTH, &nameMaxLength)); + LOG_INFO("Uniform name maxlength: %i", nameMaxLength); + GLCall(glGetProgramiv(id, GL_ACTIVE_UNIFORMS, &count)); + LOG_INFO("\n\nActive uniforms: %i", count); + for (GLuint i = 0; i < count; i++) + { + char* uniformName = (char*)alloca(nameMaxLength * sizeof(char)); + GLCall(glGetActiveUniform(id, i, nameMaxLength, &length, &size, &type, uniformName)); + } + GLuint count; + GLCall(glGetActiveUniformsiv(program, uBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &count)); + + GLint indices; + GLCall(glGetActiveUniformsiv(program, uBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, &indices)); + + std::vector<GLint> result; + result.reserve(count); + for (GLuint i = 0 < count; i++) + { + result.push_back(indices[i]); + } + return result; +}*/ + + +//UNIFORM BLOCKS + +GLint ShaderIntrospector::getActiveBlockCount(const GLuint program) +{ + GLint count; + GLCall(glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &count)); + return count; +} + +const std::string ShaderIntrospector::getUnifromBlockName(const GLuint program, const GLint uBlockIndex) +{ + //nameMaxLength = the longest name of a block for the given program + GLint nameMaxLength, length; + GLCall(glGetActiveUniformBlockiv(program, uBlockIndex, GL_UNIFORM_BLOCK_NAME_LENGTH, &nameMaxLength)); + char* name = (char*)alloca(nameMaxLength * sizeof(char)); + GLCall(glGetActiveUniformBlockName(program, uBlockIndex, nameMaxLength, &length, name)); + return std::string(name); +} + +const std::vector<GLint> ShaderIntrospector::getUniformBlockUniformIndices(const GLuint program, const GLuint uBlockIndex) +{ + GLint count; + GLCall(glGetActiveUniformBlockiv(program, uBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &count)); + + GLint* indices = (GLint*)alloca(count * sizeof(GLint)); + GLCall(glGetActiveUniformBlockiv(program, uBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, indices)); + + std::vector<GLint> result; + result.reserve(count); + for (GLuint i = 0; i < count; i++) + { + result.push_back(indices[i]); + } + return result; +} + +GLuint ShaderIntrospector::getUniformBlockIndex(const GLuint program, const std::string& name) +{ + GLuint index; + GLCall(index = glGetUniformBlockIndex(program, name.c_str())); + return index; +} + +GLint ShaderIntrospector::getUniformBlockBinding(const GLuint program, GLuint uBlockIndex) +{ + GLint value; + //GLCall(glGetActiveUniformBlockiv(program, uBlockIndex)) + return 0; +} +} \ No newline at end of file diff --git a/src/ShaderProgram.cpp b/src/ShaderProgram.cpp index 46d30b6088dc8016203e8e675ec84b5abe48f2da..ca0ce7e6e9ddc9819cc5bc8214585fe4cc9828d7 100644 --- a/src/ShaderProgram.cpp +++ b/src/ShaderProgram.cpp @@ -1,4 +1,5 @@ -#include <overkill/ShaderProgram.hpp> +#include <overkill/ShaderProgram.hpp> + namespace overkill { @@ -37,39 +38,71 @@ void ShaderProgram::construct(const std::string& vert, const std::string& frag, } ///https://stackoverflow.com/questions/440144/in-opengl-is-there-a-way-to-get-a-list-of-all-uniforms-attribs-used-by-a-shade - GLint i; + GLint count; - GLint size; // size of the variable GLenum type; // type of the variable (float, vec3 or mat4, etc) - - const GLsizei bufSize = 16; // maximum name length - GLchar name[bufSize]; // variable name in GLSL GLsizei length; // name length + + GLsizei nameMaxLength; + + LOG_INFO("\n\n= = = = = =<| ATTRIBUTE INFO |>= = = = = ="); + GLCall(glGetProgramiv(id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &nameMaxLength)); + LOG_INFO("Attribute name maxlength: %i", nameMaxLength); GLCall(glGetProgramiv(id, GL_ACTIVE_ATTRIBUTES, &count)); - std::cout << "\nActive attributes: " << count << std::endl; + LOG_INFO("Active attributes: %i", count); - for (i = 0; i < count; i++) + for (GLuint i = 0; i < count; i++) { - GLCall(glGetActiveAttrib(id, (GLuint)i, bufSize, &length, &size, &type, name)); - printf("Attribute #%d Type: %u Name: %s\n", i, type, name); - + char* attribName = (char*)alloca(nameMaxLength * sizeof(char)); + GLCall(glGetActiveAttrib(id, i, nameMaxLength, &length, &size, &type, attribName)); + LOG_INFO("Attribute #%u Type: %u Name: %s", i, type, attribName); } + LOG_INFO("\n\n= = = = = =<| UNIFORM INFO |>= = = = = ="); + + GLCall(glGetProgramiv(id, GL_ACTIVE_UNIFORM_MAX_LENGTH, &nameMaxLength)); + LOG_INFO("Uniform name maxlength: %i", nameMaxLength); GLCall(glGetProgramiv(id, GL_ACTIVE_UNIFORMS, &count)); - std::cout << "\nActive uniforms: " << count << std::endl; + LOG_INFO("\n\nActive uniforms: %i", count); - for (i = 0; i < count; i++) + for (GLuint i = 0; i < count; i++) { - GLCall(glGetActiveUniform(id, (GLuint)i, bufSize, &length, &size, &type, name)); - - printf("Uniform #%d Type: %u Name: %s\n", i, type, name); - + char* uniformName = (char*)alloca(nameMaxLength * sizeof(char)); + GLCall(glGetActiveUniform(id, i, nameMaxLength, &length, &size, &type, uniformName)); + LOG_INFO("Uniform #%u, Type: %u, Name: %s", i, type, uniformName); + if (length > 15) + { + LOG_WARN(R"( + Uniform #%d, %s of type %u: + names of uniforms should generally be shorter than 15 characters + for optimal lookup time, if %s is not touched very often this may still be OK)", + i, uniformName, type, uniformName + ); + } GLint location; - GLCall(location = glGetUniformLocation(id, name)); - uniforms.insert({ name, location}); + GLCall(location = glGetUniformLocation(id, uniformName)); + uniforms.insert({ uniformName, location }); } + auto uBlockCount = ShaderIntrospector::getActiveBlockCount(id); + uniformBlocks.reserve(uBlockCount); + for (GLint i = 0; i < uBlockCount; i++) + { + auto name = ShaderIntrospector::getUnifromBlockName(id, i); + GLuint uBlockIndex = ShaderIntrospector::getUniformBlockIndex(id, name); + LOG_INFO("Uniform Block #%i, indexed as #%u, Name: %s", i, uBlockIndex, name.c_str()); + uniformBlocks.insert({ name, i }); + const auto& indices = ShaderIntrospector::getUniformBlockUniformIndices(id, uBlockIndex); + for (const auto index : indices) + { + char* uniformName = (char*)alloca(nameMaxLength * sizeof(char)); + GLCall(glGetActiveUniform(id, index, nameMaxLength, &length, &size, &type, uniformName)); + GLsizei s = GLTypeSize(type); + LOG_INFO("#%u has: %s, with index: %u, and of type: %u, with the size: %i\n", uBlockIndex, uniformName, index, type, s); + } + } + GLCall(glValidateProgram(id)); } @@ -98,7 +131,7 @@ ShaderProgram::operator GLuint() const void ShaderProgram::setMaterial(const Material& mat) const { - LOG_DEBUG("shaderid: %u", id); + // LOG_DEBUG("Setting material on shader: %u", id); bind(); std::size_t i = 0; for (const auto unimap : mat.m_unimaps) @@ -131,7 +164,6 @@ void ShaderProgram::unbind() const { GLCall(glUseProgram(0)); } - GLint ShaderProgram::getUniformLocation(const std::string& name) const { const auto locationIter = uniforms.find(name); @@ -142,6 +174,17 @@ GLint ShaderProgram::getUniformLocation(const std::string& name) const return (*locationIter).second; } +GLuint ShaderProgram::getUniformBlockIndex(const std::string & blockName) const +{ + GLuint index; + GLCall(index = glGetUniformBlockIndex(id, blockName.c_str())); + if (index == GL_INVALID_INDEX) + { + LOG_WARN("\nTrying to access \"%s\",\n No uniform block with that name exists!", blockName.c_str()); + } + return index; +} + GLuint ShaderProgram::CompileShader(GLuint type, const std::string& source) { GLuint id; @@ -199,9 +242,9 @@ ShaderSource ShaderProgram::ParseProgram(const std::string& file) { currentlyReading = GEOM; } - getline(fileStream, line); + getline(fileStream, line); //instantly get #version tag ss[(int)currentlyReading] << line << '\n'; - ss[(int)currentlyReading] << "#line " << ++lineNr << '\n'; //inject line number to get the line as is in the shader file + ss[(int)currentlyReading] << "#line " << ++lineNr+1 << '\n'; //inject line number to get the line as is in the shader file } else { diff --git a/src/ShaderSystem.cpp b/src/ShaderSystem.cpp index b37d5f9d5092d46ec11c64c14755f551c79b7166..e7f58cce5ae37a6de53c5d80de5a736f3b5a49f5 100644 --- a/src/ShaderSystem.cpp +++ b/src/ShaderSystem.cpp @@ -2,11 +2,12 @@ namespace overkill { - -std::vector<ShaderProgram> ShaderSystem::m_shaderPrograms; -std::unordered_map<C::Tag, C::ID> ShaderSystem::m_mapShaderProgramID; -std::vector<ShaderSystem::UpdateCallback> ShaderSystem::m_updateCallbacks; - +std::unordered_map<C::Tag, std::set<GLuint>> ShaderSystem::m_mapUniformBufferTargets; +std::vector<UniformBuffer> ShaderSystem::m_uniformBuffers; +std::unordered_map<C::Tag, C::ID> ShaderSystem::m_mapUniformBuffersID; +std::vector<ShaderProgram> ShaderSystem::m_shaderPrograms; +std::unordered_map<C::Tag, C::ID> ShaderSystem::m_mapShaderProgramID; +std::vector<ShaderSystem::UpdateCallback> ShaderSystem::m_updateCallbacks; auto ShaderSystem::getIdByTag(const C::Tag& tag) -> C::ID { @@ -39,6 +40,82 @@ void ShaderSystem::push(const C::Tag tag, const std::string& filepath) ShaderSystem::m_shaderPrograms.emplace_back( ShaderProgram(filepath.data()) ); } +void ShaderSystem::pushUniformBuffer(const C::Tag&& tag, GLuint size) +{ + //ShaderSystem::m_mapUniformBufferDynamic[tag] = ShaderSystem::m_uniformBuffers.size(); + //ShaderSystem::m_uniformBuffers.emplace_back( UniformBuffer(tag.c_str(), nullptr, size, GL_DYNAMIC_DRAW) ); +} + +void ShaderSystem::linkUniformBlocks() +{ + + + std::unordered_map<C::Tag, GLint> uniformBlocks; + + for (auto& shader : m_shaderPrograms) + { + auto id = GLuint(shader); + auto uBlockCount = ShaderIntrospector::getActiveBlockCount(id); + uniformBlocks.reserve(uBlockCount); + for (GLint i = 0; i < uBlockCount; i++) + { + auto name = ShaderIntrospector::getUnifromBlockName(id, i); + GLuint uBlockIndex = ShaderIntrospector::getUniformBlockIndex(id, name); + LOG_INFO("Uniform Block #%i, indexed as #%u, Name: %s", i, uBlockIndex, name.c_str()); + auto search = m_mapUniformBufferTargets.find(name); + if (search != m_mapUniformBufferTargets.end()) + { + search->second.insert(GLuint(shader)); + } + else + { + m_mapUniformBufferTargets.insert({ name,{ GLuint(shader) } }); + } + uniformBlocks.insert({ name, i }); + /*ShaderSystem::m_mapUniformBufferTargets. + const auto& indices = ShaderIntrospector::getUniformBlockUniformIndices(id, uBlockIndex); + for (const auto index : indices) + { + char* uniformName = (char*)alloca(nameMaxLength * sizeof(char)); + GLsizei length; + GLCall(glGetActiveUniformName(id, index, nameMaxLength, &length, uniformName)); + LOG_INFO("#%u has: %s", uBlockIndex, uniformName); + }*/ + } + } +} + +/// <summary> +/// +/// +/// +/// +GLuint ShaderSystem::getBlockUniformLocation(const C::Tag& uBlock, const C::Tag& uniform ) +{ + /*for (auto& uBuffer : m_uniformBuffers) + { + uBuffer.holdsBlock(uBlock) + }*/ + return 0; +} + +auto ShaderSystem::getUniformBufferIdByTag(const C::Tag& tag) -> C::ID +{ + return ShaderSystem::m_mapUniformBuffersID[tag]; +} + +auto ShaderSystem::getUniformBufferByTag(const C::Tag& tag) -> const UniformBuffer& +{ + return ShaderSystem::m_uniformBuffers[m_mapUniformBuffersID[tag]]; +} + +auto ShaderSystem::getUniformBufferById(C::ID uBufferID) -> const UniformBuffer& +{ + return ShaderSystem::m_uniformBuffers[uBufferID]; +} + + + void ShaderSystem::load() { std::vector<FileEvent> fevents = Watcher::popEvents("discovered", "shaders"); @@ -48,6 +125,86 @@ void ShaderSystem::load() LOG_DEBUG("Shaders from file: %s", filepath.data()); ShaderSystem::push(e.tag, filepath); } + + //pushUniformBuffer("OK_Lights", sizeof(LightData) * 8); + auto matBufferLayout = BlockLayout(); + matBufferLayout.push("projection", 64); + matBufferLayout.push("view", 64); + matBufferLayout.push("view_position", 16); + + //pushUniformBuffer("OK_Matrices", sizeof(glm::mat4) * 2); + ShaderSystem::m_mapUniformBuffersID["OK_Matrices"] = ShaderSystem::m_uniformBuffers.size(); //assign ID/index + auto buf = ShaderSystem::m_uniformBuffers.emplace_back(UniformBuffer("OK_Matrices", matBufferLayout, GL_DYNAMIC_DRAW)); + + auto lightBufferLayout = BlockLayout(); + //lightBufferLayout.push<16>("light.position") + auto lightStructLayout = BlockLayout("light"); + lightStructLayout.push("position", 16); + lightStructLayout.push("intensities", 16); + + lightBufferLayout.pushBlock(lightStructLayout, 8); + //lightBufferLayout.push<GL_FLOAT_VEC4>("intensities"); + //lightBufferLayout.push<GL_FLOAT>("spread"); + //lightBufferLayout.push<GL_FLOAT>("constant"); + //lightBufferLayout.push<GL_FLOAT>("linear"); + //lightBufferLayout.push<GL_FLOAT>("quadratic"); + + ShaderSystem::m_mapUniformBuffersID["OK_Lights"] = ShaderSystem::m_uniformBuffers.size(); //assign ID/index + ShaderSystem::m_uniformBuffers.emplace_back(UniformBuffer("OK_Lights", lightBufferLayout, GL_DYNAMIC_DRAW)); + + //pushUniformBuffer("OK_Lights", sizeof(glm::vec4) * 2+sizeof(float)); + //auto buf = getUniformBufferByTag("OK_Matrices"); + + GLsizei nameMaxLength; + + linkUniformBlocksForAll(); + GLuint bindPoint = 0; + for (auto& buffer : m_uniformBuffers) + { + buffer.bind(); + for (const auto& shader : m_shaderPrograms) + { + /*if (buffer.blockCount() == 1) + {*/ + auto uBlockIndex = ShaderIntrospector::getUniformBlockIndex(GLuint(shader), C::Tag(buffer)); + if (uBlockIndex != GL_INVALID_INDEX) //this block did exist in the shader + { + GLCall(glUniformBlockBinding(GLuint(shader), uBlockIndex, bindPoint)); + GLCall(glBindBufferBase(GL_UNIFORM_BUFFER, bindPoint, GLuint(buffer))); + } + //} + //else + //{ + // //for (int blockInstance = 0; blockInstance < buffer.blockCount(); blockInstance++) + // //{ + // // const auto& blockName = C::Tag(buffer) + '[' + std::to_string(blockInstance) + ']'; + // // auto uBlockIndex = ShaderIntrospector::getUniformBlockIndex(GLuint(shader), blockName); + // // if (uBlockIndex != GL_INVALID_INDEX) //this block did exist in the shader + // // { + // // GLCall(glUniformBlockBinding(GLuint(shader), uBlockIndex, bindPoint)); + + + // // GLint offsetAlignment; + // // GLCall(glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offsetAlignment)); + // // GLint bufferBindings; + // // GLCall(glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &bufferBindings)); + // // LOG_INFO("bindingMAX: %i", bufferBindings); + // // + + // // GLint bufSize; + // // glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_SIZE, &bufSize); + // // LOG_INFO("Block: #%i,\toffset: %u,\tsize: %u,\tBufferSize: %i,\toffset alignment: %i", blockInstance, a, buffer.blockSize(), bufSize, offsetAlignment); + // // //GLCall(glBindBufferRange(GL_UNIFORM_BUFFER, bindPoint, GLuint(buffer), a, buffer.blockSize())); + // // //GLCall(glBindBufferBase(GL_UNIFORM_BUFFER, bindPoint, GLuint(buffer))); + // // + // // } + // //} + // GLCall(glBindBufferBase(GL_UNIFORM_BUFFER, bindPoint, GLuint(buffer))); + //} + } + buffer.unbind(); + bindPoint++; + } } void ShaderSystem::reload() @@ -58,9 +215,17 @@ void ShaderSystem::reload() { shaderprog.clean(); } + // Remove all shaders + ShaderSystem::m_shaderPrograms.clear(); + + // Delete from GPU + for (auto uBuffer : ShaderSystem::m_uniformBuffers) + { + uBuffer.clean(); + } + // Remove all uniformBuffers + ShaderSystem::m_uniformBuffers.clear(); - // Remove all shaders - ShaderSystem::m_shaderPrograms.clear(); // Load from file again Watcher::discoverFiles(); @@ -72,6 +237,34 @@ void ShaderSystem::reload() } } +void ShaderSystem::linkUniformBlocksForAll() +{ + GLuint bindPoint = 0; + for (const auto& shader : m_shaderPrograms) + { + auto uBlockCount = ShaderIntrospector::getActiveBlockCount(GLuint(shader)); + for (GLint i = 0; i < uBlockCount; i++) + { + auto name = ShaderIntrospector::getUnifromBlockName(GLuint(shader), i); + LOG_INFO("Uniform Block #%i, Name: %s", i, name.c_str()); + auto search = m_mapUniformBufferTargets.find(name); + if (search != m_mapUniformBufferTargets.end()) + { + search->second.insert(GLuint(shader)); + } + else + { + m_mapUniformBufferTargets.insert({ name, {GLuint(shader)} }); + } + } + + + //GLCall(glUniformBlockBinding(GLuint(shader), shader.getUniformBlockIndex(C::Tag(uBuffer)), bindPoint)); + //GLCall(glBindBufferBase(GL_UNIFORM_BUFFER, bindPoint, GLuint(uBuffer))); + } + bindPoint++; +} + void ShaderSystem::bindOnUpdate(const C::Tag& shaderTag, C::ID modelID, C::ID meshID, OnUpdate onUpdate) { ShaderSystem::m_updateCallbacks.emplace_back( diff --git a/src/TextureSystem.cpp b/src/TextureSystem.cpp index efd31ed091071d5d119dede28faf4a7cd01cdf72..7d6b0ce13a6c8b7705db3b84d48ccd3fea787d35 100644 --- a/src/TextureSystem.cpp +++ b/src/TextureSystem.cpp @@ -1,6 +1,5 @@ #include <overkill/TextureSystem.hpp> -// #include <PMS/logger.h> namespace overkill { @@ -38,12 +37,12 @@ void TextureSystem::load() { // TODO: Load these from the file system somehow std::vector<FileEvent> fevents = Watcher::popEvents("discovered", "textures"); - for (const auto e : fevents) { const auto filepath = C::TexturesFolder + ("/" + e.tag) + "." + e.extension; LOG_DEBUG("Texture from file: %s", filepath.data()); TextureSystem::push(e.tag, filepath); + } } diff --git a/src/UniformBuffer.cpp b/src/UniformBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4a82cac870c5b5fc9ff5c85966f413ca11ea2559 --- /dev/null +++ b/src/UniformBuffer.cpp @@ -0,0 +1,60 @@ +#include <overkill/UniformBuffer.hpp> + +namespace overkill +{ + BlockLayout::BlockLayout(const char * name) : m_blockSize(0), m_name(name){} + //lightblock +//mvpblock +//cam pos +BlockLayout::operator C::Tag() const +{ + return m_name; +} + +UniformBuffer::UniformBuffer(const char * name, const BlockLayout & layout, const GLenum drawMode) + : m_name(name) + , m_blockLayout(layout) +{ + GLCall(glGenBuffers(1, &m_id)); + bind(); + GLCall(glBufferData(GL_UNIFORM_BUFFER, m_blockLayout.size(), nullptr, drawMode)); + unbind(); +} + +UniformBuffer::operator C::Tag() const +{ + return m_name; +} + +UniformBuffer::operator GLuint() const +{ + return m_id; +} + +void UniformBuffer::clean() +{ + GLCall(glDeleteBuffers(1, &m_id)); +} + +void UniformBuffer::bind() const +{ + GLCall(glBindBuffer(GL_UNIFORM_BUFFER, m_id)); +} + +void UniformBuffer::unbind() const +{ + GLCall(glBindBuffer(GL_UNIFORM_BUFFER, 0)); +} + +GLuint UniformBuffer::getUniformIndex(const C::Tag& name) const +{ + return m_blockLayout.indexOfUniform(name); +} + +void UniformBuffer::update(const C::ID index, GLsizeiptr size, const void * data) +{ + bind(); + glBufferSubData(GL_UNIFORM_BUFFER, index, size, data); +} + +} \ No newline at end of file diff --git a/src/VertexArray.cpp b/src/VertexArray.cpp index 63f0459fef644f92d2e45c8ed4a647d3a2f858fe..27e646c1f983f54ac2d5e6d6d3c31e67ee80fe0d 100644 --- a/src/VertexArray.cpp +++ b/src/VertexArray.cpp @@ -35,7 +35,10 @@ void VertexArray::addBuffer(const VertexBuffer& vb, const VertexBufferAttribLayo (const void*)offset ) ); - offset += attrib.count * GLTypeSize(attrib.type); + if (attrib.type == GL_INT_2_10_10_10_REV) + offset += attrib.count; + else + offset += attrib.count * GLTypeSize(attrib.type); i++; } diff --git a/src/gl_util.cpp b/src/gl_util.cpp index cc359c2338a46b3bb3893ec890c34db7dbb44ef8..f92c54cebafb4f10f8dffe2f2c61c234824b2b9b 100644 --- a/src/gl_util.cpp +++ b/src/gl_util.cpp @@ -1,6 +1,6 @@ #include <overkill/gl_util.hpp> -void GLPrintMaxContants() +void GLPrintMaxConstants() { // @doc list of available constants https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGet.xhtml 18.04.2018 GLint out; @@ -52,21 +52,123 @@ void GLPrintMaxContants() } -GLuint GLTypeSize(const GLenum type) +// @TODO replace with a "magical" template specifier i.e. template<>GLTypeSize<GL_FLOAT>(){return sizeof(GLfloat);} +auto GLTypeSize(const GLenum type) -> GLsizei { switch (type) { - case GL_BOOL: return sizeof(GLboolean); + case GL_FLOAT : return sizeof(GLfloat); + case GL_FLOAT_VEC2 : return sizeof(GLfloat)*2; + case GL_FLOAT_VEC3 : return sizeof(GLfloat)*3; + case GL_FLOAT_VEC4 : return sizeof(GLfloat)*4; + case GL_DOUBLE : return sizeof(GLdouble); + case GL_DOUBLE_VEC2 : return sizeof(GLdouble)*2; + case GL_DOUBLE_VEC3 : return sizeof(GLdouble)*3; + case GL_DOUBLE_VEC4 : return sizeof(GLdouble)*4; + case GL_INT : return sizeof(GLint); + case GL_INT_VEC2 : return sizeof(GLint)*2; + case GL_INT_VEC3 : return sizeof(GLint)*3; + case GL_INT_VEC4 : return sizeof(GLint)*4; + case GL_UNSIGNED_INT : return sizeof(GLuint); + case GL_UNSIGNED_INT_VEC2 : return sizeof(GLuint)*2; + case GL_UNSIGNED_INT_VEC3 : return sizeof(GLuint)*3; + case GL_UNSIGNED_INT_VEC4 : return sizeof(GLuint)*4; + case GL_BOOL : return sizeof(GLboolean); + case GL_BOOL_VEC2 : return sizeof(GLboolean)*2; + case GL_BOOL_VEC3 : return sizeof(GLboolean)*3; + case GL_BOOL_VEC4 : return sizeof(GLboolean)*4; + case GL_FLOAT_MAT2 : return sizeof(GLfloat)*2*2; + case GL_FLOAT_MAT3 : return sizeof(GLfloat)*3*3; + case GL_FLOAT_MAT4 : return sizeof(GLfloat)*4*4; + case GL_FLOAT_MAT2x3 : return sizeof(GLfloat)*2*3; + case GL_FLOAT_MAT2x4 : return sizeof(GLfloat)*2*4; + case GL_FLOAT_MAT3x2 : return sizeof(GLfloat)*3*2; + case GL_FLOAT_MAT3x4 : return sizeof(GLfloat)*3*4; + case GL_FLOAT_MAT4x2 : return sizeof(GLfloat)*4*2; + case GL_FLOAT_MAT4x3 : return sizeof(GLfloat)*4*3; + case GL_DOUBLE_MAT2 : return sizeof(GLdouble)*2*2; + case GL_DOUBLE_MAT3 : return sizeof(GLdouble)*3*3; + case GL_DOUBLE_MAT4 : return sizeof(GLdouble)*4*4; + case GL_DOUBLE_MAT2x3 : return sizeof(GLdouble)*2*3; + case GL_DOUBLE_MAT2x4 : return sizeof(GLdouble)*2*4; + case GL_DOUBLE_MAT3x2 : return sizeof(GLdouble)*3*2; + case GL_DOUBLE_MAT3x4 : return sizeof(GLdouble)*3*4; + case GL_DOUBLE_MAT4x2 : return sizeof(GLdouble)*4*2; + case GL_DOUBLE_MAT4x3 : return sizeof(GLdouble)*4*3; + case GL_SAMPLER_1D : + case GL_SAMPLER_2D : + case GL_SAMPLER_3D : + case GL_SAMPLER_CUBE : + case GL_SAMPLER_1D_SHADOW : + case GL_SAMPLER_2D_SHADOW : + case GL_SAMPLER_1D_ARRAY : + case GL_SAMPLER_2D_ARRAY : + case GL_SAMPLER_1D_ARRAY_SHADOW : + case GL_SAMPLER_2D_ARRAY_SHADOW : + case GL_SAMPLER_2D_MULTISAMPLE : + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY : + case GL_SAMPLER_CUBE_SHADOW : + case GL_SAMPLER_BUFFER : + case GL_SAMPLER_2D_RECT : + case GL_SAMPLER_2D_RECT_SHADOW : + case GL_INT_SAMPLER_1D : + case GL_INT_SAMPLER_2D : + case GL_INT_SAMPLER_3D : + case GL_INT_SAMPLER_CUBE : + case GL_INT_SAMPLER_1D_ARRAY : + case GL_INT_SAMPLER_2D_ARRAY : + case GL_INT_SAMPLER_2D_MULTISAMPLE : + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY : + case GL_INT_SAMPLER_BUFFER : + case GL_INT_SAMPLER_2D_RECT : + case GL_UNSIGNED_INT_SAMPLER_1D : + case GL_UNSIGNED_INT_SAMPLER_2D : + case GL_UNSIGNED_INT_SAMPLER_3D : + case GL_UNSIGNED_INT_SAMPLER_CUBE : + case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY : + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY : + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE : + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY : + case GL_UNSIGNED_INT_SAMPLER_BUFFER : + case GL_UNSIGNED_INT_SAMPLER_2D_RECT : + case GL_IMAGE_1D : + case GL_IMAGE_2D : + case GL_IMAGE_3D : + case GL_IMAGE_2D_RECT : + case GL_IMAGE_CUBE : + case GL_IMAGE_BUFFER : + case GL_IMAGE_1D_ARRAY : + case GL_IMAGE_2D_ARRAY : + case GL_IMAGE_2D_MULTISAMPLE : + case GL_IMAGE_2D_MULTISAMPLE_ARRAY : + case GL_INT_IMAGE_1D : + case GL_INT_IMAGE_2D : + case GL_INT_IMAGE_3D : + case GL_INT_IMAGE_2D_RECT : + case GL_INT_IMAGE_CUBE : + case GL_INT_IMAGE_BUFFER : + case GL_INT_IMAGE_1D_ARRAY : + case GL_INT_IMAGE_2D_ARRAY : + case GL_INT_IMAGE_2D_MULTISAMPLE : + case GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY : + case GL_UNSIGNED_INT_IMAGE_1D : + case GL_UNSIGNED_INT_IMAGE_2D : + case GL_UNSIGNED_INT_IMAGE_3D : + case GL_UNSIGNED_INT_IMAGE_2D_RECT : + case GL_UNSIGNED_INT_IMAGE_CUBE : + case GL_UNSIGNED_INT_IMAGE_BUFFER : + case GL_UNSIGNED_INT_IMAGE_1D_ARRAY : + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY : + case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE : + case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY : + return sizeof(GLint); + case GL_UNSIGNED_INT_ATOMIC_COUNTER: return sizeof(GLuint); case GL_BYTE: return sizeof(GLbyte); case GL_UNSIGNED_BYTE: return sizeof(GLubyte); case GL_SHORT: return sizeof(GLshort); case GL_UNSIGNED_SHORT: return sizeof(GLushort); - case GL_INT: return sizeof(GLint); case GL_INT_2_10_10_10_REV: return sizeof(GLint); - case GL_UNSIGNED_INT: return sizeof(GLuint); case GL_UNSIGNED_INT_2_10_10_10_REV: return sizeof(GLuint); - case GL_FLOAT: return sizeof(GLfloat); - case GL_DOUBLE: return sizeof(GLdouble); default: printf("WARNING!\nGLenum type: %u not supported!!!", type); return 0; @@ -84,4 +186,4 @@ std::string ShaderTypeName(const GLenum typeID) printf("WARNING!\nGLenum type: %u not supported!!!", typeID); return "NONE"; } -} +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 248b418adc443fc796f1936e0ed5561edbdaf221..4ca8b511171b5f2e194d36961d7385d38168b479 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,8 +54,7 @@ int main() MaterialSystem::load(); ModelSystem::load(); - auto renderer = EdgeRenderer(); - + auto renderer = Renderer(); //translation * view * rotate(time*0.1*F, time*0.333334*F, time*0.1666666667*F) //From shader, old system. auto modelCubeObject = EntityModel("cube"); auto modelFloorObject = EntityModel("cube"); @@ -67,73 +66,121 @@ int main() modelFloorObject.setPosition(glm::vec3(0, -3, 0)); modelFloorObject.setScale(glm::vec3(20, 0.5f, 20)); + Transform modelTransform; + modelTransform.m_position = glm::vec3{ 0,0,0 }; + + Light light; + + struct LightData { + glm::vec4 position; //16->16 + glm::vec4 intensities; //16->32 + float spread; //4 ->36 + float constant; //4 ->40 + float linear; //4 ->44 + float quadratic; //4 ->48 + + } lightData[8] = { + LightData{ { 0, 4, 0, 0 },{ 1.5f, 0, 0 , 0}, /*0.0f, 0.0f, 0.0f, 0.0f */ }, + LightData{ { 1.5f, 0, 0, 0 },{ 0, 0, 1.5f , 0 },/* 0.0f, 0.0f, 0.0f, 0.0f */ }, + LightData{ { 3, 1, 0, 0 },{ 0, 1.5f, 0 , 0}, /*10.0f, 10.0f, 10.0f, 10.0f*/ }, + LightData{ { 0, -2, 0,0 },{ 1, 0, 0 , 0}, /*10.0f, 10.0f, 10.0f, 10.0f*/ }, + LightData{ { 0, 1, -4,0 },{ 1, 0, 1 , 0}, /*10.0f, 10.0f, 10.0f, 10.0f*/ }, + LightData{ { 0, -5, 0,0 },{ 1, 1, 0 , 0}, /*10.0f, 10.0f, 10.0f, 10.0f*/ }, + LightData{ { 0, 5, 0,0 },{ 1, 1, 1 , 0}, /*10.0f, 10.0f, 10.0f, 10.0f*/ }, + LightData{ { 0,3, 3 ,0 },{ 0.5, 0.5, 0.5, 0}, /*10.0f, 10.0f, 10.0f, 10.0f*/ }, + }; + - //SCALE -> ROTATE -> TRANSLATE glm::mat4 projection = glm::perspective(C::FOV, C::AspectRatio, C::NearClip, C::FarClip); - glm::mat4 camera = glm::mat4(1); - glm::mat4 pivot = glm::translate(glm::mat4(1),glm::vec3(0, 0, C::CameraOffset)); //Camera pos in world. + glm::mat4 camera = glm::mat4(1); + glm::mat4 pivot = glm::translate(glm::mat4(1), glm::vec3(0, 0, C::CameraOffset)); //Camera pos in world. glm::mat4 view = glm::mat4(1); + glm::mat4 m2w = modelTransform.modelToWorld(); + + + float oldT = 0, t = 0, dt = 0; - //GLCall(glSetUn) - GLint uniformMVP, uniformTime; - GLint uniformMVP2, uniformTime2; - GLint uniformView; //Will communicate camera orientation to shader. + auto matrixBuf = ShaderSystem::getUniformBufferByTag("OK_Matrices"); + auto lightBuf = ShaderSystem::getUniformBufferByTag("OK_Lights"); - //TODO move to shader system: - for (auto mesh : ModelSystem::getById(modelCubeObject.getModel()).m_meshes) + // Get Uniform buffer indicies + auto projectionIndex = matrixBuf.getUniformIndex("projection"); + auto viewIndex = matrixBuf.getUniformIndex("view"); + auto viewPosIndex = matrixBuf.getUniformIndex("view_position"); + + // @TODO make this getUniformIndex("light", 0) + // @note this could also be used as offset for all the other lights + auto light0PosIndex = lightBuf.getUniformIndex("light[0].position"); + auto light1PosIndex = lightBuf.getUniformIndex("light[1].position"); + auto light2PosIndex = lightBuf.getUniformIndex("light[2].position"); + + + for (auto mesh: ModelSystem::getById( modelCubeObject.getModel() ).m_meshes) + { + auto& shader = mesh.m_shaderProgram; + shader.setMaterial(MaterialSystem::getById(mesh.m_materialID)); + } + + for (auto mesh: ModelSystem::getById( modelFloorObject.getModel() ).m_meshes) { - mesh.m_shaderProgram.bind(); - uniformMVP = mesh.m_shaderProgram.getUniformLocation("projection"); - uniformTime = mesh.m_shaderProgram.getUniformLocation("time"); - uniformView = mesh.m_shaderProgram.getUniformLocation("view"); - GLCall(glUniformMatrix4fv(uniformMVP, 1, GL_FALSE, glm::value_ptr(projection))); + auto& shader = mesh.m_shaderProgram; + shader.setMaterial(MaterialSystem::getById(mesh.m_materialID)); } - float oldT = 0, t = 0, dt = 0; for(;;) { - t = glfwGetTime(); + t = (float)glfwGetTime(); dt = t - oldT; if ((glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS || glfwWindowShouldClose(window) != 0)) break; - // auto model = ModelSystem::getByTag("cube"); // This is a hack, its beting loaded every frame in case it was - Renderer::clear(); // changed by keypress. - // Renderer::draw(model, glm::mat4(1)); // Replaced by new model, however some of old models components are still being used. + Renderer::clear(); modelCubeObject.update(dt); modelFloorObject.update(dt); - // Set uniforms global shaders - for (auto mesh : ModelSystem::getById(modelCubeObject.getModel()).m_meshes) - { - mesh.m_shaderProgram.bind(); - GLCall(glUniformMatrix4fv(uniformMVP, 1, GL_FALSE, glm::value_ptr(projection))); - GLCall(glUniformMatrix4fv(uniformView, 1, GL_FALSE, glm::value_ptr(view))); - GLCall(glUniform1f(uniformTime, 0)); - } - - modelCubeObject.draw(); //Important: currently uses the old model's 0th mesh's shader to draw. Also true for the camera. - modelFloorObject.draw(); //Important: currently uses the old model's 0th mesh's shader to draw. Also true for the camera. - - //@TODO shader.bindDynamic() + // UPDATE CAMERA DATA projection = glm::perspective(Input::m_fovy, C::AspectRatio, 0.1f, -100.0f); camera = glm::rotate(glm::mat4(1), (Input::m_camRotX), glm::vec3(0.0f, 1.0f, 0.0f)); camera = glm::rotate(glm::mat4(1), (Input::m_camRotY), glm::vec3(1.0f, 0.0f, 0.0f)) * camera; - pivot = glm::translate(glm::mat4(1),glm::vec3(Input::m_camPanX, Input::m_camPanY, C::CameraOffset)); //Camera pos in world. - + pivot = glm::translate(glm::mat4(1), glm::vec3(Input::m_camPanX, Input::m_camPanY, C::CameraOffset)); view = pivot * camera; glm::inverse(view); //To reverse both axis, so controls are not reverse. + // UPDATE LIGHT DATA + lightData[0].position = glm::vec4(10 * sin(3 * t), 0, 10 * cos(3 * t), 0); + lightData[0].intensities = glm::vec4(1.5f * sin(1.33*t), 1.5 * cos(1.33*t), 0, 0); + + lightData[1].position = glm::vec4(10 * sin(1.33*t), 10 * cos(1.33*t), 0, 0); + lightData[1].intensities = glm::vec4(1.5f * sin(1.33*t + C::PI / 3), 1.5 * cos(1.33*t + C::PI / 3), 0, 0); + + lightData[2].position = glm::vec4(0, 10 * sin(4.377*t), 10 * cos(4.377*t), 0); + lightData[2].intensities = glm::vec4(1.5f * sin(1.33*t + (C::PI * 2 / 3)), 1.5 * cos(1.33*t + (C::PI * 2 / 3)), 0, 0); + + + // UPDATE GLOBAL UNIFORM BUFFERS + lightBuf.update(light0PosIndex, 16, &(lightData[0].position)); + lightBuf.update(light0PosIndex + 16, 16, &(lightData[0].intensities)); + + lightBuf.update(light1PosIndex, 16, &(lightData[1].position)); + lightBuf.update(light1PosIndex + 16, 16, &(lightData[1].intensities)); + + lightBuf.update(light2PosIndex, 16, &(lightData[2].position)); + lightBuf.update(light2PosIndex + 16, 16, &(lightData[2].intensities)); + + matrixBuf.update(projectionIndex, sizeof(glm::mat4), glm::value_ptr(projection)); + matrixBuf.update(viewIndex, sizeof(glm::mat4), glm::value_ptr(view)); + matrixBuf.update(viewPosIndex, sizeof(glm::vec4), glm::value_ptr(pivot)); + + // DRAW ENTITIES + Renderer::draw(modelCubeObject, t); + Renderer::draw(modelFloorObject, t); glfwSwapBuffers(window); glfwPollEvents(); - // LIVE UPDATE SHADER AND MATERIALS - // Util::everyTwoSeconds(t); - oldT = t; }