// Copyright (C) 2002-2007 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_OPENGL_MATERIAL_RENDERER_H_INCLUDED__ #define __C_OPENGL_MATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #include "COpenGLDriver.h" #include "IMaterialRenderer.h" #include "IMaterialRenderer.h" #if defined(_IRR_USE_OSX_DEVICE_) #define GL_COMBINE_EXT 0x8570 #define GL_COMBINE_RGB_EXT 0x8571 #define GL_COMBINE_ALPHA_EXT 0x8572 #define GL_RGB_SCALE_EXT 0x8573 #define GL_ADD_SIGNED_EXT 0x8574 #define GL_INTERPOLATE_EXT 0x8575 #define GL_CONSTANT_EXT 0x8576 #define GL_PRIMARY_COLOR_EXT 0x8577 #define GL_PREVIOUS_EXT 0x8578 #define GL_SOURCE0_RGB_EXT 0x8580 #define GL_SOURCE1_RGB_EXT 0x8581 #define GL_SOURCE2_RGB_EXT 0x8582 #define GL_SOURCE3_RGB_EXT 0x8583 #define GL_SOURCE4_RGB_EXT 0x8584 #define GL_SOURCE5_RGB_EXT 0x8585 #define GL_SOURCE6_RGB_EXT 0x8586 #define GL_SOURCE7_RGB_EXT 0x8587 #define GL_SOURCE0_ALPHA_EXT 0x8588 #define GL_SOURCE1_ALPHA_EXT 0x8589 #define GL_SOURCE2_ALPHA_EXT 0x858A #define GL_SOURCE3_ALPHA_EXT 0x858B #define GL_SOURCE4_ALPHA_EXT 0x858C #define GL_SOURCE5_ALPHA_EXT 0x858D #define GL_SOURCE6_ALPHA_EXT 0x858E #define GL_SOURCE7_ALPHA_EXT 0x858F #define GL_OPERAND0_RGB_EXT 0x8590 #define GL_OPERAND1_RGB_EXT 0x8591 #define GL_OPERAND2_RGB_EXT 0x8592 #define GL_OPERAND3_RGB_EXT 0x8593 #define GL_OPERAND4_RGB_EXT 0x8594 #define GL_OPERAND5_RGB_EXT 0x8595 #define GL_OPERAND6_RGB_EXT 0x8596 #define GL_OPERAND7_RGB_EXT 0x8597 #define GL_OPERAND0_ALPHA_EXT 0x8598 #define GL_OPERAND1_ALPHA_EXT 0x8599 #define GL_OPERAND2_ALPHA_EXT 0x859A #define GL_OPERAND3_ALPHA_EXT 0x859B #define GL_OPERAND4_ALPHA_EXT 0x859C #define GL_OPERAND5_ALPHA_EXT 0x859D #define GL_OPERAND6_ALPHA_EXT 0x859E #define GL_OPERAND7_ALPHA_EXT 0x859F #endif namespace irr { namespace video { //! Base class for all internal OpenGL material renderers class COpenGLMaterialRenderer : public IMaterialRenderer { public: //! Constructor COpenGLMaterialRenderer(video::COpenGLDriver* driver) : Driver(driver) { } protected: video::COpenGLDriver* Driver; }; //! Solid material renderer class COpenGLMaterialRenderer_SOLID : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_SOLID(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); Driver->setTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { // thanks to Murphy, the following line removed some // bugs with several OpenGL implementations. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } }; //! Generic Texture Blend class COpenGLMaterialRenderer_ONETEXTURE_BLEND : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_ONETEXTURE_BLEND(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); Driver->setTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); // if (material.MaterialType != lastMaterial.MaterialType || // material.MaterialTypeParam != lastMaterial.MaterialTypeParam || // resetAllRenderstates) { E_BLEND_FACTOR srcFact,dstFact; E_MODULATE_FUNC modulate; unpack_texureBlendFunc ( srcFact, dstFact, modulate, material.MaterialTypeParam ); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, (f32) modulate ); glBlendFunc( getGLBlend(srcFact), getGLBlend(dstFact) ); glEnable(GL_ALPHA_TEST); glEnable(GL_BLEND); if ( getTexelAlpha(srcFact) || getTexelAlpha(dstFact) ) { glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); } } } virtual void OnUnsetMaterial() { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.f ); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); } private: u32 getGLBlend ( E_BLEND_FACTOR factor ) const { u32 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; } u32 getTexelAlpha ( E_BLEND_FACTOR factor ) const { u32 r; switch ( factor ) { case EBF_SRC_ALPHA: r = 1; break; case EBF_ONE_MINUS_SRC_ALPHA: r = 1; break; case EBF_DST_ALPHA: r = 1; break; case EBF_ONE_MINUS_DST_ALPHA: r = 1; break; case EBF_SRC_ALPHA_SATURATE: r = 1; break; default: r = 0; break; } return r; } }; //! Solid 2 layer material renderer class COpenGLMaterialRenderer_SOLID_2_LAYER : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_SOLID_2_LAYER(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); Driver->setTexture(1, material.getTexture(1)); Driver->setTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR); glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA); } } } virtual void OnUnsetMaterial() { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR); Driver->extGlActiveTexture(GL_TEXTURE0_ARB); } } }; //! Transparent add color material renderer class COpenGLMaterialRenderer_TRANSPARENT_ADD_COLOR : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_ADD_COLOR(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); Driver->setTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if ((material.MaterialType != lastMaterial.MaterialType) || resetAllRenderstates) { glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glEnable(GL_BLEND); } } virtual void OnUnsetMaterial() { glDisable(GL_BLEND); } //! Returns if the material is transparent. virtual bool isTransparent() const { return true; } }; //! Transparent vertex alpha material renderer class COpenGLMaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_VERTEX_ALPHA(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); Driver->setTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT ); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PRIMARY_COLOR_EXT ); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); } glDepthMask(GL_FALSE); } virtual void OnUnsetMaterial() { // default values glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE ); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE ); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT ); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE ); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glDisable(GL_BLEND); } //! Returns if the material is transparent. virtual bool isTransparent() const { return true; } }; //! Transparent alpha channel material renderer class COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); Driver->setTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates || material.MaterialTypeParam != lastMaterial.MaterialTypeParam ) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_ALPHA_TEST); f32 refValue = material.MaterialTypeParam; if ( refValue == 0.0f ) refValue = 0.5f; glAlphaFunc(GL_GREATER, refValue); } } virtual void OnUnsetMaterial() { glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); } //! Returns if the material is transparent. virtual bool isTransparent() const { return true; } }; //! Transparent alpha channel material renderer class COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); Driver->setTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } } virtual void OnUnsetMaterial() { glDisable(GL_ALPHA_TEST); } //! Returns if the material is transparent. virtual bool isTransparent() const { return false; // this material is not really transparent because it does no blending. } }; //! material renderer for all kinds of lightmaps class COpenGLMaterialRenderer_LIGHTMAP : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_LIGHTMAP(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); Driver->setTexture(1, material.getTexture(1)); Driver->setTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { // diffuse map switch (material.MaterialType) { case EMT_LIGHTMAP_LIGHTING: case EMT_LIGHTMAP_LIGHTING_M2: case EMT_LIGHTMAP_LIGHTING_M4: glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); break; case EMT_LIGHTMAP_ADD: case EMT_LIGHTMAP: case EMT_LIGHTMAP_M2: case EMT_LIGHTMAP_M4: default: glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); break; } if (Driver->queryFeature(EVDF_MULTITEXTURE)) { // lightmap Driver->extGlActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); if (material.MaterialType == EMT_LIGHTMAP_ADD) glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD_SIGNED_ARB); else glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_ARB); switch (material.MaterialType) { case EMT_LIGHTMAP_M4: case EMT_LIGHTMAP_LIGHTING_M4: glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 4.0f); break; case EMT_LIGHTMAP_M2: case EMT_LIGHTMAP_LIGHTING_M2: glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f); break; default: glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f); } } } } virtual void OnUnsetMaterial() { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.f ); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); Driver->extGlActiveTexture(GL_TEXTURE0_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } }; //! detail map material renderer class COpenGLMaterialRenderer_DETAIL_MAP : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_DETAIL_MAP(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); Driver->setTexture(1, material.getTexture(1)); Driver->setTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { // diffuse map if (Driver->queryFeature(EVDF_MULTITEXTURE)) { // detail map Driver->extGlActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD_SIGNED_EXT); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_EXT,GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_EXT, GL_TEXTURE); Driver->extGlActiveTexture(GL_TEXTURE0_ARB); } } } }; //! sphere map material renderer class COpenGLMaterialRenderer_SPHERE_MAP : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_SPHERE_MAP(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); Driver->setTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); } } virtual void OnUnsetMaterial() { glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); } }; //! reflection 2 layer material renderer class COpenGLMaterialRenderer_REFLECTION_2_LAYER : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_REFLECTION_2_LAYER(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); Driver->setTexture(1, material.getTexture(1)); Driver->setTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); } glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); } } virtual void OnUnsetMaterial() { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE0_ARB); } } }; //! reflection 2 layer material renderer class COpenGLMaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); Driver->setTexture(1, material.getTexture(1)); Driver->setTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); } glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); glEnable(GL_BLEND); } } virtual void OnUnsetMaterial() { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE0_ARB); } glDisable(GL_BLEND); } //! Returns if the material is transparent. virtual bool isTransparent() const { return true; } }; } // end namespace video } // end namespace irr #endif #endif