1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "stddirect3d.h"
22 #include "nel/3d/vertex_buffer.h"
23 #include "nel/3d/light.h"
24 #include "nel/3d/index_buffer.h"
25 #include "nel/3d/texture_bump.h"
26 #include "nel/misc/rect.h"
27 #include "nel/3d/viewport.h"
28 #include "nel/3d/scissor.h"
29 #include "nel/3d/u_driver.h"
31 #include "driver_direct3d.h"
38 using namespace NLMISC
;
46 // ***************************************************************************
48 const D3DBLEND RemapBlendTypeNeL2D3D
[CMaterial::blendCount
]=
51 D3DBLEND_ZERO
, // zero
52 D3DBLEND_SRCALPHA
, // srcalpha
53 D3DBLEND_INVSRCALPHA
, // invsrcalpha
54 D3DBLEND_SRCCOLOR
, // srccolor
55 D3DBLEND_INVSRCCOLOR
, // invsrccolor
56 D3DBLEND_ONE
, // blendConstantColor
57 D3DBLEND_ONE
, // blendConstantInvColor
58 D3DBLEND_ONE
, // blendConstantAlpha
59 D3DBLEND_ONE
, // blendConstantInvAlpha
62 // ***************************************************************************
64 const D3DCMPFUNC RemapZFuncTypeNeL2D3D
[CMaterial::zfuncCount
]=
66 D3DCMP_ALWAYS
, // always
67 D3DCMP_NEVER
, // never
68 D3DCMP_EQUAL
, // equal
69 D3DCMP_NOTEQUAL
, // notequal
71 D3DCMP_LESSEQUAL
, // lessequal
72 D3DCMP_GREATER
, // greater
73 D3DCMP_GREATEREQUAL
,// greaterequal
76 // ***************************************************************************
79 const D3DTEXTUREOP RemapTexOpType0NeL2D3D
[CMaterial::TexOperatorCount
]=
81 D3DTOP_SELECTARG1
, // Replace
82 D3DTOP_MODULATE
, // Modulate
84 D3DTOP_ADDSIGNED
, // AddSigned
85 D3DTOP_BLENDTEXTUREALPHA
, // InterpolateTexture
86 D3DTOP_BLENDDIFFUSEALPHA
, // InterpolatePrevious
87 D3DTOP_BLENDDIFFUSEALPHA
, // InterpolateDiffuse
88 D3DTOP_LERP
, // InterpolateConstant
89 D3DTOP_BUMPENVMAP
, // EMBM
90 D3DTOP_MULTIPLYADD
// MAD
93 // ***************************************************************************
95 const D3DTEXTUREOP RemapTexOpTypeNeL2D3D
[CMaterial::TexOperatorCount
]=
97 D3DTOP_SELECTARG1
, // Replace
98 D3DTOP_MODULATE
, // Modulate
100 D3DTOP_ADDSIGNED
, // AddSigned
101 D3DTOP_BLENDTEXTUREALPHA
, // InterpolateTexture
102 D3DTOP_BLENDCURRENTALPHA
, // InterpolatePrevious
103 D3DTOP_BLENDDIFFUSEALPHA
, // InterpolateDiffuse
104 D3DTOP_LERP
, // InterpolateConstant
105 D3DTOP_BUMPENVMAP
, // EMBM
106 D3DTOP_MULTIPLYADD
// MAD
109 const uint OpNumArg
[CMaterial::TexOperatorCount
] =
115 2, // InterpolateTexture
116 2, // InterpolatePrevious
117 2, // InterpolateDiffuse
118 3, // InterpolateConstant
124 // ***************************************************************************
127 const DWORD RemapTexArg0NeL2D3D
[CMaterial::TexSourceCount
]=
129 D3DTA_TEXTURE
, // Texture
130 D3DTA_DIFFUSE
, // Previous
131 D3DTA_DIFFUSE
, // Diffuse
132 D3DTA_TFACTOR
, // todo hulud constant color D3DTA_CONSTANT, // Constant
135 // ***************************************************************************
137 const DWORD RemapTexArgNeL2D3D
[CMaterial::TexSourceCount
]=
139 D3DTA_TEXTURE
, // Texture
140 D3DTA_CURRENT
, // Previous
141 D3DTA_DIFFUSE
, // Diffuse
142 D3DTA_TFACTOR
, // todo hulud constant color D3DTA_CONSTANT, // Constant
145 // ***************************************************************************
146 const DWORD RemapTexOpArgTypeNeL2D3D
[CMaterial::TexOperandCount
]=
149 D3DTA_COMPLEMENT
, // InvSrcColor
150 D3DTA_ALPHAREPLICATE
, // SrcAlpha
151 D3DTA_ALPHAREPLICATE
|D3DTA_COMPLEMENT
, // InvSrcAlpha
155 // ***************************************************************************
157 const DWORD RemapTexArg0TypeNeL2D3D
[CMaterial::TexOperatorCount
]=
159 D3DTA_TFACTOR
, // todo hulud constant color D3DTA_CONSTANT, // Replace not used
160 D3DTA_TFACTOR
, // todo hulud constant color D3DTA_CONSTANT, // Modulate not used
161 D3DTA_TFACTOR
, // todo hulud constant color D3DTA_CONSTANT, // Add not used
162 D3DTA_TFACTOR
, // todo hulud constant color D3DTA_CONSTANT, // AddSigned not used
163 D3DTA_TFACTOR
, // todo hulud constant color D3DTA_CONSTANT, // InterpolateTexture not used
164 D3DTA_TFACTOR
, // todo hulud constant color D3DTA_CONSTANT, // InterpolatePrevious not used
165 D3DTA_TFACTOR
, // todo hulud constant color D3DTA_CONSTANT, // InterpolateDiffuse not used
166 D3DTA_TFACTOR
|D3DTA_ALPHAREPLICATE
, // todo hulud constant color D3DTA_CONSTANT|D3DTA_ALPHAREPLICATE, // InterpolateConstant
167 D3DTA_TFACTOR
, // todo hulud constant color D3DTA_CONSTANT, // EMBM not used
168 D3DTA_TFACTOR
// todo hulud constant color D3DTA_CONSTANT // MAD
171 // ***************************************************************************
173 const DWORD RemapTexGenTypeNeL2D3D
[CMaterial::numTexCoordGenMode
]=
175 D3DTSS_TCI_SPHEREMAP
, // TexCoordGenReflect
176 D3DTSS_TCI_CAMERASPACEPOSITION
, // TexCoordGenObjectSpace, not supported
177 D3DTSS_TCI_CAMERASPACEPOSITION
, // TexCoordGenEyeSpace
180 // ***************************************************************************
182 const DWORD RemapTexGenCubeTypeNeL2D3D
[CMaterial::numTexCoordGenMode
]=
184 D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
, // TexCoordGenReflect
185 D3DTSS_TCI_CAMERASPACEPOSITION
, // TexCoordGenObjectSpace, not supported
186 D3DTSS_TCI_CAMERASPACEPOSITION
, // TexCoordGenEyeSpace
189 // ***************************************************************************
191 void CMaterialDrvInfosD3D::buildTexEnv (uint stage
, const CMaterial::CTexEnv
&env
, bool textured
)
193 H_AUTO_D3D(CMaterialDrvInfosD3D_buildTexEnv
)
196 // The source operator pointer
197 const DWORD
*srcOp
= (stage
==0)?RemapTexArg0NeL2D3D
:RemapTexArgNeL2D3D
;
199 ColorOp
[stage
] = ((stage
==0)?RemapTexOpType0NeL2D3D
:RemapTexOpTypeNeL2D3D
)[env
.Env
.OpRGB
];
200 NumColorArg
[stage
] = OpNumArg
[env
.Env
.OpRGB
];
201 if (env
.Env
.OpRGB
== CMaterial::Mad
)
203 ColorArg2
[stage
] = srcOp
[env
.Env
.SrcArg0RGB
];
204 ColorArg2
[stage
] |= RemapTexOpArgTypeNeL2D3D
[env
.Env
.OpArg0RGB
];
205 ColorArg1
[stage
] = srcOp
[env
.Env
.SrcArg1RGB
];
206 ColorArg1
[stage
] |= RemapTexOpArgTypeNeL2D3D
[env
.Env
.OpArg1RGB
];
207 ColorArg0
[stage
] = srcOp
[env
.Env
.SrcArg2RGB
];
208 ColorArg0
[stage
] |= RemapTexOpArgTypeNeL2D3D
[env
.Env
.OpArg2RGB
];
212 // Only used for InterpolateConstant
213 ColorArg0
[stage
] = RemapTexArg0TypeNeL2D3D
[env
.Env
.OpRGB
];
214 ColorArg1
[stage
] = srcOp
[env
.Env
.SrcArg0RGB
];
215 ColorArg1
[stage
] |= RemapTexOpArgTypeNeL2D3D
[env
.Env
.OpArg0RGB
];
216 ColorArg2
[stage
] = srcOp
[env
.Env
.SrcArg1RGB
];
217 ColorArg2
[stage
] |= RemapTexOpArgTypeNeL2D3D
[env
.Env
.OpArg1RGB
];
219 AlphaOp
[stage
] = ((stage
==0)?RemapTexOpType0NeL2D3D
:RemapTexOpTypeNeL2D3D
)[env
.Env
.OpAlpha
];
220 NumAlphaArg
[stage
] = OpNumArg
[env
.Env
.OpAlpha
];
221 if (env
.Env
.OpAlpha
== CMaterial::Mad
)
223 AlphaArg2
[stage
] = srcOp
[env
.Env
.SrcArg0Alpha
];
224 AlphaArg2
[stage
] |= RemapTexOpArgTypeNeL2D3D
[env
.Env
.OpArg0Alpha
];
225 AlphaArg1
[stage
] = srcOp
[env
.Env
.SrcArg1Alpha
];
226 AlphaArg1
[stage
] |= RemapTexOpArgTypeNeL2D3D
[env
.Env
.OpArg1Alpha
];
227 AlphaArg0
[stage
] = srcOp
[env
.Env
.SrcArg2Alpha
];
228 AlphaArg0
[stage
] |= RemapTexOpArgTypeNeL2D3D
[env
.Env
.OpArg2Alpha
];
232 // Only used for InterpolateConstant
233 AlphaArg0
[stage
] = RemapTexArg0TypeNeL2D3D
[env
.Env
.OpAlpha
];
234 AlphaArg1
[stage
] = srcOp
[env
.Env
.SrcArg0Alpha
];
235 AlphaArg1
[stage
] |= RemapTexOpArgTypeNeL2D3D
[env
.Env
.OpArg0Alpha
];
236 AlphaArg2
[stage
] = srcOp
[env
.Env
.SrcArg1Alpha
];
237 AlphaArg2
[stage
] |= RemapTexOpArgTypeNeL2D3D
[env
.Env
.OpArg1Alpha
];
239 ConstantColor
[stage
] = NL_D3DCOLOR_RGBA(env
.ConstantColor
);
243 // The stage is disabled, active only the lighting
244 ColorOp
[stage
] = D3DTOP_SELECTARG1
;
245 DWORD opSrc
= D3DTA_DIFFUSE
;
246 ColorArg0
[stage
] = opSrc
;
247 ColorArg1
[stage
] = opSrc
;
248 ColorArg2
[stage
] = opSrc
;
249 AlphaOp
[stage
] = D3DTOP_SELECTARG1
;
250 AlphaArg0
[stage
] = opSrc
;
251 AlphaArg1
[stage
] = opSrc
;
252 AlphaArg2
[stage
] = opSrc
;
253 ConstantColor
[stage
] = NL_D3DCOLOR_RGBA(CRGBA::White
);
254 NumColorArg
[stage
] = 1;
255 NumAlphaArg
[stage
] = 1;
260 // ***************************************************************************
261 static inline DWORD
replaceDiffuseWithConstant(DWORD value
)
263 if ((value
& D3DTA_SELECTMASK
) == D3DTA_DIFFUSE
)
265 return (value
& ~D3DTA_SELECTMASK
) | D3DTA_TFACTOR
;
273 // helpers to set shaders parameters
275 // Set a color in the shader
276 static inline void setShaderParam(CMaterialDrvInfosD3D
*pShader
, uint index
, INT value
)
278 nlassert(pShader
->FXCache
);
279 pShader
->FXCache
->Params
.setColor(index
, value
);
283 static inline void setShaderParam(CMaterialDrvInfosD3D
*pShader
, uint index
, CRGBA color
)
285 nlassert(pShader
->FXCache
);
287 NL_FLOATS(values
, color
);
288 pShader
->FXCache
->Params
.setVector(index
, D3DXVECTOR4(values
[0], values
[1], values
[2], values
[3]));
292 // Set a float value in the shader
293 static inline void setShaderParam(CMaterialDrvInfosD3D
*pShader
, uint index
, FLOAT value
)
295 nlassert(pShader
->FXCache
);
296 pShader
->FXCache
->Params
.setFloat(index
, value
);
300 // Set a vector of floats
301 static inline void setShaderParam(CMaterialDrvInfosD3D
*pShader
, uint index
, float vector
[4])
303 nlassert(pShader
->FXCache
); \
304 pShader
->FXCache
->Params
.setVector(index
, D3DXVECTOR4(vector
[0], vector
[1], vector
[2], vector
[3]));
307 // ***************************************************************************
308 bool CDriverD3D::setupMaterial(CMaterial
&mat
)
310 H_AUTO_D3D(CDriverD3D_setupMaterial
)
311 CMaterialDrvInfosD3D
* pShader
;
314 _NbSetupMaterialCall
++;
317 const uint maxTexture
= inlGetNumTextStages();
320 uint32 touched
=mat
.getTouched();
323 if (!mat
._MatDrvInfo
)
325 // Insert into driver list. (so it is deleted when driver is deleted).
326 ItMatDrvInfoPtrList it
= _MatDrvInfos
.insert(_MatDrvInfos
.end(), (NL3D::IMaterialDrvInfos
*)NULL
);
328 *it
= mat
._MatDrvInfo
= new CMaterialDrvInfosD3D(this, it
);
330 // Must create all OpenGL shader states.
331 touched
= IDRV_TOUCHED_ALL
;
333 pShader
= static_cast<CMaterialDrvInfosD3D
*>((IMaterialDrvInfos
*)(mat
._MatDrvInfo
));
335 // Now we can get the supported shader from the cache.
336 CMaterial::TShader matShader
= _PixelProgramUser
? CMaterial::Program
: mat
.getShader();
338 if (_CurrentMaterialSupportedShader
!= CMaterial::Normal
)
340 // because of multipass, some shader need to disable fog
342 if(_FogEnabled
&& _FogColor
!= _RenderStateCache
[D3DRS_FOGCOLOR
].Value
)
345 setRenderState(D3DRS_FOGCOLOR
, _FogColor
);
349 H_AUTO_D3D(CDriverD3D_setupMaterial_light
)
350 // if the shader has changed since last time
351 if(matShader
!= _CurrentMaterialSupportedShader
)
353 // if current shader is normal shader, then must restore uv routing, because it may have been changed by a previous shader (such as lightmap)
354 if (matShader
== CMaterial::Normal
)
356 for(uint k
= 0; k
< MaxTexture
; ++k
)
358 setTextureIndexUV (k
, _CurrentUVRouting
[k
]);
361 // if old was lightmap, restore standard lighting
362 if(_CurrentMaterialSupportedShader
==CMaterial::LightMap
)
364 _MustRestoreLight
= true;
367 // if new is lightmap, setup dynamic lighting
368 if(matShader
==CMaterial::LightMap
)
370 setupLightMapDynamicLighting(true);
371 _MustRestoreLight
= false;
374 if (mat
.isLighted() && _MustRestoreLight
)
376 setupLightMapDynamicLighting(false);
377 _MustRestoreLight
= false;
380 _CurrentMaterialSupportedShader
= matShader
;
385 // count number of tex stages
386 uint numUsedTexStages
= 0;
387 for(numUsedTexStages
= 0; numUsedTexStages
< IDRV_MAT_MAXTEXTURES
; ++numUsedTexStages
)
389 if (mat
.getTexture(uint8(numUsedTexStages
)) == NULL
) break;
392 H_AUTO_D3D(CDriverD3D_setupMaterial_touchupdate
)
393 if (pShader
->NumUsedTexStages
!= numUsedTexStages
)
395 touched
|= IDRV_TOUCHED_TEXENV
;
397 // Something to setup ?
400 if (touched
& IDRV_TOUCHED_SHADER
)
402 delete pShader
->FXCache
;
403 pShader
->FXCache
= NULL
;
404 // See if material actually needs a fx cache
405 if (mat
.getShader() != CMaterial::Specular
&& mat
.getShader() != CMaterial::Normal
)
407 pShader
->FXCache
= new CFXCache
;
410 /* Exception: if only Textures are modified in the material, no need to "Bind OpenGL States", or even to test
411 for change, because textures are activated alone, see below.
412 No problem with delete/new problem (see below), because in this case, IDRV_TOUCHED_ALL is set (see above).
414 // If any flag is set (but a flag of texture).
415 if(touched
& (~_MaterialAllTextureTouchedFlag
))
417 // Convert Material to driver shader.
418 if (touched
& IDRV_TOUCHED_BLENDFUNC
)
420 pShader
->SrcBlend
= RemapBlendTypeNeL2D3D
[mat
.getSrcBlend()];
421 pShader
->DstBlend
= RemapBlendTypeNeL2D3D
[mat
.getDstBlend()];
423 if (touched
& IDRV_TOUCHED_ZFUNC
)
425 pShader
->ZComp
= RemapZFuncTypeNeL2D3D
[mat
.getZFunc()];
427 if (touched
& IDRV_TOUCHED_LIGHTING
)
429 // Lighted material ?
433 NL_D3DCOLORVALUE_RGBA(pShader
->Material
.Diffuse
, mat
.getDiffuse());
434 NL_D3DCOLORVALUE_RGBA(pShader
->Material
.Ambient
, mat
.getAmbient());
435 NL_D3DCOLORVALUE_RGBA(pShader
->Material
.Emissive
, mat
.getEmissive());
438 CRGBA spec
= mat
.getSpecular();
439 if (spec
!= CRGBA::Black
)
441 NL_D3DCOLORVALUE_RGBA(pShader
->Material
.Specular
, spec
);
442 pShader
->SpecularEnabled
= TRUE
;
443 pShader
->Material
.Power
= mat
.getShininess();
446 setRenderState (D3DRS_SPECULARENABLE
, FALSE
);
451 pShader
->SpecularEnabled
= FALSE
;
454 if (touched
& IDRV_TOUCHED_COLOR
)
457 pShader
->UnlightedColor
= NL_D3DCOLOR_RGBA(mat
.getColor());
459 if (touched
& IDRV_TOUCHED_ALPHA_TEST_THRE
)
461 float alphaRef
= (float)floor(mat
.getAlphaTestThreshold() * 255.f
+ 0.5f
);
462 clamp (alphaRef
, 0.f
, 255.f
);
463 pShader
->AlphaRef
= (DWORD
)alphaRef
;
465 if (touched
& IDRV_TOUCHED_SHADER
)
467 // todo hulud d3d material shaders
468 // Get shader. Fallback to other shader if not supported.
469 // pShader->SupportedShader= getSupportedShader(mat.getShader());
471 if (touched
& IDRV_TOUCHED_TEXENV
)
473 // Build the tex env cache.
474 // Do not do it for Lightmap and per pixel lighting , because done in multipass in a very special fashion.
475 // This avoid the useless multiple change of texture states per lightmapped object.
476 // Don't do it also for Specular because the EnvFunction and the TexGen may be special.
477 if(matShader
== CMaterial::Normal
)
480 for(stage
=0 ; stage
<maxTexture
; ++stage
)
483 pShader
->buildTexEnv (stage
, mat
._TexEnvs
[stage
], mat
.getTexture(uint8(stage
)) != NULL
);
487 if (touched
& (IDRV_TOUCHED_TEXGEN
|IDRV_TOUCHED_ALLTEX
))
490 for(stage
=0 ; stage
<maxTexture
; ++stage
)
492 pShader
->ActivateSpecularWorldTexMT
[stage
] = false;
493 pShader
->ActivateInvViewModelTexMT
[stage
] = false;
496 ITexture
*text
= mat
.getTexture(uint8(stage
));
497 if (text
&& text
->isTextureCube())
499 if (mat
.getTexCoordGen(stage
))
502 pShader
->TexGen
[stage
] = RemapTexGenCubeTypeNeL2D3D
[mat
.getTexCoordGenMode (stage
)];
505 pShader
->ActivateSpecularWorldTexMT
[stage
] = mat
.getTexCoordGenMode (stage
) == CMaterial::TexCoordGenReflect
;
509 pShader
->TexGen
[stage
] = mat
.getTexCoordGen(stage
);
514 if (mat
.getTexCoordGen(stage
))
516 pShader
->TexGen
[stage
] = RemapTexGenTypeNeL2D3D
[mat
.getTexCoordGenMode (stage
)];
519 pShader
->ActivateInvViewModelTexMT
[stage
] = mat
.getTexCoordGenMode (stage
) == CMaterial::TexCoordGenObjectSpace
;
523 pShader
->TexGen
[stage
] = mat
.getTexCoordGen(stage
);
529 // Does this material needs a pixel shader ?
530 if (touched
& (IDRV_TOUCHED_TEXENV
|IDRV_TOUCHED_BLEND
|IDRV_TOUCHED_ALPHA_TEST
))
532 std::fill(pShader
->RGBPipe
, pShader
->RGBPipe
+ IDRV_MAT_MAXTEXTURES
, true);
533 std::fill(pShader
->AlphaPipe
, pShader
->AlphaPipe
+ IDRV_MAT_MAXTEXTURES
, true);
535 pShader
->MultipleConstantNoPixelShader
= false;
536 pShader
->MultiplePerStageConstant
= false;
537 pShader
->VertexColorLighted
= mat
.getLightedVertexColor();
538 bool _needPixelShader
= false;
539 pShader
->ConstantIndex
= 0xff;
540 pShader
->ConstantIndex2
= 0xff;
541 if (matShader
== CMaterial::Normal
)
543 // Need of constants ?
547 needsConstants (numConstants
, firstConstant
, secondConstant
, mat
);
549 pShader
->ConstantIndex
= uint8(firstConstant
);
550 pShader
->ConstantIndex2
= uint8(secondConstant
);
552 // Need a constant color for the diffuse component ?
553 pShader
->NeedsConstantForDiffuse
= needsConstantForDiffuse (mat
);
555 // Need pixel shader ?
556 #ifndef NL_FORCE_PIXEL_SHADER_USE_FOR_NORMAL_SHADERS
557 _needPixelShader
= (numConstants
> 1) || ((numConstants
==1) && pShader
->NeedsConstantForDiffuse
);
558 #else // NL_FORCE_PIXEL_SHADER_USE_FOR_NORMAL_SHADERS
559 _needPixelShader
= true;
560 #endif // NL_FORCE_PIXEL_SHADER_USE_FOR_NORMAL_SHADERS
561 if (_needPixelShader
)
563 // The shader description
564 CNormalShaderDesc normalShaderDesc
;
568 for(stage
=0 ; stage
<(uint
)maxTexture
; stage
++)
571 normalShaderDesc
.StageUsed
[stage
] = mat
.getTexture (uint8(stage
)) != NULL
;
572 normalShaderDesc
.TexEnvMode
[stage
] = mat
.getTexEnvMode(uint8(stage
));
578 // Check, should not occur
579 nlassertex (_PixelShader
, ("STOP : no pixel shader available. Can't render this material."));
580 #endif // NL_DEBUG_D3D
582 // Build the pixel shader
583 pShader
->PixelShader
= buildPixelShader (normalShaderDesc
, false);
584 if (!mat
.isLighted())
585 pShader
->PixelShaderUnlightedNoVertexColor
= buildPixelShader (normalShaderDesc
, true);
587 pShader
->PixelShaderUnlightedNoVertexColor
= NULL
;
591 // Possible configurations are :
592 // unlighted, 1 constant diffuse + 1 per stage constant
593 // unlighted, 2 constants (second constant emulated with material emissive + diffuse), possibly with vertex color (aliased to specular)
595 // If there are no pixel shader then we're likely to have three stage or less
596 pShader
->MultipleConstantNoPixelShader
= true;
597 pShader
->MultiplePerStageConstant
= numConstants
> 1;
599 nlassert(numConstants
<= 2);
601 if (secondConstant
!= 0xffffffff)
603 pShader
->Constant2
= mat
.getTexConstantColor(secondConstant
);
605 pShader
->PixelShader
= NULL
;
606 pShader
->PixelShaderUnlightedNoVertexColor
= NULL
;
607 // compute relevant parts of the pipeline
608 computeRelevantTexEnv(mat
, pShader
->RGBPipe
, pShader
->AlphaPipe
);
613 // compute relevant parts of the pipeline
614 computeRelevantTexEnv(mat
, pShader
->RGBPipe
, pShader
->AlphaPipe
);
620 pShader
->MultipleConstantNoPixelShader
= false;
621 pShader
->NeedsConstantForDiffuse
= false;
624 if (!_needPixelShader
)
626 // Remove the old one
627 pShader
->PixelShader
= NULL
;
628 pShader
->PixelShaderUnlightedNoVertexColor
= NULL
;
629 pShader
->MultipleConstantNoPixelShader
= 0;
633 // Since modified, must rebind all D3D states. And do this also for the delete/new problem.
634 /* If an old material is deleted, _CurrentMaterial is invalid. But this is grave only if a new
635 material is created, with the same pointer (bad luck). Since an newly allocated material always
636 pass here before use, we are sure to avoid any problems.
638 _CurrentMaterial
= NULL
;
641 // Optimize: reset all flags at the end.
642 mat
.clearTouched(0xFFFFFFFF);
643 pShader
->NumUsedTexStages
= numUsedTexStages
;
649 H_AUTO_D3D(CDriverD3D_setupMaterial_bindTexture
)
650 // 2. Setup / Bind Textures.
651 //==========================
652 // Must setup textures each frame. (need to test if touched).
653 // Must separate texture setup and texture activation in 2 "for"...
654 // because setupTexture() may disable all stage.
656 if (matShader
== CMaterial::Normal
657 || ((matShader
== CMaterial::Program
) && (_PixelProgramUser
->features().MaterialFlags
& CProgramFeatures::TextureStages
))
661 for(stage
=0 ; stage
<maxTexture
; ++stage
)
663 ITexture
*text
= mat
.getTexture(uint8(stage
));
665 if (text
!= NULL
&& !setupTexture(*text
))
672 // Activate the textures.
673 // Do not do it for Lightmap and per pixel lighting , because done in multipass in a very special fashion.
674 // This avoid the useless multiple change of texture states per lightmapped object.
675 // Don't do it also for Specular because the EnvFunction and the TexGen may be special.
677 H_AUTO_D3D(CDriverD3D_setupMaterial_normalShaderActivateTextures
)
678 if (matShader
== CMaterial::Normal
679 || ((matShader
== CMaterial::Program
) && (_PixelProgramUser
->features().MaterialFlags
& CProgramFeatures::TextureStages
))
683 for(stage
=0 ; stage
<maxTexture
; ++stage
)
685 ITexture
*text
= mat
.getTexture(uint8(stage
));
688 // activate the texture, or disable texturing if NULL.
689 setTexture(stage
, text
);
693 setTexture (stage
, (LPDIRECT3DBASETEXTURE9
)NULL
);
696 setTextureState (stage
, D3DTSS_COLOROP
, D3DTOP_DISABLE
);
697 //setTextureState (stage, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
698 break; // stage after this one are ignored
702 setTextureState (1, D3DTSS_COLOROP
, D3DTOP_DISABLE
);
706 // Set the texture states
707 if (text
|| (stage
== 0))
709 if (matShader
== CMaterial::Program
)
711 // Do nothing for user pixel shader
713 else if (!pShader
->PixelShader
)
715 // Doesn't use a pixel shader ? Set the textures stages
716 if (pShader
->RGBPipe
[stage
])
718 setTextureState (stage
, D3DTSS_COLOROP
, pShader
->ColorOp
[stage
]);
719 setTextureState (stage
, D3DTSS_COLORARG1
, pShader
->ColorArg1
[stage
]);
720 if (pShader
->NumColorArg
[stage
] > 1)
722 setTextureState (stage
, D3DTSS_COLORARG2
, pShader
->ColorArg2
[stage
]);
723 if (pShader
->NumColorArg
[stage
] > 2)
725 setTextureState (stage
, D3DTSS_COLORARG0
, pShader
->ColorArg0
[stage
]);
729 if (pShader
->AlphaPipe
[stage
])
731 setTextureState (stage
, D3DTSS_ALPHAOP
, pShader
->AlphaOp
[stage
]);
732 setTextureState (stage
, D3DTSS_ALPHAARG1
, pShader
->AlphaArg1
[stage
]);
733 if (pShader
->NumAlphaArg
[stage
] > 1)
735 setTextureState (stage
, D3DTSS_ALPHAARG2
, pShader
->AlphaArg2
[stage
]);
736 if (pShader
->NumAlphaArg
[stage
] > 2)
738 setTextureState (stage
, D3DTSS_ALPHAARG0
, pShader
->AlphaArg0
[stage
]);
742 // If there is one constant and the tfactor is not needed for diffuse, use the tfactor as constant
743 if (pShader
->ConstantIndex
== stage
)
744 setRenderState (D3DRS_TEXTUREFACTOR
, pShader
->ConstantColor
[stage
]);
749 D3DCOLOR_FLOATS (colors
, pShader
->ConstantColor
[stage
]);
750 setPixelShaderConstant (stage
, colors
);
754 // Set texture generator state
755 setTextureIndexMode (stage
, pShader
->TexGen
[stage
]!=D3DTSS_TCI_PASSTHRU
, pShader
->TexGen
[stage
]);
757 // Need user matrix ?
758 bool needUserMtx
= mat
.isUserTexMatEnabled(stage
);
762 // If tex gen mode is used, or a cube texture is used, then use the matrix 'as it'.
763 // Must build a 3x3 matrix for 2D texture coordinates in D3D (which is kind of weird ...)
764 if (pShader
->TexGen
[stage
] != D3DTSS_TCI_PASSTHRU
|| (mat
.getTexture(uint8(stage
)) && mat
.getTexture(uint8(stage
))->isTextureCube()))
766 NL_D3D_MATRIX(userMtx
, mat
.getUserTexMat(stage
));
770 const CMatrix
&m
= mat
.getUserTexMat(stage
);
771 NL_D3D_TEX2D_MATRIX(userMtx
, m
);
775 // Need cubic texture coord generator ?
776 if (pShader
->ActivateSpecularWorldTexMT
[stage
])
778 // Set the driver matrix
779 setTextureState (stage
, D3DTSS_TEXTURETRANSFORMFLAGS
, D3DTTFF_COUNT3
);
781 setMatrix ((D3DTRANSFORMSTATETYPE
)(D3DTS_TEXTURE0
+stage
), _D3DSpecularWorldTex
);
784 D3DXMatrixMultiply (&userMtx
, &_D3DSpecularWorldTex
, &userMtx
);
785 setMatrix ((D3DTRANSFORMSTATETYPE
)(D3DTS_TEXTURE0
+stage
), userMtx
);
788 else if (pShader
->ActivateInvViewModelTexMT
[stage
])
790 // Set the driver matrix
791 setTextureState (stage
, D3DTSS_TEXTURETRANSFORMFLAGS
, D3DTTFF_COUNT3
);
793 setMatrix ((D3DTRANSFORMSTATETYPE
)(D3DTS_TEXTURE0
+stage
), _D3DInvModelView
);
796 D3DXMatrixMultiply (&userMtx
, &_D3DInvModelView
, &userMtx
);
797 setMatrix ((D3DTRANSFORMSTATETYPE
)(D3DTS_TEXTURE0
+stage
), userMtx
);
802 if (_NbNeLTextureStages
== 3)
804 // Fix for Radeon 7xxx
805 // In some situation, texture transform stays enabled after a material change, so enable it all the
806 // time and use identity matrix instead of the D3DTTFF_DISABLE flag
807 setTextureState (stage
, D3DTSS_TEXTURETRANSFORMFLAGS
, D3DTTFF_COUNT3
);
808 setMatrix ((D3DTRANSFORMSTATETYPE
)(D3DTS_TEXTURE0
+stage
), needUserMtx
? userMtx
: _D3DMatrixIdentity
);
812 // Set the driver matrix
815 setTextureState (stage
, D3DTSS_TEXTURETRANSFORMFLAGS
, D3DTTFF_COUNT3
);
816 setMatrix ((D3DTRANSFORMSTATETYPE
)(D3DTS_TEXTURE0
+stage
), userMtx
);
820 setTextureState (stage
, D3DTSS_TEXTURETRANSFORMFLAGS
, D3DTTFF_DISABLE
);
824 if (!text
&& stage
== 0) break;
829 if (_CurrentMaterial
!= &mat
)
831 // Material has changed ?
832 // Restore fog state to its current value
834 H_AUTO_D3D(CDriverD3D_setupMaterial_updateFog
)
835 setRenderState (D3DRS_FOGENABLE
, _FogEnabled
?TRUE
:FALSE
);
839 const uint32 flags
= mat
.getFlags();
842 _DoubleSided
= (flags
&IDRV_MAT_DOUBLE_SIDED
)!=0;
845 H_AUTO_D3D(CDriverD3D_setupMaterial_handleBackSide
)
847 if (_CullMode
== CCW
)
849 setRenderState (D3DRS_CULLMODE
, _DoubleSided
?D3DCULL_NONE
:_InvertCullMode
?D3DCULL_CCW
:D3DCULL_CW
);
853 setRenderState (D3DRS_CULLMODE
, _DoubleSided
?D3DCULL_NONE
:_InvertCullMode
?D3DCULL_CW
:D3DCULL_CCW
);
858 bool blend
= (flags
&IDRV_MAT_BLEND
) != 0;
860 H_AUTO_D3D(CDriverD3D_setupMaterial_updateBlend
)
864 setRenderState (D3DRS_ALPHABLENDENABLE
, TRUE
);
865 setRenderState (D3DRS_SRCBLEND
, pShader
->SrcBlend
);
866 setRenderState (D3DRS_DESTBLEND
, pShader
->DstBlend
);
869 setRenderState (D3DRS_ALPHABLENDENABLE
, FALSE
);
872 if (flags
&IDRV_MAT_ALPHA_TEST
)
874 setRenderState (D3DRS_ALPHATESTENABLE
, TRUE
);
875 setRenderState (D3DRS_ALPHAREF
, pShader
->AlphaRef
);
876 setRenderState (D3DRS_ALPHAFUNC
, D3DCMP_GREATER
);
879 setRenderState (D3DRS_ALPHATESTENABLE
, FALSE
);
883 H_AUTO_D3D(CDriverD3D_setupMaterial_updateZBuffer
)
885 setRenderState (D3DRS_ZWRITEENABLE
, (flags
&IDRV_MAT_ZWRITE
)?TRUE
:FALSE
);
886 setRenderState (D3DRS_ZFUNC
, pShader
->ZComp
);
887 float flt
= mat
.getZBias () * _OODeltaZ
;
888 setRenderState (D3DRS_DEPTHBIAS
, FTODW(flt
));
892 H_AUTO_D3D(CDriverD3D_setupMaterial_updateLighting
)
896 setRenderState (D3DRS_LIGHTING
, TRUE
);
897 setMaterialState(pShader
->Material
);
901 setRenderState (D3DRS_LIGHTING
, FALSE
);
903 // Set pixel shader unlighted color ?
904 if (pShader
->PixelShader
)
907 D3DCOLOR_FLOATS(colors
,pShader
->UnlightedColor
);
908 setPixelShaderConstant (5, colors
);
911 setRenderState (D3DRS_SPECULARENABLE
, pShader
->SpecularEnabled
);
915 H_AUTO_D3D(CDriverD3D_setupMaterial_updateVertexColorLighted
)
916 // Active vertex color if not lighted or vertex color forced
917 if (mat
.isLightedVertexColor ())
919 setRenderState (D3DRS_COLORVERTEX
, TRUE
);
921 setRenderState (D3DRS_DIFFUSEMATERIALSOURCE
, D3DMCS_COLOR1
);
925 setRenderState (D3DRS_COLORVERTEX
, FALSE
);
926 setRenderState (D3DRS_DIFFUSEMATERIALSOURCE
, D3DMCS_MATERIAL
);
931 H_AUTO_D3D(CDriverD3D_setupMaterial_disableFog
)
932 // Disable fog if dest blend is ONE
933 if (blend
&& (pShader
->DstBlend
== D3DBLEND_ONE
))
935 setRenderState (D3DRS_FOGENABLE
, FALSE
);
939 // Set the good shader
942 case CMaterial::Normal
:
944 H_AUTO_D3D(CDriverD3D_setupMaterial_setupNormalshader
)
948 /* If unlighted trick is needed, set the shader later */
949 if (!pShader
->NeedsConstantForDiffuse
&& _PixelProgram
)
950 setPixelShader (pShader
->PixelShader
);
953 case CMaterial::LightMap
:
955 H_AUTO_D3D(CDriverD3D_setupMaterial_setupLightmapShader
)
956 setPixelShader (NULL
);
957 static const uint32 RGBMaskPacked
= CRGBA(255,255,255,0).getPacked();
959 if (_NbNeLTextureStages
== 3)
961 touchRenderVariable(&_MaterialState
);
964 // if the dynamic lightmap light has changed since the last render (should not happen), resetup
965 // normal way is that setupLightMapDynamicLighting() is called at begin of setupMaterial() if shader different from prec
966 if(_LightMapDynamicLightDirty
)
967 setupLightMapDynamicLighting(true);
969 // Count the lightmaps
971 uint lightmapCount
= 0;
972 uint lightmapMask
= 0;
973 for(lightmap
=0 ; lightmap
<(sint
)mat
._LightMaps
.size() ; lightmap
++)
975 if (mat
._LightMaps
[lightmap
].Factor
.getPacked() & RGBMaskPacked
)
978 lightmapMask
|= 1<<lightmap
;
983 // activate the appropriate shader
986 if(mat
._LightMapsMulx2
)
988 switch (lightmapCount
)
990 case 0: activeShader (&_ShaderLightmap0BlendX2
); break;
991 case 1: activeShader (&_ShaderLightmap1BlendX2
); break;
992 case 2: activeShader (&_ShaderLightmap2BlendX2
); break;
993 case 3: activeShader (&_ShaderLightmap3BlendX2
); break;
994 default: activeShader (&_ShaderLightmap4BlendX2
); break;
999 switch (lightmapCount
)
1001 case 0: activeShader (&_ShaderLightmap0Blend
); break;
1002 case 1: activeShader (&_ShaderLightmap1Blend
); break;
1003 case 2: activeShader (&_ShaderLightmap2Blend
); break;
1004 case 3: activeShader (&_ShaderLightmap3Blend
); break;
1005 default: activeShader (&_ShaderLightmap4Blend
); break;
1011 if(mat
._LightMapsMulx2
)
1013 switch (lightmapCount
)
1015 case 0: activeShader (&_ShaderLightmap0X2
); break;
1016 case 1: activeShader (&_ShaderLightmap1X2
); break;
1017 case 2: activeShader (&_ShaderLightmap2X2
); break;
1018 case 3: activeShader (&_ShaderLightmap3X2
); break;
1019 default: activeShader (&_ShaderLightmap4X2
); break;
1024 switch (lightmapCount
)
1026 case 0: activeShader (&_ShaderLightmap0
); break;
1027 case 1: activeShader (&_ShaderLightmap1
); break;
1028 case 2: activeShader (&_ShaderLightmap2
); break;
1029 case 3: activeShader (&_ShaderLightmap3
); break;
1030 default: activeShader (&_ShaderLightmap4
); break;
1035 // Setup the texture
1036 ITexture
*texture
= mat
.getTexture(0);
1037 if (!setShaderTexture (0, texture
, pShader
->FXCache
))
1041 nlassert (_CurrentShader
);
1042 CShaderDrvInfosD3D
*shaderInfo
= static_cast<CShaderDrvInfosD3D
*>((IShaderDrvInfos
*)_CurrentShader
->_DrvInfo
);
1043 // ID3DXEffect *effect = shaderInfo->Effect;
1046 // Set the ambiant for 8Bit Light Compression
1048 // Sum ambiant of all active lightmaps.
1052 for(lightmap
=0 ; lightmap
<(sint
)mat
._LightMaps
.size() ; lightmap
++)
1054 if (lightmapMask
& (1<<lightmap
))
1057 // must mul them by their respective mapFactor too
1058 CRGBA ambFactor
= mat
._LightMaps
[wla
].Factor
;
1059 CRGBA lmcAmb
= mat
._LightMaps
[wla
].LMCAmbient
;
1060 r
+= ((uint32
)ambFactor
.R
* ((uint32
)lmcAmb
.R
+(lmcAmb
.R
>>7))) >>8;
1061 g
+= ((uint32
)ambFactor
.G
* ((uint32
)lmcAmb
.G
+(lmcAmb
.G
>>7))) >>8;
1062 b
+= ((uint32
)ambFactor
.B
* ((uint32
)lmcAmb
.B
+(lmcAmb
.B
>>7))) >>8;
1065 r
= std::min(r
, (uint32
)255);
1066 g
= std::min(g
, (uint32
)255);
1067 b
= std::min(b
, (uint32
)255);
1068 CRGBA
lmcAmbient((uint8
)r
,(uint8
)g
,(uint8
)b
,255);
1070 // Set into FX shader
1071 setShaderParam(pShader
, 0, (INT
) NL_D3DCOLOR_RGBA(lmcAmbient
));
1072 if (shaderInfo
->FactorHandle
[0])
1074 setShaderParam(pShader
, 0, lmcAmbient
);
1079 // Set the lightmaps
1081 for(lightmap
=0 ; lightmap
<(sint
)mat
._LightMaps
.size() ; lightmap
++)
1083 if (lightmapMask
& (1<<lightmap
))
1085 // Set the lightmap texture
1086 ITexture
*text
= mat
._LightMaps
[lightmap
].Texture
;
1087 if (text
!= NULL
&& !setShaderTexture (lightmapCount
+1, text
, pShader
->FXCache
))
1090 // Get the lightmap color factor, and mul by lmcDiffuse compression
1091 CRGBA lmapFactor
= mat
._LightMaps
[lightmap
].Factor
;
1092 CRGBA lmcDiff
= mat
._LightMaps
[lightmap
].LMCDiffuse
;
1093 lmapFactor
.R
= (uint8
)(((uint32
)lmapFactor
.R
* ((uint32
)lmcDiff
.R
+(lmcDiff
.R
>>7))) >>8);
1094 lmapFactor
.G
= (uint8
)(((uint32
)lmapFactor
.G
* ((uint32
)lmcDiff
.G
+(lmcDiff
.G
>>7))) >>8);
1095 lmapFactor
.B
= (uint8
)(((uint32
)lmapFactor
.B
* ((uint32
)lmcDiff
.B
+(lmcDiff
.B
>>7))) >>8);
1098 // Set the lightmap color factor into shader
1099 setShaderParam(pShader
, lightmapCount
+1, (INT
) NL_D3DCOLOR_RGBA(lmapFactor
));
1100 if (shaderInfo
->FactorHandle
[lightmapCount
+1])
1102 setShaderParam(pShader
, lightmapCount
+1, lmapFactor
);
1109 case CMaterial::Specular
:
1111 H_AUTO_D3D(CDriverD3D_setupMaterial_setupSpecularShader
)
1113 activeShader (NULL
);
1114 setPixelShader (NULL
);
1116 // Setup the texture
1117 ITexture
*texture
= mat
.getTexture(0);
1118 if (!texture
|| !setupTexture (*texture
))
1120 setTexture (0, texture
);
1122 // Setup the texture
1123 texture
= mat
.getTexture(1);
1124 if (!texture
|| !setupTexture (*texture
))
1126 setTexture (1, texture
);
1128 // Set the driver matrix
1129 if (texture
->isTextureCube())
1131 setTextureIndexMode (1, true, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
);
1132 setTextureState (1, D3DTSS_TEXTURETRANSFORMFLAGS
, D3DTTFF_COUNT3
);
1133 setMatrix ((D3DTRANSFORMSTATETYPE
)(D3DTS_TEXTURE0
+1), _D3DSpecularWorldTex
);
1136 setRenderState (D3DRS_LIGHTING
, mat
.isLighted()?TRUE
:FALSE
);
1137 setRenderState (D3DRS_DIFFUSEMATERIALSOURCE
, D3DMCS_MATERIAL
);
1138 setTextureState (0, D3DTSS_COLOROP
, D3DTOP_MODULATE
);
1139 setTextureState (0, D3DTSS_COLORARG1
, D3DTA_DIFFUSE
);
1140 setTextureState (0, D3DTSS_COLORARG2
, D3DTA_TEXTURE
);
1141 setTextureState (0, D3DTSS_ALPHAOP
, D3DTOP_SELECTARG1
);
1142 setTextureState (0, D3DTSS_ALPHAARG1
, D3DTA_TEXTURE
);
1143 setTextureState (1, D3DTSS_COLOROP
, D3DTOP_MULTIPLYADD
);
1144 setTextureState (1, D3DTSS_COLORARG0
, D3DTA_CURRENT
);
1145 setTextureState (1, D3DTSS_COLORARG1
, D3DTA_TEXTURE
);
1146 setTextureState (1, D3DTSS_COLORARG2
, D3DTA_CURRENT
|D3DTA_ALPHAREPLICATE
);
1147 setTextureState (1, D3DTSS_ALPHAOP
, D3DTOP_SELECTARG1
);
1148 setTextureState (1, D3DTSS_ALPHAARG1
, D3DTA_DIFFUSE
);
1152 case CMaterial::Cloud
:
1154 H_AUTO_D3D(CDriverD3D_setupMaterial_setupCloudShader
)
1155 activeShader (&_ShaderCloud
);
1158 nlassert (_CurrentShader
);
1159 // CShaderDrvInfosD3D *shaderInfo = static_cast<CShaderDrvInfosD3D*>((IShaderDrvInfos*)_CurrentShader->_DrvInfo);
1162 // ID3DXEffect *effect = shaderInfo->Effect;
1163 CRGBA color
= mat
.getColor();
1167 setShaderParam(pShader
, 0, color
);
1170 if (!setShaderTexture (0, mat
.getTexture(0), pShader
->FXCache
) || !setShaderTexture (1, mat
.getTexture(1), pShader
->FXCache
))
1174 case CMaterial::Water
:
1176 H_AUTO_D3D(CDriverD3D_setupMaterial_setupWaterShader
)
1177 activeShader(mat
.getTexture(3) ? &_ShaderWaterDiffuse
: &_ShaderWaterNoDiffuse
);
1179 nlassert (_CurrentShader
);
1180 // CShaderDrvInfosD3D *shaderInfo = static_cast<CShaderDrvInfosD3D*>((IShaderDrvInfos*)_CurrentShader->_DrvInfo);
1182 if (_PixelShaderVersion
>= D3DPS_VERSION(1, 4))
1184 ITexture
*tex
= mat
.getTexture(0);
1187 tex
->setUploadFormat(ITexture::RGBA8888
);
1188 // if (tex->isBumpMap())
1190 // CTextureBump *tb = static_cast<CTextureBump *>(tex);
1193 setShaderTexture (0, tex
, pShader
->FXCache
);
1196 ITexture
*tex
= mat
.getTexture(1);
1199 if (_PixelShaderVersion
< D3DPS_VERSION(1, 4))
1201 tex
->setUploadFormat(ITexture::DsDt
);
1202 // if (tex->isBumpMap())
1204 // CTextureBump *tb = static_cast<CTextureBump *>(tex);
1209 tex
->setUploadFormat(ITexture::RGBA8888
);
1210 // if (tex->isBumpMap())
1212 // CTextureBump *tb = static_cast<CTextureBump *>(tex);
1216 setShaderTexture (1, tex
, pShader
->FXCache
);
1219 tex
= mat
.getTexture(2);
1223 setShaderTexture (2, tex
, pShader
->FXCache
);
1225 tex
= mat
.getTexture(3);
1229 setShaderTexture (3, tex
, pShader
->FXCache
);
1232 // Set the constants
1233 // ID3DXEffect *effect = shaderInfo->Effect;
1234 if (_PixelShaderVersion
< D3DPS_VERSION(2, 0))
1236 if (_PixelShaderVersion
< D3DPS_VERSION(1, 4))
1238 if (mat
.getTexture(1) && mat
.getTexture(1)->isBumpMap())
1240 float factor
= NLMISC::safe_cast
<CTextureBump
*>(mat
.getTexture(1))->getNormalizationFactor();
1241 setShaderParam(pShader
, 0, factor
);
1245 setShaderParam(pShader
, 0, 1.f
);
1250 if (mat
.getTexture(0) && mat
.getTexture(0)->isBumpMap())
1252 float factor
= NLMISC::safe_cast
<CTextureBump
*>(mat
.getTexture(0))->getNormalizationFactor();
1253 float cst
[4] = { factor
, factor
, factor
, 0.f
};
1254 setShaderParam(pShader
, 0, cst
);
1258 float cst
[4] = { 1.f
, 1.f
, 1.f
, 0.f
};
1259 setShaderParam(pShader
, 0, cst
);
1262 if (mat
.getTexture(1) && mat
.getTexture(1)->isBumpMap())
1264 float factor
= NLMISC::safe_cast
<CTextureBump
*>(mat
.getTexture(1))->getNormalizationFactor();
1265 float cst
[4] = { factor
, factor
, factor
, 0.f
};
1266 setShaderParam(pShader
, 1, cst
);
1270 float cst
[4] = { 1.f
, 1.f
, 1.f
, 0.f
};
1271 setShaderParam(pShader
, 1, cst
);
1277 // setup the constant
1278 if (mat
.getTexture(0) && mat
.getTexture(0)->isBumpMap())
1280 float factor
= 0.25f
* NLMISC::safe_cast
<CTextureBump
*>(mat
.getTexture(0))->getNormalizationFactor();
1281 float bmScale
[4] = { -1.f
* factor
, -1.f
* factor
, 2.f
* factor
, 0.f
};
1282 setShaderParam(pShader
, 0, bmScale
);
1286 float bmScale
[4] = { -1.f
, -1.f
, 2.f
, 0.f
};
1287 setShaderParam(pShader
, 0, bmScale
);
1289 // setup the constant
1290 if (mat
.getTexture(1) && mat
.getTexture(1)->isBumpMap())
1292 float factor
= NLMISC::safe_cast
<CTextureBump
*>(mat
.getTexture(1))->getNormalizationFactor();
1293 float bmScale
[4] = { -1.f
* factor
, -1.f
* factor
, 2.f
* factor
, 0.f
};
1294 setShaderParam(pShader
, 1, bmScale
);
1298 float bmScale
[4] = { -1.f
, -1.f
, 2.f
, 0.f
};
1299 setShaderParam(pShader
, 1, bmScale
);
1303 break; // CMaterial::Water
1304 case CMaterial::Program
:
1306 H_AUTO_D3D(CDriverD3D_setupMaterial_setupProgramshader
)
1307 // No material shader
1313 // New material setuped
1314 _CurrentMaterial
= &mat
;
1317 _CurrentMaterialInfo
= pShader
;
1323 // ***************************************************************************
1324 // Add one set to another
1325 static void add(std::set
<uint
> &dest
, const std::set
<uint
> &toAdd
)
1327 for (std::set
<uint
>::const_iterator it
= toAdd
.begin(); it
!= toAdd
.end(); ++it
)
1334 // ***************************************************************************
1335 bool CDriverD3D::needsConstants (uint
&numConstant
, uint
&firstConstant
, uint
&secondConstant
, CMaterial
&mat
)
1337 H_AUTO_D3D(CDriverD3D_needsConstants
)
1338 firstConstant
= 0xffffffff;
1339 secondConstant
= 0xffffffff;
1340 // Of course std::set could be avoided, but much simpler that way
1341 std::set
<uint
> rgbPipe
[2]; // constant used to compute the rgb component
1342 std::set
<uint
> alphaPipe
[2]; // constant used to compute the alpha component
1343 for (uint i
=0; i
<IDRV_MAT_MAXTEXTURES
; i
++)
1345 if (!mat
.getTexture(uint8(i
))) break;
1346 CMaterial::CTexEnv texEnv
;
1347 texEnv
.EnvPacked
= mat
.getTexEnvMode(i
);
1349 alphaPipe
[1].clear();
1350 if (texEnv
.Env
.OpRGB
== CMaterial::InterpolateConstant
)
1352 rgbPipe
[1].insert(i
);
1354 if (texEnv
.Env
.OpRGB
== CMaterial::InterpolatePrevious
)
1356 rgbPipe
[1] = rgbPipe
[0];
1358 if (texEnv
.Env
.OpAlpha
== CMaterial::InterpolateConstant
)
1360 alphaPipe
[1].insert(i
);
1362 if (texEnv
.Env
.OpAlpha
== CMaterial::InterpolatePrevious
)
1364 alphaPipe
[1] = alphaPipe
[0];
1366 for(uint l
= 0; l
< OpNumArg
[texEnv
.Env
.OpRGB
]; ++l
)
1369 if (texEnv
.getColorArg(l
) == CMaterial::Constant
)
1371 rgbPipe
[1].insert(i
);
1374 if (texEnv
.getColorArg(l
) == CMaterial::Previous
)
1376 if (texEnv
.getColorOperand(l
) == CMaterial::SrcColor
|| texEnv
.getColorOperand(l
) == CMaterial::InvSrcColor
)
1378 add(rgbPipe
[1], rgbPipe
[0]);
1380 if (texEnv
.getColorOperand(l
) == CMaterial::SrcAlpha
|| texEnv
.getColorOperand(l
) == CMaterial::InvSrcColor
)
1382 add(rgbPipe
[1], alphaPipe
[0]);
1386 for(uint l
= 0; l
< OpNumArg
[texEnv
.Env
.OpAlpha
]; ++l
)
1389 if (texEnv
.getAlphaArg(l
) == CMaterial::Constant
)
1391 alphaPipe
[1].insert(i
);
1393 if (texEnv
.getAlphaArg(l
) == CMaterial::Previous
)
1395 add(alphaPipe
[1], alphaPipe
[0]);
1398 alphaPipe
[0].swap(alphaPipe
[1]);
1399 rgbPipe
[0].swap(rgbPipe
[1]);
1401 bool alphaRelevant
= false;
1402 if (mat
.getAlphaTest())
1404 alphaRelevant
= true;
1409 // see if alpha is relevant to blending
1410 if (mat
.getSrcBlend() == CMaterial::srcalpha
||
1411 mat
.getSrcBlend() == CMaterial::invsrcalpha
||
1412 mat
.getDstBlend() == CMaterial::srcalpha
||
1413 mat
.getDstBlend() == CMaterial::invsrcalpha
1416 alphaRelevant
= true;
1421 alphaPipe
[0].clear();
1423 add(rgbPipe
[0], alphaPipe
[0]);
1424 numConstant
= (uint
)rgbPipe
[0].size();
1427 firstConstant
= *(rgbPipe
[0].begin());
1428 if (numConstant
== 2)
1430 secondConstant
= *(++rgbPipe
[0].begin());
1432 // can emulate up to 2 constants only ...
1438 // ***************************************************************************
1439 bool CDriverD3D::needsConstantForDiffuse (CMaterial
&mat
)
1441 H_AUTO_D3D(CDriverD3D_needsConstantForDiffuse
)
1442 // If lighted, don't need the tfactor
1443 if (mat
.isLighted())
1445 if (mat
.getTexture(0) == NULL
) return true; // RGB diffuse is output
1446 // Inspect the RGB & alpha pipe : if a diffuse value manage to propagate to the last stage, and if the pipe is required for
1447 // fragment blending, then diffuse is useful in the shader, and thus must be replaced by constant for unlighted material
1448 bool propRGB
= false; // diffuse RGB propagated to current stage
1449 bool propAlpha
= false; // diffuse RGB propagated to current stage
1450 for (uint i
=0; i
<IDRV_MAT_MAXTEXTURES
; i
++)
1452 if (!mat
.getTexture(uint8(i
))) break;
1453 CMaterial::CTexEnv texEnv
;
1454 texEnv
.EnvPacked
= mat
.getTexEnvMode(i
);
1455 bool newPropRGB
= false;
1456 bool newPropAlpha
= false;
1457 if (texEnv
.Env
.OpRGB
== CMaterial::InterpolateDiffuse
|| (texEnv
.Env
.OpRGB
== CMaterial::InterpolatePrevious
&& i
== 0))
1461 if (texEnv
.Env
.OpRGB
== CMaterial::InterpolatePrevious
)
1463 if (propAlpha
) newPropRGB
= true;
1465 if (texEnv
.Env
.OpAlpha
== CMaterial::InterpolateDiffuse
|| (texEnv
.Env
.OpAlpha
== CMaterial::InterpolatePrevious
&& i
== 0))
1467 newPropAlpha
= true;
1469 if (texEnv
.Env
.OpAlpha
== CMaterial::InterpolatePrevious
)
1471 if (propAlpha
) newPropAlpha
= true;
1473 for(uint l
= 0; l
< OpNumArg
[texEnv
.Env
.OpRGB
]; ++l
)
1476 if (texEnv
.getColorArg(l
) == CMaterial::Diffuse
|| (texEnv
.getColorArg(l
) == CMaterial::Previous
&& i
== 0))
1481 if (texEnv
.getColorArg(l
) == CMaterial::Previous
)
1483 if (texEnv
.getColorOperand(l
) == CMaterial::SrcColor
|| texEnv
.getColorOperand(l
) == CMaterial::InvSrcColor
)
1485 if (propRGB
) newPropRGB
= true;
1487 if (texEnv
.getColorOperand(l
) == CMaterial::SrcAlpha
|| texEnv
.getColorOperand(l
) == CMaterial::InvSrcColor
)
1489 if (propAlpha
) newPropAlpha
= true;
1494 for(uint l
= 0; l
< OpNumArg
[texEnv
.Env
.OpAlpha
]; ++l
)
1496 if (texEnv
.getAlphaArg(l
) == CMaterial::Diffuse
|| (texEnv
.getAlphaArg(l
) == CMaterial::Previous
&& i
== 0))
1498 newPropAlpha
= true;
1501 if (texEnv
.getAlphaArg(l
) == CMaterial::Previous
)
1503 if (propAlpha
) newPropAlpha
= true;
1507 propRGB
= newPropRGB
;
1508 propAlpha
= newPropAlpha
;
1510 if (propRGB
) return true;
1513 if (mat
.getAlphaTest()) return true;
1516 // see if alpha is relevant to blending
1517 if (mat
.getSrcBlend() == CMaterial::srcalpha
||
1518 mat
.getSrcBlend() == CMaterial::invsrcalpha
||
1519 mat
.getDstBlend() == CMaterial::srcalpha
||
1520 mat
.getDstBlend() == CMaterial::invsrcalpha
1531 // ***************************************************************************
1532 void CDriverD3D::computeRelevantTexEnv(CMaterial
&mat
, bool rgbPipe
[IDRV_MAT_MAXTEXTURES
], bool alphaPipe
[IDRV_MAT_MAXTEXTURES
])
1534 // TODO : see if worth the trouble (during profile, I see a very small gain : 0.03% less time spent in driver for my test scene)
1535 // TODO : could be more efficient if I could see when alpha is useless...
1536 H_AUTO_D3D(CDriverD3D_computeRelevantTexEnv
)
1538 static bool testStuff
= false;
1541 std::fill(rgbPipe
, rgbPipe
+ IDRV_MAT_MAXTEXTURES
, true);
1542 std::fill(alphaPipe
, alphaPipe
+ IDRV_MAT_MAXTEXTURES
, true);
1547 for (uint i
=0; i
<IDRV_MAT_MAXTEXTURES
; i
++)
1549 if (mat
.getTexture(uint8(i
)) == NULL
) break;
1552 std::fill(rgbPipe
, rgbPipe
+ IDRV_MAT_MAXTEXTURES
, false);
1553 std::fill(alphaPipe
, alphaPipe
+ IDRV_MAT_MAXTEXTURES
, false);
1554 bool rgbUsed
= true;
1555 bool alphaUsed
= false;
1558 if (mat.getAlphaTest())
1565 // see if alpha is relevant to blending
1566 if (mat.getSrcBlend() == CMaterial::srcalpha ||
1567 mat.getSrcBlend() == CMaterial::invsrcalpha ||
1568 mat.getDstBlend() == CMaterial::srcalpha ||
1569 mat.getDstBlend() == CMaterial::invsrcalpha
1581 // just diffuse material, no textures
1582 rgbPipe
[0] = rgbUsed
;
1583 alphaPipe
[0] = alphaUsed
;
1586 sint currStage
= numStages
- 1;
1587 while (currStage
>= 0)
1589 rgbPipe
[currStage
] = rgbUsed
;
1590 alphaPipe
[currStage
] = alphaUsed
;
1591 bool newAlphaUsed
= false;
1592 bool newRGBUsed
= false;
1593 CMaterial::CTexEnv texEnv
;
1594 texEnv
.EnvPacked
= mat
.getTexEnvMode(currStage
);
1595 // test for rgb propagate
1598 if (texEnv
.Env
.OpRGB
== CMaterial::InterpolatePrevious
)
1600 newAlphaUsed
= true;
1602 for(uint l
= 0; l
< OpNumArg
[texEnv
.Env
.OpRGB
]; ++l
)
1604 if (texEnv
.getColorArg(l
) == CMaterial::Previous
||
1605 (currStage
!= 0 && texEnv
.getColorArg(l
) == CMaterial::Texture
&& mat
.getTexEnvOpRGB(currStage
- 1) == CMaterial::EMBM
)
1608 if (texEnv
.getColorOperand(l
) == CMaterial::SrcColor
|| texEnv
.getColorOperand(l
) == CMaterial::InvSrcColor
)
1612 if (texEnv
.getColorOperand(l
) == CMaterial::SrcAlpha
|| texEnv
.getColorOperand(l
) == CMaterial::InvSrcAlpha
)
1614 newAlphaUsed
= true;
1619 // test for alpha propagate
1622 if (texEnv
.Env
.OpAlpha
== CMaterial::InterpolatePrevious
)
1624 newAlphaUsed
= true;
1626 for(uint l
= 0; l
< OpNumArg
[texEnv
.Env
.OpAlpha
]; ++l
)
1628 if (texEnv
.getAlphaArg(l
) == CMaterial::Previous
||
1629 (currStage
!= 0 && texEnv
.getAlphaArg(l
) == CMaterial::Texture
&& mat
.getTexEnvOpRGB(currStage
- 1) == CMaterial::EMBM
)
1632 if (texEnv
.getAlphaOperand(l
) == CMaterial::SrcAlpha
|| texEnv
.getAlphaOperand(l
) == CMaterial::InvSrcAlpha
)
1634 newAlphaUsed
= true;
1639 alphaUsed
= newAlphaUsed
;
1640 rgbUsed
= newRGBUsed
;
1647 // ***************************************************************************
1649 const char *RemapPSInstructions
[CMaterial::TexOperatorCount
]=
1655 "lrp", // InterpolateTexture
1656 "lrp", // InterpolatePrevious
1657 "lrp", // InterpolateDiffuse
1658 "lrp", // InterpolateConstant
1663 // ***************************************************************************
1665 const char *RemapPSThirdArguments
[CMaterial::TexOperatorCount
][2]=
1667 {"", ""}, // Replace
1668 {"", ""}, // Modulate
1670 {"", ""}, // AddSigned
1671 {"t", "t"}, // InterpolateTexture
1672 {"r0", "r0"}, // InterpolatePrevious
1673 {"v0", "c5"}, // InterpolateDiffuse
1674 {"c", "c"}, // InterpolateConstant
1676 {"", ""} // MAD (not used)
1679 // ***************************************************************************
1682 const char *RemapPSThirdArguments0
[CMaterial::TexOperatorCount
][2]=
1684 {"", ""}, // Replace
1685 {"", ""}, // Modulate
1687 {"", ""}, // AddSigned
1688 {"t", "t"}, // InterpolateTexture
1689 {"v0", "c5"}, // InterpolatePrevious
1690 {"v0", "c5"}, // InterpolateDiffuse
1691 {"c", "c"}, // InterpolateConstant
1693 {"", ""} // MAD (not used)
1696 // ***************************************************************************
1698 const char *RemapPSSecondRegisterModificator
[CMaterial::TexOperatorCount
]=
1703 "_bias", // AddSigned
1704 "", // InterpolateTexture
1705 "", // InterpolatePrevious
1706 "", // InterpolateDiffuse
1707 "", // InterpolateConstant
1712 // ***************************************************************************
1714 const char *RemapPSArguments
[CMaterial::TexOperatorCount
][2]=
1716 {"t", "t"}, // Texture
1717 {"r0", "r0"}, // Previous
1718 {"v0", "c5"}, // Diffuse
1719 {"c", "c"}, // Constant
1722 // ***************************************************************************
1725 const char *RemapPSArguments0
[CMaterial::TexOperatorCount
][2]=
1727 {"t", "t"}, // Texture
1728 {"v0", "c5"}, // Previous
1729 {"v0", "c5"}, // Diffuse
1730 {"c", "c"}, // Constant
1733 // ***************************************************************************
1735 void buildColorOperation (string
&dest
, const char *prefix
, const char *destSizzle
, uint stage
, CMaterial::TTexOperator
&op
, CMaterial::TTexSource src0
, CMaterial::TTexSource src1
, CMaterial::TTexSource src2
, CMaterial::TTexOperand
&op0
, CMaterial::TTexOperand
&op1
, CMaterial::TTexOperand
&op2
, bool unlightedNoVertexColor
)
1737 H_AUTO_D3D(buildColorOperation
)
1742 dest
+= RemapPSInstructions
[op
];
1744 // Destination argument
1748 // Need a third argument ?
1749 if (op
!= CMaterial::Mad
)
1751 const char *remapPSThirdArguments
= ((stage
==0)?RemapPSThirdArguments0
:RemapPSThirdArguments
)[op
][(uint
)unlightedNoVertexColor
];
1752 if (remapPSThirdArguments
[0] != 0)
1755 dest
+= remapPSThirdArguments
;
1757 // Need stage postfix ?
1758 if ((op
== CMaterial::InterpolateTexture
) || (op
== CMaterial::InterpolateConstant
))
1759 dest
+= toString (stage
);
1761 // Add alpha swizzle
1770 if ((op0
== CMaterial::InvSrcColor
) || (op0
== CMaterial::InvSrcAlpha
))
1773 // The first operator argument
1774 dest
+= ((stage
==0)?RemapPSArguments0
:RemapPSArguments
)[src0
][(uint
)unlightedNoVertexColor
];
1776 // Need stage postfix ?
1777 if ((src0
== CMaterial::Texture
) || (src0
== CMaterial::Constant
))
1778 dest
+= toString (stage
);
1781 if ((op0
== CMaterial::SrcAlpha
) || (op0
== CMaterial::InvSrcAlpha
))
1784 if (op
!= CMaterial::Replace
)
1789 if ((op1
== CMaterial::InvSrcColor
) || (op1
== CMaterial::InvSrcAlpha
))
1792 dest
+= ((stage
==0)?RemapPSArguments0
:RemapPSArguments
)[src1
][(uint
)unlightedNoVertexColor
];
1794 // Second register modifier
1795 dest
+= RemapPSSecondRegisterModificator
[op
];
1797 // Need stage postfix ?
1798 if ((src1
== CMaterial::Texture
) || (src1
== CMaterial::Constant
))
1799 dest
+= toString (stage
);
1802 if ((op1
== CMaterial::SrcAlpha
) || (op1
== CMaterial::InvSrcAlpha
))
1806 if (op
== CMaterial::Mad
)
1811 if ((op2
== CMaterial::InvSrcColor
) || (op2
== CMaterial::InvSrcAlpha
))
1814 dest
+= ((stage
==0)?RemapPSArguments0
:RemapPSArguments
)[src2
][(uint
)unlightedNoVertexColor
];
1816 // Second register modifier
1817 dest
+= RemapPSSecondRegisterModificator
[op
];
1819 // Need stage postfix ?
1820 if ((src2
== CMaterial::Texture
) || (src2
== CMaterial::Constant
))
1821 dest
+= toString (stage
);
1824 if ((op2
== CMaterial::SrcAlpha
) || (op2
== CMaterial::InvSrcAlpha
))
1832 // ***************************************************************************
1834 IDirect3DPixelShader9
*CDriverD3D::buildPixelShader (const CNormalShaderDesc
&normalShaderDesc
, bool unlightedNoVertexColor
)
1836 H_AUTO_D3D(CDriverD3D_buildPixelShader
)
1837 static string shaderText
;
1838 shaderText
= "ps_1_1;\n";
1840 // Look for a shader already created
1841 std::list
<CNormalShaderDesc
> &normalPixelShaders
= _NormalPixelShaders
[(uint
)unlightedNoVertexColor
];
1842 std::list
<CNormalShaderDesc
>::iterator ite
= normalPixelShaders
.begin();
1843 while (ite
!= normalPixelShaders
.end())
1845 if (normalShaderDesc
== *ite
)
1848 return (*ite
).PixelShader
;
1853 // For each state, texture lookup
1855 for (i
=0; i
<IDRV_MAT_MAXTEXTURES
; i
++)
1858 if (normalShaderDesc
.StageUsed
[i
])
1861 CMaterial::CTexEnv texEnv
;
1862 texEnv
.EnvPacked
= normalShaderDesc
.TexEnvMode
[i
];
1863 nlassert(texEnv
.Env
.OpRGB
!= CMaterial::EMBM
); // Pixel shader equivalent for EMBM not supported
1864 // For now this is not a problem because
1865 // buildPixelShader is used when the shader uses per stage color
1866 // (which is not always supported by the fixed pixel pipe),
1867 // and currently all our shaders with EMBM don't use that feature.
1869 shaderText
+= "tex t"+toString (i
)+";\n";
1873 // For each state, color operations
1874 for (i
=0; i
<IDRV_MAT_MAXTEXTURES
; i
++)
1877 if (normalShaderDesc
.StageUsed
[i
])
1880 CMaterial::CTexEnv texEnv
;
1881 texEnv
.EnvPacked
= normalShaderDesc
.TexEnvMode
[i
];
1884 CMaterial::TTexOperator texOp
= (CMaterial::TTexOperator
)texEnv
.Env
.OpRGB
;
1885 CMaterial::TTexSource src0
= (CMaterial::TTexSource
)texEnv
.Env
.SrcArg0RGB
;
1886 CMaterial::TTexSource src1
= (CMaterial::TTexSource
)texEnv
.Env
.SrcArg1RGB
;
1887 CMaterial::TTexSource src2
= (CMaterial::TTexSource
)texEnv
.Env
.SrcArg2RGB
;
1888 CMaterial::TTexOperand op0
= (CMaterial::TTexOperand
)texEnv
.Env
.OpArg0RGB
;
1889 CMaterial::TTexOperand op1
= (CMaterial::TTexOperand
)texEnv
.Env
.OpArg1RGB
;
1890 CMaterial::TTexOperand op2
= (CMaterial::TTexOperand
)texEnv
.Env
.OpArg2RGB
;
1891 buildColorOperation (shaderText
, "", ".xyz", i
, texOp
, src0
, src1
, src2
, op0
, op1
, op2
, unlightedNoVertexColor
);
1894 texOp
= (CMaterial::TTexOperator
)texEnv
.Env
.OpAlpha
;
1895 src0
= (CMaterial::TTexSource
)texEnv
.Env
.SrcArg0Alpha
;
1896 src1
= (CMaterial::TTexSource
)texEnv
.Env
.SrcArg1Alpha
;
1897 src2
= (CMaterial::TTexSource
)texEnv
.Env
.SrcArg2Alpha
;
1898 op0
= (CMaterial::TTexOperand
)texEnv
.Env
.OpArg0Alpha
;
1899 op1
= (CMaterial::TTexOperand
)texEnv
.Env
.OpArg1Alpha
;
1900 op2
= (CMaterial::TTexOperand
)texEnv
.Env
.OpArg2Alpha
;
1901 buildColorOperation (shaderText
, "+", ".w", i
, texOp
, src0
, src1
, src2
, op0
, op1
, op2
, unlightedNoVertexColor
);
1903 // No texture shader ?
1907 CMaterial::TTexOperator texOp
= CMaterial::Replace
;
1908 CMaterial::TTexSource src0
= CMaterial::Diffuse
;
1909 CMaterial::TTexOperand op0
= CMaterial::SrcColor
;
1910 buildColorOperation (shaderText
, "", ".xyz", i
, texOp
, src0
, src0
, src0
, op0
, op0
, op0
, unlightedNoVertexColor
);
1913 texOp
= CMaterial::Replace
;
1914 src0
= CMaterial::Diffuse
;
1915 op0
= CMaterial::SrcAlpha
;
1916 buildColorOperation (shaderText
, "+", ".w", i
, texOp
, src0
, src0
, src0
, op0
, op0
, op0
, unlightedNoVertexColor
);
1921 shaderText
+= "add r0.rgb, r0, v1;\n";
1923 // Dump the pixel shader
1925 nlinfo("Assemble Pixel Shader : ");
1926 string::size_type lineBegin
= 0;
1927 string::size_type lineEnd
;
1928 while ((lineEnd
= shaderText
.find('\n', lineBegin
)) != string::npos
)
1930 nlinfo(shaderText
.substr (lineBegin
, lineEnd
-lineBegin
).c_str());
1931 lineBegin
= lineEnd
+1;
1933 nlinfo(shaderText
.substr (lineBegin
, lineEnd
-lineBegin
).c_str());
1934 #endif // NL_DEBUG_D3D
1937 normalPixelShaders
.push_back (normalShaderDesc
);
1939 // Assemble and create the shader
1940 LPD3DXBUFFER pShader
;
1941 LPD3DXBUFFER pErrorMsgs
;
1942 if (D3DXAssembleShader (shaderText
.c_str(), (UINT
)shaderText
.size(), NULL
, NULL
, 0, &pShader
, &pErrorMsgs
) == D3D_OK
)
1944 IDirect3DPixelShader9
*shader
;
1945 if (_DeviceInterface
->CreatePixelShader((DWORD
*)pShader
->GetBufferPointer(), &shader
) == D3D_OK
)
1946 normalPixelShaders
.back().PixelShader
= shader
;
1948 normalPixelShaders
.back().PixelShader
= NULL
;
1952 nlwarning ("Can't assemble pixel shader:");
1953 nlwarning ((const char*)pErrorMsgs
->GetBufferPointer());
1954 normalPixelShaders
.back().PixelShader
= NULL
;
1957 return normalPixelShaders
.back().PixelShader
;
1960 // ***************************************************************************
1962 void CDriverD3D::startSpecularBatch()
1964 /* Not used in direct3d, use normal caching */
1967 // ***************************************************************************
1969 void CDriverD3D::endSpecularBatch()
1971 /* Not used in direct3d, use normal caching */
1974 // ***************************************************************************
1976 bool CDriverD3D::supportBlendConstantColor() const
1978 /* Not supported in D3D */
1982 // ***************************************************************************
1984 void CDriverD3D::setBlendConstantColor(NLMISC::CRGBA
/* col */)
1986 /* Not supported in D3D */
1989 // ***************************************************************************
1991 NLMISC::CRGBA
CDriverD3D::getBlendConstantColor() const
1993 /* Not supported in D3D */
1994 return CRGBA::White
;
1997 // ***************************************************************************
1999 void CDriverD3D::enablePolygonSmoothing(bool /* smooth */)
2001 /* Not supported in D3D */
2004 // ***************************************************************************
2006 bool CDriverD3D::isPolygonSmoothingEnabled() const
2008 /* Not supported in D3D */
2012 // ***************************************************************************
2014 sint
CDriverD3D::beginMaterialMultiPass()
2016 H_AUTO_D3D(CDriverD3D_beginMaterialMultiPass
)
2018 return _CurrentShaderPassCount
;
2021 // ***************************************************************************
2023 void CDriverD3D::setupMaterialPass(uint pass
)
2025 H_AUTO_D3D(CDriver3D_setupMaterialPass
);
2029 // ***************************************************************************
2031 void CDriverD3D::endMaterialMultiPass()
2033 H_AUTO_D3D(CDriver3D_endMaterialMultiPass
);
2037 // ***************************************************************************
2039 bool CDriverD3D::supportCloudRenderSinglePass () const
2041 H_AUTO_D3D(CDriver3D_supportCloudRenderSinglePass
);
2042 return _PixelProgram
;
2045 // ***************************************************************************
2047 void CDriverD3D::getNumPerStageConstant(uint
&lightedMaterial
, uint
&unlightedMaterial
) const
2049 lightedMaterial
= _MaxNumPerStageConstantLighted
;
2050 unlightedMaterial
= _MaxNumPerStageConstantUnlighted
;