// Copyright (C) 2002-2012 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 "IMaterialRenderer.h" #include "COpenGLDriver.h" #include "COpenGLCacheHandler.h" namespace irr { namespace video { //! Solid material renderer class COpenGLMaterialRenderer_SOLID : public IMaterialRenderer { public: COpenGLMaterialRenderer_SOLID(video::COpenGLDriver* d) : Driver(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_ { if (Driver->getFixedPipelineState() == COpenGLDriver::EOFPS_DISABLE) Driver->setFixedPipelineState(COpenGLDriver::EOFPS_DISABLE_TO_ENABLE); else Driver->setFixedPipelineState(COpenGLDriver::EOFPS_ENABLE); Driver->disableTextures(1); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); } protected: video::COpenGLDriver* Driver; }; //! Generic Texture Blend class COpenGLMaterialRenderer_ONETEXTURE_BLEND : public IMaterialRenderer { public: COpenGLMaterialRenderer_ONETEXTURE_BLEND(video::COpenGLDriver* d) : Driver(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_ { if (Driver->getFixedPipelineState() == COpenGLDriver::EOFPS_DISABLE) Driver->setFixedPipelineState(COpenGLDriver::EOFPS_DISABLE_TO_ENABLE); else Driver->setFixedPipelineState(COpenGLDriver::EOFPS_ENABLE); Driver->disableTextures(1); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); // if (material.MaterialType != lastMaterial.MaterialType || // material.MaterialTypeParam != lastMaterial.MaterialTypeParam || // resetAllRenderstates) { E_BLEND_FACTOR srcRGBFact,dstRGBFact,srcAlphaFact,dstAlphaFact; E_MODULATE_FUNC modulate; u32 alphaSource; unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulate, alphaSource, material.MaterialTypeParam); Driver->getCacheHandler()->setBlend(true); if (Driver->queryFeature(EVDF_BLEND_SEPARATE)) { Driver->getCacheHandler()->setBlendFuncSeparate(Driver->getGLBlend(srcRGBFact), Driver->getGLBlend(dstRGBFact), Driver->getGLBlend(srcAlphaFact), Driver->getGLBlend(dstAlphaFact)); } else { Driver->getCacheHandler()->setBlendFunc(Driver->getGLBlend(srcRGBFact), Driver->getGLBlend(dstRGBFact)); } Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (f32) modulate ); #else 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_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, (f32) modulate ); #endif if (textureBlendFunc_hasAlpha(srcRGBFact) || textureBlendFunc_hasAlpha(dstRGBFact) || textureBlendFunc_hasAlpha(srcAlphaFact) || textureBlendFunc_hasAlpha(dstAlphaFact)) { if (alphaSource==EAS_VERTEX_COLOR) { #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); #else glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); #endif } else if (alphaSource==EAS_TEXTURE) { #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); #else glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); #endif } else { #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE); #else glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_TEXTURE); #endif } } } } virtual void OnUnsetMaterial() _IRR_OVERRIDE_ { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.f ); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); #else glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.f ); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); #endif Driver->getCacheHandler()->setBlend(false); } //! Returns if the material is transparent. /** Is not always transparent, but mostly. */ virtual bool isTransparent() const _IRR_OVERRIDE_ { return true; } protected: video::COpenGLDriver* Driver; }; //! Solid 2 layer material renderer class COpenGLMaterialRenderer_SOLID_2_LAYER : public IMaterialRenderer { public: COpenGLMaterialRenderer_SOLID_2_LAYER(video::COpenGLDriver* d) : Driver(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_ { if (Driver->getFixedPipelineState() == COpenGLDriver::EOFPS_DISABLE) Driver->setFixedPipelineState(COpenGLDriver::EOFPS_DISABLE_TO_ENABLE); else Driver->setFixedPipelineState(COpenGLDriver::EOFPS_ENABLE); Driver->disableTextures(2); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA); #else glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA); #endif } } } virtual void OnUnsetMaterial() _IRR_OVERRIDE_ { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR); #else glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR); #endif } } protected: video::COpenGLDriver* Driver; }; //! Transparent add color material renderer class COpenGLMaterialRenderer_TRANSPARENT_ADD_COLOR : public IMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_ADD_COLOR(video::COpenGLDriver* d) : Driver(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_ { if (Driver->getFixedPipelineState() == COpenGLDriver::EOFPS_DISABLE) Driver->setFixedPipelineState(COpenGLDriver::EOFPS_DISABLE_TO_ENABLE); else Driver->setFixedPipelineState(COpenGLDriver::EOFPS_ENABLE); Driver->disableTextures(1); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); Driver->getCacheHandler()->setBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); Driver->getCacheHandler()->setBlend(true); } virtual void OnUnsetMaterial() _IRR_OVERRIDE_ { Driver->getCacheHandler()->setBlend(false); } //! Returns if the material is transparent. virtual bool isTransparent() const _IRR_OVERRIDE_ { return true; } protected: video::COpenGLDriver* Driver; }; //! Transparent vertex alpha material renderer class COpenGLMaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public IMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_VERTEX_ALPHA(video::COpenGLDriver* d) : Driver(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_ { if (Driver->getFixedPipelineState() == COpenGLDriver::EOFPS_DISABLE) Driver->setFixedPipelineState(COpenGLDriver::EOFPS_DISABLE_TO_ENABLE); else Driver->setFixedPipelineState(COpenGLDriver::EOFPS_ENABLE); Driver->disableTextures(1); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); Driver->getCacheHandler()->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); Driver->getCacheHandler()->setBlend(true); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); #else glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT ); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); #endif } } virtual void OnUnsetMaterial() _IRR_OVERRIDE_ { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE ); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE ); #else glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE ); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE ); #endif Driver->getCacheHandler()->setBlend(false); } //! Returns if the material is transparent. virtual bool isTransparent() const _IRR_OVERRIDE_ { return true; } protected: video::COpenGLDriver* Driver; }; //! Transparent alpha channel material renderer class COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public IMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(video::COpenGLDriver* d) : Driver(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_ { if (Driver->getFixedPipelineState() == COpenGLDriver::EOFPS_DISABLE) Driver->setFixedPipelineState(COpenGLDriver::EOFPS_DISABLE_TO_ENABLE); else Driver->setFixedPipelineState(COpenGLDriver::EOFPS_ENABLE); Driver->disableTextures(1); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); Driver->getCacheHandler()->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); Driver->getCacheHandler()->setBlend(true); Driver->getCacheHandler()->setAlphaTest(true); Driver->getCacheHandler()->setAlphaFunc(GL_GREATER, material.MaterialTypeParam); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates || material.MaterialTypeParam != lastMaterial.MaterialTypeParam ) { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); #else 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_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); #endif } } virtual void OnUnsetMaterial() _IRR_OVERRIDE_ { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE ); #else glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE ); #endif Driver->getCacheHandler()->setAlphaTest(false); Driver->getCacheHandler()->setBlend(false); } //! Returns if the material is transparent. virtual bool isTransparent() const _IRR_OVERRIDE_ { return true; } protected: video::COpenGLDriver* Driver; }; //! Transparent alpha channel material renderer class COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public IMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(video::COpenGLDriver* d) : Driver(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_ { if (Driver->getFixedPipelineState() == COpenGLDriver::EOFPS_DISABLE) Driver->setFixedPipelineState(COpenGLDriver::EOFPS_DISABLE_TO_ENABLE); else Driver->setFixedPipelineState(COpenGLDriver::EOFPS_ENABLE); Driver->disableTextures(1); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { Driver->getCacheHandler()->setAlphaTest(true); Driver->getCacheHandler()->setAlphaFunc(GL_GREATER, 0.5f); } } virtual void OnUnsetMaterial() _IRR_OVERRIDE_ { Driver->getCacheHandler()->setAlphaTest(false); } //! Returns if the material is transparent. virtual bool isTransparent() const _IRR_OVERRIDE_ { return false; // this material is not really transparent because it does no blending. } protected: video::COpenGLDriver* Driver; }; //! material renderer for all kinds of lightmaps class COpenGLMaterialRenderer_LIGHTMAP : public IMaterialRenderer { public: COpenGLMaterialRenderer_LIGHTMAP(video::COpenGLDriver* d) : Driver(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_ { if (Driver->getFixedPipelineState() == COpenGLDriver::EOFPS_DISABLE) Driver->setFixedPipelineState(COpenGLDriver::EOFPS_DISABLE_TO_ENABLE); else Driver->setFixedPipelineState(COpenGLDriver::EOFPS_ENABLE); Driver->disableTextures(2); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB); // 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->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); if (material.MaterialType == EMT_LIGHTMAP_ADD) glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD); else glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB); #else 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); else glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT); #endif switch (material.MaterialType) { case EMT_LIGHTMAP_M4: case EMT_LIGHTMAP_LIGHTING_M4: #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 4.0f); #else glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 4.0f); #endif break; case EMT_LIGHTMAP_M2: case EMT_LIGHTMAP_LIGHTING_M2: #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2.0f); #else glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f); #endif break; default: #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f); #else glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f); #endif } } } } virtual void OnUnsetMaterial() _IRR_OVERRIDE_ { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.f ); #else glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.f ); #endif } Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } protected: video::COpenGLDriver* Driver; }; //! detail map material renderer class COpenGLMaterialRenderer_DETAIL_MAP : public IMaterialRenderer { public: COpenGLMaterialRenderer_DETAIL_MAP(video::COpenGLDriver* d) : Driver(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_ { if (Driver->getFixedPipelineState() == COpenGLDriver::EOFPS_DISABLE) Driver->setFixedPipelineState(COpenGLDriver::EOFPS_DISABLE_TO_ENABLE); else Driver->setFixedPipelineState(COpenGLDriver::EOFPS_ENABLE); Driver->disableTextures(2); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { // detail map on second layer if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); #else 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_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); #endif } } } virtual void OnUnsetMaterial() _IRR_OVERRIDE_ { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } protected: video::COpenGLDriver* Driver; }; //! sphere map material renderer class COpenGLMaterialRenderer_SPHERE_MAP : public IMaterialRenderer { public: COpenGLMaterialRenderer_SPHERE_MAP(video::COpenGLDriver* d) : Driver(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_ { if (Driver->getFixedPipelineState() == COpenGLDriver::EOFPS_DISABLE) Driver->setFixedPipelineState(COpenGLDriver::EOFPS_DISABLE_TO_ENABLE); else Driver->setFixedPipelineState(COpenGLDriver::EOFPS_ENABLE); Driver->disableTextures(1); // texture needs to be flipped for OpenGL core::matrix4 tmp = Driver->getTransform(ETS_TEXTURE_0); tmp[5]*=-1; Driver->setTransform(ETS_TEXTURE_0, tmp); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB); 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() _IRR_OVERRIDE_ { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); } protected: video::COpenGLDriver* Driver; }; //! reflection 2 layer material renderer class COpenGLMaterialRenderer_REFLECTION_2_LAYER : public IMaterialRenderer { public: COpenGLMaterialRenderer_REFLECTION_2_LAYER(video::COpenGLDriver* d) : Driver(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_ { if (Driver->getFixedPipelineState() == COpenGLDriver::EOFPS_DISABLE) Driver->setFixedPipelineState(COpenGLDriver::EOFPS_DISABLE_TO_ENABLE); else Driver->setFixedPipelineState(COpenGLDriver::EOFPS_ENABLE); Driver->disableTextures(2); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); #else 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_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); #endif glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); } } } virtual void OnUnsetMaterial() _IRR_OVERRIDE_ { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); } } protected: video::COpenGLDriver* Driver; }; //! reflection 2 layer material renderer class COpenGLMaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public IMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(video::COpenGLDriver* d) : Driver(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_ { if (Driver->getFixedPipelineState() == COpenGLDriver::EOFPS_DISABLE) Driver->setFixedPipelineState(COpenGLDriver::EOFPS_DISABLE_TO_ENABLE); else Driver->setFixedPipelineState(COpenGLDriver::EOFPS_ENABLE); Driver->disableTextures(2); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); Driver->getCacheHandler()->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); Driver->getCacheHandler()->setBlend(true); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); #else 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_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_ARB); #endif if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); #else 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_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_ARB); #endif glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); } } } virtual void OnUnsetMaterial() _IRR_OVERRIDE_ { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); } Driver->getCacheHandler()->setActiveTexture(GL_TEXTURE0_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); Driver->getCacheHandler()->setBlend(false); } //! Returns if the material is transparent. virtual bool isTransparent() const _IRR_OVERRIDE_ { return true; } protected: video::COpenGLDriver* Driver; }; } // end namespace video } // end namespace irr #endif #endif