Technically working shaders.
This commit is contained in:
		
							
								
								
									
										8
									
								
								assets/materials/simple-textured.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								assets/materials/simple-textured.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| { | ||||
|   "assets": { | ||||
|     "simpleTexturedShader": { | ||||
|       "type": "shader", | ||||
|       "path": "shaders/simple-textured.shader" | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -13,6 +13,10 @@ | ||||
|     "rosatext": { | ||||
|       "type": "texture", | ||||
|       "path": "rosa.texture" | ||||
|     }, | ||||
|     "simpleTexturedShader": { | ||||
|       "type": "shader", | ||||
|       "path": "shaders/simple-textured.slang" | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   | ||||
| @@ -1,13 +1,9 @@ | ||||
| struct Uniforms { | ||||
|   float4x4 projection; | ||||
|   float4x4 view; | ||||
|   float4x4 model; | ||||
|   float4 color; | ||||
|   bool hasTexture; | ||||
|   Sampler2D texture; | ||||
| } | ||||
| 
 | ||||
| uniform Uniforms uniforms; | ||||
| uniform float4x4 projection; | ||||
| uniform float4x4 view; | ||||
| uniform float4x4 model; | ||||
| uniform float4 color; | ||||
| uniform bool hasTexture; | ||||
| uniform Sampler2D texture; | ||||
| 
 | ||||
| struct AssembledVertex { | ||||
|   float3 position : POSITION; | ||||
| @@ -35,7 +31,7 @@ VertexStageOutput vertexMain( | ||||
| 
 | ||||
|   output.sv_position = mul( | ||||
|     float4(position, 1.0), | ||||
|     mul(uniforms.model, mul(uniforms.view, uniforms.projection)) | ||||
|     mul(model, mul(view, projection)) | ||||
|   ); | ||||
| 
 | ||||
|   return output; | ||||
| @@ -46,10 +42,11 @@ Fragment fragmentMain( | ||||
|   float2 uv: UV | ||||
| ) : SV_Target { | ||||
|   Fragment output; | ||||
|   if (uniforms.hasTexture) { | ||||
|     output.color = uniforms.texture.Sample(uv) * uniforms.color; | ||||
|    | ||||
|   if (hasTexture) { | ||||
|     output.color = texture.Sample(uv) * color; | ||||
|   } else { | ||||
|     output.color = uniforms.color; | ||||
|     output.color = color; | ||||
|   } | ||||
|    | ||||
|   return output; | ||||
| @@ -43,6 +43,6 @@ add_subdirectory(util) | ||||
|  | ||||
| # Assets | ||||
| tool_copy(en en.json) | ||||
| tool_copy(helloShader shaders/hello-world.slang) | ||||
| tool_copy(simpleTexturedShader shaders/simple-textured.slang) | ||||
|  | ||||
| add_dependencies(${DAWN_TARGET_NAME} dawnassets) | ||||
| @@ -6,6 +6,7 @@ | ||||
| #include "LoaderForSceneItems.hpp" | ||||
| #include "asset/loader/TextureLoader.hpp" | ||||
| #include "asset/loader/scene/PrefabLoader.hpp" | ||||
| #include "asset/loader/ShaderLoader.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| @@ -58,6 +59,9 @@ void LoaderForSceneItems::setupDependencies() { | ||||
|         prefabLoader->ctx->parent = ctx; | ||||
|         loader = prefabLoader; | ||||
|  | ||||
|       } else if(type == "shader") { | ||||
|         loader = getAssetManager()->get<ShaderLoader>(path); | ||||
|  | ||||
|       } else { | ||||
|         assertUnreachable("Unknown asset type: %s", type.c_str()); | ||||
|       } | ||||
|   | ||||
| @@ -11,10 +11,21 @@ | ||||
| using namespace Dawn; | ||||
|  | ||||
| void SimpleTexturedMaterial::initShaderPrograms() { | ||||
|   this->shader = getGame()->assetManager->get<ShaderLoader>("shaders/hello-world.slang")->getShader(); | ||||
|   if(this->shader) return; | ||||
|  | ||||
|   auto shaderFile = getGame()->assetManager->get<ShaderLoader>("shaders/simple-textured.slang"); | ||||
|   this->shader = shaderFile->getShader(); | ||||
|  | ||||
|   auto structure = this->shader->getStructure(); | ||||
|   this->data = structure->createData(); | ||||
|  | ||||
|   this->setColor(COLOR_WHITE); | ||||
|   this->setTexture(nullptr); | ||||
| } | ||||
|  | ||||
| void SimpleTexturedMaterial::load(std::shared_ptr<SceneLoadContext> ctx) { | ||||
|   this->initShaderPrograms(); | ||||
|  | ||||
|   if(ctx->data.contains("color")) { | ||||
|     this->setColor(JSON::color(ctx->data["color"])); | ||||
|   } | ||||
| @@ -28,41 +39,47 @@ void SimpleTexturedMaterial::load(std::shared_ptr<SceneLoadContext> ctx) { | ||||
| } | ||||
|  | ||||
| struct Color SimpleTexturedMaterial::getColor() { | ||||
|   // return this->data.color; | ||||
|   return COLOR_WHITE; | ||||
|   auto structure = this->shader->getStructure(); | ||||
|   return data->get<struct Color>(structure->getOffset("color")); | ||||
| } | ||||
|  | ||||
| std::shared_ptr<Texture> SimpleTexturedMaterial::getTexture() { | ||||
|   return this->texture; | ||||
|   auto structure = this->shader->getStructure(); | ||||
|   return data->get<std::shared_ptr<Texture>>(structure->getOffset("texture")); | ||||
| } | ||||
|  | ||||
| void SimpleTexturedMaterial::setTexture( | ||||
|   const std::shared_ptr<Texture> texture | ||||
| ) { | ||||
|   this->texture = texture; | ||||
|   auto structure = this->shader->getStructure(); | ||||
|   data->set<std::shared_ptr<Texture>>(structure->getOffset("texture"), texture); | ||||
|   data->set<bool_t>(structure->getOffset("hasTexture"), texture != nullptr); | ||||
| } | ||||
|  | ||||
| void SimpleTexturedMaterial::setColor(const struct Color color) { | ||||
|   // this->data.color = color; | ||||
|   auto structure = this->shader->getStructure(); | ||||
|   data->set<struct Color>(structure->getOffset("color"), color); | ||||
| } | ||||
|  | ||||
| std::vector<std::shared_ptr<RenderPass>> SimpleTexturedMaterial::getPasses( | ||||
|   struct RenderPassContext &ctx | ||||
| ) { | ||||
|   // this->data.model = this->getItem()->getWorldTransform(); | ||||
|   // this->data.projection = ctx.camera->getProjection(); | ||||
|   // this->data.view = ctx.camera->getItem()->getWorldTransform(); | ||||
|   // auto textures = std::unordered_map< | ||||
|   //   shadertexturebinding_t, std::shared_ptr<Texture> | ||||
|   // >(); | ||||
|    | ||||
|   // if(this->texture) { | ||||
|   //   this->data.hasTexture = true; | ||||
|   //   this->data.texture = 0; | ||||
|   //   textures[this->data.texture] = this->texture; | ||||
|   // } else { | ||||
|   //   this->data.data.hasTexture = false; | ||||
|   // } | ||||
|   auto structure = this->shader->getStructure(); | ||||
|  | ||||
|   data->set<glm::mat4>( | ||||
|     structure->getOffset("projection"), | ||||
|     ctx.camera->getProjection() | ||||
|   ); | ||||
|  | ||||
|   data->set<glm::mat4>( | ||||
|     structure->getOffset("view"), | ||||
|     ctx.camera->getItem()->getWorldTransform() | ||||
|   ); | ||||
|  | ||||
|   data->set<glm::mat4>( | ||||
|     structure->getOffset("model"), | ||||
|     this->getItem()->getWorldTransform() | ||||
|   ); | ||||
|  | ||||
|   return { | ||||
|     std::make_shared<RenderPass>( | ||||
| @@ -71,7 +88,8 @@ std::vector<std::shared_ptr<RenderPass>> SimpleTexturedMaterial::getPasses( | ||||
|       MeshDrawMode::TRIANGLES,// Move this later. | ||||
|       0,// Move this later. | ||||
|       -1,// Move this later. | ||||
|       this->shader | ||||
|       this->shader, | ||||
|       this->data | ||||
|     ) | ||||
|   }; | ||||
| } | ||||
|   | ||||
| @@ -9,8 +9,8 @@ | ||||
| namespace Dawn { | ||||
|   class SimpleTexturedMaterial : public Material { | ||||
|     private: | ||||
|       std::shared_ptr<ShaderProgram> shader; | ||||
|       std::shared_ptr<Texture> texture; | ||||
|       std::shared_ptr<ShaderProgram> shader = nullptr; | ||||
|       std::shared_ptr<ShaderData> data; | ||||
|        | ||||
|     protected: | ||||
|       void initShaderPrograms() override; | ||||
|   | ||||
| @@ -14,13 +14,15 @@ RenderPass::RenderPass( | ||||
|   const enum MeshDrawMode drawMode, | ||||
|   const int32_t indiceStart, | ||||
|   const int32_t indiceCount, | ||||
|   const std::shared_ptr<ShaderProgram> shaderProgram | ||||
|   const std::shared_ptr<ShaderProgram> shaderProgram, | ||||
|   const std::shared_ptr<ShaderData> shaderData | ||||
| ) : | ||||
|   mesh(mesh), | ||||
|   drawMode(drawMode), | ||||
|   indiceStart(indiceStart), | ||||
|   indiceCount(indiceCount), | ||||
|   shaderProgram(shaderProgram) | ||||
|   shaderProgram(shaderProgram), | ||||
|   shaderData(shaderData) | ||||
| { | ||||
|   // Need mesh? | ||||
|   if(!this->mesh) { | ||||
| @@ -30,6 +32,10 @@ RenderPass::RenderPass( | ||||
| } | ||||
|  | ||||
| void RenderPass::draw() { | ||||
|   shaderProgram->bind(); | ||||
|   shaderData->bind(); | ||||
|   shaderData->upload(); | ||||
|  | ||||
|   mesh->draw(drawMode, indiceStart, indiceCount); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -7,12 +7,14 @@ | ||||
| #include "display/mesh/Mesh.hpp" | ||||
| #include "scene/SceneComponent.hpp" | ||||
| #include "display/shader/ShaderProgram.hpp" | ||||
| #include "display/shader/ShaderData.hpp" | ||||
|  | ||||
| namespace Dawn { | ||||
|   class RenderPass { | ||||
|     private: | ||||
|       std::shared_ptr<Mesh> mesh; | ||||
|       std::shared_ptr<ShaderProgram> shaderProgram; | ||||
|       std::shared_ptr<ShaderData> shaderData; | ||||
|       const enum MeshDrawMode drawMode; | ||||
|       const int32_t indiceStart; | ||||
|       const int32_t indiceCount; | ||||
| @@ -27,6 +29,7 @@ namespace Dawn { | ||||
|        * @param indiceStart The indice to start drawing from. | ||||
|        * @param indiceCount The number of indices to draw. | ||||
|        * @param shaderProgram The shader program to use for this render pass. | ||||
|        * @param shaderData The shader data to use for this render pass. | ||||
|        */ | ||||
|       RenderPass( | ||||
|         SceneComponent &self, | ||||
| @@ -36,7 +39,8 @@ namespace Dawn { | ||||
|         const int32_t indiceStart, | ||||
|         const int32_t indiceCount, | ||||
|          | ||||
|         const std::shared_ptr<ShaderProgram> shaderProgram | ||||
|         const std::shared_ptr<ShaderProgram> shaderProgram, | ||||
|         const std::shared_ptr<ShaderData> shaderData | ||||
|       ); | ||||
|  | ||||
|       /** | ||||
|   | ||||
| @@ -51,6 +51,16 @@ namespace Dawn { | ||||
|       template<typename T> | ||||
|       void set(const size_t offset, const T value); | ||||
|  | ||||
|       /** | ||||
|        * Binds the buffer to the shader. | ||||
|        */ | ||||
|       virtual void bind() = 0; | ||||
|  | ||||
|       /** | ||||
|        * Uploads the data to the GPU. | ||||
|        */ | ||||
|       virtual void upload() = 0; | ||||
|  | ||||
|       /** | ||||
|        * Cleans up the data. | ||||
|        */ | ||||
|   | ||||
| @@ -129,6 +129,10 @@ void IShaderProgram::init( | ||||
|   ); | ||||
| } | ||||
|  | ||||
| std::shared_ptr<struct ShaderStructure> IShaderProgram::getStructure() { | ||||
|   return structure; | ||||
| } | ||||
|  | ||||
| IShaderProgram::~IShaderProgram() { | ||||
|   // Release the linked program | ||||
|   if(linkedProgram) { | ||||
|   | ||||
| @@ -39,6 +39,18 @@ namespace Dawn { | ||||
|         ComPtr<ISession> session | ||||
|       ); | ||||
|  | ||||
|       /** | ||||
|        * Returns the structure of the shader program. | ||||
|        *  | ||||
|        * @return The structure of the shader program. | ||||
|        */ | ||||
|       std::shared_ptr<struct ShaderStructure> getStructure(); | ||||
|  | ||||
|       /** | ||||
|        * Binds this shader program as the currently active shader program. | ||||
|        */ | ||||
|       virtual void bind() = 0; | ||||
|  | ||||
|       /** | ||||
|        * Destroy the IShaderProgram2 object | ||||
|        */ | ||||
|   | ||||
| @@ -27,6 +27,7 @@ void ShaderManager::init(const std::shared_ptr<Game> &game) { | ||||
|   createGlobalSession(globalSession.writeRef()); | ||||
|  | ||||
|   // Set the target description, TODO: interface | ||||
|   std::cout << "Need to fix GLSL hard code" << std::endl; | ||||
|   targetDescription.format = SLANG_GLSL; | ||||
|   targetDescription.profile = globalSession->findProfile("glsl_330"); | ||||
|  | ||||
|   | ||||
| @@ -60,7 +60,18 @@ ShaderStructure::ShaderStructure( | ||||
|       break; | ||||
|  | ||||
|     case TypeReflection::Kind::Resource: | ||||
|       this->type = ShaderStructureType::RESOURCE; | ||||
|       switch(typeLayout->getResourceShape()) { | ||||
|         case SlangResourceShape::SLANG_TEXTURE_2D: | ||||
|           this->type = ShaderStructureType::TEXTURE2D; | ||||
|           break; | ||||
|  | ||||
|         default: | ||||
|           assertUnreachable( | ||||
|             "Unknown resource shape: %d", | ||||
|             typeLayout->getResourceShape() | ||||
|           ); | ||||
|           break; | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     default: { | ||||
| @@ -93,6 +104,18 @@ std::shared_ptr<ShaderStructure> ShaderStructure::getArrayMember( | ||||
|   return this->members.at(index); | ||||
| } | ||||
|  | ||||
| size_t ShaderStructure::getOffset() { | ||||
|   return this->start; | ||||
| } | ||||
|  | ||||
| size_t ShaderStructure::getOffset(const std::string &name) { | ||||
|   return this->getStructMember(name)->getOffset(); | ||||
| } | ||||
|  | ||||
| size_t ShaderStructure::getOffset(size_t index) { | ||||
|   return this->getArrayMember(index)->getOffset(); | ||||
| } | ||||
|  | ||||
| std::shared_ptr<ShaderData> ShaderStructure::createData() { | ||||
|   return std::make_shared<ShaderData>(shared_from_this()); | ||||
| } | ||||
| @@ -18,6 +18,7 @@ namespace Dawn { | ||||
|     STRUCT, | ||||
|     ARRAY, | ||||
|     VARIABLE, | ||||
|     TEXTURE2D, | ||||
|     RESOURCE | ||||
|   }; | ||||
|  | ||||
| @@ -67,6 +68,29 @@ namespace Dawn { | ||||
|        */ | ||||
|       std::shared_ptr<ShaderStructure> getArrayMember(size_t index); | ||||
|  | ||||
|       /** | ||||
|        * Gets the offset of this structure. | ||||
|        *  | ||||
|        * @return The offset of this structure. | ||||
|        */ | ||||
|       size_t getOffset(); | ||||
|  | ||||
|       /** | ||||
|        * Gets the offset of a member of this structure. | ||||
|        *  | ||||
|        * @param name Name of the member to get. | ||||
|        * @return The offset of the member. | ||||
|        */ | ||||
|       size_t getOffset(const std::string &name); | ||||
|  | ||||
|       /** | ||||
|        * Gets the offset of a member of this array structure. | ||||
|        *  | ||||
|        * @param index Index of the member to get. | ||||
|        * @return The offset of the member. | ||||
|        */ | ||||
|       size_t getOffset(size_t index); | ||||
|  | ||||
|       /** | ||||
|        * Creates data for a shader that matches this structure. | ||||
|        *  | ||||
|   | ||||
| @@ -10,7 +10,12 @@ | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| void SceneComponent::init(const std::shared_ptr<SceneItem> item) { | ||||
| void SceneComponent::init() { | ||||
|   assertNotNull( | ||||
|     this->item.lock(), | ||||
|     "SceneItem has unloaded, or was not set before initialization" | ||||
|   ); | ||||
|    | ||||
|   assertFlagOff( | ||||
|     state, | ||||
|     SceneComponentState::INITIALIZED, | ||||
|   | ||||
| @@ -10,6 +10,7 @@ namespace Dawn { | ||||
|   class Game; | ||||
|   class Scene; | ||||
|   class SceneItem; | ||||
|   class SceneItemComponents; | ||||
|  | ||||
|   enum class SceneComponentState : flag_t { | ||||
|     INITIAL = FLAG(0), | ||||
| @@ -42,10 +43,8 @@ namespace Dawn { | ||||
|  | ||||
|       /** | ||||
|        * Initializes this scene component. | ||||
|        *  | ||||
|        * @param item Scene item that this component belongs to. | ||||
|        */ | ||||
|       void init(const std::shared_ptr<SceneItem> item); | ||||
|       void init(); | ||||
|  | ||||
|       /** | ||||
|        * Disposes this scene component. | ||||
| @@ -92,5 +91,8 @@ namespace Dawn { | ||||
|        * Disposes this scene component. | ||||
|        */ | ||||
|       virtual ~SceneComponent(); | ||||
|        | ||||
|       friend class SceneItem; | ||||
|       friend class SceneItemComponents; | ||||
|   }; | ||||
| } | ||||
| @@ -34,8 +34,6 @@ void SceneItem::init() { | ||||
|   assertFlagOff(state, SceneItemState::DEINITIALIZED, "Already deinited."); | ||||
|   Flag::turnOn(state, SceneItemState::INITIALIZED); | ||||
|  | ||||
|   auto sharedThis = shared_from_this(); | ||||
|  | ||||
|   // Loop until all components initialized... | ||||
|   while(true) { | ||||
|     // Create copy of the components, components may chose to add more | ||||
| @@ -43,7 +41,7 @@ void SceneItem::init() { | ||||
|     auto components = this->components; | ||||
|     for(auto &component : components) { | ||||
|       if(component->isInitialized()) continue; | ||||
|       component->init(sharedThis); | ||||
|       component->init(); | ||||
|     } | ||||
|  | ||||
|     // If they are all initalized we are fine. | ||||
|   | ||||
| @@ -4,6 +4,8 @@ | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "SceneItemComponents.hpp" | ||||
| #include "scene/SceneItem.hpp" | ||||
| #include "assert/assert.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| @@ -20,6 +22,14 @@ void SceneItemComponents::removeComponent( | ||||
|   components.erase(it); | ||||
| } | ||||
|  | ||||
| void SceneItemComponents::sceneItemComponentsReferenceSelf( | ||||
|   std::shared_ptr<SceneComponent> component | ||||
| ) { | ||||
|   assertNotNull(component, "Component cannot be NULL"); | ||||
|   auto self = (SceneItem *)this; | ||||
|   component->item = self->shared_from_this(); | ||||
| } | ||||
|  | ||||
| SceneItemComponents::~SceneItemComponents() { | ||||
|  | ||||
| } | ||||
| @@ -10,6 +10,16 @@ namespace Dawn { | ||||
|   class SceneItem; | ||||
|  | ||||
|   class SceneItemComponents { | ||||
|     private: | ||||
|       /** | ||||
|        * Internal method to set the scene item reference on a component. | ||||
|        *  | ||||
|        * @param component Component to check. | ||||
|        */ | ||||
|       void sceneItemComponentsReferenceSelf( | ||||
|         std::shared_ptr<SceneComponent> component | ||||
|       ); | ||||
|  | ||||
|     protected: | ||||
|       std::vector<std::shared_ptr<SceneComponent>> components; | ||||
|  | ||||
| @@ -40,9 +50,9 @@ namespace Dawn { | ||||
|       std::shared_ptr<T> addComponent() { | ||||
|         //Create the component and add it. | ||||
|         std::shared_ptr<T> component = std::make_shared<T>(); | ||||
|         this->components.push_back( | ||||
|           static_pointer_cast<SceneComponent>(component) | ||||
|         ); | ||||
|         auto asSceneComponent = static_pointer_cast<SceneComponent>(component); | ||||
|         this->sceneItemComponentsReferenceSelf(asSceneComponent); | ||||
|         this->components.push_back(asSceneComponent); | ||||
|         return component; | ||||
|       } | ||||
|  | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
| // https://opensource.org/licenses/MIT | ||||
|  | ||||
| #include "display/shader/ShaderData.hpp" | ||||
| #include "assert/assert.hpp" | ||||
| #include "assert/assertgl.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
| @@ -13,6 +14,37 @@ ShaderData::ShaderData( | ||||
| ) : IShaderData(structure) { | ||||
|   glGenBuffers(1, &this->buffer); | ||||
|   assertNoGLError(); | ||||
|  | ||||
|   // Quickly scan the structure for textures that we can bind to. | ||||
|   int32_t nextTexture = 0; | ||||
|   std::function<void(const std::shared_ptr<ShaderStructure>&)> | ||||
|     recursivelyAppendTextures | ||||
|   ; | ||||
|   recursivelyAppendTextures = [&]( | ||||
|     const std::shared_ptr<ShaderStructure> &structure | ||||
|   ) { | ||||
|     assertTrue( | ||||
|       structure->type == ShaderStructureType::STRUCT, | ||||
|       "Can only scan for texture indices in structures." | ||||
|     ); | ||||
|  | ||||
|     for(auto &field : structure->members) { | ||||
|       switch(field->type) { | ||||
|         case ShaderStructureType::STRUCT: | ||||
|           recursivelyAppendTextures(field); | ||||
|           break; | ||||
|          | ||||
|         case ShaderStructureType::TEXTURE2D: | ||||
|           this->textureIndices[field->getOffset()] = nextTexture++; | ||||
|           break; | ||||
|  | ||||
|         default: | ||||
|           break; | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
|   recursivelyAppendTextures(structure); | ||||
|  | ||||
| } | ||||
|  | ||||
| void ShaderData::upload() { | ||||
| @@ -20,19 +52,59 @@ void ShaderData::upload() { | ||||
|  | ||||
|   glBindBuffer(GL_UNIFORM_BUFFER, this->buffer); | ||||
|   assertNoGLError(); | ||||
|   glBindBufferBase(GL_UNIFORM_BUFFER, 0, this->buffer); | ||||
|   assertNoGLError(); | ||||
|   this->bind(); | ||||
|   glBufferData(GL_UNIFORM_BUFFER, this->structure->size, this->data, GL_STATIC_DRAW); | ||||
|   assertNoGLError(); | ||||
|  | ||||
|   for(auto &pair : this->textureBindings) { | ||||
|     if(!pair.second) continue; | ||||
|     pair.second->bind(pair.first); | ||||
|     glUniform1i(pair.first, pair.first); | ||||
|   } | ||||
|    | ||||
|   this->dirty = false; | ||||
| } | ||||
|  | ||||
| void ShaderData::bind(const GLuint index) { | ||||
|   glBindBufferBase(GL_UNIFORM_BUFFER, index, this->buffer); | ||||
| void ShaderData::bind() { | ||||
|   glBindBufferBase(GL_UNIFORM_BUFFER, 0, this->buffer); | ||||
|   assertNoGLError(); | ||||
| } | ||||
|  | ||||
| template<> | ||||
| std::shared_ptr<Texture> IShaderData::get<std::shared_ptr<Texture>>( | ||||
|   const size_t offset | ||||
| ) { | ||||
|   ShaderData *self = (ShaderData *)this; | ||||
|   auto map = self->textureIndices.find(offset); | ||||
|   assertTrue( | ||||
|     map != self->textureIndices.end(), | ||||
|     "Texture is not found in the structure or the offset is incorrect." | ||||
|   ); | ||||
|  | ||||
|   auto index = map->second; | ||||
|   return self->textureBindings[index]; | ||||
| } | ||||
|  | ||||
| template<> | ||||
| void IShaderData::set<std::shared_ptr<Texture>>( | ||||
|   const size_t offset, const std::shared_ptr<Texture> value | ||||
| ) { | ||||
|   ShaderData *self = (ShaderData *)this; | ||||
|   auto map = self->textureIndices.find(offset); | ||||
|   assertTrue( | ||||
|     map != self->textureIndices.end(), | ||||
|     "Texture is not found in the structure or the offset is incorrect." | ||||
|   ); | ||||
|  | ||||
|   // I didn't implement it, but in theory we can check if the texture is | ||||
|   // already bound to an index and reuse its existing index to avoid | ||||
|   // binding a texture twice if we don't need to, however this would | ||||
|   // require all bindings be flushed and re-bound each frame. | ||||
|   auto index = map->second; | ||||
|   self->textureBindings[map->second] = value;// Releases textures too. | ||||
|   if(value) this->dirty = true; | ||||
| } | ||||
|  | ||||
| ShaderData::~ShaderData() { | ||||
|   if(this->buffer != -1) { | ||||
|     glDeleteBuffers(1, &this->buffer); | ||||
|   | ||||
| @@ -13,11 +13,16 @@ namespace Dawn { | ||||
|       GLuint buffer = -1; | ||||
|  | ||||
|     public: | ||||
|       std::unordered_map<size_t, uint8_t> textureIndices; | ||||
|       std::unordered_map<uint8_t, std::shared_ptr<Texture>> textureBindings; | ||||
|  | ||||
|       ShaderData( | ||||
|         const std::shared_ptr<ShaderStructure> &structure | ||||
|       ); | ||||
|       void upload(); | ||||
|       void bind(const GLuint index); | ||||
|  | ||||
|       void upload() override; | ||||
|       void bind() override; | ||||
|        | ||||
|       ~ShaderData() override; | ||||
|   }; | ||||
| } | ||||
| @@ -7,20 +7,9 @@ | ||||
| #include "assert/assert.hpp" | ||||
| #include "assert/assertgl.hpp" | ||||
| #include "display/shader/ShaderData.hpp" | ||||
| #include "component/display/material/SimpleTexturedMaterial.hpp" | ||||
|  | ||||
| using namespace Dawn; | ||||
|  | ||||
| struct TestData { | ||||
|   glm::mat4 projection; | ||||
|   glm::mat4 view; | ||||
|   glm::mat4 model; | ||||
|   int hasTexture; | ||||
|   int padding[3]; | ||||
|   struct Color color; | ||||
|   int test; | ||||
| }; | ||||
|  | ||||
| void ShaderProgram::init( | ||||
|   IModule *module, | ||||
|   Slang::ComPtr<ISession> session | ||||
| @@ -57,73 +46,11 @@ void ShaderProgram::init( | ||||
|     assertNoGLError(); | ||||
|     assertUnreachable("Failed to link shader program:\n%s", log); | ||||
|   } | ||||
| } | ||||
|  | ||||
|   // So the uniforms that are in slang are kinda odd when compiled. | ||||
| void ShaderProgram::bind() { | ||||
|   glUseProgram(this->id); | ||||
|   assertNoGLError(); | ||||
|  | ||||
|   data = this->structure->createData(); | ||||
|  | ||||
|   size_t offset = 0; | ||||
|   data->set<glm::mat4>(offset, glm::perspective( | ||||
|     glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 10000.0f | ||||
|   )); | ||||
|   offset += sizeof(glm::mat4); | ||||
|  | ||||
|   data->set<glm::mat4>(offset, glm::lookAt( | ||||
|     glm::vec3(300,300,300), glm::vec3(0,0,0), glm::vec3(0,1,0) | ||||
|   )); | ||||
|   offset += sizeof(glm::mat4); | ||||
|  | ||||
|   data->set<glm::mat4>(offset, glm::mat4(1.0f)); | ||||
|   offset += sizeof(glm::mat4); | ||||
|  | ||||
|   data->set<struct Color>(offset, COLOR_WHITE); | ||||
|   offset += sizeof(glm::vec4); | ||||
|  | ||||
|   data->set<bool_t>(offset, true); | ||||
|   offset += sizeof(bool_t); | ||||
|  | ||||
|   data->upload(); | ||||
|   data->bind(0); | ||||
|  | ||||
|  | ||||
|   // struct TestData data; | ||||
|   // data.color = COLOR_WHITE; | ||||
|   // data.model = glm::mat4(1.0f); | ||||
|   // data.projection = glm::perspective( | ||||
|   //   glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 10000.0f | ||||
|   // ); | ||||
|   // data.view = glm::lookAt( | ||||
|   //   glm::vec3(300,300,300), glm::vec3(0,0,0), glm::vec3(0,1,0) | ||||
|   // ); | ||||
|   // data.hasTexture = false; | ||||
|   // data.test = 1; | ||||
|  | ||||
|   // glBindBuffer(GL_UNIFORM_BUFFER, ubo); | ||||
|   // assertNoGLError(); | ||||
|   // glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo); | ||||
|   // assertNoGLError(); | ||||
|   // glBufferData(GL_UNIFORM_BUFFER, sizeof(struct TestData), &data, GL_STATIC_DRAW); | ||||
|   // assertNoGLError(); | ||||
|  | ||||
|   testTexture = std::make_shared<Texture>(); | ||||
|   testTexture->setSize(2, 2, TextureFormat::RGBA, TextureDataFormat::UNSIGNED_BYTE); | ||||
|   uint8_t colors[4 * 4]; | ||||
|   colors[0] = 255; colors[1] = 255; colors[2] = 0; colors[3] = 255; | ||||
|   colors[4] = 0; colors[5] = 255; colors[6] = 0; colors[7] = 255; | ||||
|   colors[8] = 0; colors[9] = 0; colors[10] = 255; colors[11] = 255; | ||||
|   colors[12] = 255; colors[13] = 255; colors[14] = 255; colors[15] = 255; | ||||
|   testTexture->buffer(colors); | ||||
|   testTexture->bind(0); | ||||
|  | ||||
|   int index = glGetUniformLocation(this->id, "globalParams_uniforms_texture_0"); | ||||
|   assertNoGLError(); | ||||
|   std::cout << "Index: " << index << std::endl; | ||||
|   glUniform1i(index, 0); | ||||
|   assertNoGLError(); | ||||
|  | ||||
|   // data->write(shared_from_this()); | ||||
| } | ||||
|  | ||||
| ShaderProgram::~ShaderProgram() { | ||||
|   | ||||
| @@ -27,7 +27,10 @@ namespace Dawn { | ||||
|       void init( | ||||
|         IModule *module, | ||||
|         Slang::ComPtr<ISession> session | ||||
|       ); | ||||
|       ) override; | ||||
|  | ||||
|       void bind() override; | ||||
|  | ||||
|       ~ShaderProgram() override; | ||||
|   }; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user