//---------------------------------------------------------------------------------- // Include //---------------------------------------------------------------------------------- #include "EffekseerRendererGL.RenderState.h" #include "EffekseerRendererGL.Renderer.h" #include "EffekseerRendererGL.RendererImplemented.h" #include "EffekseerRendererGL.GLExtension.h" //----------------------------------------------------------------------------------- // //----------------------------------------------------------------------------------- namespace EffekseerRendererGL { //----------------------------------------------------------------------------------- // //----------------------------------------------------------------------------------- RenderState::RenderState(RendererImplemented* renderer) : m_renderer(renderer) { if (m_renderer->GetDeviceType() == OpenGLDeviceType::OpenGL3 || m_renderer->GetDeviceType() == OpenGLDeviceType::OpenGLES3) { GLExt::glGenSamplers(Effekseer::TextureSlotMax, m_samplers.data()); } GLint frontFace = 0; glGetIntegerv(GL_FRONT_FACE, &frontFace); if (GL_CW == frontFace) { m_isCCW = false; } } //----------------------------------------------------------------------------------- // //----------------------------------------------------------------------------------- RenderState::~RenderState() { if (m_renderer->GetDeviceType() == OpenGLDeviceType::OpenGL3 || m_renderer->GetDeviceType() == OpenGLDeviceType::OpenGLES3) { GLExt::glDeleteSamplers(Effekseer::TextureSlotMax, m_samplers.data()); } } //----------------------------------------------------------------------------------- // //----------------------------------------------------------------------------------- void RenderState::Update(bool forced) { GLCheckError(); if (m_active.DepthTest != m_next.DepthTest || forced) { if (m_next.DepthTest) { glEnable(GL_DEPTH_TEST); } else { glDisable(GL_DEPTH_TEST); } } GLCheckError(); if (m_active.DepthWrite != m_next.DepthWrite || forced) { glDepthMask(m_next.DepthWrite); } GLCheckError(); if (m_active.CullingType != m_next.CullingType || forced) { if (m_isCCW) { if (m_next.CullingType == Effekseer::CullingType::Front) { glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); } else if (m_next.CullingType == Effekseer::CullingType::Back) { glEnable(GL_CULL_FACE); glCullFace(GL_BACK); } else if (m_next.CullingType == Effekseer::CullingType::Double) { glDisable(GL_CULL_FACE); glCullFace(GL_FRONT_AND_BACK); } } else { if (m_next.CullingType == Effekseer::CullingType::Front) { glEnable(GL_CULL_FACE); glCullFace(GL_BACK); } else if (m_next.CullingType == Effekseer::CullingType::Back) { glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); } else if (m_next.CullingType == Effekseer::CullingType::Double) { glDisable(GL_CULL_FACE); glCullFace(GL_FRONT_AND_BACK); } } } GLCheckError(); if (m_active.AlphaBlend != m_next.AlphaBlend || forced) { { glEnable(GL_BLEND); if (m_next.AlphaBlend == ::Effekseer::AlphaBlendType::Opacity) { GLExt::glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX); GLExt::glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ONE); } else if (m_next.AlphaBlend == ::Effekseer::AlphaBlendType::Sub) { GLExt::glBlendEquationSeparate(GL_FUNC_REVERSE_SUBTRACT, GL_FUNC_ADD); GLExt::glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE); } else { GLExt::glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); if (m_next.AlphaBlend == ::Effekseer::AlphaBlendType::Blend) { GLExt::glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); } else if (m_next.AlphaBlend == ::Effekseer::AlphaBlendType::Add) { GLExt::glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE); } else if (m_next.AlphaBlend == ::Effekseer::AlphaBlendType::Mul) { GLExt::glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE); } } } } GLCheckError(); static const GLint glfilterMin[] = {GL_NEAREST, GL_LINEAR_MIPMAP_LINEAR}; static const GLint glfilterMin_NoneMipmap[] = {GL_NEAREST, GL_LINEAR}; static const GLint glfilterMag[] = {GL_NEAREST, GL_LINEAR}; static const GLint glwrap[] = {GL_REPEAT, GL_CLAMP_TO_EDGE}; if (m_renderer->GetDeviceType() == OpenGLDeviceType::OpenGL3 || m_renderer->GetDeviceType() == OpenGLDeviceType::OpenGLES3) { for (int32_t i = 0; i < (int32_t)m_renderer->GetCurrentTextures().size(); i++) { // If a texture is not assigned, skip it. const auto& texture = m_renderer->GetCurrentTextures()[i]; if (texture == nullptr) continue; if (m_active.TextureFilterTypes[i] != m_next.TextureFilterTypes[i] || forced || m_active.TextureIDs[i] != m_next.TextureIDs[i]) { GLExt::glActiveTexture(GL_TEXTURE0 + i); // for webngl #ifndef NDEBUG // GLint bound = 0; // glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound); // assert(bound > 0); #endif int32_t filter_ = (int32_t)m_next.TextureFilterTypes[i]; GLExt::glSamplerParameteri(m_samplers[i], GL_TEXTURE_MAG_FILTER, glfilterMag[filter_]); if (texture->GetParameter().MipLevelCount != 1) { GLExt::glSamplerParameteri(m_samplers[i], GL_TEXTURE_MIN_FILTER, glfilterMin[filter_]); } else { GLExt::glSamplerParameteri(m_samplers[i], GL_TEXTURE_MIN_FILTER, glfilterMin_NoneMipmap[filter_]); } // glSamplerParameteri( m_samplers[i], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // glSamplerParameteri( m_samplers[i], GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); GLExt::glBindSampler(i, m_samplers[i]); } if (m_active.TextureWrapTypes[i] != m_next.TextureWrapTypes[i] || forced || m_active.TextureIDs[i] != m_next.TextureIDs[i]) { GLExt::glActiveTexture(GL_TEXTURE0 + i); int32_t wrap_ = (int32_t)m_next.TextureWrapTypes[i]; GLExt::glSamplerParameteri(m_samplers[i], GL_TEXTURE_WRAP_S, glwrap[wrap_]); GLExt::glSamplerParameteri(m_samplers[i], GL_TEXTURE_WRAP_T, glwrap[wrap_]); GLExt::glBindSampler(i, m_samplers[i]); } } } else { GLCheckError(); for (int32_t i = 0; i < (int32_t)m_renderer->GetCurrentTextures().size(); i++) { // If a texture is not assigned, skip it. const auto& texture = m_renderer->GetCurrentTextures()[i]; if (texture == nullptr) continue; // always changes because a flag is assigned into a texture // if (m_active.TextureFilterTypes[i] != m_next.TextureFilterTypes[i] || forced) { GLExt::glActiveTexture(GL_TEXTURE0 + i); GLCheckError(); // for webngl #ifndef NDEBUG GLint bound = 0; glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound); assert(bound > 0); #endif int32_t filter_ = (int32_t)m_next.TextureFilterTypes[i]; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glfilterMag[filter_]); GLCheckError(); if (texture->GetParameter().MipLevelCount != 1) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glfilterMin[filter_]); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glfilterMin_NoneMipmap[filter_]); } } // always changes because a flag is assigned into a texture // if (m_active.TextureWrapTypes[i] != m_next.TextureWrapTypes[i] || forced) { GLExt::glActiveTexture(GL_TEXTURE0 + i); GLCheckError(); int32_t wrap_ = (int32_t)m_next.TextureWrapTypes[i]; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glwrap[wrap_]); GLCheckError(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glwrap[wrap_]); GLCheckError(); } } GLCheckError(); } GLExt::glActiveTexture(GL_TEXTURE0); m_active = m_next; GLCheckError(); } //----------------------------------------------------------------------------------- // //----------------------------------------------------------------------------------- } // namespace EffekseerRendererGL //----------------------------------------------------------------------------------- // //-----------------------------------------------------------------------------------