From 03fceb34d38a7f3e54bba7d3366cc54b3bbcc2fb Mon Sep 17 00:00:00 2001 From: nadro Date: Sat, 10 May 2014 21:47:14 +0000 Subject: [PATCH] - Added separate blending support to both OpenGL ES1.x and 2.0 drivers. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@4861 dfc29bdd-3216-0410-991c-e03cc46cb475 --- source/Irrlicht/COGLES2Driver.cpp | 104 ++++++++--- source/Irrlicht/COGLES2Driver.h | 16 +- source/Irrlicht/COGLES2ExtensionHandler.h | 4 +- source/Irrlicht/COGLES2MaterialRenderer.cpp | 24 +-- source/Irrlicht/COGLESDriver.cpp | 180 +++++++++++++++++++- source/Irrlicht/COGLESDriver.h | 39 ++++- source/Irrlicht/COGLESExtensionHandler.cpp | 9 + source/Irrlicht/COGLESExtensionHandler.h | 34 ++++ source/Irrlicht/COGLESMaterialRenderer.h | 47 +++-- 9 files changed, 387 insertions(+), 70 deletions(-) diff --git a/source/Irrlicht/COGLES2Driver.cpp b/source/Irrlicht/COGLES2Driver.cpp index 79339170..a1c8b61a 100644 --- a/source/Irrlicht/COGLES2Driver.cpp +++ b/source/Irrlicht/COGLES2Driver.cpp @@ -44,9 +44,9 @@ COGLES2Driver::COGLES2Driver(const SIrrlichtCreationParameters& params, , CIrrDeviceIPhone* device #endif ) : CNullDriver(io, params.WindowSize), COGLES2ExtensionHandler(), - BridgeCalls(0), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), + CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), AntiAlias(params.AntiAlias), - RenderTargetTexture(0), CurrentRendertargetSize(0, 0), ColorFormat(ECF_R8G8B8) + RenderTargetTexture(0), CurrentRendertargetSize(0, 0), ColorFormat(ECF_R8G8B8), BridgeCalls(0) #if defined(_IRR_COMPILE_WITH_X11_DEVICE_) || defined(_IRR_WINDOWS_API_) || defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) || defined(_IRR_COMPILE_WITH_FB_DEVICE_) , ContextManager(contextManager) #elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_) @@ -1691,7 +1691,7 @@ bool COGLES2Driver::endScene() { // Reset Texture Stages BridgeCalls->setBlend(false); - BridgeCalls->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + BridgeCalls->setBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); ResetRenderStates = true; } @@ -1812,32 +1812,45 @@ bool COGLES2Driver::endScene() (material.ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE); } - // Blend operation - if (resetAllRenderStates|| lastmaterial.BlendOperation != material.BlendOperation) + // Blend Equation + if (material.BlendOperation == EBO_NONE) + BridgeCalls->setBlend(false); + else { - if (material.BlendOperation==EBO_NONE) - BridgeCalls->setBlend(false); - else - { - BridgeCalls->setBlend(true); + BridgeCalls->setBlend(true); - switch (material.BlendOperation) - { - case EBO_ADD: - glBlendEquation(GL_FUNC_ADD); - break; - case EBO_SUBTRACT: - glBlendEquation(GL_FUNC_SUBTRACT); - break; - case EBO_REVSUBTRACT: - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - break; - default: - break; - } + switch (material.BlendOperation) + { + case EBO_ADD: + BridgeCalls->setBlendEquation(GL_FUNC_ADD); + break; + case EBO_SUBTRACT: + BridgeCalls->setBlendEquation(GL_FUNC_SUBTRACT); + break; + case EBO_REVSUBTRACT: + BridgeCalls->setBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + break; + default: + break; } } + // Blend Factor + if (material.BlendFactor != 0.f) + { + E_BLEND_FACTOR srcRGBFact = EBF_ZERO; + E_BLEND_FACTOR dstRGBFact = EBF_ZERO; + E_BLEND_FACTOR srcAlphaFact = EBF_ZERO; + E_BLEND_FACTOR dstAlphaFact = EBF_ZERO; + E_MODULATE_FUNC modulo = EMFN_MODULATE_1X; + u32 alphaSource = 0; + + unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulo, alphaSource, material.BlendFactor); + + BridgeCalls->setBlendFuncSeparate(getGLBlend(srcRGBFact), getGLBlend(dstRGBFact), + getGLBlend(srcAlphaFact), getGLBlend(dstAlphaFact)); + } + // Anti aliasing if (resetAllRenderStates || lastmaterial.AntiAliasing != material.AntiAliasing) { @@ -2727,7 +2740,8 @@ bool COGLES2Driver::endScene() } COGLES2CallBridge::COGLES2CallBridge(COGLES2Driver* driver) : Driver(driver), - BlendSource(GL_ONE), BlendDestination(GL_ZERO), Blend(false), + BlendEquation(GL_FUNC_ADD), BlendSourceRGB(GL_ONE), BlendDestinationRGB(GL_ZERO), + BlendSourceAlpha(GL_ONE), BlendDestinationAlpha(GL_ZERO), Blend(false), CullFaceMode(GL_BACK), CullFace(false), DepthFunc(GL_LESS), DepthMask(true), DepthTest(false), Program(0), ActiveTexture(GL_TEXTURE0), Viewport(core::rect(0, 0, 0, 0)) @@ -2751,14 +2765,48 @@ bool COGLES2Driver::endScene() glDisable(GL_DEPTH_TEST); } + void COGLES2CallBridge::setBlendEquation(GLenum mode) + { + if (BlendEquation != mode) + { + glBlendEquation(mode); + + BlendEquation = mode; + } + } + void COGLES2CallBridge::setBlendFunc(GLenum source, GLenum destination) { - if (BlendSource != source || BlendDestination != destination) + if (BlendSourceRGB != source || BlendDestinationRGB != destination || + BlendSourceAlpha != source || BlendDestinationAlpha != destination) { glBlendFunc(source, destination); - BlendSource = source; - BlendDestination = destination; + BlendSourceRGB = source; + BlendDestinationRGB = destination; + BlendSourceAlpha = source; + BlendDestinationAlpha = destination; + } + } + + void COGLES2CallBridge::setBlendFuncSeparate(GLenum sourceRGB, GLenum destinationRGB, GLenum sourceAlpha, GLenum destinationAlpha) + { + if (sourceRGB != sourceAlpha || destinationRGB != destinationAlpha) + { + if (BlendSourceRGB != sourceRGB || BlendDestinationRGB != destinationRGB || + BlendSourceAlpha != sourceAlpha || BlendDestinationAlpha != destinationAlpha) + { + glBlendFuncSeparate(sourceRGB, destinationRGB, sourceAlpha, destinationAlpha); + + BlendSourceRGB = sourceRGB; + BlendDestinationRGB = destinationRGB; + BlendSourceAlpha = sourceAlpha; + BlendDestinationAlpha = destinationAlpha; + } + } + else + { + setBlendFunc(sourceRGB, destinationRGB); } } diff --git a/source/Irrlicht/COGLES2Driver.h b/source/Irrlicht/COGLES2Driver.h index 7f6eecfa..abc924f2 100644 --- a/source/Irrlicht/COGLES2Driver.h +++ b/source/Irrlicht/COGLES2Driver.h @@ -364,9 +364,6 @@ namespace video COGLES2CallBridge* getBridgeCalls() const; private: - // Bridge calls. - COGLES2CallBridge* BridgeCalls; - void uploadClipPlane(u32 index); //! inits the opengl-es driver @@ -450,6 +447,8 @@ namespace video COGLES2Renderer2D* MaterialRenderer2D; + COGLES2CallBridge* BridgeCalls; + #if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_) CIrrDeviceIPhone* Device; GLuint ViewFramebuffer; @@ -470,8 +469,12 @@ namespace video // Blending calls. + void setBlendEquation(GLenum mode); + void setBlendFunc(GLenum source, GLenum destination); + void setBlendFuncSeparate(GLenum sourceRGB, GLenum destinationRGB, GLenum sourceAlpha, GLenum destinationAlpha); + void setBlend(bool enable); // Cull face calls. @@ -507,8 +510,11 @@ namespace video private: COGLES2Driver* Driver; - GLenum BlendSource; - GLenum BlendDestination; + GLenum BlendEquation; + GLenum BlendSourceRGB; + GLenum BlendDestinationRGB; + GLenum BlendSourceAlpha; + GLenum BlendDestinationAlpha; bool Blend; GLenum CullFaceMode; diff --git a/source/Irrlicht/COGLES2ExtensionHandler.h b/source/Irrlicht/COGLES2ExtensionHandler.h index c859e0d5..4d09e6f5 100644 --- a/source/Irrlicht/COGLES2ExtensionHandler.h +++ b/source/Irrlicht/COGLES2ExtensionHandler.h @@ -217,6 +217,8 @@ namespace video case EVDF_COLOR_MASK: case EVDF_ALPHA_TO_COVERAGE: case EVDF_POLYGON_OFFSET: + case EVDF_BLEND_OPERATIONS: + case EVDF_BLEND_SEPARATE: case EVDF_TEXTURE_MATRIX: case EVDF_TEXTURE_CUBE_MAP: return true; @@ -229,8 +231,6 @@ namespace video case EVDF_MRT_BLEND_FUNC: case EVDF_OCCLUSION_QUERY: return false; - case EVDF_BLEND_OPERATIONS: - return false; case EVDF_TEXTURE_COMPRESSED_DXT: return false; // NV Tegra need improvements here case EVDF_TEXTURE_COMPRESSED_PVRTC: diff --git a/source/Irrlicht/COGLES2MaterialRenderer.cpp b/source/Irrlicht/COGLES2MaterialRenderer.cpp index 7e03a96b..69be5ff4 100644 --- a/source/Irrlicht/COGLES2MaterialRenderer.cpp +++ b/source/Irrlicht/COGLES2MaterialRenderer.cpp @@ -160,32 +160,36 @@ void COGLES2MaterialRenderer::OnSetMaterial(const video::SMaterial& material, bool resetAllRenderstates, video::IMaterialRendererServices* services) { - Driver->getBridgeCalls()->setProgram(Program); + COGLES2CallBridge* bridgeCalls = Driver->getBridgeCalls(); + + bridgeCalls->setProgram(Program); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (Alpha) { - Driver->getBridgeCalls()->setBlend(true); - Driver->getBridgeCalls()->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + bridgeCalls->setBlend(true); + bridgeCalls->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else if (FixedBlending) { - Driver->getBridgeCalls()->setBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); - Driver->getBridgeCalls()->setBlend(true); + bridgeCalls->setBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); + bridgeCalls->setBlend(true); } else if (Blending) { - E_BLEND_FACTOR srcFact,dstFact; + E_BLEND_FACTOR srcRGBFact,dstRGBFact,srcAlphaFact,dstAlphaFact; E_MODULATE_FUNC modulate; u32 alphaSource; - unpack_textureBlendFunc(srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam); + unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulate, alphaSource, material.MaterialTypeParam); - Driver->getBridgeCalls()->setBlendFunc(Driver->getGLBlend(srcFact), Driver->getGLBlend(dstFact)); - Driver->getBridgeCalls()->setBlend(true); + bridgeCalls->setBlendFuncSeparate(Driver->getGLBlend(srcRGBFact), Driver->getGLBlend(dstRGBFact), + Driver->getGLBlend(srcAlphaFact), Driver->getGLBlend(dstAlphaFact)); + + bridgeCalls->setBlend(true); } else - Driver->getBridgeCalls()->setBlend(false); + bridgeCalls->setBlend(false); if (CallBack) CallBack->OnSetMaterial(material); diff --git a/source/Irrlicht/COGLESDriver.cpp b/source/Irrlicht/COGLESDriver.cpp index c54ec94b..6b33519f 100644 --- a/source/Irrlicht/COGLESDriver.cpp +++ b/source/Irrlicht/COGLESDriver.cpp @@ -33,7 +33,7 @@ COGLES1Driver::COGLES1Driver(const SIrrlichtCreationParameters& params, ) : CNullDriver(io, params.WindowSize), COGLES1ExtensionHandler(), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), AntiAlias(params.AntiAlias), - RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8) + RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), BridgeCalls(0) #if defined(_IRR_COMPILE_WITH_X11_DEVICE_) || defined(_IRR_WINDOWS_API_) || defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) , ContextManager(contextManager) #elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_) @@ -99,6 +99,8 @@ COGLES1Driver::~COGLES1Driver() deleteMaterialRenders(); deleteAllTextures(); + delete BridgeCalls; + #if defined(_IRR_COMPILE_WITH_X11_DEVICE_) || defined(_IRR_WINDOWS_API_) || defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) if (ContextManager) { @@ -143,6 +145,10 @@ bool COGLES1Driver::genericDriverInit(const core::dimension2d& screenSize, CurrentTexture[i]=0; // load extensions initExtensions(this, stencilBuffer); + + if (!BridgeCalls) + BridgeCalls = new COGLES1CallBridge(this); + StencilBuffer=stencilBuffer; DriverAttributes->setAttribute("MaxTextures", MaxTextureUnits); @@ -1639,9 +1645,9 @@ void COGLES1Driver::setRenderStates3DMode() if (CurrentRenderMode != ERM_3D) { // Reset Texture Stages - glDisable(GL_BLEND); + BridgeCalls->setBlend(false); glDisable(GL_ALPHA_TEST); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); + BridgeCalls->setBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); // switch back the matrices glMatrixMode(GL_MODELVIEW); @@ -2013,6 +2019,61 @@ void COGLES1Driver::setBasicRenderStates(const SMaterial& material, const SMater (material.ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE); } + // Blend Equation + if (material.BlendOperation == EBO_NONE) + BridgeCalls->setBlend(false); + else + { + BridgeCalls->setBlend(true); + + if (queryFeature(EVDF_BLEND_OPERATIONS)) + { + switch (material.BlendOperation) + { + case EBO_ADD: +#if defined(GL_OES_blend_subtract) + BridgeCalls->setBlendEquation(GL_FUNC_ADD_OES); +#endif + break; + case EBO_SUBTRACT: +#if defined(GL_OES_blend_subtract) + BridgeCalls->setBlendEquation(GL_FUNC_SUBTRACT_OES); +#endif + break; + case EBO_REVSUBTRACT: +#if defined(GL_OES_blend_subtract) + BridgeCalls->setBlendEquation(GL_FUNC_REVERSE_SUBTRACT_OES); +#endif + break; + default: + break; + } + } + } + + // Blend Factor + if (material.BlendFactor != 0.f) + { + E_BLEND_FACTOR srcRGBFact = EBF_ZERO; + E_BLEND_FACTOR dstRGBFact = EBF_ZERO; + E_BLEND_FACTOR srcAlphaFact = EBF_ZERO; + E_BLEND_FACTOR dstAlphaFact = EBF_ZERO; + E_MODULATE_FUNC modulo = EMFN_MODULATE_1X; + u32 alphaSource = 0; + + unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulo, alphaSource, material.BlendFactor); + + if (queryFeature(EVDF_BLEND_SEPARATE)) + { + BridgeCalls->setBlendFuncSeparate(getGLBlend(srcRGBFact), getGLBlend(dstRGBFact), + getGLBlend(srcAlphaFact), getGLBlend(dstAlphaFact)); + } + else + { + BridgeCalls->setBlendFunc(getGLBlend(srcRGBFact), getGLBlend(dstRGBFact)); + } + } + // thickness if (resetAllRenderStates || lastmaterial.Thickness != material.Thickness) { @@ -2109,7 +2170,6 @@ void COGLES1Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh setBasicRenderStates(InitMaterial2D, LastMaterial, true); LastMaterial = InitMaterial2D; } - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } if (OverrideMaterial2DEnabled) { @@ -2120,13 +2180,14 @@ void COGLES1Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh if (alphaChannel || alpha) { - glEnable(GL_BLEND); + BridgeCalls->setBlend(true); + BridgeCalls->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.f); } else { - glDisable(GL_BLEND); + BridgeCalls->setBlend(false); glDisable(GL_ALPHA_TEST); } @@ -3021,6 +3082,113 @@ core::dimension2du COGLES1Driver::getMaxTextureSize() const return core::dimension2du(MaxTextureSize, MaxTextureSize); } + +GLenum COGLES1Driver::getGLBlend(E_BLEND_FACTOR factor) const +{ + GLenum r = 0; + switch (factor) + { + case EBF_ZERO: r = GL_ZERO; break; + case EBF_ONE: r = GL_ONE; break; + case EBF_DST_COLOR: r = GL_DST_COLOR; break; + case EBF_ONE_MINUS_DST_COLOR: r = GL_ONE_MINUS_DST_COLOR; break; + case EBF_SRC_COLOR: r = GL_SRC_COLOR; break; + case EBF_ONE_MINUS_SRC_COLOR: r = GL_ONE_MINUS_SRC_COLOR; break; + case EBF_SRC_ALPHA: r = GL_SRC_ALPHA; break; + case EBF_ONE_MINUS_SRC_ALPHA: r = GL_ONE_MINUS_SRC_ALPHA; break; + case EBF_DST_ALPHA: r = GL_DST_ALPHA; break; + case EBF_ONE_MINUS_DST_ALPHA: r = GL_ONE_MINUS_DST_ALPHA; break; + case EBF_SRC_ALPHA_SATURATE: r = GL_SRC_ALPHA_SATURATE; break; + } + return r; +} + + +COGLES1CallBridge* COGLES1Driver::getBridgeCalls() const +{ + return BridgeCalls; +} + + +COGLES1CallBridge::COGLES1CallBridge(COGLES1Driver* driver) : Driver(driver), +#if defined(GL_OES_blend_subtract) + BlendEquation(GL_FUNC_ADD_OES), +#endif + BlendSourceRGB(GL_ONE), BlendDestinationRGB(GL_ZERO), + BlendSourceAlpha(GL_ONE), BlendDestinationAlpha(GL_ZERO), + Blend(false) +{ + // Initial OpenGL ES1.x values from specification. + + if (Driver->queryFeature(EVDF_BLEND_OPERATIONS)) + { +#if defined(GL_OES_blend_subtract) + Driver->extGlBlendEquation(GL_FUNC_ADD_OES); +#endif + } + + glBlendFunc(GL_ONE, GL_ZERO); + glDisable(GL_BLEND); +} + +void COGLES1CallBridge::setBlendEquation(GLenum mode) +{ + if (BlendEquation != mode) + { + Driver->extGlBlendEquation(mode); + + BlendEquation = mode; + } +} + +void COGLES1CallBridge::setBlendFunc(GLenum source, GLenum destination) +{ + if (BlendSourceRGB != source || BlendDestinationRGB != destination || + BlendSourceAlpha != source || BlendDestinationAlpha != destination) + { + glBlendFunc(source, destination); + + BlendSourceRGB = source; + BlendDestinationRGB = destination; + BlendSourceAlpha = source; + BlendDestinationAlpha = destination; + } +} + +void COGLES1CallBridge::setBlendFuncSeparate(GLenum sourceRGB, GLenum destinationRGB, GLenum sourceAlpha, GLenum destinationAlpha) +{ + if (sourceRGB != sourceAlpha || destinationRGB != destinationAlpha) + { + if (BlendSourceRGB != sourceRGB || BlendDestinationRGB != destinationRGB || + BlendSourceAlpha != sourceAlpha || BlendDestinationAlpha != destinationAlpha) + { + Driver->extGlBlendFuncSeparate(sourceRGB, destinationRGB, sourceAlpha, destinationAlpha); + + BlendSourceRGB = sourceRGB; + BlendDestinationRGB = destinationRGB; + BlendSourceAlpha = sourceAlpha; + BlendDestinationAlpha = destinationAlpha; + } + } + else + { + setBlendFunc(sourceRGB, destinationRGB); + } +} + +void COGLES1CallBridge::setBlend(bool enable) +{ + if (Blend != enable) + { + if (enable) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + + Blend = enable; + } +} + } // end namespace } // end namespace diff --git a/source/Irrlicht/COGLESDriver.h b/source/Irrlicht/COGLESDriver.h index b35a03e7..d49c9a6f 100644 --- a/source/Irrlicht/COGLESDriver.h +++ b/source/Irrlicht/COGLESDriver.h @@ -26,6 +26,7 @@ namespace irr { namespace video { + class COGLES1CallBridge; class COGLES1Texture; class COGLES1Driver : public CNullDriver, public IMaterialRendererServices, public COGLES1ExtensionHandler @@ -282,8 +283,13 @@ namespace video ITexture* createDepthTexture(ITexture* texture, bool shared=true); void removeDepthTexture(ITexture* texture); - private: + //! Convert E_BLEND_FACTOR to OpenGL equivalent + GLenum getGLBlend(E_BLEND_FACTOR factor) const; + //! Get bridge calls. + COGLES1CallBridge* getBridgeCalls() const; + + private: void uploadClipPlane(u32 index); //! inits the opengl-es driver @@ -366,6 +372,8 @@ namespace video }; core::array RequestedLights; + COGLES1CallBridge* BridgeCalls; + #if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_) CIrrDeviceIPhone* Device; GLuint ViewFramebuffer; @@ -376,6 +384,35 @@ namespace video #endif }; + //! This bridge between Irlicht pseudo OpenGL ES1.x calls + //! and true OpenGL ES1.x calls. + + class COGLES1CallBridge + { + public: + COGLES1CallBridge(COGLES1Driver* driver); + + // Blending calls. + + void setBlendEquation(GLenum mode); + + void setBlendFunc(GLenum source, GLenum destination); + + void setBlendFuncSeparate(GLenum sourceRGB, GLenum destinationRGB, GLenum sourceAlpha, GLenum destinationAlpha); + + void setBlend(bool enable); + + private: + COGLES1Driver* Driver; + + GLenum BlendEquation; + GLenum BlendSourceRGB; + GLenum BlendDestinationRGB; + GLenum BlendSourceAlpha; + GLenum BlendDestinationAlpha; + bool Blend; + }; + } // end namespace video } // end namespace irr diff --git a/source/Irrlicht/COGLESExtensionHandler.cpp b/source/Irrlicht/COGLESExtensionHandler.cpp index 4934d992..2d37ff53 100644 --- a/source/Irrlicht/COGLESExtensionHandler.cpp +++ b/source/Irrlicht/COGLESExtensionHandler.cpp @@ -128,6 +128,7 @@ COGLES1ExtensionHandler::COGLES1ExtensionHandler() : #if defined(_IRR_OGLES1_USE_EXTPOINTER_) pGlDrawTexiOES(0), pGlDrawTexfOES(0), pGlDrawTexivOES(0), pGlDrawTexfvOES(0), + pGlBlendEquationOES(0), pGlBlendFuncSeparateOES(0), pGlBindRenderbufferOES(0), pGlDeleteRenderbuffersOES(0), pGlGenRenderbuffersOES(0), pGlRenderbufferStorageOES(0), pGlBindFramebufferOES(0), pGlDeleteFramebuffersOES(0), @@ -248,6 +249,14 @@ void COGLES1ExtensionHandler::initExtensions(COGLES1Driver* driver, bool withSte pGlDrawTexivOES = (PFNGLDRAWTEXIVOES) eglGetProcAddress("glDrawTexivOES"); pGlDrawTexfvOES = (PFNGLDRAWTEXFVOES) eglGetProcAddress("glDrawTexfvOES"); } + if (FeatureAvailable[IRR_OES_blend_subtract]) + { + pGlBlendEquationOES = (PFNGLBLENDEQUATIONOESPROC) eglGetProcAddress("glBlendEquationOES"); + } + if (FeatureAvailable[IRR_OES_blend_func_separate]) + { + pGlBlendFuncSeparateOES = (PFNGLBLENDFUNCSEPARATEOESPROC) eglGetProcAddress("glBlendFuncSeparateOES"); + } if (FeatureAvailable[IRR_OES_framebuffer_object]) { pGlBindRenderbufferOES = (PFNGLBINDRENDERBUFFEROES) eglGetProcAddress("glBindRenderbufferOES"); diff --git a/source/Irrlicht/COGLESExtensionHandler.h b/source/Irrlicht/COGLESExtensionHandler.h index 576b350b..2852b97a 100644 --- a/source/Irrlicht/COGLESExtensionHandler.h +++ b/source/Irrlicht/COGLESExtensionHandler.h @@ -200,6 +200,12 @@ namespace video return Version>100; // Supported in version 1.1 case EVDF_STENCIL_BUFFER: return StencilBuffer; + case EVDF_BLEND_OPERATIONS: + return FeatureAvailable[IRR_OES_blend_subtract]; + case EVDF_BLEND_SEPARATE: + return FeatureAvailable[IRR_OES_blend_func_separate]; + case EVDF_FRAMEBUFFER_OBJECT: + return FeatureAvailable[IRR_OES_framebuffer_object]; case EVDF_TEXTURE_NSQUARE: return true; // non-square is always supported case EVDF_TEXTURE_NPOT: @@ -224,6 +230,30 @@ namespace video void initExtensions(COGLES1Driver* driver, bool withStencil); public: + void extGlBlendEquation(GLenum mode) + { +#ifdef _IRR_OGLES1_USE_EXTPOINTER_ + if (pGlBlendEquationOES) + pGlBlendEquationOES(mode); +#elif defined(GL_OES_blend_subtract) + glBlendEquationOES(mode); +#else + os::Printer::log("glBlendEquation not supported", ELL_ERROR); +#endif + } + + void extGlBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) + { +#ifdef _IRR_OGLES1_USE_EXTPOINTER_ + if (pGlBlendFuncSeparateOES) + pGlBlendFuncSeparateOES(srcRGB, dstRGB, srcAlpha, dstAlpha); +#elif defined(GL_OES_blend_func_separate) + glBlendFuncSeparateOES(srcRGB, dstRGB, srcAlpha, dstAlpha); +#else + os::Printer::log("glBlendFuncSeparate not supported", ELL_ERROR); +#endif + } + void extGlBindFramebuffer(GLenum target, GLuint framebuffer) { #ifdef _IRR_OGLES1_USE_EXTPOINTER_ @@ -439,6 +469,8 @@ namespace video typedef void (GL_APIENTRYP PFNGLDRAWTEXIVOES) (const GLint* coords); typedef void (GL_APIENTRYP PFNGLDRAWTEXFOES) (GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height); typedef void (GL_APIENTRYP PFNGLDRAWTEXFVOES) (const GLfloat* coords); + typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONOESPROC) (GLenum mode); + typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEOESPROC) (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFEROES) (GLuint renderbuffer); typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFEROES) (GLenum target, GLuint renderbuffer); typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSOES) (GLsizei n, const GLuint* renderbuffers); @@ -459,6 +491,8 @@ namespace video PFNGLDRAWTEXFOES pGlDrawTexfOES; PFNGLDRAWTEXIVOES pGlDrawTexivOES; PFNGLDRAWTEXFVOES pGlDrawTexfvOES; + PFNGLBLENDEQUATIONOESPROC pGlBlendEquationOES; + PFNGLBLENDFUNCSEPARATEOESPROC pGlBlendFuncSeparateOES; PFNGLBINDRENDERBUFFEROES pGlBindRenderbufferOES; PFNGLDELETERENDERBUFFERSOES pGlDeleteRenderbuffersOES; PFNGLGENRENDERBUFFERSOES pGlGenRenderbuffersOES; diff --git a/source/Irrlicht/COGLESMaterialRenderer.h b/source/Irrlicht/COGLESMaterialRenderer.h index d7448507..0c79bd11 100644 --- a/source/Irrlicht/COGLESMaterialRenderer.h +++ b/source/Irrlicht/COGLESMaterialRenderer.h @@ -76,10 +76,22 @@ public: // material.MaterialTypeParam != lastMaterial.MaterialTypeParam || // resetAllRenderstates) { - E_BLEND_FACTOR srcFact,dstFact; + E_BLEND_FACTOR srcRGBFact,dstRGBFact,srcAlphaFact,dstAlphaFact; E_MODULATE_FUNC modulate; u32 alphaSource; - unpack_textureBlendFunc ( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam ); + unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulate, alphaSource, material.MaterialTypeParam); + + Driver->getBridgeCalls()->setBlend(true); + + if (Driver->queryFeature(EVDF_BLEND_SEPARATE)) + { + Driver->getBridgeCalls()->setBlendFuncSeparate(Driver->getGLBlend(srcRGBFact), Driver->getGLBlend(dstRGBFact), + Driver->getGLBlend(srcAlphaFact), Driver->getGLBlend(dstAlphaFact)); + } + else + { + Driver->getBridgeCalls()->setBlendFunc(Driver->getGLBlend(srcRGBFact), Driver->getGLBlend(dstRGBFact)); + } glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); @@ -88,12 +100,11 @@ public: glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, (f32) modulate ); - glBlendFunc( getGLBlend(srcFact), getGLBlend(dstFact) ); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.f); - glEnable(GL_BLEND); - if ( textureBlendFunc_hasAlpha(srcFact) || textureBlendFunc_hasAlpha(dstFact) ) + if (textureBlendFunc_hasAlpha(srcRGBFact) || textureBlendFunc_hasAlpha(dstRGBFact) || + textureBlendFunc_hasAlpha(srcAlphaFact) || textureBlendFunc_hasAlpha(dstAlphaFact)) { glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE); @@ -109,7 +120,7 @@ public: glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, 1.f ); glTexEnvf(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS); - glDisable(GL_BLEND); + Driver->getBridgeCalls()->setBlend(false); glDisable(GL_ALPHA_TEST); } @@ -207,15 +218,15 @@ public: if ((material.MaterialType != lastMaterial.MaterialType) || resetAllRenderstates) { - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); + Driver->getBridgeCalls()->setBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glEnable(GL_BLEND); + Driver->getBridgeCalls()->setBlend(true); } } virtual void OnUnsetMaterial() { - glDisable(GL_BLEND); + Driver->getBridgeCalls()->setBlend(false); } //! Returns if the material is transparent. @@ -252,8 +263,8 @@ public: glTexEnvf(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PRIMARY_COLOR ); glTexEnvf(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); + Driver->getBridgeCalls()->setBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + Driver->getBridgeCalls()->setBlend(true); } } @@ -268,7 +279,7 @@ public: glTexEnvf(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE ); glTexEnvf(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS); - glDisable(GL_BLEND); + Driver->getBridgeCalls()->setBlend(false); } //! Returns if the material is transparent. @@ -305,8 +316,8 @@ public: glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); + Driver->getBridgeCalls()->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + Driver->getBridgeCalls()->setBlend(true); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, material.MaterialTypeParam); @@ -316,7 +327,7 @@ public: virtual void OnUnsetMaterial() { glDisable(GL_ALPHA_TEST); - glDisable(GL_BLEND); + Driver->getBridgeCalls()->setBlend(false); } //! Returns if the material is transparent. @@ -602,8 +613,8 @@ public: // glEnable(GL_TEXTURE_GEN_S); // glEnable(GL_TEXTURE_GEN_T); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); - glEnable(GL_BLEND); + Driver->getBridgeCalls()->setBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); + Driver->getBridgeCalls()->setBlend(true); } } @@ -620,7 +631,7 @@ public: { Driver->extGlActiveTexture(GL_TEXTURE0); } - glDisable(GL_BLEND); + Driver->getBridgeCalls()->setBlend(false); } //! Returns if the material is transparent.