// 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 __S_MATERIAL_H_INCLUDED__ #define __S_MATERIAL_H_INCLUDED__ #include "SColor.h" #include "matrix4.h" #include "irrArray.h" namespace irr { namespace video { class ITexture; //! Abstracted and easy to use fixed function/programmable pipeline material modes. enum E_MATERIAL_TYPE { //! Standard solid material. Only first texture is used, which is //! supposed to be the diffuse material. EMT_SOLID = 0, //! Solid material with 2 texture layers. The second is blended onto the //! first using the alpha value of the vertex colors. //! This material is currently not implemented in OpenGL, but it //! works with DirectX. EMT_SOLID_2_LAYER, //! Material type with standard lightmap technique: //! There should be 2 textures: The first texture layer is a diffuse map, //! the second is a light map. Vertex light is ignored. EMT_LIGHTMAP, //! Material type with lightmap technique like EMT_LIGHTMAP, but //! lightmap and diffuse texture are not modulated, but added instead. EMT_LIGHTMAP_ADD, //! Material type with standard lightmap technique: //! There should be 2 textures: The first texture layer is a diffuse map, //! the second is a light map. Vertex light is ignored. //! The texture colors are effectively multiplyied by 2 for brightening. //! like known in DirectX as D3DTOP_MODULATE2X. EMT_LIGHTMAP_M2, //! Material type with standard lightmap technique: //! There should be 2 textures: The first texture layer is a diffuse map, //! the second is a light map. Vertex light is ignored. //! The texture colors are effectively multiplyied by 4 for brightening. //! like known in DirectX as D3DTOP_MODULATE4X. EMT_LIGHTMAP_M4, //! Like EMT_LIGHTMAP, but also supports dynamic lighting. EMT_LIGHTMAP_LIGHTING, //! Like EMT_LIGHTMAP_M2, but also supports dynamic lighting. EMT_LIGHTMAP_LIGHTING_M2, //! Like EMT_LIGHTMAP_4, but also supports dynamic lighting. EMT_LIGHTMAP_LIGHTING_M4, //! Detail mapped material. The first texture is diffuse color map, the //! second is added to this and usually displayed with a bigger scale value //! so that it adds more detail. The detail map is added to the diffuse map using //! ADD_SIGNED, so that it is possible to add and substract color from the diffuse //! map. For example a value of (127,127,127) will not change the appearance of //! the diffuse map at all. //! Often used for terrain rendering. EMT_DETAIL_MAP, //! Makes the material look like it was reflection the environment //! around it. To make this possible, a texture called 'sphere map' //! is used, which must be set as Textures[0]. EMT_SPHERE_MAP, //! A reflecting material with an //! optional additional non reflecting texture layer. The reflection //! map should be set as Texture 1. EMT_REFLECTION_2_LAYER, //! A transparent material. Only the first texture is used. //! The new color is calculated by simply adding the source color and //! the dest color. This means if for example a billboard using a texture with //! black background and a red circle on it is drawn with this material, the //! result is that only the red circle will be drawn a little bit transparent, //! and everything which was black is 100% transparent and not visible. //! This material type is useful for e.g. particle effects. EMT_TRANSPARENT_ADD_COLOR, //! Makes the material transparent based on the texture alpha channel. //! The final color is blended together from the destination color and the //! texture color, using the alpha channel value as blend factor. //! Only first texture is used. If you are using this material with small //! textures, it is a good idea to load the texture in 32 bit //! mode (video::IVideoDriver::setTextureCreationFlag()). //! Also, an alpha ref is used, which can be manipulated using SMaterial::MaterialTypeParam. //! If set to 0, the alpha ref gets its default value which is 0.5f and which means //! that pixels with an alpha value >127 will be written, others not. In other, simple //! words: this value controls how sharp the edges become when going from a //! transparent to a solid spot on the texture. EMT_TRANSPARENT_ALPHA_CHANNEL, //! Makes the material transparent based on the texture alpha channel. //! If the alpha channel value is greater than 127, a pixel is written to the //! target, otherwise not. This material does not use alpha blending //! and is a lot faster than EMT_TRANSPARENT_ALPHA_CHANNEL. It //! is ideal for drawing stuff like leafes of plants, because the borders //! are not blurry but sharp. //! Only first texture is used. If you are using this material with small //! textures and 3d object, it is a good idea to load the texture in 32 bit //! mode (video::IVideoDriver::setTextureCreationFlag()). EMT_TRANSPARENT_ALPHA_CHANNEL_REF, //! Makes the material transparent based on the vertex alpha value. EMT_TRANSPARENT_VERTEX_ALPHA, //! A transparent reflecting material with an //! optional additional non reflecting texture layer. The reflection //! map should be set as Texture 1. The transparency depends on the //! alpha value in the vertex colors. A texture which will not reflect //! can be set als Texture 2. //! Please note that this material type is currently not 100% implemented //! in OpenGL. It works in Direct3D. EMT_TRANSPARENT_REFLECTION_2_LAYER, //! A solid normal map renderer. First texture is the color map, the //! second should be the normal map. Note that you should use this material //! only when drawing geometry consisting of vertices of type S3DVertexTangents //! (EVT_TANGENTS). You can convert any mesh into this format using //! IMeshManipulator::createMeshWithTangents() (See SpecialFX2 Tutorial). //! This shader runs on vertex shader 1.1 and pixel shader 1.1 capable hardware and //! falls back on a fixed function lighted material if this hardware is not available. //! Only two lights are supported by this shader, if there are more, the nearest two //! are chosen. Currently, this shader is only implemented for the D3D8 and D3D9 renderers. EMT_NORMAL_MAP_SOLID, //! A transparent normal map renderer. First texture is the color map, the //! second should be the normal map. Note that you should use this material //! only when drawing geometry consisting of vertices of type S3DVertexTangents //! (EVT_TANGENTS). You can convert any mesh into this format using //! IMeshManipulator::createMeshWithTangents() (See SpecialFX2 Tutorial). //! This shader runs on vertex shader 1.1 and pixel shader 1.1 capable hardware and //! falls back on a fixed function lighted material if this hardware is not available. //! Only two lights are supported by this shader, if there are more, the nearest two //! are chosen. Currently, this shader is only implemented for the D3D8 and D3D9 renderers. EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR, //! A transparent (based on the vertex alpha value) normal map renderer. //! First texture is the color map, the //! second should be the normal map. Note that you should use this material //! only when drawing geometry consisting of vertices of type S3DVertexTangents //! (EVT_TANGENTS). You can convert any mesh into this format using //! IMeshManipulator::createMeshWithTangents() (See SpecialFX2 Tutorial). //! This shader runs on vertex shader 1.1 and pixel shader 1.1 capable hardware and //! falls back on a fixed function lighted material if this hardware is not available. //! Only two lights are supported by this shader, if there are more, the nearest two //! are chosen. Currently, this shader is only implemented for the D3D8 and D3D9 renderers. EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA, //! Just like EMT_NORMAL_MAP_SOLID, but uses parallax mapping too, which //! looks a lot more realistic. This only works when the hardware supports at //! least vertex shader 1.1 and pixel shader 1.4. //! First texture is the color map, the second should be the normal map. //! The normal map texture should contain the height value in the //! alpha component. The IVideoDriver::makeNormalMapTexture() method writes //! this value automaticly when creating normal maps from a heightmap when using a 32 bit //! texture. //! The height scale of the material (affecting the bumpiness) is being controlled //! by the SMaterial::MaterialTypeParam member. //! If set to zero, the default value (0.02f) will be applied. Otherwise //! the value set in SMaterial::MaterialTypeParam is taken. This value depends on with which //! scale the texture is mapped on the material. Too high or low values of MaterialTypeParam //! can result in strange artifacts. EMT_PARALLAX_MAP_SOLID, //! A material just like EMT_PARALLAX_MAP_SOLID, but it is transparent, using //! EMT_TRANSPARENT_ADD_COLOR as base material. EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR, //! A material just like EMT_PARALLAX_MAP_SOLID, but it is transparent, using //! EMT_TRANSPARENT_VERTEX_ALPHA as base material. EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA, //! BlendFunc = source * sourceFactor + dest * destFactor ( E_BLEND_FUNC ) //! Using only Textures[0]. generic Blender EMT_ONETEXTURE_BLEND, //! This value is not used. It only forces this enumeration to compile in 32 bit. EMT_FORCE_32BIT = 0x7fffffff }; //! Array holding the built in material type names const char* const sBuiltInMaterialTypeNames[] = { "solid", "solid_2layer", "lightmap", "lightmap_add", "lightmap_m2", "lightmap_m4", "lightmap_light", "lightmap_light_m2", "lightmap_light_m4", "detail_map", "sphere_map", "reflection_2layer", "trans_add", "trans_alphach", "trans_alphach_ref", "trans_vertex_alpha", "trans_reflection_2layer", "normalmap_solid", "normalmap_trans_add", "normalmap_trans_vertexalpha", "parallaxmap_solid", "parallaxmap_trans_add", "parallaxmap_trans_vertexalpha", "onetexture_blend", 0 }; //! Flag for EMT_ONETEXTURE_BLEND, ( BlendFactor ) //! BlendFunc = source * sourceFactor + dest * destFactor enum E_BLEND_FACTOR { EBF_ZERO = 0, // src & dest (0, 0, 0, 0) EBF_ONE, // src & dest (1, 1, 1, 1) EBF_DST_COLOR, // src (destR, destG, destB, destA) EBF_ONE_MINUS_DST_COLOR, // src (1-destR, 1-destG, 1-destB, 1-destA) EBF_SRC_COLOR, // dest (srcR, srcG, srcB, srcA) EBF_ONE_MINUS_SRC_COLOR, // dest (1-srcR, 1-srcG, 1-srcB, 1-srcA) EBF_SRC_ALPHA, // src & dest (srcA, srcA, srcA, srcA) EBF_ONE_MINUS_SRC_ALPHA, // src & dest (1-srcA, 1-srcA, 1-srcA, 1-srcA) EBF_DST_ALPHA, // src & dest (destA, destA, destA, destA) EBF_ONE_MINUS_DST_ALPHA, // src & dest (1-destA, 1-destA, 1-destA, 1-destA) EBF_SRC_ALPHA_SATURATE // src (min(srcA, 1-destA), idem, ...) }; //! Texture coord clamp mode outside [0.0, 1.0] enum E_TEXTURE_CLAMP { //! Texture repeats ETC_REPEAT = 0, //! Texture is clamped to the last pixel ETC_CLAMP, //! Texture is clamped to the edge pixel ETC_CLAMP_TO_EDGE, //! Texture is clamped to the border pixel (if exists) ETC_CLAMP_TO_BORDER, //! Texture is alternatingly mirrored (0..1..0..1..0..) ETC_MIRROR }; static const char* const aTextureClampNames[] = { "texture_clamp_repeat", "texture_clamp_clamp", "texture_clamp_clamp_to_edge", "texture_clamp_clamp_to_border", "texture_clamp_mirror", 0}; //! MaterialTypeParam: eg. DirectX: D3DTOP_MODULATE, D3DTOP_MODULATE2X, D3DTOP_MODULATE4X enum E_MODULATE_FUNC { EMFN_MODULATE_1X = 1, EMFN_MODULATE_2X = 2, EMFN_MODULATE_4X = 4 }; //! EMT_ONETEXTURE_BLEND: pack srcFact & dstFact and Modulo to MaterialTypeParam inline f32 pack_texureBlendFunc ( const E_BLEND_FACTOR srcFact, const E_BLEND_FACTOR dstFact, const E_MODULATE_FUNC modulate ) { return (f32)(modulate << 16 | srcFact << 8 | dstFact); } //! EMT_ONETEXTURE_BLEND: unpack srcFact & dstFact and Modulo to MaterialTypeParam inline void unpack_texureBlendFunc ( E_BLEND_FACTOR &srcFact, E_BLEND_FACTOR &dstFact, E_MODULATE_FUNC &modulo, const f32 param ) { const u32 state = (u32)param; modulo = E_MODULATE_FUNC ( ( state & 0x00FF0000 ) >> 16 ); srcFact = E_BLEND_FACTOR ( ( state & 0x0000FF00 ) >> 8 ); dstFact = E_BLEND_FACTOR ( ( state & 0x000000FF ) ); } //! Material flags enum E_MATERIAL_FLAG { //! Draw as wireframe or filled triangles? Default: false EMF_WIREFRAME = 0, //! Draw as point cloud or filled triangles? Default: false EMF_POINTCLOUD, //! Flat or Gouraud shading? Default: true EMF_GOURAUD_SHADING, //! Will this material be lighted? Default: true EMF_LIGHTING, //! Is the ZBuffer enabled? Default: true EMF_ZBUFFER, //! May be written to the zbuffer or is it readonly. Default: true //! This flag is ignored, if the material type is a transparent type. EMF_ZWRITE_ENABLE, //! Is backfaceculling enabled? Default: true EMF_BACK_FACE_CULLING, //! Is bilinear filtering enabled? Default: true EMF_BILINEAR_FILTER, //! Is trilinear filtering enabled? Default: false //! If the trilinear filter flag is enabled, //! the bilinear filtering flag is ignored. EMF_TRILINEAR_FILTER, //! Is anisotropic filtering? Default: false //! In Irrlicht you can use anisotropic texture filtering in //! conjunction with bilinear or trilinear texture filtering //! to improve rendering results. Primitives will look less //! blurry with this flag switched on. EMF_ANISOTROPIC_FILTER, //! Is fog enabled? Default: false EMF_FOG_ENABLE, //! Normalizes normals.You can enable this if you need //! to scale a dynamic lighted model. Usually, its normals will get scaled //! too then and it will get darker. If you enable the EMF_NORMALIZE_NORMALS flag, //! the normals will be normalized again, and the model will look as bright as it should. EMF_NORMALIZE_NORMALS, //! Access to all layers texture wrap settings. Overwrites separate layer settings. EMF_TEXTURE_WRAP, //! This is not a flag, but a value indicating how much flags there are. EMF_MATERIAL_FLAG_COUNT }; //! Maximum number of texture an SMaterial can have. const u32 MATERIAL_MAX_TEXTURES = 4; //! struct for holding parameters for a material renderer class SMaterial { public: //! default constructor, creates a solid material with standard colors SMaterial() : MaterialType(EMT_SOLID), AmbientColor(255,255,255,255), DiffuseColor(255,255,255,255), EmissiveColor(0,0,0,0), SpecularColor(255,255,255,255), Shininess(0.0f), MaterialTypeParam(0.0f), MaterialTypeParam2(0.0f), Thickness(1.0f), Wireframe(false), PointCloud(false), GouraudShading(true), Lighting(true), ZBuffer(true), ZWriteEnable(true), BackfaceCulling(true), FogEnable(false), NormalizeNormals(false) { for (u32 i=0; igetMaterial(0).Shininess = 20.0f; \endcode You can also change the color of the highlights using \code sceneNode->getMaterial(0).SpecularColor.set(255,255,255,255); \endcode The specular color of the dynamic lights (SLight::SpecularColor) will influence the the highlight color too, but they are set to a useful value by default when creating the light scene node. Here is a simple example on how to use specular highlights: \code // load and display mesh scene::IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( smgr->getMesh("data/faerie.md2")); node->setMaterialTexture(0, driver->getTexture("data/Faerie2.pcx")); // set diffuse texture node->setMaterialFlag(video::EMF_LIGHTING, true); // enable dynamic lighting node->getMaterial(0).Shininess = 20.0f; // set size of specular highlights // add white light scene::ILightSceneNode* light = smgr->addLightSceneNode(0, core::vector3df(5,5,5), video::SColorf(1.0f, 1.0f, 1.0f)); \endcode */ f32 Shininess; //! Free parameter dependend on the material type. /** Mostly ignored, used for example in EMT_PARALLAX_MAP_SOLID and EMT_TRANSPARENT_ALPHA_CHANNEL. */ f32 MaterialTypeParam; //! Second free parameter dependend on the material type. /** Mostly ignored. */ f32 MaterialTypeParam2; //! Thickness of non-3dimensional elements such as lines and points. f32 Thickness; //! Texture layer array. ITexture* Textures[MATERIAL_MAX_TEXTURES]; //! Texture Matrix array //! Do not acces the elements directly as the internal //! ressource management has to cope with Null pointers etc. core::matrix4* TextureMatrix[MATERIAL_MAX_TEXTURES]; //! Texture Clamp Mode E_TEXTURE_CLAMP TextureWrap[MATERIAL_MAX_TEXTURES]; //! material flags /** The user can access the material flag using material.Wireframe = true or material.setFlag(EMF_WIREFRAME, true); */ //! Draw as wireframe or filled triangles? Default: false bool Wireframe; //! Draw as point cloud or filled triangles? Default: false bool PointCloud; //! Flat or Gouraud shading? Default: true bool GouraudShading; //! Will this material be lighted? Default: true bool Lighting; //! Is the ZBuffer enabled? Default: true //! Changed from Bool to Integer // ( 0 == ZBuffer Off, 1 == ZBuffer LessEqual, 2 == ZBuffer Equal ) u32 ZBuffer; //! May be written to the zbuffer or is it readonly. /** Default: 1 This flag is ignored, if the MaterialType is a transparent type. */ bool ZWriteEnable; //! Is backfaceculling enabled? Default: true bool BackfaceCulling; //! Is bilinear filtering enabled? Default: true bool BilinearFilter[MATERIAL_MAX_TEXTURES]; //! Is trilinear filtering enabled? Default: false /** If the trilinear filter flag is enabled, the bilinear filtering flag is ignored. */ bool TrilinearFilter[MATERIAL_MAX_TEXTURES]; //! Is anisotropic filtering enabled? Default: false /** In Irrlicht you can use anisotropic texture filtering in conjunction with bilinear or trilinear texture filtering to improve rendering results. Primitives will look less blurry with this flag switched on. */ bool AnisotropicFilter[MATERIAL_MAX_TEXTURES]; //! Is fog enabled? Default: false bool FogEnable; //! Should normals be normalized? Default: false bool NormalizeNormals; //! Gets the texture transformation matrix for level i core::matrix4& getTextureMatrix(u32 i) { if (i=MATERIAL_MAX_TEXTURES) return; if (!TextureMatrix[i]) TextureMatrix[i] = new core::matrix4(mat); else *TextureMatrix[i] = mat; } //! Sets the Material flag to the given value void setFlag(E_MATERIAL_FLAG flag, bool value) { switch (flag) { case EMF_WIREFRAME: Wireframe = value; break; case EMF_POINTCLOUD: PointCloud = value; break; case EMF_GOURAUD_SHADING: GouraudShading = value; break; case EMF_LIGHTING: Lighting = value; break; case EMF_ZBUFFER: ZBuffer = value; break; case EMF_ZWRITE_ENABLE: ZWriteEnable = value; break; case EMF_BACK_FACE_CULLING: BackfaceCulling = value; break; case EMF_BILINEAR_FILTER: { for (u32 i=0; i