1
// Copyright (C) 2002-2011 Nikolaus Gebhardt
2
// This file is part of the "Irrlicht Engine".
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
5
#include "IrrCompileConfig.h"
6
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
8
#include "CD3D9ShaderMaterialRenderer.h"
9
#include "IShaderConstantSetCallBack.h"
10
#include "IMaterialRendererServices.h"
11
#include "IVideoDriver.h"
13
#include "irrString.h"
15
#ifndef _IRR_D3D_NO_SHADER_DEBUGGING
25
//! Public constructor
26
CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
27
s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
28
IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData)
29
: pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
30
VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData)
33
setDebugName("CD3D9ShaderMaterialRenderer");
42
init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram);
46
//! constructor only for use by derived classes who want to
47
//! create a fall back material for example.
48
CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev,
49
video::IVideoDriver* driver,
50
IShaderConstantSetCallBack* callback,
51
IMaterialRenderer* baseMaterial, s32 userData)
52
: pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
53
VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData)
56
setDebugName("CD3D9ShaderMaterialRenderer");
67
void CD3D9ShaderMaterialRenderer::init(s32& outMaterialTypeNr,
68
const c8* vertexShaderProgram, const c8* pixelShaderProgram)
70
outMaterialTypeNr = -1;
72
// create vertex shader
73
if (!createVertexShader(vertexShaderProgram))
76
// create pixel shader
77
if (!createPixelShader(pixelShaderProgram))
80
// register myself as new material
81
outMaterialTypeNr = Driver->addMaterialRenderer(this);
86
CD3D9ShaderMaterialRenderer::~CD3D9ShaderMaterialRenderer()
92
VertexShader->Release();
95
PixelShader->Release();
102
bool CD3D9ShaderMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
104
// call callback to set shader constants
105
if (CallBack && (VertexShader || PixelShader))
106
CallBack->OnSetConstants(service, UserData);
112
void CD3D9ShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial,
113
bool resetAllRenderstates, video::IMaterialRendererServices* services)
115
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
119
// save old vertex shader
120
pID3DDevice->GetVertexShader(&OldVertexShader);
122
// set new vertex shader
123
if (FAILED(pID3DDevice->SetVertexShader(VertexShader)))
124
os::Printer::log("Could not set vertex shader.", ELL_WARNING);
127
// set new pixel shader
130
if (FAILED(pID3DDevice->SetPixelShader(PixelShader)))
131
os::Printer::log("Could not set pixel shader.", ELL_WARNING);
135
BaseMaterial->OnSetMaterial(material, material, true, services);
138
//let callback know used material
140
CallBack->OnSetMaterial(material);
142
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
146
void CD3D9ShaderMaterialRenderer::OnUnsetMaterial()
149
pID3DDevice->SetVertexShader(OldVertexShader);
152
pID3DDevice->SetPixelShader(0);
155
BaseMaterial->OnUnsetMaterial();
159
//! Returns if the material is transparent. The scene managment needs to know this
160
//! for being able to sort the materials by opaque and transparent.
161
bool CD3D9ShaderMaterialRenderer::isTransparent() const
163
return BaseMaterial ? BaseMaterial->isTransparent() : false;
167
bool CD3D9ShaderMaterialRenderer::createPixelShader(const c8* pxsh)
174
LPD3DXBUFFER code = 0;
175
LPD3DXBUFFER errors = 0;
177
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
179
// compile shader without debug info
180
stubD3DXAssembleShader(pxsh, (UINT)strlen(pxsh), 0, 0, 0, &code, &errors);
183
// compile shader and emitt some debug informations to
184
// make it possible to debug the shader in visual studio
186
static int irr_dbg_file_nr = 0;
189
sprintf(tmp, "irr_d3d9_dbg_shader_%d.psh", irr_dbg_file_nr);
191
FILE* f = fopen(tmp, "wb");
192
fwrite(pxsh, strlen(pxsh), 1, f);
196
stubD3DXAssembleShaderFromFile(tmp, 0, 0, D3DXSHADER_DEBUG, &code, &errors);
203
// print out compilation errors.
204
os::Printer::log("Pixel shader compilation failed:", ELL_ERROR);
205
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
214
if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)code->GetBufferPointer(), &PixelShader)))
216
os::Printer::log("Could not create pixel shader.", ELL_ERROR);
226
bool CD3D9ShaderMaterialRenderer::createVertexShader(const char* vtxsh)
233
LPD3DXBUFFER code = 0;
234
LPD3DXBUFFER errors = 0;
236
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
238
// compile shader without debug info
239
stubD3DXAssembleShader(vtxsh, (UINT)strlen(vtxsh), 0, 0, 0, &code, &errors);
243
// compile shader and emitt some debug informations to
244
// make it possible to debug the shader in visual studio
246
static int irr_dbg_file_nr = 0;
249
sprintf(tmp, "irr_d3d9_dbg_shader_%d.vsh", irr_dbg_file_nr);
251
FILE* f = fopen(tmp, "wb");
252
fwrite(vtxsh, strlen(vtxsh), 1, f);
256
stubD3DXAssembleShaderFromFile(tmp, 0, 0, D3DXSHADER_DEBUG, &code, &errors);
262
// print out compilation errors.
263
os::Printer::log("Vertex shader compilation failed:", ELL_ERROR);
264
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
273
if (!code || FAILED(pID3DDevice->CreateVertexShader((DWORD*)code->GetBufferPointer(), &VertexShader)))
275
os::Printer::log("Could not create vertex shader.", ELL_ERROR);
286
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader(LPCSTR pSrcData,
287
UINT SrcDataLen, CONST D3DXMACRO* pDefines,
288
LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader,
289
LPD3DXBUFFER* ppErrorMsgs)
291
// Because Irrlicht needs to be able to start up even without installed d3d dlls, it
292
// needs to load external d3d dlls manually. examples for the dlls are:
293
// SDK dll name D3DX_SDK_VERSION
294
// Summer 2004: no dll 22
295
// February 2005: d3dx9_24.dll 24
296
// April 2005: d3dx9_25.dll 25
297
// June 2005: d3dx9_26.dll 26
298
// August 2005: d3dx9_27.dll 27
300
// December 2005: d3dx9_28.dll 28
302
#if ( D3DX_SDK_VERSION < 24 )
303
// directly link functions, old d3d sdks didn't try to load external dlls
304
// when linking to the d3dx9.lib
306
#pragma comment (lib, "d3dx9.lib")
309
// invoke static linked function
310
return D3DXAssembleShader(pSrcData, SrcDataLen, pDefines, pInclude,
311
Flags, ppShader, ppErrorMsgs);
314
// try to load shader functions from the dll and print error if failed.
316
// D3DXAssembleShader signature
317
typedef HRESULT (WINAPI *AssembleShaderFunction)(LPCSTR pSrcData, UINT SrcDataLen,
318
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude,
319
DWORD Flags, LPD3DXBUFFER* ppShader,
320
LPD3DXBUFFER* ppErrorMsgs);
322
static bool LoadFailed = false;
323
static AssembleShaderFunction pFn = 0;
325
if (!pFn && !LoadFailed)
328
io::path strDllName = "d3dx9_";
329
strDllName += (int)D3DX_SDK_VERSION;
330
strDllName += ".dll";
332
HMODULE hMod = LoadLibrary(strDllName.c_str());
334
pFn = (AssembleShaderFunction)GetProcAddress(hMod, "D3DXAssembleShader");
339
os::Printer::log("Could not load shader function D3DXAssembleShader from dll, shaders disabled",
340
strDllName.c_str(), ELL_ERROR);
346
// call already loaded function
347
return (*pFn)(pSrcData, SrcDataLen, pDefines, pInclude, Flags, ppShader, ppErrorMsgs);
350
#endif // D3DX_SDK_VERSION < 24
356
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShaderFromFile(LPCSTR pSrcFile,
357
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags,
358
LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs)
360
// wondering what I'm doing here?
361
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
363
#if ( D3DX_SDK_VERSION < 24 )
364
// directly link functions, old d3d sdks didn't try to load external dlls
365
// when linking to the d3dx9.lib
367
#pragma comment (lib, "d3dx9.lib")
370
// invoke static linked function
371
return D3DXAssembleShaderFromFileA(pSrcFile, pDefines, pInclude, Flags,
372
ppShader, ppErrorMsgs);
375
// try to load shader functions from the dll and print error if failed.
377
// D3DXAssembleShaderFromFileA signature
378
typedef HRESULT (WINAPI *AssembleShaderFromFileFunction)(LPCSTR pSrcFile,
379
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags,
380
LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs);
382
static bool LoadFailed = false;
383
static AssembleShaderFromFileFunction pFn = 0;
385
if (!pFn && !LoadFailed)
388
io::path strDllName = "d3dx9_";
389
strDllName += (int)D3DX_SDK_VERSION;
390
strDllName += ".dll";
392
HMODULE hMod = LoadLibrary(strDllName.c_str());
394
pFn = (AssembleShaderFromFileFunction)GetProcAddress(hMod, "D3DXAssembleShaderFromFileA");
399
os::Printer::log("Could not load shader function D3DXAssembleShaderFromFileA from dll, shaders disabled",
400
strDllName.c_str(), ELL_ERROR);
406
// call already loaded function
407
return (*pFn)(pSrcFile, pDefines, pInclude, Flags, ppShader, ppErrorMsgs);
410
#endif // D3DX_SDK_VERSION < 24
416
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines,
417
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
418
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader,
419
LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable)
421
// wondering what I'm doing here?
422
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
424
#if ( D3DX_SDK_VERSION < 24 )
425
// directly link functions, old d3d sdks didn't try to load external dlls
426
// when linking to the d3dx9.lib
428
#pragma comment (lib, "d3dx9.lib")
431
// invoke static linked function
432
return D3DXCompileShader(pSrcData, SrcDataLen, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
435
// try to load shader functions from the dll and print error if failed.
438
typedef HRESULT (WINAPI *D3DXCompileShaderFunction)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines,
439
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
440
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader,
441
LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
443
static bool LoadFailed = false;
444
static D3DXCompileShaderFunction pFn = 0;
446
if (!pFn && !LoadFailed)
449
io::path strDllName = "d3dx9_";
450
strDllName += (int)D3DX_SDK_VERSION;
451
strDllName += ".dll";
453
HMODULE hMod = LoadLibrary(strDllName.c_str());
455
pFn = (D3DXCompileShaderFunction)GetProcAddress(hMod, "D3DXCompileShader");
460
os::Printer::log("Could not load shader function D3DXCompileShader from dll, shaders disabled",
461
strDllName.c_str(), ELL_ERROR);
467
// call already loaded function
468
return (*pFn)(pSrcData, SrcDataLen, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
471
#endif // D3DX_SDK_VERSION < 24
476
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines,
477
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
478
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs,
479
LPD3DXCONSTANTTABLE* ppConstantTable)
481
// wondering what I'm doing here?
482
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
484
#if ( D3DX_SDK_VERSION < 24 )
485
// directly link functions, old d3d sdks didn't try to load external dlls
486
// when linking to the d3dx9.lib
488
#pragma comment (lib, "d3dx9.lib")
491
// invoke static linked function
492
return D3DXCompileShaderFromFileA(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
495
// try to load shader functions from the dll and print error if failed.
497
// D3DXCompileShaderFromFileA
498
typedef HRESULT (WINAPI *D3DXCompileShaderFromFileFunction)(LPCSTR pSrcFile,
499
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
500
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs,
501
LPD3DXCONSTANTTABLE* ppConstantTable);
503
static bool LoadFailed = false;
504
static D3DXCompileShaderFromFileFunction pFn = 0;
506
if (!pFn && !LoadFailed)
509
io::path strDllName = "d3dx9_";
510
strDllName += (int)D3DX_SDK_VERSION;
511
strDllName += ".dll";
513
HMODULE hMod = LoadLibrary(strDllName.c_str());
515
pFn = (D3DXCompileShaderFromFileFunction)GetProcAddress(hMod, "D3DXCompileShaderFromFileA");
520
os::Printer::log("Could not load shader function D3DXCompileShaderFromFileA from dll, shaders disabled",
521
strDllName.c_str(), ELL_ERROR);
527
// call already loaded function
528
return (*pFn)(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
531
#endif // D3DX_SDK_VERSION < 24
537
} // end namespace video
538
} // end namespace irr
540
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_