//---------------------------------------------------------------------------------- // Include //---------------------------------------------------------------------------------- #include "EffekseerRendererGL.Renderer.h" #include "EffekseerRendererGL.RenderState.h" #include "EffekseerRendererGL.RendererImplemented.h" #include "EffekseerRendererGL.DeviceObject.h" #include "EffekseerRendererGL.IndexBuffer.h" #include "EffekseerRendererGL.MaterialLoader.h" #include "EffekseerRendererGL.ModelRenderer.h" #include "EffekseerRendererGL.Shader.h" #include "EffekseerRendererGL.VertexArray.h" #include "EffekseerRendererGL.VertexBuffer.h" #include "EffekseerRendererGL.GLExtension.h" #include "../../EffekseerRendererCommon/EffekseerRenderer.Renderer_Impl.h" #include "../../EffekseerRendererCommon/EffekseerRenderer.RibbonRendererBase.h" #include "../../EffekseerRendererCommon/EffekseerRenderer.RingRendererBase.h" #include "../../EffekseerRendererCommon/EffekseerRenderer.SpriteRendererBase.h" #include "../../EffekseerRendererCommon/EffekseerRenderer.TrackRendererBase.h" #include "../../EffekseerRendererCommon/ModelLoader.h" #include "../../EffekseerRendererCommon/TextureLoader.h" #include "ShaderHeader/ad_model_distortion_ps.h" #include "ShaderHeader/ad_model_lit_ps.h" #include "ShaderHeader/ad_model_unlit_ps.h" #include "ShaderHeader/ad_sprite_distortion_vs.h" #include "ShaderHeader/ad_sprite_lit_vs.h" #include "ShaderHeader/ad_sprite_unlit_vs.h" #include "ShaderHeader/model_distortion_ps.h" #include "ShaderHeader/model_lit_ps.h" #include "ShaderHeader/model_unlit_ps.h" #include "ShaderHeader/sprite_distortion_vs.h" #include "ShaderHeader/sprite_lit_vs.h" #include "ShaderHeader/sprite_unlit_vs.h" #include "GraphicsDevice.h" #ifdef __APPLE__ #import #endif namespace EffekseerRendererGL { ::Effekseer::Backend::GraphicsDeviceRef CreateGraphicsDevice(OpenGLDeviceType deviceType, bool isExtensionsEnabled) { GLCheckError(); auto g = Effekseer::MakeRefPtr(deviceType, isExtensionsEnabled); if (!g->GetIsValid()) { GLCheckError(); return nullptr; } GLCheckError(); return g; } ::Effekseer::MaterialLoaderRef CreateMaterialLoader(::Effekseer::Backend::GraphicsDeviceRef graphicsDevice, ::Effekseer::FileInterfaceRef fileInterface) { return ::Effekseer::MakeRefPtr(graphicsDevice.DownCast(), fileInterface); } Effekseer::Backend::TextureRef CreateTexture(Effekseer::Backend::GraphicsDeviceRef graphicsDevice, GLuint buffer, bool hasMipmap, const std::function& onDisposed) { auto gd = graphicsDevice.DownCast(); return gd->CreateTexture(buffer, hasMipmap, onDisposed); } TextureProperty GetTextureProperty(::Effekseer::Backend::TextureRef texture) { if (texture != nullptr) { auto t = texture.DownCast(); return TextureProperty{t->GetBuffer()}; } else { return TextureProperty{}; } } RendererRef Renderer::Create(int32_t squareMaxCount, OpenGLDeviceType deviceType, bool isExtensionsEnabled) { GLCheckError(); auto device = CreateGraphicsDevice(deviceType, isExtensionsEnabled); if (device == nullptr) { return nullptr; } return Create(device, squareMaxCount); } RendererRef Renderer::Create(Effekseer::Backend::GraphicsDeviceRef graphicsDevice, int32_t squareMaxCount) { GLCheckError(); if (graphicsDevice == nullptr) { return nullptr; } auto g = graphicsDevice.DownCast(); auto renderer = ::Effekseer::MakeRefPtr(squareMaxCount, g); if (renderer->Initialize()) { return renderer; } return nullptr; } int32_t RendererImplemented::GetIndexSpriteCount() const { int vsSize = EffekseerRenderer::GetMaximumVertexSizeInAllTypes() * m_squareMaxCount * 4; size_t size = sizeof(EffekseerRenderer::SimpleVertex); size = (std::min)(size, sizeof(EffekseerRenderer::DynamicVertex)); size = (std::min)(size, sizeof(EffekseerRenderer::LightingVertex)); return (int32_t)(vsSize / size / 4 + 1); } void VertexArrayGroup::Create( Backend::GraphicsDeviceRef graphicsDevice, VertexBuffer* vertexBuffer, IndexBuffer* indexBuffer, IndexBuffer* indexBufferForWireframe, Shader* shader_unlit, Shader* shader_distortion, Shader* shader_lit, Shader* shader_ad_unlit, Shader* shader_ad_lit, Shader* shader_ad_distortion) { vao_ad_distortion = std::unique_ptr(VertexArray::Create(graphicsDevice, shader_ad_distortion, vertexBuffer, indexBuffer)); vao_distortion = std::unique_ptr(VertexArray::Create(graphicsDevice, shader_distortion, vertexBuffer, indexBuffer)); vao_ad_lit = std::unique_ptr(VertexArray::Create(graphicsDevice, shader_ad_lit, vertexBuffer, indexBuffer)); vao_lit = std::unique_ptr(VertexArray::Create(graphicsDevice, shader_lit, vertexBuffer, indexBuffer)); vao_unlit = std::unique_ptr(VertexArray::Create(graphicsDevice, shader_unlit, vertexBuffer, indexBuffer)); vao_ad_unlit = std::unique_ptr(VertexArray::Create(graphicsDevice, shader_ad_unlit, vertexBuffer, indexBuffer)); vao_unlit_wire = std::unique_ptr(VertexArray::Create(graphicsDevice, shader_unlit, vertexBuffer, indexBufferForWireframe)); vao_lit_wire = std::unique_ptr(VertexArray::Create(graphicsDevice, shader_lit, vertexBuffer, indexBufferForWireframe)); vao_distortion_wire = std::unique_ptr(VertexArray::Create(graphicsDevice, shader_distortion, vertexBuffer, indexBufferForWireframe)); vao_ad_unlit_wire = std::unique_ptr(VertexArray::Create(graphicsDevice, shader_ad_unlit, vertexBuffer, indexBufferForWireframe)); vao_ad_lit_wire = std::unique_ptr(VertexArray::Create(graphicsDevice, shader_ad_lit, vertexBuffer, indexBufferForWireframe)); vao_ad_distortion_wire = std::unique_ptr(VertexArray::Create(graphicsDevice, shader_ad_distortion, vertexBuffer, indexBufferForWireframe)); } RendererImplemented::PlatformSetting RendererImplemented::GetPlatformSetting() { #if defined(EMSCRIPTEN) || defined(__ANDROID__) || (defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)) return PlatformSetting{false, 1}; #endif return PlatformSetting{true, 3}; } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- RendererImplemented::RendererImplemented(int32_t squareMaxCount, Backend::GraphicsDeviceRef graphicsDevice) : m_indexBuffer(nullptr) , m_indexBufferForWireframe(nullptr) , m_squareMaxCount(squareMaxCount) , m_renderState(nullptr) , m_restorationOfStates(true) , m_currentVertexArray(nullptr) , m_standardRenderer(nullptr) , m_distortingCallback(nullptr) , m_deviceType(graphicsDevice->GetDeviceType()) { graphicsDevice_ = graphicsDevice; } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- RendererImplemented::~RendererImplemented() { GetImpl()->DeleteProxyTextures(this); ES_SAFE_DELETE(m_distortingCallback); ES_SAFE_DELETE(m_standardRenderer); ES_SAFE_DELETE(shader_unlit_); ES_SAFE_DELETE(shader_distortion_); ES_SAFE_DELETE(shader_lit_); ES_SAFE_DELETE(shader_ad_unlit_); ES_SAFE_DELETE(shader_ad_lit_); ES_SAFE_DELETE(shader_ad_distortion_); ES_SAFE_DELETE(m_renderState); ES_SAFE_DELETE(m_indexBuffer); ES_SAFE_DELETE(m_indexBufferForWireframe); if (GLExt::IsSupportedVertexArray() && defaultVertexArray_ > 0) { GLExt::glDeleteVertexArrays(1, &defaultVertexArray_); defaultVertexArray_ = 0; } } void RendererImplemented::OnLostDevice() { if (graphicsDevice_ != nullptr) graphicsDevice_->LostDevice(); } void RendererImplemented::OnResetDevice() { if (graphicsDevice_ != nullptr) graphicsDevice_->ResetDevice(); GenerateIndexData(); } void RendererImplemented::GenerateIndexData() { if (indexBufferStride_ == 2) { GenerateIndexDataStride(); } else if (indexBufferStride_ == 4) { GenerateIndexDataStride(); } } template void RendererImplemented::GenerateIndexDataStride() { // generate an index buffer if (m_indexBuffer != nullptr) { m_indexBuffer->Lock(); for (int i = 0; i < GetIndexSpriteCount(); i++) { std::array buf; buf[0] = (T)(3 + 4 * i); buf[1] = (T)(1 + 4 * i); buf[2] = (T)(0 + 4 * i); buf[3] = (T)(3 + 4 * i); buf[4] = (T)(0 + 4 * i); buf[5] = (T)(2 + 4 * i); memcpy(m_indexBuffer->GetBufferDirect(6), buf.data(), sizeof(T) * 6); } m_indexBuffer->Unlock(); } // generate an index buffer for a wireframe if (m_indexBufferForWireframe != nullptr) { m_indexBufferForWireframe->Lock(); for (int i = 0; i < GetIndexSpriteCount(); i++) { std::array buf; buf[0] = (T)(0 + 4 * i); buf[1] = (T)(1 + 4 * i); buf[2] = (T)(2 + 4 * i); buf[3] = (T)(3 + 4 * i); buf[4] = (T)(0 + 4 * i); buf[5] = (T)(2 + 4 * i); buf[6] = (T)(1 + 4 * i); buf[7] = (T)(3 + 4 * i); memcpy(m_indexBufferForWireframe->GetBufferDirect(8), buf.data(), sizeof(T) * 8); } m_indexBufferForWireframe->Unlock(); } } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- bool RendererImplemented::Initialize() { GLCheckError(); GLint currentVAO = 0; if (GLExt::IsSupportedVertexArray()) { glGetIntegerv(GL_VERTEX_ARRAY_BINDING, ¤tVAO); } int arrayBufferBinding = 0; int elementArrayBufferBinding = 0; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &arrayBufferBinding); glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &elementArrayBufferBinding); if (GetIndexSpriteCount() * 4 > 65536) { indexBufferStride_ = 4; } GLCheckError(); m_renderState = new RenderState(this); ShaderCodeView unlit_ad_vs(get_ad_sprite_unlit_vs(GetDeviceType())); ShaderCodeView unlit_ad_ps(get_ad_model_unlit_ps(GetDeviceType())); ShaderCodeView distortion_ad_vs(get_ad_sprite_distortion_vs(GetDeviceType())); ShaderCodeView distortion_ad_ps(get_ad_model_distortion_ps(GetDeviceType())); ShaderCodeView lit_ad_vs(get_ad_sprite_lit_vs(GetDeviceType())); ShaderCodeView lit_ad_ps(get_ad_model_lit_ps(GetDeviceType())); ShaderCodeView unlit_vs(get_sprite_unlit_vs(GetDeviceType())); ShaderCodeView unlit_ps(get_model_unlit_ps(GetDeviceType())); ShaderCodeView distortion_vs(get_sprite_distortion_vs(GetDeviceType())); ShaderCodeView distortion_ps(get_model_distortion_ps(GetDeviceType())); ShaderCodeView lit_vs(get_sprite_lit_vs(GetDeviceType())); ShaderCodeView lit_ps(get_model_lit_ps(GetDeviceType())); const auto texLocUnlit = GetTextureLocations(EffekseerRenderer::RendererShaderType::Unlit); const auto texLocLit = GetTextureLocations(EffekseerRenderer::RendererShaderType::AdvancedLit); const auto texLocDist = GetTextureLocations(EffekseerRenderer::RendererShaderType::BackDistortion); const auto texLocAdUnlit = GetTextureLocations(EffekseerRenderer::RendererShaderType::AdvancedUnlit); const auto texLocAdLit = GetTextureLocations(EffekseerRenderer::RendererShaderType::AdvancedLit); const auto texLocAdDist = GetTextureLocations(EffekseerRenderer::RendererShaderType::AdvancedBackDistortion); Effekseer::CustomVector uniformLayoutElementsLitUnlit; AddVertexUniformLayout(uniformLayoutElementsLitUnlit); AddPixelUniformLayout(uniformLayoutElementsLitUnlit); Effekseer::CustomVector uniformLayoutElementsDist; AddVertexUniformLayout(uniformLayoutElementsDist); AddDistortionPixelUniformLayout(uniformLayoutElementsDist); auto uniformLayoutUnlitAd = Effekseer::MakeRefPtr(texLocAdUnlit, uniformLayoutElementsLitUnlit); auto shader_unlit_ad = graphicsDevice_->CreateShaderFromCodes({unlit_ad_vs}, {unlit_ad_ps}, uniformLayoutUnlitAd).DownCast(); shader_ad_unlit_ = Shader::Create(GetInternalGraphicsDevice(), shader_unlit_ad, "UnlitAd"); if (shader_ad_unlit_ == nullptr) { Effekseer::Log(Effekseer::LogType::Error, "Failed to compile UnlitAd"); return false; } auto uniformLayoutDistAd = Effekseer::MakeRefPtr(texLocAdDist, uniformLayoutElementsDist); auto shader_distortion_ad = graphicsDevice_->CreateShaderFromCodes({distortion_ad_vs}, {distortion_ad_ps}, uniformLayoutDistAd).DownCast(); shader_ad_distortion_ = Shader::Create(GetInternalGraphicsDevice(), shader_distortion_ad, "DistAd"); if (shader_ad_distortion_ == nullptr) { Effekseer::Log(Effekseer::LogType::Error, "Failed to compile DistAd"); return false; } auto uniformLayoutLitAd = Effekseer::MakeRefPtr(texLocAdLit, uniformLayoutElementsLitUnlit); auto shader_lit_ad = graphicsDevice_->CreateShaderFromCodes({lit_ad_vs}, {lit_ad_ps}, uniformLayoutLitAd).DownCast(); shader_ad_lit_ = Shader::Create(GetInternalGraphicsDevice(), shader_lit_ad, "LitAd"); if (shader_ad_lit_ == nullptr) { Effekseer::Log(Effekseer::LogType::Error, "Failed to compile LitAd"); return false; } auto uniformLayoutUnlit = Effekseer::MakeRefPtr(texLocUnlit, uniformLayoutElementsLitUnlit); auto shader_unlit = graphicsDevice_->CreateShaderFromCodes({unlit_vs}, {unlit_ps}, uniformLayoutUnlit).DownCast(); shader_unlit_ = Shader::Create(GetInternalGraphicsDevice(), shader_unlit, "Unlit"); if (shader_unlit_ == nullptr) { Effekseer::Log(Effekseer::LogType::Error, "Failed to compile Unlit"); return false; } auto uniformLayoutDist = Effekseer::MakeRefPtr(texLocDist, uniformLayoutElementsDist); auto shader_distortion = graphicsDevice_->CreateShaderFromCodes({distortion_vs}, {distortion_ps}, uniformLayoutDist).DownCast(); shader_distortion_ = Shader::Create(GetInternalGraphicsDevice(), shader_distortion, "Dist"); if (shader_distortion_ == nullptr) { Effekseer::Log(Effekseer::LogType::Error, "Failed to compile Dist"); return false; } auto uniformLayoutLit = Effekseer::MakeRefPtr(texLocLit, uniformLayoutElementsLitUnlit); auto shader_lit = graphicsDevice_->CreateShaderFromCodes({lit_vs}, {lit_ps}, uniformLayoutLit).DownCast(); shader_lit_ = Shader::Create(GetInternalGraphicsDevice(), shader_lit, "Lit"); if (shader_lit_ == nullptr) { Effekseer::Log(Effekseer::LogType::Error, "Failed to compile Lit"); return false; } // Unlit auto vlUnlitAd = EffekseerRenderer::GetVertexLayout(graphicsDevice_, EffekseerRenderer::RendererShaderType::AdvancedUnlit).DownCast(); shader_ad_unlit_->SetVertexLayout(vlUnlitAd); auto vlUnlit = EffekseerRenderer::GetVertexLayout(graphicsDevice_, EffekseerRenderer::RendererShaderType::Unlit).DownCast(); shader_unlit_->SetVertexLayout(vlUnlit); for (auto& shader : {shader_ad_unlit_, shader_unlit_}) { shader->SetVertexConstantBufferSize(sizeof(EffekseerRenderer::StandardRendererVertexBuffer)); shader->SetPixelConstantBufferSize(sizeof(EffekseerRenderer::PixelConstantBuffer)); } // Distortion auto vlLitDistAd = EffekseerRenderer::GetVertexLayout(graphicsDevice_, EffekseerRenderer::RendererShaderType::AdvancedLit).DownCast(); auto vlLitDist = EffekseerRenderer::GetVertexLayout(graphicsDevice_, EffekseerRenderer::RendererShaderType::Lit).DownCast(); shader_ad_distortion_->SetVertexLayout(vlLitDistAd); shader_distortion_->SetVertexLayout(vlLitDist); for (auto& shader : {shader_ad_distortion_, shader_distortion_}) { shader->SetVertexConstantBufferSize(sizeof(EffekseerRenderer::StandardRendererVertexBuffer)); shader->SetPixelConstantBufferSize(sizeof(EffekseerRenderer::PixelConstantBufferDistortion)); } // Lit shader_ad_lit_->SetVertexLayout(vlLitDistAd); shader_lit_->SetVertexLayout(vlLitDist); for (auto shader : {shader_ad_lit_, shader_lit_}) { shader->SetVertexConstantBufferSize(sizeof(EffekseerRenderer::StandardRendererVertexBuffer)); shader->SetPixelConstantBufferSize(sizeof(EffekseerRenderer::PixelConstantBuffer)); } SetSquareMaxCount(m_squareMaxCount); m_standardRenderer = new EffekseerRenderer::StandardRenderer(this); GLExt::glBindBuffer(GL_ARRAY_BUFFER, arrayBufferBinding); GLExt::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBufferBinding); GetImpl()->isSoftParticleEnabled = GetDeviceType() == OpenGLDeviceType::OpenGL3 || GetDeviceType() == OpenGLDeviceType::OpenGLES3; if (GLExt::IsSupportedVertexArray()) { GLExt::glBindVertexArray(currentVAO); } GetImpl()->CreateProxyTextures(this); if (GLExt::IsSupportedVertexArray()) { GLExt::glGenVertexArrays(1, &defaultVertexArray_); } // Transpiled shader for OpenGL 3.x is transposed if (GetDeviceType() == OpenGLDeviceType::OpenGL3 || GetDeviceType() == OpenGLDeviceType::OpenGLES3) { shader_unlit_->SetIsTransposeEnabled(true); shader_distortion_->SetIsTransposeEnabled(true); shader_lit_->SetIsTransposeEnabled(true); shader_ad_unlit_->SetIsTransposeEnabled(true); shader_ad_lit_->SetIsTransposeEnabled(true); shader_ad_distortion_->SetIsTransposeEnabled(true); } GLCheckError(); return true; } void RendererImplemented::SetRestorationOfStatesFlag(bool flag) { m_restorationOfStates = flag; } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- bool RendererImplemented::BeginRendering() { GLCheckError(); impl->CalculateCameraProjectionMatrix(); // store state if (m_restorationOfStates) { m_originalState.blend = glIsEnabled(GL_BLEND); m_originalState.cullFace = glIsEnabled(GL_CULL_FACE); m_originalState.depthTest = glIsEnabled(GL_DEPTH_TEST); if (GetDeviceType() == OpenGLDeviceType::OpenGL2) { m_originalState.texture = glIsEnabled(GL_TEXTURE_2D); } glGetBooleanv(GL_DEPTH_WRITEMASK, &m_originalState.depthWrite); glGetIntegerv(GL_DEPTH_FUNC, &m_originalState.depthFunc); glGetIntegerv(GL_CULL_FACE_MODE, &m_originalState.cullFaceMode); glGetIntegerv(GL_BLEND_SRC_RGB, &m_originalState.blendSrc); glGetIntegerv(GL_BLEND_DST_RGB, &m_originalState.blendDst); glGetIntegerv(GL_BLEND_SRC_ALPHA, &m_originalState.blendSrcAlpha); glGetIntegerv(GL_BLEND_DST_ALPHA, &m_originalState.blendDstAlpha); glGetIntegerv(GL_BLEND_EQUATION, &m_originalState.blendEquation); glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &m_originalState.arrayBufferBinding); glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &m_originalState.elementArrayBufferBinding); glGetIntegerv(GL_CURRENT_PROGRAM, &m_originalState.program); for (size_t i = 0; i < m_originalState.boundTextures.size(); i++) { GLint bound = 0; GLExt::glActiveTexture(GL_TEXTURE0 + (GLenum)i); glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound); m_originalState.boundTextures[i] = bound; } if (GLExt::IsSupportedVertexArray()) { glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &m_originalState.vao); } } glDepthFunc(GL_LEQUAL); glEnable(GL_BLEND); glDisable(GL_CULL_FACE); currentTextures_.clear(); m_renderState->GetActiveState().Reset(); m_renderState->Update(true); m_renderState->GetActiveState().TextureIDs.fill(0); // reset renderer m_standardRenderer->ResetAndRenderingIfRequired(); GLCheckError(); return true; } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- bool RendererImplemented::EndRendering() { GLCheckError(); // reset renderer m_standardRenderer->ResetAndRenderingIfRequired(); // restore states if (m_restorationOfStates) { if (GLExt::IsSupportedVertexArray()) { GLExt::glBindVertexArray(m_originalState.vao); } for (size_t i = 0; i < m_originalState.boundTextures.size(); i++) { GLExt::glActiveTexture(GL_TEXTURE0 + (GLenum)i); glBindTexture(GL_TEXTURE_2D, m_originalState.boundTextures[i]); } GLExt::glActiveTexture(GL_TEXTURE0); if (m_originalState.blend) glEnable(GL_BLEND); else glDisable(GL_BLEND); if (m_originalState.cullFace) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); if (m_originalState.depthTest) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); if (GetDeviceType() == OpenGLDeviceType::OpenGL2) { if (m_originalState.texture) glEnable(GL_TEXTURE_2D); else glDisable(GL_TEXTURE_2D); } glDepthFunc(m_originalState.depthFunc); glDepthMask(m_originalState.depthWrite); glCullFace(m_originalState.cullFaceMode); GLExt::glBlendFuncSeparate(m_originalState.blendSrc, m_originalState.blendDst, m_originalState.blendSrcAlpha, m_originalState.blendDstAlpha); GLExt::glBlendEquation(m_originalState.blendEquation); GLExt::glBindBuffer(GL_ARRAY_BUFFER, m_originalState.arrayBufferBinding); GLExt::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_originalState.elementArrayBufferBinding); GLExt::glUseProgram(m_originalState.program); if (GetDeviceType() == OpenGLDeviceType::OpenGL3 || GetDeviceType() == OpenGLDeviceType::OpenGLES3) { for (int32_t i = 0; i < (int32_t)GetCurrentTextures().size(); i++) { GLExt::glBindSampler(i, 0); } } } GLCheckError(); return true; } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- VertexBuffer* RendererImplemented::GetVertexBuffer() { return ringVs_[GetImpl()->CurrentRingBufferIndex]->vertexBuffer.get(); } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- IndexBuffer* RendererImplemented::GetIndexBuffer() { if (GetRenderMode() == ::Effekseer::RenderMode::Wireframe) { return m_indexBufferForWireframe; } return m_indexBuffer; } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- int32_t RendererImplemented::GetSquareMaxCount() const { return m_squareMaxCount; } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- void RendererImplemented::SetSquareMaxCount(int32_t count) { int arrayBufferBinding = 0; int elementArrayBufferBinding = 0; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &arrayBufferBinding); glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &elementArrayBufferBinding); m_squareMaxCount = count; const auto setting = GetPlatformSetting(); ES_SAFE_DELETE(m_indexBuffer); ringVs_.clear(); GetImpl()->CurrentRingBufferIndex = 0; GetImpl()->RingBufferCount = setting.ringBufferCount; int vertexBufferSize = EffekseerRenderer::GetMaximumVertexSizeInAllTypes() * m_squareMaxCount * 4; auto storage = std::make_shared(); storage->buffer.resize(vertexBufferSize); // generate an index buffer { m_indexBuffer = IndexBuffer::Create(graphicsDevice_, GetIndexSpriteCount() * 6, false, indexBufferStride_); if (m_indexBuffer == nullptr) return; } // generate an index buffer for a wireframe { m_indexBufferForWireframe = IndexBuffer::Create(graphicsDevice_, GetIndexSpriteCount() * 8, false, indexBufferStride_); if (m_indexBufferForWireframe == nullptr) return; } // generate index data GenerateIndexData(); for (int i = 0; i < GetImpl()->RingBufferCount; i++) { auto rv = std::make_shared(); rv->vertexBuffer = std::unique_ptr(VertexBuffer::Create( graphicsDevice_, setting.isRingBufferEnabled, vertexBufferSize, true, storage)); if (rv->vertexBuffer == nullptr) { return; } rv->vao = std::unique_ptr(new VertexArrayGroup()); rv->vao->Create( graphicsDevice_, rv->vertexBuffer.get(), m_indexBuffer, m_indexBufferForWireframe, shader_unlit_, shader_distortion_, shader_lit_, shader_ad_unlit_, shader_ad_lit_, shader_ad_distortion_); ringVs_.emplace_back(rv); } GLExt::glBindBuffer(GL_ARRAY_BUFFER, arrayBufferBinding); GLExt::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBufferBinding); } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- ::EffekseerRenderer::RenderStateBase* RendererImplemented::GetRenderState() { return m_renderState; } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- ::Effekseer::SpriteRendererRef RendererImplemented::CreateSpriteRenderer() { return ::Effekseer::SpriteRendererRef(new ::EffekseerRenderer::SpriteRendererBase(this)); } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- ::Effekseer::RibbonRendererRef RendererImplemented::CreateRibbonRenderer() { return ::Effekseer::RibbonRendererRef(new ::EffekseerRenderer::RibbonRendererBase(this)); } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- ::Effekseer::RingRendererRef RendererImplemented::CreateRingRenderer() { return ::Effekseer::RingRendererRef(new ::EffekseerRenderer::RingRendererBase(this)); } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- ::Effekseer::ModelRendererRef RendererImplemented::CreateModelRenderer() { return ModelRenderer::Create(this); } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- ::Effekseer::TrackRendererRef RendererImplemented::CreateTrackRenderer() { return ::Effekseer::TrackRendererRef(new ::EffekseerRenderer::TrackRendererBase(this)); } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- ::Effekseer::TextureLoaderRef RendererImplemented::CreateTextureLoader(::Effekseer::FileInterfaceRef fileInterface) { return ::EffekseerRenderer::CreateTextureLoader(graphicsDevice_, fileInterface, ::Effekseer::ColorSpaceType::Gamma); } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- ::Effekseer::ModelLoaderRef RendererImplemented::CreateModelLoader(::Effekseer::FileInterfaceRef fileInterface) { return ::Effekseer::MakeRefPtr(graphicsDevice_, fileInterface); } ::Effekseer::MaterialLoaderRef RendererImplemented::CreateMaterialLoader(::Effekseer::FileInterfaceRef fileInterface) { return ::Effekseer::MakeRefPtr(GetInternalGraphicsDevice(), fileInterface); } void RendererImplemented::SetBackground(GLuint background, bool hasMipmap) { if (m_backgroundGL == nullptr) { m_backgroundGL = graphicsDevice_->CreateTexture(background, hasMipmap, nullptr); } else { auto texture = static_cast(m_backgroundGL.Get()); texture->Init(background, hasMipmap, nullptr); } EffekseerRenderer::Renderer::SetBackground((background) ? m_backgroundGL : nullptr); } EffekseerRenderer::DistortingCallback* RendererImplemented::GetDistortingCallback() { return m_distortingCallback; } void RendererImplemented::SetDistortingCallback(EffekseerRenderer::DistortingCallback* callback) { ES_SAFE_DELETE(m_distortingCallback); m_distortingCallback = callback; } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- void RendererImplemented::SetVertexBuffer(VertexBuffer* vertexBuffer, int32_t size) { if (m_currentVertexArray == nullptr || m_currentVertexArray->GetVertexBuffer() == nullptr) { GLExt::glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer->GetInterface()); } } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- void RendererImplemented::SetVertexBuffer(GLuint vertexBuffer, int32_t size) { if (m_currentVertexArray == nullptr || m_currentVertexArray->GetVertexBuffer() == nullptr) { GLExt::glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); } } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- void RendererImplemented::SetIndexBuffer(IndexBuffer* indexBuffer) { if (m_currentVertexArray == nullptr || m_currentVertexArray->GetIndexBuffer() == nullptr) { GLExt::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer->GetInterface()); indexBufferCurrentStride_ = indexBuffer->GetStride(); } else { indexBufferCurrentStride_ = m_currentVertexArray->GetIndexBuffer()->GetStride(); } } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- void RendererImplemented::SetIndexBuffer(GLuint indexBuffer) { if (m_currentVertexArray == nullptr || m_currentVertexArray->GetIndexBuffer() == nullptr) { GLExt::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); indexBufferCurrentStride_ = 4; } else { indexBufferCurrentStride_ = m_currentVertexArray->GetIndexBuffer()->GetStride(); } } void RendererImplemented::SetVertexBuffer(const Effekseer::Backend::VertexBufferRef& vertexBuffer, int32_t size) { auto vb = static_cast(vertexBuffer.Get()); SetVertexBuffer(vb->GetBuffer(), size); } void RendererImplemented::SetIndexBuffer(const Effekseer::Backend::IndexBufferRef& indexBuffer) { auto ib = static_cast(indexBuffer.Get()); SetIndexBuffer(ib->GetBuffer()); } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- void RendererImplemented::SetVertexArray(VertexArray* vertexArray) { m_currentVertexArray = vertexArray; } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- void RendererImplemented::SetLayout(Shader* shader) { GLCheckError(); if (m_currentVertexArray == nullptr || m_currentVertexArray->GetVertexBuffer() == nullptr) { shader->EnableAttribs(); GLCheckError(); } } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- void RendererImplemented::DrawSprites(int32_t spriteCount, int32_t vertexOffset) { GLCheckError(); impl->drawcallCount++; impl->drawvertexCount += spriteCount * 4; GLsizei stride = GL_UNSIGNED_SHORT; if (indexBufferCurrentStride_ == 4) { stride = GL_UNSIGNED_INT; } if (GetRenderMode() == ::Effekseer::RenderMode::Normal) { glDrawElements(GL_TRIANGLES, spriteCount * 6, stride, (void*)((size_t)vertexOffset / 4 * 6 * indexBufferCurrentStride_)); } else if (GetRenderMode() == ::Effekseer::RenderMode::Wireframe) { glDrawElements(GL_LINES, spriteCount * 8, stride, (void*)((size_t)vertexOffset / 4 * 8 * indexBufferCurrentStride_)); } GLCheckError(); } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- void RendererImplemented::DrawPolygon(int32_t vertexCount, int32_t indexCount) { GLCheckError(); impl->drawcallCount++; impl->drawvertexCount += vertexCount; if (GetRenderMode() == ::Effekseer::RenderMode::Normal) { glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, nullptr); } else if (GetRenderMode() == ::Effekseer::RenderMode::Wireframe) { glDrawElements(GL_LINES, indexCount, GL_UNSIGNED_INT, nullptr); } GLCheckError(); } void RendererImplemented::DrawPolygonInstanced(int32_t vertexCount, int32_t indexCount, int32_t instanceCount) { GLCheckError(); impl->drawcallCount++; impl->drawvertexCount += vertexCount * instanceCount; if (GetRenderMode() == ::Effekseer::RenderMode::Normal) { GLExt::glDrawElementsInstanced(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, nullptr, instanceCount); } else if (GetRenderMode() == ::Effekseer::RenderMode::Wireframe) { GLExt::glDrawElementsInstanced(GL_LINES, indexCount, GL_UNSIGNED_INT, nullptr, instanceCount); } GLCheckError(); } Shader* RendererImplemented::GetShader(::EffekseerRenderer::RendererShaderType type) const { if (type == ::EffekseerRenderer::RendererShaderType::AdvancedBackDistortion) { return shader_ad_distortion_; } else if (type == ::EffekseerRenderer::RendererShaderType::AdvancedLit) { return shader_ad_lit_; } else if (type == ::EffekseerRenderer::RendererShaderType::AdvancedUnlit) { return shader_ad_unlit_; } else if (type == ::EffekseerRenderer::RendererShaderType::BackDistortion) { return shader_distortion_; } else if (type == ::EffekseerRenderer::RendererShaderType::Lit) { return shader_lit_; } else if (type == ::EffekseerRenderer::RendererShaderType::Unlit) { if (GetExternalShaderSettings() == nullptr) { shader_unlit_->OverrideShader(nullptr); } else { shader_unlit_->OverrideShader(GetExternalShaderSettings()->StandardShader); } return shader_unlit_; } return shader_unlit_; } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- void RendererImplemented::BeginShader(Shader* shader) { GLCheckError(); auto& ringv = ringVs_[GetImpl()->CurrentRingBufferIndex]; // change VAO with shader if (m_currentVertexArray != nullptr) { SetVertexArray(m_currentVertexArray); } else if (shader == shader_unlit_) { if (GetRenderMode() == ::Effekseer::RenderMode::Wireframe) { SetVertexArray(ringv->vao->vao_unlit_wire.get()); } else { SetVertexArray(ringv->vao->vao_unlit.get()); } } else if (shader == shader_distortion_) { if (GetRenderMode() == ::Effekseer::RenderMode::Wireframe) { SetVertexArray(ringv->vao->vao_distortion_wire.get()); } else { SetVertexArray(ringv->vao->vao_distortion.get()); } } else if (shader == shader_lit_) { if (GetRenderMode() == ::Effekseer::RenderMode::Wireframe) { SetVertexArray(ringv->vao->vao_lit_wire.get()); } else { SetVertexArray(ringv->vao->vao_lit.get()); } } else if (shader == shader_ad_unlit_) { if (GetRenderMode() == ::Effekseer::RenderMode::Wireframe) { SetVertexArray(ringv->vao->vao_ad_unlit_wire.get()); } else { SetVertexArray(ringv->vao->vao_ad_unlit.get()); } } else if (shader == shader_ad_distortion_) { if (GetRenderMode() == ::Effekseer::RenderMode::Wireframe) { SetVertexArray(ringv->vao->vao_ad_distortion_wire.get()); } else { SetVertexArray(ringv->vao->vao_ad_distortion.get()); } } else if (shader == shader_ad_lit_) { if (GetRenderMode() == ::Effekseer::RenderMode::Wireframe) { SetVertexArray(ringv->vao->vao_ad_lit_wire.get()); } else { SetVertexArray(ringv->vao->vao_ad_lit.get()); } } else { m_currentVertexArray = nullptr; if (defaultVertexArray_ > 0) { GLExt::glBindVertexArray(defaultVertexArray_); } } shader->BeginScene(); if (m_currentVertexArray) { GLExt::glBindVertexArray(m_currentVertexArray->GetInterface()); } assert(currentShader == nullptr); currentShader = shader; GLCheckError(); } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- void RendererImplemented::EndShader(Shader* shader) { assert(currentShader == shader); currentShader = nullptr; GLCheckError(); if (m_currentVertexArray) { if (m_currentVertexArray->GetVertexBuffer() == nullptr) { shader->DisableAttribs(); GLCheckError(); GLExt::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); GLCheckError(); GLExt::glBindBuffer(GL_ARRAY_BUFFER, 0); GLCheckError(); } GLExt::glBindVertexArray(0); GLCheckError(); m_currentVertexArray = nullptr; } else { shader->DisableAttribs(); GLCheckError(); GLExt::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); GLCheckError(); GLExt::glBindBuffer(GL_ARRAY_BUFFER, 0); GLCheckError(); if (defaultVertexArray_ > 0) { GLExt::glBindVertexArray(0); } } shader->EndScene(); GLCheckError(); } void RendererImplemented::SetVertexBufferToShader(const void* data, int32_t size, int32_t dstOffset) { assert(currentShader != nullptr); auto p = static_cast(currentShader->GetVertexConstantBuffer()) + dstOffset; memcpy(p, data, size); } void RendererImplemented::SetPixelBufferToShader(const void* data, int32_t size, int32_t dstOffset) { assert(currentShader != nullptr); auto p = static_cast(currentShader->GetPixelConstantBuffer()) + dstOffset; memcpy(p, data, size); } void RendererImplemented::SetTextures(Shader* shader, Effekseer::Backend::TextureRef* textures, int32_t count) { GLCheckError(); for (int i = count; i < currentTextures_.size(); i++) { m_renderState->GetActiveState().TextureIDs[i] = 0; } currentTextures_.resize(count); for (int32_t i = 0; i < count; i++) { GLuint id = 0; if (textures[i] != nullptr) { auto texture = static_cast(textures[i].Get()); id = texture->GetBuffer(); } GLExt::glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, id); if (textures[i] != nullptr) { m_renderState->GetActiveState().TextureIDs[i] = id; currentTextures_[i] = textures[i]; } else { m_renderState->GetActiveState().TextureIDs[i] = 0; currentTextures_[i].Reset(); } if (shader->GetTextureSlotEnable(i)) { GLExt::glUniform1i(shader->GetTextureSlot(i), i); } } GLExt::glActiveTexture(GL_TEXTURE0); GLCheckError(); } //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- void RendererImplemented::ResetRenderState() { m_renderState->GetActiveState().Reset(); m_renderState->Update(true); } bool RendererImplemented::IsVertexArrayObjectSupported() const { return GLExt::IsSupportedVertexArray(); } void AddVertexUniformLayout(Effekseer::CustomVector& uniformLayout) { using namespace Effekseer::Backend; int vsOffset = 0; auto storeVector = [&](const char* name) { uniformLayout.emplace_back(UniformLayoutElement{ShaderStageType::Vertex, name, UniformBufferLayoutElementType::Vector4, 1, vsOffset}); vsOffset += sizeof(float[4]); }; auto storeMatrix = [&](const char* name) { uniformLayout.emplace_back(UniformLayoutElement{ShaderStageType::Vertex, name, UniformBufferLayoutElementType::Matrix44, 1, vsOffset}); vsOffset += sizeof(Effekseer::Matrix44); }; storeMatrix("CBVS0.mCamera"); storeMatrix("CBVS0.mCameraProj"); storeVector("CBVS0.mUVInversed"); storeVector("CBVS0.flipbookParameter1"); storeVector("CBVS0.flipbookParameter2"); } void AddPixelUniformLayout(Effekseer::CustomVector& uniformLayout) { using namespace Effekseer::Backend; int psOffset = 0; auto storeVector = [&](const char* name) { uniformLayout.emplace_back(UniformLayoutElement{ShaderStageType::Pixel, name, UniformBufferLayoutElementType::Vector4, 1, psOffset}); psOffset += sizeof(float[4]); }; storeVector("CBPS0.fLightDirection"); storeVector("CBPS0.fLightColor"); storeVector("CBPS0.fLightAmbient"); storeVector("CBPS0.fFlipbookParameter"); storeVector("CBPS0.fUVDistortionParameter"); storeVector("CBPS0.fBlendTextureParameter"); storeVector("CBPS0.fCameraFrontDirection"); storeVector("CBPS0.fFalloffParameter"); storeVector("CBPS0.fFalloffBeginColor"); storeVector("CBPS0.fFalloffEndColor"); storeVector("CBPS0.fEmissiveScaling"); storeVector("CBPS0.fEdgeColor"); storeVector("CBPS0.fEdgeParameter"); storeVector("CBPS0.softParticleParam"); storeVector("CBPS0.reconstructionParam1"); storeVector("CBPS0.reconstructionParam2"); storeVector("CBPS0.mUVInversedBack"); storeVector("CBPS0.miscFlags"); } void AddDistortionPixelUniformLayout(Effekseer::CustomVector& uniformLayout) { using namespace Effekseer::Backend; int psOffset = 0; auto storeVector = [&](const char* name) { uniformLayout.emplace_back(UniformLayoutElement{ShaderStageType::Pixel, name, UniformBufferLayoutElementType::Vector4, 1, psOffset}); psOffset += sizeof(float[4]); }; storeVector("CBPS0.g_scale"); storeVector("CBPS0.mUVInversedBack"); storeVector("CBPS0.fFlipbookParameter"); storeVector("CBPS0.fUVDistortionParameter"); storeVector("CBPS0.fBlendTextureParameter"); storeVector("CBPS0.softParticleParam"); storeVector("CBPS0.reconstructionParam1"); storeVector("CBPS0.reconstructionParam2"); storeVector("CBPS0.miscFlags"); } Effekseer::CustomVector> GetTextureLocations(EffekseerRenderer::RendererShaderType type) { Effekseer::CustomVector> texLoc; auto pushColor = [](Effekseer::CustomVector>& texLoc) { texLoc.emplace_back("Sampler_sampler_colorTex"); }; auto pushDepth = [](Effekseer::CustomVector>& texLoc) { texLoc.emplace_back("Sampler_sampler_depthTex"); }; auto pushBack = [](Effekseer::CustomVector>& texLoc) { texLoc.emplace_back("Sampler_sampler_backTex"); }; auto pushNormal = [](Effekseer::CustomVector>& texLoc) { texLoc.emplace_back("Sampler_sampler_normalTex"); }; auto pushAdvancedRendererParameterLoc = [](Effekseer::CustomVector>& texLoc) -> void { texLoc.emplace_back("Sampler_sampler_alphaTex"); texLoc.emplace_back("Sampler_sampler_uvDistortionTex"); texLoc.emplace_back("Sampler_sampler_blendTex"); texLoc.emplace_back("Sampler_sampler_blendAlphaTex"); texLoc.emplace_back("Sampler_sampler_blendUVDistortionTex"); }; pushColor(texLoc); if (type == EffekseerRenderer::RendererShaderType::Lit) { pushNormal(texLoc); } else if (type == EffekseerRenderer::RendererShaderType::BackDistortion) { pushBack(texLoc); } else if (type == EffekseerRenderer::RendererShaderType::AdvancedUnlit) { pushAdvancedRendererParameterLoc(texLoc); } else if (type == EffekseerRenderer::RendererShaderType::AdvancedLit) { pushNormal(texLoc); pushAdvancedRendererParameterLoc(texLoc); } else if (type == EffekseerRenderer::RendererShaderType::AdvancedBackDistortion) { pushBack(texLoc); pushAdvancedRendererParameterLoc(texLoc); } pushDepth(texLoc); return texLoc; } } // namespace EffekseerRendererGL //---------------------------------------------------------------------------------- // //----------------------------------------------------------------------------------