1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
4 
5 #ifndef __C_D3D9_MATERIAL_RENDERER_H_INCLUDED__
6 #define __C_D3D9_MATERIAL_RENDERER_H_INCLUDED__
7 
8 #include "IrrCompileConfig.h"
9 #ifdef _IRR_WINDOWS_
10 
11 #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
12 #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
13 #include "irrMath.h"    // needed by borland for sqrtf define
14 #endif
15 #include <d3d9.h>
16 
17 #include "IMaterialRenderer.h"
18 
19 namespace irr
20 {
21 namespace video
22 {
23 
24 namespace
25 {
26 D3DMATRIX UnitMatrixD3D9;
27 D3DMATRIX SphereMapMatrixD3D9;
setTextureColorStage(IDirect3DDevice9 * dev,DWORD i,DWORD arg1,DWORD op,DWORD arg2)28 inline void setTextureColorStage(IDirect3DDevice9* dev, DWORD i,
29 		DWORD arg1, DWORD op, DWORD arg2)
30 {
31 	dev->SetTextureStageState(i, D3DTSS_COLOROP, op);
32 	dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1);
33 	dev->SetTextureStageState(i, D3DTSS_COLORARG2, arg2);
34 }
setTextureColorStage(IDirect3DDevice9 * dev,DWORD i,DWORD arg1)35 inline void setTextureColorStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1)
36 {
37 	dev->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
38 	dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1);
39 }
40 
setTextureAlphaStage(IDirect3DDevice9 * dev,DWORD i,DWORD arg1,DWORD op,DWORD arg2)41 inline void setTextureAlphaStage(IDirect3DDevice9* dev, DWORD i,
42 		DWORD arg1, DWORD op, DWORD arg2)
43 {
44 	dev->SetTextureStageState(i, D3DTSS_ALPHAOP, op);
45 	dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1);
46 	dev->SetTextureStageState(i, D3DTSS_ALPHAARG2, arg2);
47 }
setTextureAlphaStage(IDirect3DDevice9 * dev,DWORD i,DWORD arg1)48 inline void setTextureAlphaStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1)
49 {
50 	dev->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
51 	dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1);
52 }
53 } // anonymous namespace
54 
55 //! Base class for all internal D3D9 material renderers
56 class CD3D9MaterialRenderer : public IMaterialRenderer
57 {
58 public:
59 
60 	//! Constructor
CD3D9MaterialRenderer(IDirect3DDevice9 * d3ddev,video::IVideoDriver * driver)61 	CD3D9MaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver)
62 		: pID3DDevice(d3ddev), Driver(driver)
63 	{
64 	}
65 
66 	//! sets a variable in the shader.
67 	//! \param vertexShader: True if this should be set in the vertex shader, false if
68 	//! in the pixel shader.
69 	//! \param name: Name of the variable
70 	//! \param floats: Pointer to array of floats
71 	//! \param count: Amount of floats in array.
setVariable(bool vertexShader,const c8 * name,const f32 * floats,int count)72 	virtual bool setVariable(bool vertexShader, const c8* name, const f32* floats, int count)
73 	{
74 		os::Printer::log("Invalid material to set variable in.");
75 		return false;
76 	}
77 
78 	//! Bool interface for the above.
setVariable(bool vertexShader,const c8 * name,const bool * bools,int count)79 	virtual bool setVariable(bool vertexShader, const c8* name, const bool* bools, int count)
80 	{
81 		os::Printer::log("Invalid material to set variable in.");
82 		return false;
83 	}
84 
85 	//! Int interface for the above.
setVariable(bool vertexShader,const c8 * name,const s32 * ints,int count)86 	virtual bool setVariable(bool vertexShader, const c8* name, const s32* ints, int count)
87 	{
88 		os::Printer::log("Invalid material to set variable in.");
89 		return false;
90 	}
91 
92 protected:
93 
94 	IDirect3DDevice9* pID3DDevice;
95 	video::IVideoDriver* Driver;
96 };
97 
98 
99 //! Solid material renderer
100 class CD3D9MaterialRenderer_SOLID : public CD3D9MaterialRenderer
101 {
102 public:
103 
CD3D9MaterialRenderer_SOLID(IDirect3DDevice9 * p,video::IVideoDriver * d)104 	CD3D9MaterialRenderer_SOLID(IDirect3DDevice9* p, video::IVideoDriver* d)
105 		: CD3D9MaterialRenderer(p, d) {}
106 
OnSetMaterial(const SMaterial & material,const SMaterial & lastMaterial,bool resetAllRenderstates,IMaterialRendererServices * services)107 	virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
108 		bool resetAllRenderstates, IMaterialRendererServices* services)
109 	{
110 		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
111 
112 		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
113 		{
114 			setTextureColorStage(pID3DDevice, 0,
115 				D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
116 		}
117 
118 		pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
119 		pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
120 	}
121 };
122 
123 //! Generic Texture Blend
124 class CD3D9MaterialRenderer_ONETEXTURE_BLEND : public CD3D9MaterialRenderer
125 {
126 public:
127 
CD3D9MaterialRenderer_ONETEXTURE_BLEND(IDirect3DDevice9 * p,video::IVideoDriver * d)128 	CD3D9MaterialRenderer_ONETEXTURE_BLEND(IDirect3DDevice9* p, video::IVideoDriver* d)
129 		: CD3D9MaterialRenderer(p, d) {}
130 
OnSetMaterial(const SMaterial & material,const SMaterial & lastMaterial,bool resetAllRenderstates,IMaterialRendererServices * services)131 	virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
132 		bool resetAllRenderstates, IMaterialRendererServices* services)
133 	{
134 		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
135 
136 		if (material.MaterialType != lastMaterial.MaterialType ||
137 			material.MaterialTypeParam != lastMaterial.MaterialTypeParam ||
138 			resetAllRenderstates)
139 		{
140 
141 			E_BLEND_FACTOR srcFact,dstFact;
142 			E_MODULATE_FUNC modulate;
143 			u32 alphaSource;
144 			unpack_textureBlendFunc ( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam );
145 
146 			if (srcFact == EBF_SRC_COLOR && dstFact == EBF_ZERO)
147 			{
148 				pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
149 			}
150 			else
151 			{
152 				pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
153 				pID3DDevice->SetRenderState(D3DRS_SRCBLEND, getD3DBlend ( srcFact ) );
154 				pID3DDevice->SetRenderState(D3DRS_DESTBLEND, getD3DBlend ( dstFact ) );
155 			}
156 
157 			setTextureColorStage(pID3DDevice, 0,
158 				D3DTA_TEXTURE, getD3DModulate(modulate), D3DTA_DIFFUSE);
159 
160 			if ( textureBlendFunc_hasAlpha ( srcFact ) || textureBlendFunc_hasAlpha ( dstFact ) )
161 			{
162 				if (alphaSource==EAS_VERTEX_COLOR)
163 				{
164 					setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
165 				}
166 				else if (alphaSource==EAS_TEXTURE)
167 				{
168 					setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
169 				}
170 				else
171 				{
172 					setTextureAlphaStage(pID3DDevice, 0,
173 						D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
174 				}
175 			}
176 
177 			pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
178 
179 		}
180 	}
181 
182 	//! Returns if the material is transparent.
183 	/** The scene management needs to know this for being able to sort the
184 	materials by opaque and transparent.
185 	The return value could be optimized, but we'd need to know the
186 	MaterialTypeParam for it. */
isTransparent()187 	virtual bool isTransparent() const
188 	{
189 		return true;
190 	}
191 
192 	private:
193 
getD3DBlend(E_BLEND_FACTOR factor)194 		u32 getD3DBlend ( E_BLEND_FACTOR factor ) const
195 		{
196 			u32 r = 0;
197 			switch ( factor )
198 			{
199 				case EBF_ZERO:					r = D3DBLEND_ZERO; break;
200 				case EBF_ONE:					r = D3DBLEND_ONE; break;
201 				case EBF_DST_COLOR:				r = D3DBLEND_DESTCOLOR; break;
202 				case EBF_ONE_MINUS_DST_COLOR:	r = D3DBLEND_INVDESTCOLOR; break;
203 				case EBF_SRC_COLOR:				r = D3DBLEND_SRCCOLOR; break;
204 				case EBF_ONE_MINUS_SRC_COLOR:	r = D3DBLEND_INVSRCCOLOR; break;
205 				case EBF_SRC_ALPHA:				r = D3DBLEND_SRCALPHA; break;
206 				case EBF_ONE_MINUS_SRC_ALPHA:	r = D3DBLEND_INVSRCALPHA; break;
207 				case EBF_DST_ALPHA:				r = D3DBLEND_DESTALPHA; break;
208 				case EBF_ONE_MINUS_DST_ALPHA:	r = D3DBLEND_INVDESTALPHA; break;
209 				case EBF_SRC_ALPHA_SATURATE:	r = D3DBLEND_SRCALPHASAT; break;
210 			}
211 			return r;
212 		}
213 
getD3DModulate(E_MODULATE_FUNC func)214 		u32 getD3DModulate ( E_MODULATE_FUNC func ) const
215 		{
216 			u32 r = D3DTOP_MODULATE;
217 			switch ( func )
218 			{
219 				case EMFN_MODULATE_1X: r = D3DTOP_MODULATE; break;
220 				case EMFN_MODULATE_2X: r = D3DTOP_MODULATE2X; break;
221 				case EMFN_MODULATE_4X: r = D3DTOP_MODULATE4X; break;
222 			}
223 			return r;
224 		}
225 
226 		bool transparent;
227 
228 };
229 
230 
231 
232 //! Solid 2 layer material renderer
233 class CD3D9MaterialRenderer_SOLID_2_LAYER : public CD3D9MaterialRenderer
234 {
235 public:
236 
CD3D9MaterialRenderer_SOLID_2_LAYER(IDirect3DDevice9 * p,video::IVideoDriver * d)237 	CD3D9MaterialRenderer_SOLID_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
238 		: CD3D9MaterialRenderer(p, d) {}
239 
OnSetMaterial(const SMaterial & material,const SMaterial & lastMaterial,bool resetAllRenderstates,IMaterialRendererServices * services)240 	virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
241 		bool resetAllRenderstates, IMaterialRendererServices* services)
242 	{
243 		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
244 
245 		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
246 		{
247 			setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE);
248 
249 			pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
250 			pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);
251 
252 			pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
253 		}
254 	}
255 };
256 
257 
258 //! Transparent add color material renderer
259 class CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR : public CD3D9MaterialRenderer
260 {
261 public:
262 
CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR(IDirect3DDevice9 * p,video::IVideoDriver * d)263 	CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR(IDirect3DDevice9* p, video::IVideoDriver* d)
264 		: CD3D9MaterialRenderer(p, d) {}
265 
OnSetMaterial(const SMaterial & material,const SMaterial & lastMaterial,bool resetAllRenderstates,IMaterialRendererServices * services)266 	virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
267 		bool resetAllRenderstates, IMaterialRendererServices* services)
268 	{
269 		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
270 
271 		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
272 		{
273 			setTextureColorStage(pID3DDevice, 0,
274 				D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
275 
276 			pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
277 			pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
278 			pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
279 			pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
280 		}
281 	}
282 
283 	//! Returns if the material is transparent. The scene management needs to know this
284 	//! for being able to sort the materials by opaque and transparent.
isTransparent()285 	virtual bool isTransparent() const
286 	{
287 		return true;
288 	}
289 };
290 
291 
292 //! Transparent vertex alpha material renderer
293 class CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public CD3D9MaterialRenderer
294 {
295 public:
296 
CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(IDirect3DDevice9 * p,video::IVideoDriver * d)297 	CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(IDirect3DDevice9* p, video::IVideoDriver* d)
298 		: CD3D9MaterialRenderer(p, d) {}
299 
OnSetMaterial(const SMaterial & material,const SMaterial & lastMaterial,bool resetAllRenderstates,IMaterialRendererServices * services)300 	virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
301 		bool resetAllRenderstates, IMaterialRendererServices* services)
302 	{
303 		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
304 
305 		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
306 		{
307 			setTextureColorStage(pID3DDevice, 0,
308 				D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
309 			setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
310 
311 			pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
312 			pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
313 			pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
314 			pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
315 		}
316 	}
317 
318 	//! Returns if the material is transparent. The scene managment needs to know this
319 	//! for being able to sort the materials by opaque and transparent.
isTransparent()320 	virtual bool isTransparent() const
321 	{
322 		return true;
323 	}
324 };
325 
326 
327 //! Transparent alpha channel material renderer
328 class CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public CD3D9MaterialRenderer
329 {
330 public:
331 
CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(IDirect3DDevice9 * p,video::IVideoDriver * d)332 	CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(IDirect3DDevice9* p, video::IVideoDriver* d)
333 		: CD3D9MaterialRenderer(p, d) {}
334 
OnSetMaterial(const SMaterial & material,const SMaterial & lastMaterial,bool resetAllRenderstates,IMaterialRendererServices * services)335 	virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
336 		bool resetAllRenderstates, IMaterialRendererServices* services)
337 	{
338 		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
339 
340 		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates
341 			|| material.MaterialTypeParam != lastMaterial.MaterialTypeParam )
342 		{
343 			setTextureColorStage(pID3DDevice, 0,
344 				D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
345 			setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
346 
347 			pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
348 			pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
349 			pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
350 			pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
351 
352 			pID3DDevice->SetRenderState(D3DRS_ALPHAREF, core::floor32(material.MaterialTypeParam * 255.f));
353 			pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
354 			pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
355 		}
356 	}
357 
OnUnsetMaterial()358 	virtual void OnUnsetMaterial()
359 	{
360 		pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
361 	}
362 
363 	//! Returns if the material is transparent. The scene managment needs to know this
364 	//! for being able to sort the materials by opaque and transparent.
isTransparent()365 	virtual bool isTransparent() const
366 	{
367 		return true;
368 	}
369 };
370 
371 
372 
373 //! Transparent alpha channel material renderer
374 class CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public CD3D9MaterialRenderer
375 {
376 public:
377 
CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(IDirect3DDevice9 * p,video::IVideoDriver * d)378 	CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(IDirect3DDevice9* p, video::IVideoDriver* d)
379 		: CD3D9MaterialRenderer(p, d) {}
380 
OnSetMaterial(const SMaterial & material,const SMaterial & lastMaterial,bool resetAllRenderstates,IMaterialRendererServices * services)381 	virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
382 		bool resetAllRenderstates, IMaterialRendererServices* services)
383 	{
384 		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
385 
386 		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
387 		{
388 			setTextureColorStage(pID3DDevice, 0,
389 				D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
390 			setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
391 
392 			pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
393 
394 			pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
395 
396 			// 127 is required by EMT_TRANSPARENT_ALPHA_CHANNEL_REF
397 			pID3DDevice->SetRenderState(D3DRS_ALPHAREF, 127);
398 			pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
399 			pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
400 		}
401 	}
402 
OnUnsetMaterial()403 	virtual void OnUnsetMaterial()
404 	{
405 		pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
406 	}
407 
408 	//! Returns if the material is transparent. The scene managment needs to know this
409 	//! for being able to sort the materials by opaque and transparent.
isTransparent()410 	virtual bool isTransparent() const
411 	{
412 		return false; // this material is not really transparent because it does no blending.
413 	}
414 };
415 
416 
417 //! material renderer for all kinds of lightmaps
418 class CD3D9MaterialRenderer_LIGHTMAP : public CD3D9MaterialRenderer
419 {
420 public:
421 
CD3D9MaterialRenderer_LIGHTMAP(IDirect3DDevice9 * p,video::IVideoDriver * d)422 	CD3D9MaterialRenderer_LIGHTMAP(IDirect3DDevice9* p, video::IVideoDriver* d)
423 		: CD3D9MaterialRenderer(p, d) {}
424 
OnSetMaterial(const SMaterial & material,const SMaterial & lastMaterial,bool resetAllRenderstates,IMaterialRendererServices * services)425 	virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
426 		bool resetAllRenderstates, IMaterialRendererServices* services)
427 	{
428 		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
429 
430 		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
431 		{
432 			if (material.MaterialType >= EMT_LIGHTMAP_LIGHTING)
433 			{
434 				// with lighting
435 				setTextureColorStage(pID3DDevice, 0,
436 					D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
437 			}
438 			else
439 			{
440 				setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE);
441 			}
442 
443 			pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
444 
445 			setTextureColorStage(pID3DDevice, 1,
446 				D3DTA_TEXTURE,
447 				(material.MaterialType == EMT_LIGHTMAP_ADD)?
448 				D3DTOP_ADD:
449 				(material.MaterialType == EMT_LIGHTMAP_M4 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M4)?
450 				D3DTOP_MODULATE4X:
451 				(material.MaterialType == EMT_LIGHTMAP_M2 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M2)?
452 				D3DTOP_MODULATE2X:
453 				D3DTOP_MODULATE,
454 				D3DTA_CURRENT);
455 
456 			pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
457 		}
458 	}
459 };
460 
461 
462 
463 //! material renderer for detail maps
464 class CD3D9MaterialRenderer_DETAIL_MAP : public CD3D9MaterialRenderer
465 {
466 public:
467 
CD3D9MaterialRenderer_DETAIL_MAP(IDirect3DDevice9 * p,video::IVideoDriver * d)468 	CD3D9MaterialRenderer_DETAIL_MAP(IDirect3DDevice9* p, video::IVideoDriver* d)
469 		: CD3D9MaterialRenderer(p, d) {}
470 
OnSetMaterial(const SMaterial & material,const SMaterial & lastMaterial,bool resetAllRenderstates,IMaterialRendererServices * services)471 	virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
472 		bool resetAllRenderstates, IMaterialRendererServices* services)
473 	{
474 		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
475 
476 		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
477 		{
478 			setTextureColorStage(pID3DDevice, 0,
479 				D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
480 			setTextureColorStage(pID3DDevice, 1,
481 				D3DTA_TEXTURE, D3DTOP_ADDSIGNED, D3DTA_CURRENT);
482 			pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
483 			pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
484 		}
485 	}
486 };
487 
488 
489 //! sphere map material renderer
490 class CD3D9MaterialRenderer_SPHERE_MAP : public CD3D9MaterialRenderer
491 {
492 public:
493 
CD3D9MaterialRenderer_SPHERE_MAP(IDirect3DDevice9 * p,video::IVideoDriver * d)494 	CD3D9MaterialRenderer_SPHERE_MAP(IDirect3DDevice9* p, video::IVideoDriver* d)
495 		: CD3D9MaterialRenderer(p, d) {}
496 
OnSetMaterial(const SMaterial & material,const SMaterial & lastMaterial,bool resetAllRenderstates,IMaterialRendererServices * services)497 	virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
498 		bool resetAllRenderstates, IMaterialRendererServices* services)
499 	{
500 		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
501 
502 		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
503 		{
504 			setTextureColorStage(pID3DDevice, 0,
505 				D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
506 
507 			pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
508 			pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
509 
510 			pID3DDevice->SetTransform( D3DTS_TEXTURE0, &SphereMapMatrixD3D9 );
511 			pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
512 			pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL );
513 		}
514 	}
515 
OnUnsetMaterial()516 	virtual void OnUnsetMaterial()
517 	{
518 		pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
519 		pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0);
520 		pID3DDevice->SetTransform( D3DTS_TEXTURE0, &UnitMatrixD3D9 );
521 	}
522 };
523 
524 
525 //! reflection 2 layer material renderer
526 class CD3D9MaterialRenderer_REFLECTION_2_LAYER : public CD3D9MaterialRenderer
527 {
528 public:
529 
CD3D9MaterialRenderer_REFLECTION_2_LAYER(IDirect3DDevice9 * p,video::IVideoDriver * d)530 	CD3D9MaterialRenderer_REFLECTION_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
531 		: CD3D9MaterialRenderer(p, d) {}
532 
OnSetMaterial(const SMaterial & material,const SMaterial & lastMaterial,bool resetAllRenderstates,IMaterialRendererServices * services)533 	virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
534 		bool resetAllRenderstates, IMaterialRendererServices* services)
535 	{
536 		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
537 
538 		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
539 		{
540 			setTextureColorStage(pID3DDevice, 0,
541 				D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
542 
543 			setTextureColorStage(pID3DDevice, 1,
544 				D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
545 
546 			pID3DDevice->SetTransform( D3DTS_TEXTURE1, &SphereMapMatrixD3D9 );
547 			pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
548 			pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
549 			pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
550 		}
551 	}
552 
OnUnsetMaterial()553 	virtual void OnUnsetMaterial()
554 	{
555 		pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
556 		pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1);
557 		pID3DDevice->SetTransform( D3DTS_TEXTURE1, &UnitMatrixD3D9 );
558 	}
559 };
560 
561 
562 //! reflection 2 layer material renderer
563 class CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public CD3D9MaterialRenderer
564 {
565 public:
566 
CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(IDirect3DDevice9 * p,video::IVideoDriver * d)567 	CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
568 		: CD3D9MaterialRenderer(p, d) {}
569 
OnSetMaterial(const SMaterial & material,const SMaterial & lastMaterial,bool resetAllRenderstates,IMaterialRendererServices * services)570 	virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
571 		bool resetAllRenderstates, IMaterialRendererServices* services)
572 	{
573 		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
574 
575 		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
576 		{
577 			setTextureColorStage(pID3DDevice, 0,
578 				D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
579 			setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
580 			setTextureColorStage(pID3DDevice, 1,
581 				D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
582 			setTextureAlphaStage(pID3DDevice, 1, D3DTA_CURRENT);
583 
584 			pID3DDevice->SetTransform(D3DTS_TEXTURE1, &SphereMapMatrixD3D9 );
585 			pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
586 			pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
587 
588 			pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
589 			pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
590 			pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
591 		}
592 	}
593 
OnUnsetMaterial()594 	virtual void OnUnsetMaterial()
595 	{
596 		pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
597 		pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
598 		pID3DDevice->SetTransform(D3DTS_TEXTURE1, &UnitMatrixD3D9);
599 	}
600 
601 	//! Returns if the material is transparent. The scene managment needs to know this
602 	//! for being able to sort the materials by opaque and transparent.
isTransparent()603 	virtual bool isTransparent() const
604 	{
605 		return true;
606 	}
607 };
608 
609 } // end namespace video
610 } // end namespace irr
611 
612 #endif
613 #endif
614 #endif
615 
616