#ifndef __EFFEKSEERRENDERER_GL_GRAPHICS_DEVICE_H__ #define __EFFEKSEERRENDERER_GL_GRAPHICS_DEVICE_H__ #include "EffekseerRendererGL.GLExtension.h" #include #include #include #include namespace EffekseerRendererGL { namespace Backend { class GraphicsDevice; class VertexBuffer; class IndexBuffer; class UniformBuffer; class Shader; class VertexLayout; class FrameBuffer; class Texture; class RenderPass; class PipelineState; class UniformLayout; using GraphicsDeviceRef = Effekseer::RefPtr; using VertexBufferRef = Effekseer::RefPtr; using IndexBufferRef = Effekseer::RefPtr; using UniformBufferRef = Effekseer::RefPtr; using ShaderRef = Effekseer::RefPtr; using VertexLayoutRef = Effekseer::RefPtr; using FrameBufferRef = Effekseer::RefPtr; using TextureRef = Effekseer::RefPtr; using RenderPassRef = Effekseer::RefPtr; using PipelineStateRef = Effekseer::RefPtr; using UniformLayoutRef = Effekseer::RefPtr; Effekseer::CustomVector GetVertexAttribLocations(const VertexLayoutRef& vertexLayout, const ShaderRef& shader); void EnableLayouts(const VertexLayoutRef& vertexLayout, const Effekseer::CustomVector& locations); void DisableLayouts(const Effekseer::CustomVector& locations); void StoreUniforms(const ShaderRef& shader, const UniformBufferRef& vertexUniform, const UniformBufferRef& fragmentUniform, bool transpose); class DeviceObject { private: public: virtual void OnLostDevice(); virtual void OnResetDevice(); }; /** @brief VertexBuffer of OpenGL @note TODO : Optimize it */ class VertexBuffer : public DeviceObject, public Effekseer::Backend::VertexBuffer { private: GLuint buffer_ = 0; std::vector resources_; GraphicsDevice* graphicsDevice_ = nullptr; int32_t size_ = 0; bool isDynamic_ = false; public: VertexBuffer(GraphicsDevice* graphicsDevice); ~VertexBuffer() override; bool Allocate(int32_t size, bool isDynamic); void Deallocate(); void OnLostDevice() override; void OnResetDevice() override; bool Init(int32_t size, bool isDynamic); void UpdateData(const void* src, int32_t size, int32_t offset); GLuint GetBuffer() const { return buffer_; } }; /** @brief IndexBuffer of OpenGL TODO : Optimize it */ class IndexBuffer : public DeviceObject, public Effekseer::Backend::IndexBuffer { private: GLuint buffer_ = 0; std::vector resources_; GraphicsDevice* graphicsDevice_ = nullptr; int32_t stride_ = 0; public: IndexBuffer(GraphicsDevice* graphicsDevice); ~IndexBuffer() override; bool Allocate(int32_t elementCount, int32_t stride); void Deallocate(); void OnLostDevice() override; void OnResetDevice() override; bool Init(int32_t elementCount, int32_t stride); void UpdateData(const void* src, int32_t size, int32_t offset); GLuint GetBuffer() const { return buffer_; } }; class UniformBuffer : public DeviceObject, public Effekseer::Backend::UniformBuffer { private: Effekseer::CustomVector buffer_; public: UniformBuffer() = default; ~UniformBuffer() override = default; bool Init(int32_t size, const void* initialData); const Effekseer::CustomVector& GetBuffer() const { return buffer_; } Effekseer::CustomVector& GetBuffer() { return buffer_; } void UpdateData(const void* src, int32_t size, int32_t offset); }; class Texture : public DeviceObject, public Effekseer::Backend ::Texture { private: GLuint buffer_ = 0; GLuint renderbuffer_ = 0; int32_t target_ = -1; GraphicsDevice* graphicsDevice_ = nullptr; std::function onDisposed_; public: Texture(GraphicsDevice* graphicsDevice); ~Texture() override; bool Init(const Effekseer::Backend::TextureParameter& param, const Effekseer::CustomVector& initialData); bool Init(const Effekseer::Backend::RenderTextureParameter& param); bool Init(const Effekseer::Backend::DepthTextureParameter& param); bool Init(GLuint buffer, bool hasMipmap, const std::function& onDisposed); GLuint GetBuffer() const { return buffer_; } GLuint GetRenderBuffer() const { return renderbuffer_; } int32_t GetTarget() const { return target_; } }; class VertexLayout : public DeviceObject, public Effekseer::Backend::VertexLayout { private: Effekseer::CustomVector elements_; public: VertexLayout() = default; ~VertexLayout() = default; bool Init(const Effekseer::Backend::VertexLayoutElement* elements, int32_t elementCount); const Effekseer::CustomVector& GetElements() const { return elements_; } }; class Shader : public DeviceObject, public Effekseer::Backend::Shader { private: static const size_t elementMax = 16; GraphicsDevice* graphicsDevice_ = nullptr; GLuint program_ = 0; GLuint vao_ = 0; Effekseer::CustomVector> vsCodes_; Effekseer::CustomVector> psCodes_; Effekseer::Backend::UniformLayoutRef layout_ = nullptr; Effekseer::CustomVector textureLocations_; Effekseer::CustomVector uniformLocations_; bool Compile(); void Reset(); public: Shader(GraphicsDevice* graphicsDevice); ~Shader() override; bool Init(const Effekseer::CustomVector>& vsCodes, const Effekseer::CustomVector>& psCodes, Effekseer::Backend::UniformLayoutRef& layout); void OnLostDevice() override; void OnResetDevice() override; GLuint GetProgram() const { return program_; } GLuint GetVAO() const { return vao_; } const Effekseer::Backend::UniformLayoutRef& GetLayout() const { return layout_; } const Effekseer::CustomVector& GetTextureLocations() const { return textureLocations_; } const Effekseer::CustomVector& GetUniformLocations() const { return uniformLocations_; } }; class PipelineState : public DeviceObject, public Effekseer::Backend::PipelineState { private: Effekseer::Backend::PipelineStateParameter param_; Effekseer::CustomVector attribLocations_; public: PipelineState() = default; ~PipelineState() = default; bool Init(const Effekseer::Backend::PipelineStateParameter& param); const Effekseer::Backend::PipelineStateParameter& GetParam() const { return param_; } const Effekseer::CustomVector& GetAttribLocations() const { return attribLocations_; } }; class RenderPass : public DeviceObject, public Effekseer::Backend::RenderPass { private: GLuint buffer_ = 0; GraphicsDevice* graphicsDevice_ = nullptr; Effekseer::FixedSizeVector textures_; Effekseer::Backend::TextureRef depthTexture_; public: RenderPass(GraphicsDevice* graphicsDevice); ~RenderPass() override; bool Init(Effekseer::FixedSizeVector& textures, Effekseer::Backend::TextureRef depthTexture); const Effekseer::FixedSizeVector& GetTextures() const { return textures_; } GLuint GetBuffer() const { return buffer_; } }; enum class DevicePropertyType { MaxVaryingVectors, MaxVertexUniformVectors, MaxFragmentUniformVectors, MaxVertexTextureImageUnits, MaxTextureImageUnits, }; /** @brief GraphicsDevice of OpenGL */ class GraphicsDevice : public Effekseer::Backend::GraphicsDevice { private: std::set objects_; OpenGLDeviceType deviceType_; std::array samplers_; GLuint frameBufferTemp_ = 0; std::map properties_; bool isValid_ = true; public: GraphicsDevice(OpenGLDeviceType deviceType, bool isExtensionsEnabled = true); ~GraphicsDevice() override; bool GetIsValid() const; int GetProperty(DevicePropertyType type) const; void LostDevice(); void ResetDevice(); OpenGLDeviceType GetDeviceType() const; void Register(DeviceObject* deviceObject); void Unregister(DeviceObject* deviceObject); Effekseer::Backend::VertexBufferRef CreateVertexBuffer(int32_t size, const void* initialData, bool isDynamic) override; Effekseer::Backend::IndexBufferRef CreateIndexBuffer(int32_t elementCount, const void* initialData, Effekseer::Backend::IndexBufferStrideType stride) override; Effekseer::Backend::TextureRef CreateTexture(const Effekseer::Backend::TextureParameter& param, const Effekseer::CustomVector& initialData) override; Effekseer::Backend::TextureRef CreateRenderTexture(const Effekseer::Backend::RenderTextureParameter& param) override; Effekseer::Backend::TextureRef CreateDepthTexture(const Effekseer::Backend::DepthTextureParameter& param) override; bool CopyTexture(Effekseer::Backend::TextureRef& dst, Effekseer::Backend::TextureRef& src, const std::array& dstPos, const std::array& srcPos, const std::array& size, int32_t dstLayer, int32_t srcLayer) override; Effekseer::Backend::UniformBufferRef CreateUniformBuffer(int32_t size, const void* initialData) override; Effekseer::Backend::VertexLayoutRef CreateVertexLayout(const Effekseer::Backend::VertexLayoutElement* elements, int32_t elementCount) override; Effekseer::Backend::RenderPassRef CreateRenderPass(Effekseer::FixedSizeVector& textures, Effekseer::Backend::TextureRef& depthTexture) override; Effekseer::Backend::ShaderRef CreateShaderFromKey(const char* key) override; Effekseer::Backend::ShaderRef CreateShaderFromCodes(const Effekseer::CustomVector>& vsCodes, const Effekseer::CustomVector>& psCodes, Effekseer::Backend::UniformLayoutRef layout) override; Effekseer::Backend::PipelineStateRef CreatePipelineState(const Effekseer::Backend::PipelineStateParameter& param) override; void Draw(const Effekseer::Backend::DrawParameter& drawParam) override; void SetViewport(int32_t x, int32_t y, int32_t width, int32_t height) override; void BeginRenderPass(Effekseer::Backend::RenderPassRef& renderPass, bool isColorCleared, bool isDepthCleared, Effekseer::Color clearColor) override; void EndRenderPass() override; bool UpdateUniformBuffer(Effekseer::Backend::UniformBufferRef& buffer, int32_t size, int32_t offset, const void* data) override; std::string GetDeviceName() const override { return "OpenGL"; } Effekseer::Backend::TextureRef CreateTexture(GLuint buffer, bool hasMipmap, const std::function& onDisposed); }; } // namespace Backend } // namespace EffekseerRendererGL #endif