Skip to content

Instantly share code, notes, and snippets.

@Jackster
Last active December 23, 2022 23:29
Show Gist options
  • Save Jackster/20104b36871b28906026649f9e2a2346 to your computer and use it in GitHub Desktop.
Save Jackster/20104b36871b28906026649f9e2a2346 to your computer and use it in GitHub Desktop.
C3DLow_dx9_MatUtil.cpp
#define DBLOCATION2 ,"C3DLow_dx9_matutil.cpp",0
#include "options_3d.h" //
#include "options_d.h" //
#include "C3DLow_dx9_MatUtil.h"
#include "File/IFile.h"
#ifdef PROFILE_SAVE_TIME_C3DLOW
#define PROFILE_SAVE_TIME
#endif
#ifdef C3DLOW_DEBUG
int g_dontrender_palskinned = 0;
#endif
#ifndef C3DLOW_DEBUG
#define USE_SHADERLIB
#else
#define SANITY_CHECK
#endif
#ifdef DEBUG
#define SHADER_ERRORS
#endif
#include "Debug/SaveTime.h"
#define SAFE_RELEASE(p) {if((p)!=NULL){(p)->Release();(p)=NULL;}}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Material validation Note
// The validation assumes that the supported cards can handle two textures
// and two texture stage state (with arbitrarliy set ops/args) so
// the 'shaders' that don't exceed these limit assumed to be valid
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
typedef unsigned int T_UL;
void SetVDM_TC(vertexdatamapping &vdm, int index, MatParam &mp)
{
vdm.map_channels[index] = mp.m_Tex.ch;
vdm.type_ids[index] = mp.type_id; //used by variation computing for uv channels
vdm.format |= VDF_TEXCOORD(index);
}
void SetVDM_TC(vertexdatamapping &vdm, int index, int channel)
{
vdm.map_channels[index] = channel;
vdm.type_ids[index] = MATPARAMTEX_DIFFUSE; //used by variation computing for uv channels
vdm.format |= VDF_TEXCOORD(index);
}
void SetVDM_TC(vertexdatamapping &vdm, int index)
{
vdm.map_channels[index] = -1;
vdm.format |= VDF_TEXCOORD(index);
}
// *********************************************
// Material Parameter implementations
// *********************************************
// color init functions
void MatParam::SetParamColor(int tid, int color)
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_COLOR )
{
OutputDebugStringA("SetParamColor invalid id\n");
}
#endif
type_id = tid;
m_Color.color = color;
m_Color.a=((color>>24)&0xff)/255.0f;
m_Color.r=((color>>16)&0xff)/255.0f;
m_Color.g=((color>>8)&0xff)/255.0f;
m_Color.b=(color&0xff)/255.0f;
}
void MatParam::SetParamColor(int tid, float r, float g, float b, float a)
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_COLOR )
{
OutputDebugStringA("SetParamColor invalid id\n");
}
#endif
type_id = tid;
m_Color.color = (((int)(a*255))<<24 |
(((int)(r*255))<<16)|
(((int)(g*255))<<8)|
((int)(b*255)));
m_Color.a=a;
m_Color.r=r;
m_Color.g=g;
m_Color.b=b;
}
void MatParam::SetParamColorWhite(int tid) //init with default value
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_COLOR )
{
OutputDebugStringA("SetParamColorWhite invalid id\n");
}
#endif
type_id = tid;
m_Color.color = 0xffffffff;
m_Color.r = m_Color.g = m_Color.b = m_Color.a = 1.0f;
}
void MatParam::SetParamColorBlack(int tid) //init with default value
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_COLOR )
{
OutputDebugStringA("SetParamColorBlack invalid id\n");
}
#endif
type_id = tid;
m_Color.color = 0x0;
m_Color.r = m_Color.g = m_Color.b = 0.0f;
m_Color.a = 1.0f;
}
void MatParam::SetParamFloat1(int tid, float v1)
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_FLOAT1 )
{
OutputDebugStringA("SetParamFloat1 invalid id\n");
}
#endif
type_id = tid;
m_Float1 = v1;
}
void MatParam::SetParamFloat2(int tid, float v1, float v2)
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_FLOAT2 )
{
OutputDebugStringA("SetParamFloat2 invalid id\n");
}
#endif
type_id = tid;
m_Float2[0] = v1;
m_Float2[1] = v2;
}
void MatParam::SetParamFloat3(int tid, float v1, float v2, float v3)
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_FLOAT3 )
{
OutputDebugStringA("SetParamFloat3 invalid id\n");
}
#endif
type_id = tid;
m_Float3[0] = v1;
m_Float3[1] = v2;
m_Float3[2] = v3;
}
void MatParam::SetParamFloat4(int tid, float v1, float v2, float v3, float v4)
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_FLOAT4 )
{
OutputDebugStringA("SetParamFloat4 invalid id\n");
}
#endif
type_id = tid;
m_Float4[0] = v1;
m_Float4[1] = v2;
m_Float4[2] = v3;
m_Float4[3] = v4;
}
void MatParam::SetParamInt(int tid, int v)
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_INT )
{
OutputDebugStringA("SetParamInt invalid id\n");
}
#endif
type_id = tid;
m_Int = v;
}
//texture init functions
void MatParam::SetParamTex(int tid, int index, int ch)
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_TEX )
{
OutputDebugStringA("SetParamTex2D invalid id\n");
}
#endif
type_id = tid;
m_Tex.index = index;
m_Tex.ch = ch;
m_Tex.u_scale = 1.0f;
m_Tex.v_scale = 1.0f;
m_Tex.u_offset = 0.0f;
m_Tex.v_offset = 0.0f;
m_Tex.flags = TF_UWRAP|TF_VWRAP;
m_Tex.m_pTexture = NULL;
}
void MatParam::SetParamTex(int tid, int index, int ch, int flags,
float u_scale, float v_scale, float u_offset, float v_offset )
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_TEX )
{
OutputDebugStringA("SetParamTex2D invalid id\n");
}
#endif
type_id = tid;
m_Tex.index = index;
m_Tex.ch = ch;
m_Tex.u_scale = u_scale;
m_Tex.v_scale = v_scale;
m_Tex.u_offset = u_offset;
m_Tex.v_offset = v_offset;
m_Tex.flags = flags;
if ( m_Tex.u_scale != 1.0f || m_Tex.v_scale != 1.0f ||
m_Tex.u_offset != 0.0f || m_Tex.v_offset != 0.0f )
m_Tex.flags |= TF_TRANSFORM;
m_Tex.m_pTexture = NULL;
}
void MatParam::SetParamTex(int tid)
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_TEX )
{
OutputDebugStringA("SetParamTex invalid id\n");
}
#endif
type_id = tid;
m_Tex.index = -1;
//m_Tex2D.ch = -1;
m_Tex.ch = 0;
m_Tex.m_pTexture = NULL;
m_Tex.u_scale = 1.0f;
m_Tex.v_scale = 1.0f;
m_Tex.u_offset = 0.0f;
m_Tex.v_offset = 0.0f;
m_Tex.flags = TF_UWRAP|TF_VWRAP;
}
void MatParam::SetParamCubeTex(int tid)
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_CUBETEX )
{
OutputDebugStringA("SetParamCubeTex invalid id\n");
}
#endif
type_id = tid;
m_Tex.index = -1;
m_CubeTex.m_pTexture = NULL;
}
void MatParam::SetParamCubeTex(int tid, int index)
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_CUBETEX )
{
OutputDebugStringA("SetParamCubeTex invalid id\n");
}
#endif
type_id = tid;
m_CubeTex.index = index;
m_CubeTex.m_pTexture = NULL;
}
void MatParam::SetParamString(int tid, char *str)
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_STRING )
{
OutputDebugStringA("SetParamString invalid id\n");
}
#endif
type_id = tid;
strncpy_s(m_String.str,32, str,31);
m_String.str[31] = 0;
}
void MatParam::SetParamRedirect(int tid, int rtid, int remap)
{
#ifdef SANITY_CHECK
if ( ((tid>>24)&0xff) != MATPARAMTYPE_INT )
{
OutputDebugStringA("SetParamInt invalid id\n");
}
#endif
type_id = tid;
m_Redirect.type_id = rtid;
m_Redirect.color_remap = remap;
}
int MatParam::SetParam(unsigned char *data)
{
int paramid= *((int*)data);
data+=sizeof(int);
switch(paramid>>24)
{
case MATPARAMTYPE_COLOR :
SetParamColor(paramid,*((int*)data));
return 2*sizeof(int);
break;
case MATPARAMTYPE_FLOAT1 :
SetParamFloat1(paramid,*((float*)data));
return sizeof(int)+sizeof(float);
break;
case MATPARAMTYPE_FLOAT2:
SetParamFloat2(paramid,*((float*)data),*(((float*)data)+1));
return sizeof(int)+2*sizeof(float);
break;
case MATPARAMTYPE_FLOAT3:
SetParamFloat3(paramid,*((float*)data),*(((float*)data)+1),
*(((float*)data)+2));
return sizeof(int)+3*sizeof(float);
break;
case MATPARAMTYPE_FLOAT4:
SetParamFloat4(paramid,*((float*)data),*(((float*)data)+1),
*(((float*)data)+2),*(((float*)data)+3));
return sizeof(int)+4*sizeof(float);
break;
case MATPARAMTYPE_INT:
SetParamInt(paramid,*((int*)data));
return 2*sizeof(int);
break;
case MATPARAMTYPE_TEX:
SetParamTex(paramid,*((int*)data),*((int*)(data+sizeof(int))),
*((int*)(data+2*sizeof(int))),
*(float*)(data+3*sizeof(int)), *(float*)(data+3*sizeof(int)+sizeof(float)),
*(float*)(data+3*sizeof(int)+2*sizeof(float)), *(float*)(data+3*sizeof(int)+3*sizeof(float)));
return 4*sizeof(int)+4*sizeof(float);
break;
case MATPARAMTYPE_CUBETEX:
SetParamCubeTex(paramid,*((int*)data) );
return 2*sizeof(int);
break;
case MATPARAMTYPE_STRING:
SetParamString(paramid,(char*)data);
return sizeof(int) + 32*sizeof(char);
break;
case MATPARAMTYPE_REDIRECT:
SetParamRedirect(paramid, *((int*)data),*((int*)(data+sizeof(int))) );
return 3 * sizeof(int);
break;
}
return sizeof(int);
}
//return the written size ()
int MatParam::Write(unsigned char * mem)
{
if (mem)
{
*((int*)mem) = type_id;
mem+=sizeof(int);
}
switch( (type_id>>24)&0xff)
{
case MATPARAMTYPE_COLOR:
if (mem)
{
*((int*)mem) = m_Color.color;
}
return 2 * sizeof(int) ;
break;
case MATPARAMTYPE_FLOAT1:
if (mem)
{
*((float*)mem) = m_Float1;
}
return sizeof(int) + sizeof(float);
break;
case MATPARAMTYPE_FLOAT2:
if (mem)
{
*((float*)mem) = m_Float2[0];
*(((float*)mem)+1) = m_Float2[1];
}
return sizeof(int) + 2 * sizeof(float);
break;
case MATPARAMTYPE_FLOAT3:
if (mem)
{
*((float*)mem) = m_Float3[0];
*(((float*)mem)+1) = m_Float3[1];
*(((float*)mem)+2) = m_Float3[2];
}
return sizeof(int) + 3 * sizeof(float);
break;
case MATPARAMTYPE_FLOAT4:
if (mem)
{
*((float*)mem) = m_Float4[0];
*(((float*)mem)+1) = m_Float4[1];
*(((float*)mem)+2) = m_Float4[2];
*(((float*)mem)+3) = m_Float4[3];
}
return sizeof(int) + 4 * sizeof(float);
break;
case MATPARAMTYPE_INT:
if (mem)
{
*((int*)mem) = m_Int;
}
return 2 * sizeof(int) ;
break;
case MATPARAMTYPE_TEX:
if (mem)
{
*((int*)mem) = m_Tex.index;
*(((int*)mem)+1) = m_Tex.ch;
*(((int*)mem)+2) = m_Tex.flags;
mem+= 3 * sizeof(int);
*((float*)mem) = m_Tex.u_scale;
*(((float*)mem)+1) = m_Tex.v_scale;
*(((float*)mem)+2) = m_Tex.u_offset;
*(((float*)mem)+3) = m_Tex.v_offset;
}
return 4*sizeof(int) + 4 * sizeof(float);
break;
case MATPARAMTYPE_CUBETEX:
if (mem)
{
*((int*)mem) = m_CubeTex.index;
}
return 2 * sizeof(int);
break;
case MATPARAMTYPE_STRING:
if (mem)
{
memcpy(mem,m_String.str,sizeof(char)*32);
}
return sizeof(int) + 32 * sizeof(char);
break;
case MATPARAMTYPE_REDIRECT:
if (mem)
{
*((int*)mem) = m_Redirect.type_id;
*(((int*)mem)+1) = m_Redirect.color_remap;
}
return 3 * sizeof(int) ;
break;
}
return 0;
}
bool MatParam::operator==(MatParam &param)
{
if (param.type_id != type_id)
return false;
switch((type_id>>24)&0xff)
{
case MATPARAMTYPE_COLOR:
return m_Color.color == param.m_Color.color;
case MATPARAMTYPE_FLOAT1:
return m_Float1 == param.m_Float1;
case MATPARAMTYPE_FLOAT2:
return m_Float2[0] == param.m_Float2[0] &&
m_Float2[1] == param.m_Float2[1];
case MATPARAMTYPE_FLOAT3:
return m_Float3[0] == param.m_Float3[0] &&
m_Float3[1] == param.m_Float3[1] &&
m_Float3[2] == param.m_Float3[2];
case MATPARAMTYPE_FLOAT4:
return m_Float4[0] == param.m_Float4[0] &&
m_Float4[1] == param.m_Float4[1] &&
m_Float4[2] == param.m_Float4[2] &&
m_Float4[3] == param.m_Float4[3];
case MATPARAMTYPE_INT:
return m_Int == param.m_Int;
case MATPARAMTYPE_TEX:
return m_Tex.m_pTexture == param.m_Tex.m_pTexture
&& m_Tex.flags == param.m_Tex.flags
&& m_Tex.u_scale == param.m_Tex.u_scale
&& m_Tex.v_scale == param.m_Tex.v_scale
&& m_Tex.u_offset == param.m_Tex.u_offset
&& m_Tex.v_offset == param.m_Tex.v_offset;
case MATPARAMTYPE_CUBETEX:
return m_CubeTex.m_pTexture == param.m_CubeTex.m_pTexture;
case MATPARAMTYPE_REDIRECT:
return m_Redirect.type_id == param.m_Redirect.type_id &&
m_Redirect.color_remap == param.m_Redirect.color_remap;
/*
case MATPARAMTYPE_TEXCUBE:
return true;
case MATPARAMTYPE_STRING: //it is not important
return true;
*/
}
return true;
}
bool MatParam::operator<(MatParam &param)
{ //used only on tex and CubeTex
switch((type_id>>24)&0xff)
{
case MATPARAMTYPE_TEX:
return m_Tex.m_pTexture < param.m_Tex.m_pTexture;
}
return true;
}
// *********************************************
// MatParamVariations implementations
// *********************************************
MaterialVariation::MaterialVariation(u8* data)
{
m_VariationCount = *((int*)data);
data+=sizeof(int);
if (m_VariationCount==0)
{
m_pVariations = NULL;
return;
}
m_pVariations = new MatVariationParam[m_VariationCount];
for(int i=0;i<m_VariationCount;++i)
{
m_pVariations[i].m_ParamType = *((int*)data);
data+=sizeof(int);
m_pVariations[i].m_VariationType = *((int*)data);
data+=sizeof(int);
m_pVariations[i].m_VariationCount = *((int*)data);
data+=sizeof(int);
m_pVariations[i].m_Tex = new MatVariationParamTex[m_pVariations[i].m_VariationCount];
switch(m_pVariations[i].m_VariationType)
{
case MATPARAMVARIATION_TEX:
{
for(int j=0;j<m_pVariations[i].m_VariationCount;++j)
{
m_pVariations[i].m_Tex[j].u_offset = *((float*)data);
data+=sizeof(float);
m_pVariations[i].m_Tex[j].v_offset = *((float*)data);
data+=sizeof(float);
m_pVariations[i].m_Tex[j].u_scale = *((float*)data);
data+=sizeof(float);
m_pVariations[i].m_Tex[j].v_scale = *((float*)data);
data+=sizeof(float);
}
}
break;
}
}
}
MaterialVariation::MaterialVariation(MaterialVariation &mpv)
{
m_pVariations = new MatVariationParam[mpv.m_VariationCount];
memcpy(m_pVariations,mpv.m_pVariations,mpv.m_VariationCount*sizeof(MatVariationParam));
m_VariationCount = mpv.m_VariationCount;
}
MaterialVariation* C3DLowInterface::CreateMaterialVariation(u8 *data)
{
return new MaterialVariation(data);
}
// *********************************************
// Misc helper functions
// *********************************************
static D3DMATERIAL9 g_D3DMat;
static D3DCOLORVALUE g_D3DColorValueZero={0.0f,0.0f,0.0f,0.0f};
//material setting helper function
void SetD3DDiffuseMaterial(float r, float g, float b, float a)
{
g_D3DMat.Diffuse.r = g_D3DMat.Ambient.r =r;
g_D3DMat.Diffuse.g = g_D3DMat.Ambient.g= g;
g_D3DMat.Diffuse.b = g_D3DMat.Ambient.b= b;
g_D3DMat.Diffuse.a = g_D3DMat.Ambient.a= a;
g_D3DMat.Specular =
g_D3DMat.Emissive = g_D3DColorValueZero;
g_D3DMat.Power = 0.0f;
g_pD3DDevice->SetMaterial(&g_D3DMat);
}
void SetD3DDiffuseMaterial(MatParam &mpc)
{
SetD3DDiffuseMaterial(mpc.m_Color.r, mpc.m_Color.g,
mpc.m_Color.b, mpc.m_Color.a);
}
//material setting helper function
void SetD3DDiffuseMaterial(MatParam &emissive, float r, float g, float b, float a)
{
g_D3DMat.Diffuse.r = g_D3DMat.Ambient.r =r;
g_D3DMat.Diffuse.g = g_D3DMat.Ambient.g= g;
g_D3DMat.Diffuse.b = g_D3DMat.Ambient.b= b;
g_D3DMat.Diffuse.a = g_D3DMat.Ambient.a= a;
g_D3DMat.Specular = g_D3DColorValueZero;
g_D3DMat.Emissive.r = emissive.m_Color.r * 0.5f;
g_D3DMat.Emissive.g = emissive.m_Color.g * 0.5f;
g_D3DMat.Emissive.b = emissive.m_Color.b * 0.5f;
g_D3DMat.Emissive.a = 0.0f;
g_D3DMat.Power = 0.0f;
g_pD3DDevice->SetMaterial(&g_D3DMat);
}
void SetD3DDiffuseMaterial(MatParam &emissive, MatParam &mpc)
{
SetD3DDiffuseMaterial(emissive, mpc.m_Color.r, mpc.m_Color.g,
mpc.m_Color.b, mpc.m_Color.a);
}
void SetReflectionCubemapStage(int stage)
{
C3DLowMatrix pMInvView = *g_C3DLow.GetInvViewMatrix();
pMInvView._41 = 0.0f; pMInvView._42 = 0.0f; pMInvView._43 = 0.0f; pMInvView._44 = 1.0f;
g_pD3DDevice->SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+stage), (D3DMATRIX*)&pMInvView);
//the states below can be put into a StateBlock
g_pD3DDevice->SetTextureStageState(stage,D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
g_pD3DDevice->SetTextureStageState(stage,D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
//g_pD3DDevice->SetTextureStageState(stage,D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL);
}
void RestoreReflectionCubemapStage(int stage)
{
//the states below can be put into a StateBlock
g_pD3DDevice->SetTextureStageState(stage,D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
g_pD3DDevice->SetTextureStageState(stage,D3DTSS_TEXCOORDINDEX, stage);
}
void SetProjectedShadowStage(int depthstage, int tilestage)
{
// projected shadow depth
if (depthstage != -1 && g_C3DLow.GetProjectedShadow())
{
Texture *tex = g_C3DLow.GetProjectedShadow()->GetDepthTexture();
g_C3DLow.SetTexture(depthstage, tex);
if (tex != NULL && tex->GetPixelType() != RENDERDEPTH_Z)
{
g_pD3DDevice->SetSamplerState(depthstage, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
g_pD3DDevice->SetSamplerState(depthstage, D3DSAMP_MINFILTER, D3DTEXF_POINT);
}
else
{
g_C3DLow.SetTextureFilter(depthstage, C3DLOWTFILTER_LOW);
}
g_pD3DDevice->SetSamplerState(depthstage, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
g_pD3DDevice->SetSamplerState(depthstage, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
}
//projected shadow tile
if (tilestage != -1 && g_C3DLow.GetProjectedShadow())
{
Texture *tex = g_C3DLow.GetProjectedShadow()->GetTileTexture();
if (tex != NULL)
{
g_C3DLow.SetTexture(tilestage, tex);
g_pD3DDevice->SetSamplerState(tilestage, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
g_pD3DDevice->SetSamplerState(tilestage, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
g_pD3DDevice->SetSamplerState(tilestage, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
g_pD3DDevice->SetSamplerState(tilestage, D3DSAMP_MINFILTER, D3DTEXF_POINT);
}
}
}
void RestoreProjectedShadowStage(int depthstage, int tilestage)
{
if (depthstage != -1)
{
g_pD3DDevice->SetSamplerState(depthstage, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
g_pD3DDevice->SetSamplerState(depthstage, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
g_C3DLow.SetTextureFilter(depthstage, 0, TRUE);
}
if (tilestage != -1)
{
g_pD3DDevice->SetSamplerState(tilestage, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
g_pD3DDevice->SetSamplerState(tilestage, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
g_C3DLow.SetTextureFilter(tilestage, 0, TRUE);
}
}
void SetReflectionStage(int stage, MatParam &default_cubetex)
{
if (stage != -1)
{
if (g_C3DLow.m_pReflectionParaboloid)
{
g_C3DLow.SetTexture(stage, g_C3DLow.m_pReflectionParaboloid);
g_C3DLow.SetTextureFilter(stage, C3DLOWTFILTER_LOW);
g_pD3DDevice->SetSamplerState(stage, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
g_pD3DDevice->SetSamplerState(stage, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
}
else
{
g_C3DLow.SetTexture(stage, default_cubetex);
}
}
}
void RestoreReflectionStage(int stage, MatParam &default_cubetex)
{
if (stage != -1)
{
if (g_C3DLow.m_pReflectionParaboloid)
{
g_pD3DDevice->SetSamplerState(stage, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
g_pD3DDevice->SetSamplerState(stage, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
}
else
{
g_C3DLow.RestoreTexture(stage, default_cubetex);
}
}
}
// ***************************************
// Blending for multipass effects
// ***************************************
void C3DLow::SetAddBlend(bool set_alpha_test)
{
//we have to modify the color of the fog to avoid the brightening of object
g_pD3DDevice->SetRenderState(D3DRS_FOGCOLOR, 0x0);
g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
g_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
g_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
g_pD3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
if (set_alpha_test)
{
if (!g_C3DLow.m_AlphaTestEnabled)
g_pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, true);
int alpha_ref = 0x04;
g_pD3DDevice->SetRenderState(D3DRS_ALPHAREF, alpha_ref);
}
else
{
if (g_C3DLow.m_AlphaTestEnabled)
g_pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false);
}
}
void C3DLow::RestoreAddBlend(bool set_alpha_test)
{
//we have to modify of the effect of the fog
g_pD3DDevice->SetRenderState(D3DRS_FOGCOLOR, g_C3DLow.m_FogInfo.fogcolor);
//the states below can be put into a StateBlock (maybe the two above too but
// without the if() !!!)
g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, g_C3DLow.m_AlphaBlendEnabled);
g_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, g_C3DLow.m_SrcBlend);
g_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, g_C3DLow.m_DestBlend);
g_pD3DDevice->SetRenderState(D3DRS_BLENDOP, g_C3DLow.m_BlendOp);
g_pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, g_C3DLow.m_AlphaTestEnabled);
//g_pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
}
// ***************************************
// Light
// ***************************************
void C3DLow::GetAmbientAndDiffuseLight(ColorValue &v, float greyScaleFactor)
{
v.r = m_Light.Diffuse.r + m_Light.SH.red[0] * C3DLowSH3::m_SHC[0];
v.g = m_Light.Diffuse.g + m_Light.SH.green[0] * C3DLowSH3::m_SHC[0];
v.b = m_Light.Diffuse.b + m_Light.SH.blue[0] * C3DLowSH3::m_SHC[0];
v.a = 1.0f;
float grayScale = 0.333f * (v.r + v.g + v.b);
v.r += greyScaleFactor * (grayScale - v.r);
v.g += greyScaleFactor * (grayScale - v.g);
v.b += greyScaleFactor * (grayScale - v.b);
if (v.r>1.0f) v.r = 1.0f;
if (v.g>1.0f) v.g = 1.0f;
if (v.b>1.0f) v.b = 1.0f;
}
int C3DLow::IsD3DStateValid()
{
//check
int num_error=0;
DWORD value;
unsigned int i;
//check color states
g_pD3DDevice->GetTextureStageState(0, D3DTSS_COLOROP, &value);
if (value!=D3DTOP_MODULATE) num_error++;
g_pD3DDevice->GetTextureStageState(0, D3DTSS_COLORARG1, &value);
if (value!=D3DTA_TEXTURE) num_error++;
g_pD3DDevice->GetTextureStageState(0, D3DTSS_COLORARG2, &value);
if (value!=D3DTA_CURRENT && value!=D3DTA_DIFFUSE) num_error++;
g_pD3DDevice->GetTextureStageState(0, D3DTSS_COLORARG0, &value);
if (value!=D3DTA_CURRENT) num_error++;
for(i=1; i<8; ++i)
{
g_pD3DDevice->GetTextureStageState(i, D3DTSS_COLOROP, &value);
if (value!=D3DTOP_DISABLE) num_error++;
g_pD3DDevice->GetTextureStageState(i, D3DTSS_COLORARG1, &value);
if (value!=D3DTA_TEXTURE) num_error++;
g_pD3DDevice->GetTextureStageState(i, D3DTSS_COLORARG2, &value);
if (value!=D3DTA_CURRENT) num_error++;
g_pD3DDevice->GetTextureStageState(i, D3DTSS_COLORARG0, &value);
if (value!=D3DTA_CURRENT) num_error++;
}
//check alpha states
g_pD3DDevice->GetTextureStageState(0, D3DTSS_ALPHAOP, &value);
if (value!=D3DTOP_MODULATE) num_error++;
g_pD3DDevice->GetTextureStageState(0, D3DTSS_ALPHAARG1, &value);
if (value!=D3DTA_TEXTURE) num_error++;
g_pD3DDevice->GetTextureStageState(0, D3DTSS_ALPHAARG2, &value);
//if (value!=D3DTA_CURRENT && value!=D3DTA_DIFFUSE) num_error++;
if (value!=D3DTA_TFACTOR) num_error++;
g_pD3DDevice->GetTextureStageState(0, D3DTSS_ALPHAARG0, &value);
if (value!=D3DTA_CURRENT) num_error++;
for(i=1; i<8; ++i)
{
g_pD3DDevice->GetTextureStageState(i, D3DTSS_ALPHAOP, &value);
if (value!=D3DTOP_DISABLE) num_error++;
g_pD3DDevice->GetTextureStageState(i, D3DTSS_ALPHAARG1, &value);
if (value!=D3DTA_TEXTURE) num_error++;
g_pD3DDevice->GetTextureStageState(i, D3DTSS_ALPHAARG2, &value);
if (value!=D3DTA_CURRENT) num_error++;
g_pD3DDevice->GetTextureStageState(i, D3DTSS_ALPHAARG0, &value);
if (value!=D3DTA_CURRENT) num_error++;
}
g_pD3DDevice->GetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, &value);
if (value!=D3DMCS_MATERIAL) num_error++;
g_pD3DDevice->GetRenderState(D3DRS_AMBIENTMATERIALSOURCE, &value);
if (value!=D3DMCS_MATERIAL) num_error++;
g_pD3DDevice->GetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, &value);
if (value!=D3DMCS_MATERIAL) num_error++;
g_pD3DDevice->GetRenderState(D3DRS_SPECULARMATERIALSOURCE, &value);
if (value!=D3DMCS_MATERIAL) num_error++;
g_pD3DDevice->GetRenderState(D3DRS_CULLMODE, &value);
if (value!=(DWORD)g_C3DLow.m_CullMode) num_error++;
g_pD3DDevice->GetRenderState(D3DRS_ALPHABLENDENABLE, &value);
if (value!=(DWORD)g_C3DLow.m_AlphaBlendEnabled) num_error++;
if (g_C3DLow.m_AlphaBlendEnabled)
{
g_pD3DDevice->GetRenderState(D3DRS_SRCBLEND, &value);
if (value!=(DWORD)g_C3DLow.m_SrcBlend) num_error++;
g_pD3DDevice->GetRenderState(D3DRS_DESTBLEND, &value);
if (value!=(DWORD)g_C3DLow.m_DestBlend) num_error++;
g_pD3DDevice->GetRenderState(D3DRS_BLENDOP, &value);
if (value!=(DWORD)g_C3DLow.m_BlendOp) num_error++;
}
g_pD3DDevice->GetRenderState(D3DRS_ALPHATESTENABLE, &value);
if (value!=(DWORD)g_C3DLow.m_AlphaTestEnabled) num_error++;
//texcoordindex and sampler state
//LPDIRECT3DBASETEXTURE9 tex;
for(i=0; i<8; ++i)
{
g_pD3DDevice->GetTextureStageState(i, D3DTSS_TEXCOORDINDEX, &value);
if (value!=i) num_error++;
g_pD3DDevice->GetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
if (value!= D3DTTFF_DISABLE) num_error++;
// Because of an optimization textures don't need to be set to NULL in material end
// g_pD3DDevice->GetTexture(i, &tex);
// if (tex) num_error++;
g_pD3DDevice->GetSamplerState(i, D3DSAMP_MINFILTER, &value);
if ((D3DTEXTUREFILTERTYPE)value != g_C3DLow.m_DefaultFilterStates[ g_C3DLow.m_CurrentTFilterQualities[i] ].minFilter) num_error++;
g_pD3DDevice->GetSamplerState(i, D3DSAMP_MAGFILTER, &value);
if ((D3DTEXTUREFILTERTYPE)value != g_C3DLow.m_DefaultFilterStates[ g_C3DLow.m_CurrentTFilterQualities[i] ].magFilter) num_error++;
g_pD3DDevice->GetSamplerState(i, D3DSAMP_MIPFILTER, &value);
if ((D3DTEXTUREFILTERTYPE)value != g_C3DLow.m_DefaultFilterStates[ g_C3DLow.m_CurrentTFilterQualities[i]].mipFilter) num_error++;
g_pD3DDevice->GetSamplerState(i, D3DSAMP_MAXANISOTROPY, &value);
if (value!= g_C3DLow.m_DefaultFilterStates[ g_C3DLow.m_CurrentTFilterQualities[i]].maxAnisotropy) num_error++;
g_pD3DDevice->GetSamplerState(i, D3DSAMP_ADDRESSU, &value);
if ((D3DTEXTUREADDRESS)value!=D3DTADDRESS_WRAP) num_error++;
g_pD3DDevice->GetSamplerState(i, D3DSAMP_ADDRESSV, &value);
if ((D3DTEXTUREADDRESS)value!=D3DTADDRESS_WRAP) num_error++;
g_pD3DDevice->GetSamplerState(i, D3DSAMP_ADDRESSW, &value);
if ((D3DTEXTUREADDRESS)value!=D3DTADDRESS_WRAP) num_error++;
}
// Because of an optimization shaders don't need to be set to NULL in material end
//LPDIRECT3DPIXELSHADER9 pshader;
//g_pD3DDevice->GetPixelShader(&pshader);
//if (pshader) num_error++;
//LPDIRECT3DVERTEXSHADER9 vshader;
//g_pD3DDevice->GetVertexShader(&vshader);
//if (vshader) num_error++;
if (num_error)
OutputDebugStringA("IsD3DStateValid failed\n");
if (num_error!=0)
_asm nop;
return num_error==0;
}
// ***************************************************
// D3D State handler
// ***************************************************
//reads the default states
StateManager::StateManager()
{
ShaderParamClear();
m_VertexShaderConstantCount=g_C3DLow.GetMaxVertexShaderConst();
m_PixelShaderConstantCount=MAXPIXELSHADERCONST;
m_UpdateVertexF.empty();
m_UpdatePixelF.empty();
}
void StateManager::Apply()
{
g_C3DLow.ClearDirtyStates();
//set shader constants
Profile_StartTimerFast("PSConstantApply");
if (m_UpdatePixelF.m_from<=m_UpdatePixelF.m_to)
{
g_pD3DDevice->SetPixelShaderConstantF(m_UpdatePixelF.m_from,
m_PixelShaderConstants[m_UpdatePixelF.m_from],m_UpdatePixelF.m_to - m_UpdatePixelF.m_from + 1);
Profile_AddToCounterFast("PSConstantApplyC", m_UpdatePixelF.m_to - m_UpdatePixelF.m_from + 1);
}
Profile_EndTimerFast("PSConstantApply");
Profile_StartTimerFast("VSConstantApply_FLush");
//g_C3DLow.FlushGPU();
Profile_EndTimerFast("VSConstantApply_FLush");
Profile_StartTimerFast("VSConstantApply");
if (m_UpdateVertexF.m_from <= m_UpdateVertexF.m_to)
{
g_pD3DDevice->SetVertexShaderConstantF(m_UpdateVertexF.m_from,
m_VertexShaderConstants[m_UpdateVertexF.m_from],m_UpdateVertexF.m_to - m_UpdateVertexF.m_from + 1);
Profile_AddToCounterFast("VSConstantApplyC", m_UpdateVertexF.m_to - m_UpdateVertexF.m_from + 1);
}
Profile_EndTimerFast("VSConstantApply");
m_UpdateVertexF.empty();
m_UpdatePixelF.empty();
}
//
//helper functions to set 1PLUS3LIGHT
//
void StateManager::SetSHConstants(float4 *constants, C3DLowSH2 *sh)
{
#define ind(i,j) ((i)*(i)+(i)+(j))
//rotate with MatView matrix
float red[4],green[4],blue[4];
D3DXSHRotate(red, 2, (D3DXMATRIX*) &g_C3DLow.m_MatView, sh->red);
D3DXSHRotate(green,2, (D3DXMATRIX*) &g_C3DLow.m_MatView, sh->green);
D3DXSHRotate(blue, 2, (D3DXMATRIX*) &g_C3DLow.m_MatView, sh->blue);
//cAr
constants[0][0] = - C3DLowSH3::m_SHC[1] * red[ind(1,1)];
constants[0][1] = - C3DLowSH3::m_SHC[1] * red[ind(1,-1)];
constants[0][2] = C3DLowSH3::m_SHC[1] * red[ind(1,0)];
constants[0][3] = C3DLowSH3::m_SHC[0] * red[ind(0,0)] ;
//cAg
constants[1][0] = - C3DLowSH3::m_SHC[1] * green[ind(1,1)];
constants[1][1] = - C3DLowSH3::m_SHC[1] * green[ind(1,-1)];
constants[1][2] = C3DLowSH3::m_SHC[1] * green[ind(1,0)];
constants[1][3] = C3DLowSH3::m_SHC[0] * green[ind(0,0)] ;
//cAb
constants[2][0] = - C3DLowSH3::m_SHC[1] * blue[ind(1,1)];
constants[2][1] = - C3DLowSH3::m_SHC[1] * blue[ind(1,-1)];
constants[2][2] = C3DLowSH3::m_SHC[1] * blue[ind(1,0)];
constants[2][3] = C3DLowSH3::m_SHC[0] * blue[ind(0,0)];
#undef ind
}
void StateManager::SetSHConstantsWorld(float4 *constants, C3DLowSH2 *sh)
{
#define ind(i,j) ((i)*(i)+(i)+(j))
//cAr
constants[0][0] = - C3DLowSH3::m_SHC[1] * sh->red[ind(1,1)];
constants[0][1] = - C3DLowSH3::m_SHC[1] * sh->red[ind(1,-1)];
constants[0][2] = C3DLowSH3::m_SHC[1] * sh->red[ind(1,0)];
constants[0][3] = C3DLowSH3::m_SHC[0] * sh->red[ind(0,0)] ;
//cAg
constants[1][0] = - C3DLowSH3::m_SHC[1] * sh->green[ind(1,1)];
constants[1][1] = - C3DLowSH3::m_SHC[1] * sh->green[ind(1,-1)];
constants[1][2] = C3DLowSH3::m_SHC[1] * sh->green[ind(1,0)];
constants[1][3] = C3DLowSH3::m_SHC[0] * sh->green[ind(0,0)] ;
//cAb
constants[2][0] = - C3DLowSH3::m_SHC[1] * sh->blue[ind(1,1)];
constants[2][1] = - C3DLowSH3::m_SHC[1] * sh->blue[ind(1,-1)];
constants[2][2] = C3DLowSH3::m_SHC[1] * sh->blue[ind(1,0)];
constants[2][3] = C3DLowSH3::m_SHC[0] * sh->blue[ind(0,0)];
#undef ind
}
void StateManager::SetSHConstants(float4 *constants, C3DLowSH3 *sh, int bands)
{
#define ind(i,j) ((i)*(i)+(i)+(j))
//rotate with MatView matrix
if (bands == 2)
{
float red[9],green[9],blue[9];
D3DXSHRotate(red, 2, (D3DXMATRIX*) &g_C3DLow.m_MatView, sh->red);
D3DXSHRotate(green,2, (D3DXMATRIX*) &g_C3DLow.m_MatView, sh->green);
D3DXSHRotate(blue, 2, (D3DXMATRIX*) &g_C3DLow.m_MatView, sh->blue);
//cAr
constants[0][0] = - C3DLowSH3::m_SHC[1] * red[ind(1,1)];
constants[0][1] = - C3DLowSH3::m_SHC[1] * red[ind(1,-1)];
constants[0][2] = C3DLowSH3::m_SHC[1] * red[ind(1,0)];
constants[0][3] = C3DLowSH3::m_SHC[0] * red[ind(0,0)] ;
//cAg
constants[1][0] = - C3DLowSH3::m_SHC[1] * green[ind(1,1)];
constants[1][1] = - C3DLowSH3::m_SHC[1] * green[ind(1,-1)];
constants[1][2] = C3DLowSH3::m_SHC[1] * green[ind(1,0)];
constants[1][3] = C3DLowSH3::m_SHC[0] * green[ind(0,0)] ;
//cAb
constants[2][0] = - C3DLowSH3::m_SHC[1] * blue[ind(1,1)];
constants[2][1] = - C3DLowSH3::m_SHC[1] * blue[ind(1,-1)];
constants[2][2] = C3DLowSH3::m_SHC[1] * blue[ind(1,0)];
constants[2][3] = C3DLowSH3::m_SHC[0] * blue[ind(0,0)];
}
else
{ //bands == 3
float red[9],green[9],blue[9];
D3DXSHRotate(red, 3, (D3DXMATRIX*) &g_C3DLow.m_MatView, sh->red);
D3DXSHRotate(green,3, (D3DXMATRIX*) &g_C3DLow.m_MatView, sh->green);
D3DXSHRotate(blue, 3, (D3DXMATRIX*) &g_C3DLow.m_MatView, sh->blue);
//cAr
constants[0][0] = - C3DLowSH3::m_SHC[1] * red[ind(1,1)];
constants[0][1] = - C3DLowSH3::m_SHC[1] * red[ind(1,-1)];
constants[0][2] = C3DLowSH3::m_SHC[1] * red[ind(1,0)];
constants[0][3] = C3DLowSH3::m_SHC[0] * red[ind(0,0)]
- C3DLowSH3::m_SHC[3] * red[ind(2,0)] ;
//cAg
constants[1][0] = - C3DLowSH3::m_SHC[1] * green[ind(1,1)];
constants[1][1] = - C3DLowSH3::m_SHC[1] * green[ind(1,-1)];
constants[1][2] = C3DLowSH3::m_SHC[1] * green[ind(1,0)];
constants[1][3] = C3DLowSH3::m_SHC[0] * green[ind(0,0)]
- C3DLowSH3::m_SHC[3] * green[ind(2,0)] ;
//cAb
constants[2][0] = - C3DLowSH3::m_SHC[1] * blue[ind(1,1)];
constants[2][1] = - C3DLowSH3::m_SHC[1] * blue[ind(1,-1)];
constants[2][2] = C3DLowSH3::m_SHC[1] * blue[ind(1,0)];
constants[2][3] = C3DLowSH3::m_SHC[0] * blue[ind(0,0)]
- C3DLowSH3::m_SHC[3] * blue[ind(2,0)];
//cBr
constants[3][0] = C3DLowSH3::m_SHC[2] * red[ind(2,-2)];
constants[3][1] = - C3DLowSH3::m_SHC[2] * red[ind(2,-1)];
constants[3][2] = 3.0f * C3DLowSH3::m_SHC[3] * red[ind(2,0)];
constants[3][3] = - C3DLowSH3::m_SHC[2] * red[ind(2,1)];
//cBg
constants[4][0] = C3DLowSH3::m_SHC[2] * green[ind(2,-2)];
constants[4][1] = - C3DLowSH3::m_SHC[2] * green[ind(2,-1)];
constants[4][2] = 3.0f * C3DLowSH3::m_SHC[3] * green[ind(2,0)];
constants[4][3] = - C3DLowSH3::m_SHC[2] * green[ind(2,1)];
//cBb
constants[5][0] = C3DLowSH3::m_SHC[2] * blue[ind(2,-2)];
constants[5][1] = - C3DLowSH3::m_SHC[2] * blue[ind(2,-1)];
constants[5][2] = 3.0f * C3DLowSH3::m_SHC[3] * blue[ind(2,0)];
constants[5][3] = - C3DLowSH3::m_SHC[2] * blue[ind(2,1)];
//cC
constants[6][0] = C3DLowSH3::m_SHC[4] * red[ind(2,2)];
constants[6][1] = C3DLowSH3::m_SHC[4] * green[ind(2,2)];
constants[6][2] = C3DLowSH3::m_SHC[4] * blue[ind(2,2)];
}
#undef ind
}
void StateManager::SetSHConstantsWorld(float4 *constants, C3DLowSH3 *sh, int bands)
{
#define ind(i,j) ((i)*(i)+(i)+(j))
//rotate with MatView matrix
if (bands == 2)
{
//cAr
constants[0][0] = - C3DLowSH3::m_SHC[1] * sh->red[ind(1,1)];
constants[0][1] = - C3DLowSH3::m_SHC[1] * sh->red[ind(1,-1)];
constants[0][2] = C3DLowSH3::m_SHC[1] * sh->red[ind(1,0)];
constants[0][3] = C3DLowSH3::m_SHC[0] * sh->red[ind(0,0)] ;
//cAg
constants[1][0] = - C3DLowSH3::m_SHC[1] * sh->green[ind(1,1)];
constants[1][1] = - C3DLowSH3::m_SHC[1] * sh->green[ind(1,-1)];
constants[1][2] = C3DLowSH3::m_SHC[1] * sh->green[ind(1,0)];
constants[1][3] = C3DLowSH3::m_SHC[0] * sh->green[ind(0,0)] ;
//cAb
constants[2][0] = - C3DLowSH3::m_SHC[1] * sh->blue[ind(1,1)];
constants[2][1] = - C3DLowSH3::m_SHC[1] * sh->blue[ind(1,-1)];
constants[2][2] = C3DLowSH3::m_SHC[1] * sh->blue[ind(1,0)];
constants[2][3] = C3DLowSH3::m_SHC[0] * sh->blue[ind(0,0)];
}
else
{ //bands == 3
//cAr
constants[0][0] = - C3DLowSH3::m_SHC[1] * sh->red[ind(1,1)];
constants[0][1] = - C3DLowSH3::m_SHC[1] * sh->red[ind(1,-1)];
constants[0][2] = C3DLowSH3::m_SHC[1] * sh->red[ind(1,0)];
constants[0][3] = C3DLowSH3::m_SHC[0] * sh->red[ind(0,0)]
- C3DLowSH3::m_SHC[3] * sh->red[ind(2,0)] ;
//cAg
constants[1][0] = - C3DLowSH3::m_SHC[1] * sh->green[ind(1,1)];
constants[1][1] = - C3DLowSH3::m_SHC[1] * sh->green[ind(1,-1)];
constants[1][2] = C3DLowSH3::m_SHC[1] * sh->green[ind(1,0)];
constants[1][3] = C3DLowSH3::m_SHC[0] * sh->green[ind(0,0)]
- C3DLowSH3::m_SHC[3] * sh->green[ind(2,0)] ;
//cAb
constants[2][0] = - C3DLowSH3::m_SHC[1] * sh->blue[ind(1,1)];
constants[2][1] = - C3DLowSH3::m_SHC[1] * sh->blue[ind(1,-1)];
constants[2][2] = C3DLowSH3::m_SHC[1] * sh->blue[ind(1,0)];
constants[2][3] = C3DLowSH3::m_SHC[0] * sh->blue[ind(0,0)]
- C3DLowSH3::m_SHC[3] * sh->blue[ind(2,0)];
//cBr
constants[3][0] = C3DLowSH3::m_SHC[2] * sh->red[ind(2,-2)];
constants[3][1] = - C3DLowSH3::m_SHC[2] * sh->red[ind(2,-1)];
constants[3][2] = 3.0f * C3DLowSH3::m_SHC[3] * sh->red[ind(2,0)];
constants[3][3] = - C3DLowSH3::m_SHC[2] * sh->red[ind(2,1)];
//cBg
constants[4][0] = C3DLowSH3::m_SHC[2] * sh->green[ind(2,-2)];
constants[4][1] = - C3DLowSH3::m_SHC[2] * sh->green[ind(2,-1)];
constants[4][2] = 3.0f * C3DLowSH3::m_SHC[3] * sh->green[ind(2,0)];
constants[4][3] = - C3DLowSH3::m_SHC[2] * sh->green[ind(2,1)];
//cBb
constants[5][0] = C3DLowSH3::m_SHC[2] * sh->blue[ind(2,-2)];
constants[5][1] = - C3DLowSH3::m_SHC[2] * sh->blue[ind(2,-1)];
constants[5][2] = 3.0f * C3DLowSH3::m_SHC[3] * sh->blue[ind(2,0)];
constants[5][3] = - C3DLowSH3::m_SHC[2] * sh->blue[ind(2,1)];
//cC
constants[6][0] = C3DLowSH3::m_SHC[4] * sh->red[ind(2,2)];
constants[6][1] = C3DLowSH3::m_SHC[4] * sh->green[ind(2,2)];
constants[6][2] = C3DLowSH3::m_SHC[4] * sh->blue[ind(2,2)];
}
#undef ind
}
void StateManager::SetVertexShaderConstantF(int index, shader_param_type type)
{
//the float4s will be set in ShaderParamUpdate
if (m_VShaderParamStateCount<MAXVERTEXSHADERCONST)
{
m_VShaderParamStates[m_VShaderParamStateCount].index = index;
m_VShaderParamStates[m_VShaderParamStateCount++].type = type;
}
else
{
#ifdef C3DLOW_DEBUG
OutputDebugStringA("StateManager::SetVertexShaderConstantF: Too many constant\n");
#endif
}
}
void StateManager::SetPixelShaderConstantF(int index, shader_param_type type)
{
//the float4s will be set in ShaderParamUpdate
if (m_PShaderParamStateCount<MAXPIXELSHADERCONST)
{
m_PShaderParamStates[m_PShaderParamStateCount].index = index;
m_PShaderParamStates[m_PShaderParamStateCount++].type = type;
}
else
{
#ifdef C3DLOW_DEBUG
OutputDebugStringA("StateManager::SetPixelShaderConstantF: Too many constant\n");
#endif
}
}
float g_sky_dist = -10.0f;
void StateManager::SetShaderConstantF(int shader_type, int index, shader_param_type param_type){
int size = 0;
float4 *constants = NULL;
Interval *interval = NULL;
if (shader_type == ST_VERTEX)
{
constants = &m_VertexShaderConstants[index];
interval = &m_UpdateVertexF;
}
else //ST_PIXEL
{
constants = &m_PixelShaderConstants[index];
interval = &m_UpdatePixelF;
}
switch(param_type)
{
case SYSFLOAT_WORLDVIEWPROJECTION:
{
D3DXMatrixMultiply((D3DXMATRIX*)&constants[0][0],
(D3DXMATRIX*)&g_C3DLow.m_MatWorld, (D3DXMATRIX*)g_C3DLow.GetViewProjMatrix());
size = 4;
}
break;
case SYSFLOAT_WORLDVIEWPROJECTIONT:
{
D3DXMATRIX temp1;
D3DXMatrixMultiply(&temp1, (D3DXMATRIX*)&g_C3DLow.m_MatWorld, (D3DXMATRIX*)g_C3DLow.GetViewProjMatrix());
D3DXMatrixTranspose((D3DXMATRIX*)&constants[0][0], &temp1);
size = 4;
}
break;
case SYSFLOAT_WORLDVIEW:
{
D3DXMATRIX temp1;
D3DXMatrixMultiply((D3DXMATRIX*)&constants[0][0],
(D3DXMATRIX*)&g_C3DLow.m_MatWorld,
(D3DXMATRIX*)&g_C3DLow.m_MatView);
size = 4;
}
break;
case SYSFLOAT_WORLDVIEWT:
{
D3DXMATRIX temp1;
D3DXMatrixMultiply(&temp1, (D3DXMATRIX*)&g_C3DLow.m_MatWorld,
(D3DXMATRIX*)&g_C3DLow.m_MatView);
// D3DXMatrixTranspose((D3DXMATRIX*)&m_VertexShaderConstants[index][0], &temp1);
constants[0][0] = temp1._11;
constants[0][1] = temp1._21;
constants[0][2] = temp1._31;
constants[0][3] = temp1._41;
constants[1][0] = temp1._12;
constants[1][1] = temp1._22;
constants[1][2] = temp1._32;
constants[1][3] = temp1._42;
constants[2][0] = temp1._13;
constants[2][1] = temp1._23;
constants[2][2] = temp1._33;
constants[2][3] = temp1._43;
size = 3;
}
break;
case SYSFLOAT_VIEWPROJECTION:
{
D3DXMatrixMultiply((D3DXMATRIX*)&constants[0][0],
(D3DXMATRIX*)&g_C3DLow.m_MatView,
(D3DXMATRIX*)&g_C3DLow.m_MatProj);
size = 4;
}
break;
case SYSFLOAT_VIEWPROJECTIONT:
{
C3DLowMatrix* viewproj = g_C3DLow.GetViewProjMatrix();
constants[0][0] = viewproj->_11;
constants[0][1] = viewproj->_21;
constants[0][2] = viewproj->_31;
constants[0][3] = viewproj->_41;
constants[1][0] = viewproj->_12;
constants[1][1] = viewproj->_22;
constants[1][2] = viewproj->_32;
constants[1][3] = viewproj->_42;
constants[2][0] = viewproj->_13;
constants[2][1] = viewproj->_23;
constants[2][2] = viewproj->_33;
constants[2][3] = viewproj->_43;
constants[3][0] = viewproj->_14;
constants[3][1] = viewproj->_24;
constants[3][2] = viewproj->_34;
constants[3][3] = viewproj->_44;
size = 4;
}
break;
case SYSFLOAT_VIEWPROJECTIONT_EC:
{
C3DLowMatrix* viewproj = g_C3DLow.GetViewProjECMatrix();
constants[0][0] = viewproj->_11;
constants[0][1] = viewproj->_21;
constants[0][2] = viewproj->_31;
constants[0][3] = viewproj->_41;
constants[1][0] = viewproj->_12;
constants[1][1] = viewproj->_22;
constants[1][2] = viewproj->_32;
constants[1][3] = viewproj->_42;
constants[2][0] = viewproj->_13;
constants[2][1] = viewproj->_23;
constants[2][2] = viewproj->_33;
constants[2][3] = viewproj->_43;
constants[3][0] = viewproj->_14;
constants[3][1] = viewproj->_24;
constants[3][2] = viewproj->_34;
constants[3][3] = viewproj->_44;
D3DXMATRIX vpec = D3DXMATRIX((const float*)constants);
size = 4;
}
break;
case SYSFLOAT_WORLD:
{
* ((D3DXMATRIX*)&constants[0][0]) = (*(D3DXMATRIX*)&g_C3DLow.m_MatWorld);
size = 4;
}
break;
case SYSFLOAT_WORLDT:
{
// D3DXMatrixTranspose((D3DXMATRIX*)&constants[0][0],
// (D3DXMATRIX*)&g_C3DLow.m_MatWorld);
C3DLowMatrix &temp1 = g_C3DLow.m_MatWorld;
//transpose
constants[0][0] = temp1._11;
constants[0][1] = temp1._21;
constants[0][2] = temp1._31;
constants[0][3] = temp1._41;
constants[1][0] = temp1._12;
constants[1][1] = temp1._22;
constants[1][2] = temp1._32;
constants[1][3] = temp1._42;
constants[2][0] = temp1._13;
constants[2][1] = temp1._23;
constants[2][2] = temp1._33;
constants[2][3] = temp1._43;
size = 3;
}
break;
case SYSFLOAT_WORLDT_EC:
{
// D3DXMatrixTranspose((D3DXMATRIX*)&constants[0][0],
// (D3DXMATRIX*)&g_C3DLow.m_MatWorld);
C3DLowMatrix &temp1 = g_C3DLow.m_MatWorld;
C3DLowMatrix *invview = g_C3DLow.GetInvViewMatrix();
//transpose
constants[0][0] = temp1._11;
constants[0][1] = temp1._21;
constants[0][2] = temp1._31;
constants[0][3] = temp1._41 - invview->_41;
constants[1][0] = temp1._12;
constants[1][1] = temp1._22;
constants[1][2] = temp1._32;
constants[1][3] = temp1._42 - invview->_42;
constants[2][0] = temp1._13;
constants[2][1] = temp1._23;
constants[2][2] = temp1._33;
constants[2][3] = temp1._43 - invview->_43;
D3DXMATRIX wec = D3DXMATRIX((const float *)constants);
size = 3;
}
break;
case SYSFLOAT_WORLDI:
{
D3DXMatrixInverse((D3DXMATRIX*)&constants[0][0], NULL,
(D3DXMATRIX*)&g_C3DLow.m_MatWorld);
size = 4;
}
break;
case SYSFLOAT_WORLDIT:
{
D3DXMATRIX temp1;
D3DXMatrixInverse(&temp1, NULL, (D3DXMATRIX*)&g_C3DLow.m_MatWorld);
D3DXMatrixTranspose((D3DXMATRIX*)&constants[0][0], &temp1);
size = 4;
}
break;
case SYSFLOAT_PROJECTION:
{
* ((D3DXMATRIX*)&constants[0][0]) = (*(D3DXMATRIX*)&g_C3DLow.m_MatProj);
size = 4;
}
break;
case SYSFLOAT_PARABOLOID_PROJECTION:
{
constants[0][0] = 0.0f;
constants[0][1] = 0.0f;
constants[0][2] = (g_C3DLow.m_ParaboloidMode==C3DLOWPARABOLOIDMODE_BACK)?1.0f:-1.0f;
constants[0][3] = 0.0001f;
size = 1;
}
break;
case SYSFLOAT_PROJECTIONT:
{
D3DXMatrixTranspose((D3DXMATRIX*)&constants[0][0],
(D3DXMATRIX*)&g_C3DLow.m_MatProj);
size = 4;
}
break;
case SYSFLOAT_VIEWT:
{
D3DXMATRIX* temp1 = (D3DXMATRIX*)&g_C3DLow.m_MatView;
constants[0][0] = temp1->_11;
constants[0][1] = temp1->_21;
constants[0][2] = temp1->_31;
constants[0][3] = temp1->_41;
constants[1][0] = temp1->_12;
constants[1][1] = temp1->_22;
constants[1][2] = temp1->_32;
constants[1][3] = temp1->_42;
constants[2][0] = temp1->_13;
constants[2][1] = temp1->_23;
constants[2][2] = temp1->_33;
constants[2][3] = temp1->_43;
size = 3;
}
break;
case SYSFLOAT_VIEWT_EC:
{
D3DXMATRIX* temp1 = (D3DXMATRIX*)&g_C3DLow.m_MatView;
constants[0][0] = temp1->_11;
constants[0][1] = temp1->_21;
constants[0][2] = temp1->_31;
constants[0][3] = 0.0f;
constants[1][0] = temp1->_12;
constants[1][1] = temp1->_22;
constants[1][2] = temp1->_32;
constants[1][3] = 0.0f;
constants[2][0] = temp1->_13;
constants[2][1] = temp1->_23;
constants[2][2] = temp1->_33;
constants[2][3] = 0.0f;
size = 3;
}
break;
case SYSFLOAT_VIEWIT:
{
//frequently used
D3DXMATRIX temp1;
D3DXMatrixInverse((D3DXMATRIX*)&temp1, NULL,
(D3DXMATRIX*)&g_C3DLow.m_MatView);
constants[0][0] = temp1._11;
constants[0][1] = temp1._21;
constants[0][2] = temp1._31;
constants[0][3] = temp1._41;
constants[1][0] = temp1._12;
constants[1][1] = temp1._22;
constants[1][2] = temp1._32;
constants[1][3] = temp1._42;
constants[2][0] = temp1._13;
constants[2][1] = temp1._23;
constants[2][2] = temp1._33;
constants[2][3] = temp1._43;
size = 3;
}
break;
case SYSFLOAT_VIEWZ:
constants[0][0] = g_C3DLow.m_MatView._13;
constants[0][1] = g_C3DLow.m_MatView._23;
constants[0][2] = g_C3DLow.m_MatView._33;
constants[0][3] = g_C3DLow.m_MatView._43;
size = 1;
break;
case SYSFLOAT_WORLDVIEWZ:
{
D3DXMATRIX temp1;
D3DXMatrixMultiply(&temp1, (D3DXMATRIX*)&g_C3DLow.m_MatWorld,
(D3DXMATRIX*)&g_C3DLow.m_MatView);
constants[0][0] = temp1._13;
constants[0][1] = temp1._23;
constants[0][2] = temp1._33;
constants[0][3] = temp1._43;
size = 1;
}
break;
case SYSFLOAT_CAMERAPOS_WORLD:
{
// we will need the inverse of the view matrix
C3DLowMatrix *invview = g_C3DLow.GetInvViewMatrix();
constants[0][0] = invview->_41;
constants[0][1] = invview->_42;
constants[0][2] = invview->_43;
constants[0][3] = 1.0f;
size = 1;
}
break;
case SYSFLOAT_CAMERAPOS_OBJECT:
{
// ONLY TRANSLATE WORLD TRANSFORMATION IS SUPPOSED!!!
// we will need the inverse of the view matrix
C3DLowMatrix *world = g_C3DLow.GetWorldMatrix();
C3DLowMatrix *invview = g_C3DLow.GetInvViewMatrix();
constants[0][0] = invview->_41 - world->_41;
constants[0][1] = invview->_42 - world->_42;
constants[0][2] = invview->_43 - world->_43;
constants[0][3] = 1.0f;
size = 1;
}
break;
case SYSFLOAT_BONES:
{
if(g_C3DLow.m_pBoneMatrices==NULL)
return;
int ci=0;
for (int i = 0; i < g_C3DLow.m_BoneMatrixIndexCount; ++i)
{
D3DXMATRIX temp1;
D3DXMatrixMultiply(&temp1,(D3DXMATRIX*)&g_C3DLow.m_pBoneMatrices[g_C3DLow.m_pBoneMatrixIndices[i]],
(D3DXMATRIX*)&g_C3DLow.m_MatView);
constants[ci][0] = temp1._11;
constants[ci][1] = temp1._21;
constants[ci][2] = temp1._31;
constants[ci++][3] = temp1._41;
constants[ci][0] = temp1._12;
constants[ci][1] = temp1._22;
constants[ci][2] = temp1._32;
constants[ci++][3] = temp1._42;
constants[ci][0] = temp1._13;
constants[ci][1] = temp1._23;
constants[ci][2] = temp1._33;
constants[ci++][3] = temp1._43;
}
size= 3 * g_C3DLow.m_BoneMatrixIndexCount;
}
break;
case SYSFLOAT_BONES_WORLD:
{
if(g_C3DLow.m_pBoneMatrices==NULL)
return;
int ci=0;
for (int i = 0; i < g_C3DLow.m_BoneMatrixIndexCount; ++i)
{
C3DLowMatrix &temp1 = g_C3DLow.m_pBoneMatrices[g_C3DLow.m_pBoneMatrixIndices[i]];
constants[ci][0] = temp1._11;
constants[ci][1] = temp1._21;
constants[ci][2] = temp1._31;
constants[ci++][3] = temp1._41;
constants[ci][0] = temp1._12;
constants[ci][1] = temp1._22;
constants[ci][2] = temp1._32;
constants[ci++][3] = temp1._42;
constants[ci][0] = temp1._13;
constants[ci][1] = temp1._23;
constants[ci][2] = temp1._33;
constants[ci++][3] = temp1._43;
}
size= 3 * g_C3DLow.m_BoneMatrixIndexCount;
}
break;
case SYSFLOAT_BONES_WORLD_EC:
{
if(g_C3DLow.m_pBoneMatrices==NULL)
return;
C3DLowMatrix *invview = g_C3DLow.GetInvViewMatrix();
C3DLowVector eyepos = {invview->_41,invview->_42,invview->_43};
int ci=0;
for (int i = 0; i < g_C3DLow.m_BoneMatrixIndexCount; ++i)
{
C3DLowMatrix &temp1 = g_C3DLow.m_pBoneMatrices[g_C3DLow.m_pBoneMatrixIndices[i]];
constants[ci][0] = temp1._11;
constants[ci][1] = temp1._21;
constants[ci][2] = temp1._31;
constants[ci++][3] = temp1._41 - eyepos.x;
constants[ci][0] = temp1._12;
constants[ci][1] = temp1._22;
constants[ci][2] = temp1._32;
constants[ci++][3] = temp1._42 - eyepos.y;
constants[ci][0] = temp1._13;
constants[ci][1] = temp1._23;
constants[ci][2] = temp1._33;
constants[ci++][3] = temp1._43 - eyepos.z;
}
size= 3 * g_C3DLow.m_BoneMatrixIndexCount;
}
break;
case SYSFLOAT_SLOTS:
{
if(g_C3DLow.m_pSlots==NULL)
return;
int ci=0;
for (int i = 0; i < g_C3DLow.m_SlotCount; ++i)
{
C3DLowSlot *slot = &g_C3DLow.m_pSlots[i];
D3DXMATRIX temp1;
D3DXMatrixMultiply(&temp1,(D3DXMATRIX*)&slot->world,
(D3DXMATRIX*)&g_C3DLow.m_MatView);
//xaxis + intensity1
constants[ci][0] = temp1._11;
constants[ci][1] = temp1._21;
constants[ci][2] = temp1._31;
constants[ci++][3] = temp1._41;
//yaxis + intensity2
constants[ci][0] = temp1._12;
constants[ci][1] = temp1._22;
constants[ci][2] = temp1._32;
constants[ci++][3] = temp1._42;
//pos + variation
constants[ci][0] = slot->diff_intensity;
constants[ci][1] = slot->spec_intensity;
constants[ci][2] = 0.0f; //(float)slot->variation_index;
//constants[index++][3] = (float)slot->variation_index;
constants[ci++][3] = temp1._43;
if (slot->pSH!=NULL)
SetSHConstants(&constants[ci], slot->pSH);
else //this is possibly a bug!!!!
SetSHConstants(&constants[ci], &g_C3DLow.GetLight()->SH, 2);
ci+=3;
}
size = 6 * g_C3DLow.m_SlotCount;
//quaternion version version store only intensity
/*
if(g_C3DLow.m_pSlots==NULL)
return 2 * g_C3DLow.m_SlotCount;
for (int i = 0; i < g_C3DLow.m_SlotCount; ++i)
{
C3DLowSlot *slot = &g_C3DLow.m_pSlots[i];
D3DXQUATERNION quat;
D3DXMATRIX temp1;
temp1 = *((D3DXMATRIX*)&g_C3DLow.m_MatView);
// D3DXMatrixMultiply(&temp1,(D3DXMATRIX*)&slot->world,
// (D3DXMATRIX*)&g_C3DLow.m_MatView);
D3DXQuaternionRotationMatrix( &quat, &temp1);
D3DXQuaternionNormalize(&quat, &quat);
//should prescale by -1 if .w is negative
if (quat.w<0.0f)
{
quat.x *= -1.0f;
quat.y *= -1.0f;
quat.z *= -1.0f;
}
// position + intensity
constants[index][0] = temp1._41;
constants[index][1] = temp1._42;
constants[index][2] = temp1._43;
constants[index++][3] = 0.5f + 0.5f* slot->intensity;
// quaternion + variation index
constants[index][0] = quat.x;
constants[index][1] = quat.y;
constants[index][2] = quat.z;
constants[index++][3] = 0.0f; //variation index
// 4*3 float ambient light + extra lights (SH)
}
size= 2 * g_C3DLow.m_SlotCount;
index -=size;
*/
}
break;
case SYSFLOAT_SLOTS_WORLD:
{
if(g_C3DLow.m_pSlots==NULL)
return;
int ci=0;
for (int i = 0; i < g_C3DLow.m_SlotCount; ++i)
{
C3DLowSlot *slot = &g_C3DLow.m_pSlots[i];
//xaxis + posx
constants[ci][0] = slot->world._11;
constants[ci][1] = slot->world._21;
constants[ci][2] = slot->world._31;
constants[ci++][3] = slot->world._41;
//yaxis + posy
constants[ci][0] = slot->world._12;
constants[ci][1] = slot->world._22;
constants[ci][2] = slot->world._32;
constants[ci++][3] = slot->world._42;
//intensity + pos-z
constants[ci][0] = slot->diff_intensity;
constants[ci][1] = slot->spec_intensity;
constants[ci][2] = 0.0f; //(float)slot->variation_index;
constants[ci++][3] = slot->world._43;
//SH bands 1
if (slot->pSH!=NULL)
SetSHConstantsWorld(&constants[ci], slot->pSH);
else //this is possibly a bug!!!!
SetSHConstantsWorld(&constants[ci], &g_C3DLow.GetLight()->SH, 2);
ci+=3;
}
size = 6 * g_C3DLow.m_SlotCount;
}
break;
case SYSFLOAT_SLOTS_WORLD_EC:
{
if(g_C3DLow.m_pSlots==NULL)
return;
C3DLowMatrix *invview = g_C3DLow.GetInvViewMatrix();
C3DLowVector eyepos = {invview->_41,invview->_42,invview->_43};
int ci=0;
for (int i = 0; i < g_C3DLow.m_SlotCount; ++i)
{
C3DLowSlot *slot = &g_C3DLow.m_pSlots[i];
//xaxis + posx
constants[ci][0] = slot->world._11;
constants[ci][1] = slot->world._21;
constants[ci][2] = slot->world._31;
constants[ci++][3] = slot->world._41 - eyepos.x;
//yaxis + posy
constants[ci][0] = slot->world._12;
constants[ci][1] = slot->world._22;
constants[ci][2] = slot->world._32;
constants[ci++][3] = slot->world._42 - eyepos.y;
//intensity + pos-z
constants[ci][0] = slot->diff_intensity;
constants[ci][1] = slot->spec_intensity;
constants[ci][2] = 0.0f; //(float)slot->variation_index;
constants[ci++][3] = slot->world._43 - eyepos.z;
//SH bands 1
if (slot->pSH!=NULL)
SetSHConstantsWorld(&constants[ci], slot->pSH);
else //this is possibly a bug!!!!
SetSHConstantsWorld(&constants[ci], &g_C3DLow.GetLight()->SH, 2);
ci+=3;
}
size = 6 * g_C3DLow.m_SlotCount;
}
break;
case SYSFLOAT_FOG:
if (g_C3DLow.m_FogInfo.enabled)
{
constants[0][0] = 1.0f / ( g_C3DLow.m_FogScale * (g_C3DLow.m_FogInfo.fogend - g_C3DLow.m_FogInfo.fogstart));
constants[0][1] = g_C3DLow.m_FogScale * g_C3DLow.m_FogInfo.fogend * constants[0][0];
}
size = 1;
break;
case SYSFLOAT_SUN:
{
//sets the first directional lamp
// mapping
// 0 : SUN_DIRECTION
// 1 : SUN_DIFFUSE
// 2 : SUN_SPECULAR
//set sun's direction always we need it for fogging
// direction transform to view space (.a is undefined)
C3DLowLightSH *light = g_C3DLow.GetLight();
constants[0][0] = light->Direction.x * g_C3DLow.m_MatView._11 +
light->Direction.y * g_C3DLow.m_MatView._21 +
light->Direction.z * g_C3DLow.m_MatView._31;
constants[0][1] = light->Direction.x * g_C3DLow.m_MatView._12 +
light->Direction.y * g_C3DLow.m_MatView._22 +
light->Direction.z * g_C3DLow.m_MatView._32;
constants[0][2] = light->Direction.x * g_C3DLow.m_MatView._13 +
light->Direction.y * g_C3DLow.m_MatView._23 +
light->Direction.z * g_C3DLow.m_MatView._33;
if (!g_C3DLow.m_LightingEnabled )
{ //full ambient no sun
// sun diffuse
constants[1][0] = 0.0f;
constants[1][1] = 0.0f;
constants[1][2] = 0.0f;
//sun specular
constants[2][0] = 0.0f;
constants[2][1] = 0.0f;
constants[2][2] = 0.0f;
}
else
{
// sun diffuse
constants[1][0] = light->Diffuse.r;
constants[1][1] = light->Diffuse.g;
constants[1][2] = light->Diffuse.b;
//sun specular
constants[2][0] = light->Specular.r;
constants[2][1] = light->Specular.g;
constants[2][2] = light->Specular.b;
}
size = 3;
}
break;
case SYSFLOAT_SUN_WORLD:
{
//sets the first directional lamp
// mapping
// 0 : SUN_DIRECTION
// 1 : SUN_DIFFUSE
// 2 : SUN_SPECULAR
//set sun's direction always we need it for fogging
// direction transform to view space (.a is undefined)
C3DLowLightSH *light = g_C3DLow.GetLight();
constants[0][0] = light->Direction.x;
constants[0][1] = light->Direction.y;
constants[0][2] = light->Direction.z;
if (!g_C3DLow.m_LightingEnabled )
{ //full ambient no sun
// sun diffuse
constants[1][0] = 0.0f;
constants[1][1] = 0.0f;
constants[1][2] = 0.0f;
//sun specular
constants[2][0] = 0.0f;
constants[2][1] = 0.0f;
constants[2][2] = 0.0f;
}
else
{
// sun diffuse
constants[1][0] = light->Diffuse.r;
constants[1][1] = light->Diffuse.g;
constants[1][2] = light->Diffuse.b;
//sun specular
constants[2][0] = light->Specular.r;
constants[2][1] = light->Specular.g;
constants[2][2] = light->Specular.b;
}
size = 3;
}
break;
case SYSFLOAT_SUNANDSH1:
{
//sets the first directional lamp
// mapping
// 0 : SUN_DIRECTION
// 1 : SUN_DIFFUSE
// 2 : SUN_SPECULAR
// 3-5 : SH params
//set sun's direction always we need it for fogging
// direction transform to view space (.a is undefined)
C3DLowLightSH *light = g_C3DLow.GetLight();
constants[0][0] = light->Direction.x * g_C3DLow.m_MatView._11 +
light->Direction.y * g_C3DLow.m_MatView._21 +
light->Direction.z * g_C3DLow.m_MatView._31;
constants[0][1] = light->Direction.x * g_C3DLow.m_MatView._12 +
light->Direction.y * g_C3DLow.m_MatView._22 +
light->Direction.z * g_C3DLow.m_MatView._32;
constants[0][2] = light->Direction.x * g_C3DLow.m_MatView._13 +
light->Direction.y * g_C3DLow.m_MatView._23 +
light->Direction.z * g_C3DLow.m_MatView._33;
if (!g_C3DLow.m_LightingEnabled )
{ //full ambient no sun
// sun diffuse
constants[1][0] = 0.0f;
constants[1][1] = 0.0f;
constants[1][2] = 0.0f;
//sun specular
constants[2][0] = 0.0f;
constants[2][1] = 0.0f;
constants[2][2] = 0.0f;
//constant one ambient
//SH - red
constants[3][0] = 0.0f;
constants[3][1] = 0.0f;
constants[3][2] = 0.0f;
constants[3][3] = 0.5f;
//SH - green
constants[4][0] = 0.0f;
constants[4][1] = 0.0f;
constants[4][2] = 0.0f;
constants[4][3] = 0.5f;
//SH - blue
constants[5][0] = 0.0f;
constants[5][1] = 0.0f;
constants[5][2] = 0.0f;
constants[5][3] = 0.5f;
}
else
{
// sun diffuse
constants[1][0] = light->Diffuse.r;
constants[1][1] = light->Diffuse.g;
constants[1][2] = light->Diffuse.b;
//sun specular
constants[2][0] = light->Specular.r;
constants[2][1] = light->Specular.g;
constants[2][2] = light->Specular.b;
//rotates sh to viewspace
SetSHConstants(&constants[3], &light->SH, 2);
}
size = 6;
}
break;
case SYSFLOAT_SUNANDSH2:
{
//sets the first directional lamp
// mapping
// 0 : SUN_DIRECTION
// 1 : SUN_DIFFUSE
// 2 : SUN_SPECULAR
// 3-9 : SH params
//set sun's direction always we need it for fogging
// direction transform to view space (.a is undefined)
C3DLowLightSH *light = g_C3DLow.GetLight();
constants[0][0] = light->Direction.x * g_C3DLow.m_MatView._11 +
light->Direction.y * g_C3DLow.m_MatView._21 +
light->Direction.z * g_C3DLow.m_MatView._31;
constants[0][1] = light->Direction.x * g_C3DLow.m_MatView._12 +
light->Direction.y * g_C3DLow.m_MatView._22 +
light->Direction.z * g_C3DLow.m_MatView._32;
constants[0][2] = light->Direction.x * g_C3DLow.m_MatView._13 +
light->Direction.y * g_C3DLow.m_MatView._23 +
light->Direction.z * g_C3DLow.m_MatView._33;
if (!g_C3DLow.m_LightingEnabled )
{ //full ambient no sun
// sun diffuse
constants[1][0] = 0.0f;
constants[1][1] = 0.0f;
constants[1][2] = 0.0f;
//sun specular
constants[2][0] = 0.0f;
constants[2][1] = 0.0f;
constants[2][2] = 0.0f;
//SH
for(int i = 0; i < 7; ++i)
{
constants[3+i][0] = 0.0f;
constants[3+i][1] = 0.0f;
constants[3+i][2] = 0.0f;
constants[3+i][3] = 0.0f;
}
// constant one ambient
constants[3+0][3] = 0.5f;
constants[3+1][3] = 0.5f;
constants[3+2][3] = 0.5f;
}
else
{
// sun diffuse
constants[1][0] = light->Diffuse.r;
constants[1][1] = light->Diffuse.g;
constants[1][2] = light->Diffuse.b;
//sun specular
constants[2][0] = light->Specular.r;
constants[2][1] = light->Specular.g;
constants[2][2] = light->Specular.b;
//rotates sh to viewspace
SetSHConstants(&constants[3], &light->SH, 3);
}
size = 10;
}
break;
case SYSFLOAT_SUNANDSH2_WORLD:
{
//sets the first directional lamp
// mapping
// 0 : SUN_DIRECTION
// 1 : SUN_DIFFUSE
// 2 : SUN_SPECULAR
// 3-9 : SH params
//set sun's direction always we need it for fogging
// direction transform to view space (.a is undefined)
C3DLowLightSH *light = g_C3DLow.GetLight();
constants[0][0] = light->Direction.x;
constants[0][1] = light->Direction.y;
constants[0][2] = light->Direction.z;
if (!g_C3DLow.m_LightingEnabled )
{ //full ambient no sun
// sun diffuse
constants[1][0] = 0.0f;
constants[1][1] = 0.0f;
constants[1][2] = 0.0f;
//sun specular
constants[2][0] = 0.0f;
constants[2][1] = 0.0f;
constants[2][2] = 0.0f;
//SH
for(int i = 0; i < 7; ++i)
{
constants[3+i][0] = 0.0f;
constants[3+i][1] = 0.0f;
constants[3+i][2] = 0.0f;
constants[3+i][3] = 0.0f;
}
// constant one ambient
constants[3+0][3] = 0.5f;
constants[3+1][3] = 0.5f;
constants[3+2][3] = 0.5f;
}
else
{
// sun diffuse
constants[1][0] = light->Diffuse.r;
constants[1][1] = light->Diffuse.g;
constants[1][2] = light->Diffuse.b;
//sun specular
constants[2][0] = light->Specular.r;
constants[2][1] = light->Specular.g;
constants[2][2] = light->Specular.b;
//rotates sh to viewspace
SetSHConstantsWorld(&constants[3], &light->SH, 3);
}
size = 10;
}
break;
case SYSFLOAT_SUNDIR_FOR_PLANARSPECULAR:
{
C3DLowLightSH *light = g_C3DLow.GetLight();
float azimuth = asin(light->Direction.y);
float sun_x = light->Direction.x / cos(azimuth);
float sun_y = light->Direction.y;
float sun_z = light->Direction.z / cos(azimuth);
azimuth = - ((90.0f * 3.14159f / 180.0f) + azimuth);
sun_x *= cos(azimuth);
sun_y = sin(azimuth);
sun_z *= cos(azimuth);
//diry = - sin( (90.0f * 3.14159f / 180.0f) - diry);
constants[0][0] = sun_x * g_C3DLow.m_MatView._11 +
sun_y * g_C3DLow.m_MatView._21 +
sun_z * g_C3DLow.m_MatView._31;
constants[0][1] = sun_x * g_C3DLow.m_MatView._12 +
sun_y * g_C3DLow.m_MatView._22 +
sun_z * g_C3DLow.m_MatView._32;
constants[0][2] = sun_x * g_C3DLow.m_MatView._13 +
sun_y * g_C3DLow.m_MatView._23 +
sun_z * g_C3DLow.m_MatView._33;
size = 1;
}
break;
case SYSFLOAT_SUNDIR_FOR_PLANARSPECULAR_WORLD:
{
C3DLowLightSH *light = g_C3DLow.GetLight();
float azimuth = asin(light->Direction.y);
float sun_x = light->Direction.x / cos(azimuth);
float sun_y = light->Direction.y;
float sun_z = light->Direction.z / cos(azimuth);
azimuth = - ((90.0f * 3.14159f / 180.0f) + azimuth);
sun_x *= cos(azimuth);
sun_y = sin(azimuth);
sun_z *= cos(azimuth);
//diry = - sin( (90.0f * 3.14159f / 180.0f) - diry);
constants[0][0] = sun_x;
constants[0][1] = sun_y;
constants[0][2] = sun_z;
size = 1;
}
break;
case SYSFLOAT_SPECREF:
{
float v;
CMaterial *mat = g_C3DLow.m_pCurrentMaterialImpl->GetMaterial();
constants[0][0] = constants[0][1] = constants[0][2] = constants[0][3] = 1.0f;
//.rgb specular (material*specular)
mat->GetColor(MATPARAMCOLOR_SPECULAR,&constants[0][0],&constants[0][1],&constants[0][2],&v);
if (g_C3DLow.m_LightingEnabled)
{
C3DLowLightSH *light = g_C3DLow.GetLight();
constants[0][0] *= light->Specular.r;
constants[0][1] *= light->Specular.g;
constants[0][2] *= light->Specular.b;
}
//.a reflection intensity (material * global)
mat->GetFloat1(MATPARAMFLOAT1_REFLECTIONINTENSITY,&constants[0][3]);
constants[0][3] *= g_C3DLow.GetReflectionIntensity();
size = 1;
}
break;
case SYSFLOAT_LIGHT_WATERLOW:
{
CMaterial *mat = g_C3DLow.m_pCurrentMaterialImpl->GetMaterial();
float v[4];
mat->GetColor(MATPARAMCOLOR_DIFFUSE, v+0, v+1, v+2, v+3);
if (g_C3DLow.m_LightingEnabled)
{
C3DLowLightSH *light = g_C3DLow.GetLight();
constants[0][0] = min(0.19f, light->Diffuse.r * v[0]);
constants[0][1] = min(0.24f, light->Diffuse.g * v[1]);
constants[0][2] = min(0.30f, light->Diffuse.b * v[2]);
constants[0][3] = 0.0f;
constants[1][0] = (0.43f - constants[0][0]) * light->Diffuse.r;
constants[1][1] = (0.46f - constants[0][1]) * light->Diffuse.g;
constants[1][2] = (0.50f - constants[0][2]) * light->Diffuse.b;
constants[1][3] = 0.0f;
}
size = 2;
}
break;
case SYSFLOAT_LIGHT_DIFFUSE:
{
if (g_C3DLow.m_LightingEnabled)
{
C3DLowLightSH *light = g_C3DLow.GetLight();
constants[0][0] = light->Diffuse.r;
constants[0][1] = light->Diffuse.g;
constants[0][2] = light->Diffuse.b;
}
else
constants[0][0] = constants[0][1] = constants[0][2] = 0.0f;
constants[0][3] = 0.0f;
size = 1;
}
break;
case SYSFLOAT_SCATTERING_FOG_VS:
{
FogInfo fog_info = g_C3DLow.GetFog();
if (fog_info.enabled)
{
#ifndef LIGHTMAPPER
// static float g_sky_val = - 10.0f;
float scale = fog_info.enabled ? -1.0f / max(0.001f, g_C3DLow.m_FogScale): 0.0f;
//patch: skydome is not that far
if (g_C3DLow.m_FogScale < 0.00001f)
scale = fog_info.enabled ? g_sky_dist : 0.0f;
//float scale = g_C3DLow.m_WorldScale > 0.00001f ? -g_fog_scale: 0.0f;
#else
// static float g_sky_val = - 1.0f;
float scale = fog_info.enabled ? -1.0f / max(0.001f, g_C3DLow.m_WorldScale) * 0.1f: 0.0f;
// float scale = fog_info.enabled ? g_C3DLow.m_WorldScale * 0.1f : 0.0f;
//patch: skydome is not that far
if (g_C3DLow.m_WorldScale < 0.00001f)
scale = fog_info.enabled ? -g_sky_dist : 0.0f;
#endif
float ray_mult = fog_info.rayleigh;
float mie_mult = fog_info.mie;
float g = fog_info.hg;
scale *= 1/log(2.0f);
constants[0][0] = scale * (ray_mult * FogInfo::m_vBetaRay.x + mie_mult * fog_info.beta_mie.x);
constants[0][1] = scale * (ray_mult * FogInfo::m_vBetaRay.y + mie_mult * fog_info.beta_mie.y);
constants[0][2] = scale * (ray_mult * FogInfo::m_vBetaRay.z + mie_mult * fog_info.beta_mie.z);
constants[1][0] = 1-g*g;
constants[1][1] = 1+g*g;
constants[1][2] = -2.0f * g;
}
else
{
constants[0][0] = 0.0f;
constants[0][1] = 0.0f;
constants[0][2] = 0.0f;
constants[1][0] = 1.0f;
constants[1][1] = 1.0f;
constants[1][2] = 0.0f;
}
size = 2;
}
break;
case SYSFLOAT_SCATTERING_FOG_PS:
{
FogInfo fog_info = g_C3DLow.GetFog();
ColorValue fog_color;
if (fog_info.enabled)
{
fog_color.r = (((fog_info.fogcolor)>>16)&0xff) / 255.0f;
fog_color.g = (((fog_info.fogcolor)>>8)&0xff) / 255.0f;
fog_color.b = ((fog_info.fogcolor)&0xff) / 255.0f;
float ray_mult = fog_info.rayleigh;
float mie_mult = fog_info.mie;
float in_scatter = fog_info.in_scatter;
//decrease wavelength dependency with increasing g
//the used values are at 0.2, if smaller increated
float one_over_mieray[3] = { 1.0f / ( ray_mult * FogInfo::m_vBetaRay.x + mie_mult * fog_info.beta_mie.x),
1.0f / ( ray_mult * FogInfo::m_vBetaRay.y + mie_mult * fog_info.beta_mie.y),
1.0f / ( ray_mult * FogInfo::m_vBetaRay.z + mie_mult * fog_info.beta_mie.z) };
constants[0][0] = fog_color.r * in_scatter * (mie_mult * fog_info.beta_dash_mie.x) * one_over_mieray[0];
constants[0][1] = fog_color.g * in_scatter * (mie_mult * fog_info.beta_dash_mie.y) * one_over_mieray[1];
constants[0][2] = fog_color.b * in_scatter * (mie_mult * fog_info.beta_dash_mie.z) * one_over_mieray[2];
constants[1][0] = fog_color.r * in_scatter * (ray_mult * FogInfo::m_vBetaDashRay.x) * one_over_mieray[0];
constants[1][1] = fog_color.g * in_scatter * (ray_mult * FogInfo::m_vBetaDashRay.y) * one_over_mieray[1];
constants[1][2] = fog_color.b * in_scatter * (ray_mult * FogInfo::m_vBetaDashRay.z) * one_over_mieray[2];
}
else
{
constants[0][0] = 0.0f;
constants[0][1] = 0.0f;
constants[0][2] = 0.0f;
constants[1][0] = 0.0f;
constants[1][1] = 0.0f;
constants[1][2] = 0.0f;
}
size = 2;
}
break;
case SYSFLOAT_SCATTERING_FOG:
{
FogInfo fog_info = g_C3DLow.GetFog();
if (fog_info.enabled)
{
float scale = fog_info.enabled ? -1.0f / max(0.001f, g_C3DLow.m_FogScale): 0.0f;
//patch: skydome is not that far
if (g_C3DLow.m_FogScale < 0.00001f)
scale = fog_info.enabled ? g_sky_dist : 0.0f;
//float scale = g_C3DLow.m_WorldScale > 0.00001f ? -g_fog_scale: 0.0f;
float ray_mult = fog_info.rayleigh;
float mie_mult = fog_info.mie;
float in_scatter = fog_info.in_scatter;
float g = fog_info.hg;
scale *= 1/log(2.0f);
ColorValue fog_color;
fog_color.r = (((fog_info.fogcolor)>>16)&0xff) / 255.0f;
fog_color.g = (((fog_info.fogcolor)>>8)&0xff) / 255.0f;
fog_color.b = ((fog_info.fogcolor)&0xff) / 255.0f;
//decrease wavelength dependency with increasing g
//the used values are at 0.2, if smaller increated
float one_over_mieray[3] = { 1.0f / ( ray_mult * FogInfo::m_vBetaRay.x + mie_mult * fog_info.beta_mie.x),
1.0f / ( ray_mult * FogInfo::m_vBetaRay.y + mie_mult * fog_info.beta_mie.y),
1.0f / ( ray_mult * FogInfo::m_vBetaRay.z + mie_mult * fog_info.beta_mie.z) };
constants[0][0] = scale * (ray_mult * FogInfo::m_vBetaRay.x + mie_mult * fog_info.beta_mie.x);
constants[0][1] = scale * (ray_mult * FogInfo::m_vBetaRay.y + mie_mult * fog_info.beta_mie.y);
constants[0][2] = scale * (ray_mult * FogInfo::m_vBetaRay.z + mie_mult * fog_info.beta_mie.z);
constants[1][0] = 1-g*g;
constants[1][1] = 1+g*g;
constants[1][2] = -2.0f * g;
constants[2][0] = fog_color.r * in_scatter * (mie_mult * fog_info.beta_dash_mie.x) * one_over_mieray[0];
constants[2][1] = fog_color.g * in_scatter * (mie_mult * fog_info.beta_dash_mie.y) * one_over_mieray[1];
constants[2][2] = fog_color.b * in_scatter * (mie_mult * fog_info.beta_dash_mie.z) * one_over_mieray[2];
constants[3][0] = fog_color.r * in_scatter * (ray_mult * FogInfo::m_vBetaDashRay.x) * one_over_mieray[0];
constants[3][1] = fog_color.g * in_scatter * (ray_mult * FogInfo::m_vBetaDashRay.y) * one_over_mieray[1];
constants[3][2] = fog_color.b * in_scatter * (ray_mult * FogInfo::m_vBetaDashRay.z) * one_over_mieray[2];
}
else
{
constants[0][0] = 0.0f;
constants[0][1] = 0.0f;
constants[0][2] = 0.0f;
constants[1][0] = 1.0f;
constants[1][1] = 1.0f;
constants[1][2] = 0.0f;
constants[2][0] = 0.0f;
constants[2][1] = 0.0f;
constants[2][2] = 0.0f;
constants[3][0] = 0.0f;
constants[3][1] = 0.0f;
constants[3][2] = 0.0f;
}
size = 4;
}
break;
case SYSFLOAT_PROJECTED_LIGHT_VS:
{
size = 1;
constants[0][0] = 1.0f;
}
break;
case SYSFLOAT_PROJECTED_LIGHT_PS:
{
size = 1;
constants[0][0] = 1.0f;
}
break;
case SYSFLOAT_PROJECTED_SHADOW_MATRIX:
{
int lighting = 0;
float fBias = -0.3f;
float fDistBias = 0.01000f;
float offsx = 0.0f; //1.0f;
float offsy = 0.0f; //-1.0f;
if (g_C3DLow.IsProjectedShadowEnabledAndValid())
lighting = (g_C3DLow.GetProjectedShadow()->GetType() == PROJSHADOW_CSM) ? 2 : 1;
if (lighting == 1)
{
Texture *tex = g_C3DLow.GetProjectedShadow()->GetDepthTexture();
//set special texture matrix for shadow mapping
float fOffsetX = 0.5f + (0.5f / (float)tex->GetWidth());
float fOffsetY = 0.5f + (0.5f / (float)tex->GetHeight());
D3DXMATRIX m( 0.5f, 0.0f, 0.0f, 0.0f,
0.0f, -0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
fOffsetX, fOffsetY, 0.0f, 1.0f );
D3DXMatrixMultiply(&m, (D3DXMATRIX*)g_C3DLow.GetProjectedShadow()->GetLightMatrix(), &m);
D3DXMatrixMultiply(&m, (D3DXMATRIX*)g_C3DLow.GetWorldMatrix(), &m);
D3DXVECTOR4 vec;
g_C3DLow.GetProjectedShadow()->GetLightAxis((float*)&vec);
D3DXVECTOR4 v;
D3DXVec4Transform(&v, &vec, (D3DXMATRIX*)g_C3DLow.GetWorldMatrix());
constants[0][0] = m._11;
constants[0][1] = m._21;
constants[0][2] = m._31;
constants[0][3] = m._41;
constants[1][0] = m._12;
constants[1][1] = m._22;
constants[1][2] = m._32;
constants[1][3] = m._42;
constants[2][0] = v.x;
constants[2][1] = v.y;
constants[2][2] = v.z;
constants[2][3] = v.w;
constants[3][0] = m._14;
constants[3][1] = m._24;
constants[3][2] = m._34;
constants[3][3] = m._44;
}
else if (lighting == 2)
{
C3DLowMatrix m;
GetShadowLightMatrix(m, false); //!m_pShaderInstance->m_ShaderMatType.lightmapped);
constants[0][0] = m._11;
constants[0][1] = m._21;
constants[0][2] = m._31;
constants[0][3] = m._41;
constants[1][0] = m._12;
constants[1][1] = m._22;
constants[1][2] = m._32;
constants[1][3] = m._42;
constants[2][0] = m._13;
constants[2][1] = m._23;
constants[2][2] = m._33;
constants[2][3] = m._43;
constants[3][0] = m._14;
constants[3][1] = m._24;
constants[3][2] = m._34;
constants[3][3] = m._44;
/*Texture *tex = g_C3DLow.GetProjectedShadow()->GetTileTexture();
float inv_depth = 1.0f / g_C3DLow.GetProjectedShadow()->GetShadowDepth();
//set special texture matrix for shadow mapping
D3DXMATRIX m( 0.5f, 0.0f, 0.0f, 0.0f,
0.0f, -0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.5f,0.5f, fBias * inv_depth, 1.0f ); // (tex->GetPixelType() == RENDERDEPTH_Z) ? 0.0f : fBias * inv_depth
D3DXMatrixMultiply(&m, (D3DXMATRIX*)g_C3DLow.GetProjectedShadow()->GetLightMatrix(), &m);
constants[0][0] = m._11;
constants[0][1] = m._21;
constants[0][2] = m._31;
constants[0][3] = m._41;
constants[1][0] = m._12;
constants[1][1] = m._22;
constants[1][2] = m._32;
constants[1][3] = m._42;
constants[2][0] = m._13;
constants[2][1] = m._23;
constants[2][2] = m._33;
constants[2][3] = m._43;
//.w cam direction scaled for z offset
//view z vector with scale
C3DLowMatrix *mat_view = g_C3DLow.GetViewMatrix();
constants[3][0] = fDistBias * inv_depth * mat_view->_13;
constants[3][1] = fDistBias * inv_depth * mat_view->_23;
constants[3][2] = fDistBias * inv_depth * mat_view->_33;
constants[3][3] = fDistBias * inv_depth * mat_view->_43;*/
}
size = 4;
}
break;
case SYSFLOAT_SUNDIR:
{
C3DLowLightSH *light = g_C3DLow.GetLight();
constants[0][0] = light->Direction.x * g_C3DLow.m_MatView._11 +
light->Direction.y * g_C3DLow.m_MatView._21 +
light->Direction.z * g_C3DLow.m_MatView._31;
constants[0][1] = light->Direction.x * g_C3DLow.m_MatView._12 +
light->Direction.y * g_C3DLow.m_MatView._22 +
light->Direction.z * g_C3DLow.m_MatView._32;
constants[0][2] = light->Direction.x * g_C3DLow.m_MatView._13 +
light->Direction.y * g_C3DLow.m_MatView._23 +
light->Direction.z * g_C3DLow.m_MatView._33;
size = 1;
}
break;
case SYSFLOAT_SUNDIR_WORLD:
{
C3DLowLightSH *light = g_C3DLow.GetLight();
constants[0][0] = light->Direction.x;
constants[0][1] = light->Direction.y;
constants[0][2] = light->Direction.z;
size = 1;
}
break;
case SYSFLOAT_FLAGMOTION:
{
//* ((D3DXMATRIX*)&constants[0][0]) = (*(D3DXMATRIX*)&g_C3DLow.m_MatWorld);
C3DLowMatrix &world = g_C3DLow.m_MatWorld;
float phasing[3] = { world._41 * 0.048945f, world._42 * 0.048945f, world._43 * 0.048945f };
float variance = phasing[0] * phasing[2] + phasing[0] + phasing[1];
float altertime = GetWorldTime() * 8.0f;
float windint = cos(altertime * 0.8f + variance) + 1.0f;
constants[0][0] = windint * 1.0f;
constants[0][1] = windint * 0.02f;
constants[0][2] = altertime * 1.0f + variance;
constants[0][3] = altertime * 1.8f + variance;
size = 1;
}
break;
}
interval->add(index,index+size-1);
}
void StateManager::SetVertexShaderConstantF(int index, float v1, float v2, float v3, float v4)
{
m_VertexShaderConstants[index][0]=v1;
m_VertexShaderConstants[index][1]=v2;
m_VertexShaderConstants[index][2]=v3;
m_VertexShaderConstants[index][3]=v4;
//add index to interval
m_UpdateVertexF.add(index);
}
void StateManager::SetVertexShaderConstantF(int index, float *v)
{
m_VertexShaderConstants[index][0]=v[0];
m_VertexShaderConstants[index][1]=v[1];
m_VertexShaderConstants[index][2]=v[2];
m_VertexShaderConstants[index][3]=v[3];
//add index to interval
m_UpdateVertexF.add(index);
}
void StateManager::SetVertexShaderConstantF(int index, const D3DXMATRIX& m)
{
memcpy(m_VertexShaderConstants[index], &m, sizeof(float)*16);
m_UpdateVertexF.add(index, index+4-1);
}
void StateManager::SetVertexShaderConstantF(int index, MatParamColor &mpc)
{
m_VertexShaderConstants[index][0]=mpc.r;
m_VertexShaderConstants[index][1]=mpc.g;
m_VertexShaderConstants[index][2]=mpc.b;
m_VertexShaderConstants[index][3]=mpc.a;
//add index to interval
m_UpdateVertexF.add(index);
}
void StateManager::SetVertexShaderConstantF(int index, MatParam &mp)
{
unsigned int type = ((mp.type_id>>24)&0xff);
switch(type)
{
case MATPARAMTYPE_COLOR:
m_VertexShaderConstants[index][0] = mp.m_Color.r;
m_VertexShaderConstants[index][1] = mp.m_Color.g;
m_VertexShaderConstants[index][2] = mp.m_Color.b;
m_VertexShaderConstants[index][3] = mp.m_Color.a;
break;
case MATPARAMTYPE_FLOAT1:
m_VertexShaderConstants[index][0] = mp.m_Float1;
m_VertexShaderConstants[index][1] = 0.0f;
m_VertexShaderConstants[index][2] = 0.0f;
m_VertexShaderConstants[index][3] = 0.0f;
break;
case MATPARAMTYPE_FLOAT2:
m_VertexShaderConstants[index][0] = mp.m_Float2[0];
m_VertexShaderConstants[index][1] = mp.m_Float2[1];
m_VertexShaderConstants[index][2] = 0.0f;
m_VertexShaderConstants[index][3] = 0.0f;
break;
case MATPARAMTYPE_FLOAT3:
m_VertexShaderConstants[index][0] = mp.m_Float3[0];
m_VertexShaderConstants[index][1] = mp.m_Float3[1];
m_VertexShaderConstants[index][2] = mp.m_Float3[2];
m_VertexShaderConstants[index][3] = 0.0f;
break;
case MATPARAMTYPE_FLOAT4:
m_VertexShaderConstants[index][0] = mp.m_Float4[0];
m_VertexShaderConstants[index][1] = mp.m_Float4[1];
m_VertexShaderConstants[index][2] = mp.m_Float4[2];
m_VertexShaderConstants[index][3] = mp.m_Float4[3];
break;
case MATPARAMTYPE_TEX:
m_VertexShaderConstants[index][0] = mp.m_Tex.u_scale;
m_VertexShaderConstants[index][1] = 0.5f-(0.5f+mp.m_Tex.u_offset)*mp.m_Tex.u_scale;
m_VertexShaderConstants[index][2] = mp.m_Tex.v_scale;
m_VertexShaderConstants[index][3] = 0.5f+(mp.m_Tex.v_offset-0.5f)*mp.m_Tex.v_scale;
break;
}
//add index to interval
m_UpdateVertexF.add(index);
}
void StateManager::SetVertexShaderConstantF(int index, MatParamColor &mpc, float fourth)
{
m_VertexShaderConstants[index][0]=mpc.r;
m_VertexShaderConstants[index][1]=mpc.g;
m_VertexShaderConstants[index][2]=mpc.b;
m_VertexShaderConstants[index][3]=fourth;
//add index to interval
m_UpdateVertexF.add(index);
}
void StateManager::SetVertexShaderConstantF(int index, MatParamTexture &mpt) //set transform paremeters
{
m_VertexShaderConstants[index][0] = mpt.u_scale;
m_VertexShaderConstants[index][1] = 0.5f-(0.5f+mpt.u_offset)*mpt.u_scale;
m_VertexShaderConstants[index][2] = mpt.v_scale;
m_VertexShaderConstants[index][3] = 0.5f+(mpt.v_offset-0.5f)*mpt.v_scale;
//add index to interval
m_UpdateVertexF.add(index);
}
void StateManager::SetVertexShaderConstantF_VariationTex(int index, CMaterial *mat, int ch)
{
if (!mat)
return;
for(int i=0;i<4;++i)
{
float u_offset, v_offset;
float u_scale, v_scale;
// mat->GetVariationTex(i, ch, u_offset, v_offset,
// u_scale, v_scale);
u_offset = v_offset = 0.0f;
u_scale = v_scale = 1.0f;
m_VertexShaderConstants[index+i][0] = u_scale;
m_VertexShaderConstants[index+i][1] = 0.5f-(0.5f+u_offset)*u_scale;
m_VertexShaderConstants[index+i][2] = v_scale;
m_VertexShaderConstants[index+i][3] = 0.5f+(v_offset-0.5f)*v_scale;
}
}
void StateManager::SetPixelShaderConstantF(int index, float v1, float v2, float v3, float v4)
{
m_PixelShaderConstants[index][0]=v1;
m_PixelShaderConstants[index][1]=v2;
m_PixelShaderConstants[index][2]=v3;
m_PixelShaderConstants[index][3]=v4;
//add index to interval
m_UpdatePixelF.add(index);
}
void StateManager::SetPixelShaderConstantF(int index, float *v)
{
m_PixelShaderConstants[index][0]=v[0];
m_PixelShaderConstants[index][1]=v[1];
m_PixelShaderConstants[index][2]=v[2];
m_PixelShaderConstants[index][3]=v[3];
//add index to interval
m_UpdatePixelF.add(index);
}
void StateManager::SetPixelShaderConstantF(int index, MatParamColor &mpc)
{
m_PixelShaderConstants[index][0]=mpc.r;
m_PixelShaderConstants[index][1]=mpc.g;
m_PixelShaderConstants[index][2]=mpc.b;
m_PixelShaderConstants[index][3]=mpc.a;
//add index to interval
m_UpdatePixelF.add(index);
}
void StateManager::SetPixelShaderConstantF(int index, MatParamColor &mpc, float fourth)
{
m_PixelShaderConstants[index][0]=mpc.r;
m_PixelShaderConstants[index][1]=mpc.g;
m_PixelShaderConstants[index][2]=mpc.b;
m_PixelShaderConstants[index][3]=fourth;
//add index to interval
m_UpdatePixelF.add(index);
}
void StateManager::SetPixelShaderConstantF(int index, MatParam &mp)
{
unsigned int type = ((mp.type_id>>24)&0xff);
switch(type)
{
case MATPARAMTYPE_COLOR:
m_PixelShaderConstants[index][0] = mp.m_Color.r;
m_PixelShaderConstants[index][1] = mp.m_Color.g;
m_PixelShaderConstants[index][2] = mp.m_Color.b;
m_PixelShaderConstants[index][3] = mp.m_Color.a;
break;
case MATPARAMTYPE_FLOAT1:
m_PixelShaderConstants[index][0] = mp.m_Float1;
m_PixelShaderConstants[index][1] = 0.0f;
m_PixelShaderConstants[index][2] = 0.0f;
m_PixelShaderConstants[index][3] = 0.0f;
break;
case MATPARAMTYPE_FLOAT2:
m_PixelShaderConstants[index][0] = mp.m_Float2[0];
m_PixelShaderConstants[index][1] = mp.m_Float2[1];
m_PixelShaderConstants[index][2] = 0.0f;
m_PixelShaderConstants[index][3] = 0.0f;
break;
case MATPARAMTYPE_FLOAT3:
m_PixelShaderConstants[index][0] = mp.m_Float3[0];
m_PixelShaderConstants[index][1] = mp.m_Float3[1];
m_PixelShaderConstants[index][2] = mp.m_Float3[2];
m_PixelShaderConstants[index][3] = 0.0f;
break;
case MATPARAMTYPE_FLOAT4:
m_PixelShaderConstants[index][0] = mp.m_Float4[0];
m_PixelShaderConstants[index][1] = mp.m_Float4[1];
m_PixelShaderConstants[index][2] = mp.m_Float4[2];
m_PixelShaderConstants[index][3] = mp.m_Float4[3];
break;
}
//add index to interval
m_UpdatePixelF.add(index);
}
bool StateManager::IsDirty(shader_param_type param_type)
{
int dirty_states = g_C3DLow.GetDirtyStates();
switch(param_type)
{
case SYSFLOAT_WORLDVIEWPROJECTION:
case SYSFLOAT_WORLDVIEWPROJECTIONT:
case SYSFLOAT_WORLDVIEW:
case SYSFLOAT_WORLDVIEWT:
case SYSFLOAT_VIEWT_EC:
case SYSFLOAT_VIEWPROJECTIONT_EC:
case SYSFLOAT_WORLDT_EC:
case SYSFLOAT_CAMERAPOS_OBJECT:
return (dirty_states&(C3DLOWSTATE_TRANSFORMWORLD|C3DLOWSTATE_TRANSFORMVIEWPROJ))!=0;
break;
case SYSFLOAT_VIEWPROJECTION:
case SYSFLOAT_VIEWPROJECTIONT:
case SYSFLOAT_PARABOLOID_PROJECTION:
case SYSFLOAT_PROJECTION:
case SYSFLOAT_PROJECTIONT:
case SYSFLOAT_VIEWIT:
case SYSFLOAT_VIEWT:
case SYSFLOAT_VIEWZ:
return (dirty_states&C3DLOWSTATE_TRANSFORMVIEWPROJ)!=0;
break;
case SYSFLOAT_WORLD:
case SYSFLOAT_WORLDI:
case SYSFLOAT_WORLDIT:
case SYSFLOAT_WORLDT:
case SYSFLOAT_SLOTS:
case SYSFLOAT_SLOTS_WORLD:
case SYSFLOAT_FLAGMOTION:
return (dirty_states&C3DLOWSTATE_TRANSFORMWORLD)!=0;
break;
case SYSFLOAT_SLOTS_WORLD_EC:
return (dirty_states&C3DLOWSTATE_TRANSFORMWORLD|C3DLOWSTATE_TRANSFORMVIEWPROJ)!=0;
break;
// case SYSFLOAT_DIFFUSEENVMAP:
// return (dirty_states&(C3DLOWSTATE_LIGHT|C3DLOWSTATE_OBJECTPOS)) !=0;
// break;
case SYSFLOAT_CAMERAPOS_WORLD:
return (dirty_states&(C3DLOWSTATE_TRANSFORMVIEWPROJ))!=0;
break;
case SYSFLOAT_BONES:
case SYSFLOAT_BONES_WORLD:
return (dirty_states&C3DLOWSTATE_TRANSFORMWORLD)!=0;
break;
case SYSFLOAT_BONES_WORLD_EC:
return (dirty_states&C3DLOWSTATE_TRANSFORMWORLD|C3DLOWSTATE_TRANSFORMVIEWPROJ)!=0;
break;
case SYSFLOAT_FOG:
case SYSFLOAT_SCATTERING_FOG:
case SYSFLOAT_SCATTERING_FOG_VS:
case SYSFLOAT_SCATTERING_FOG_PS:
return (dirty_states&C3DLOWSTATE_FOG)!=0;
break;
// case SYSFLOAT_1DIRECTIONAL:
case SYSFLOAT_SUNANDSH1:
case SYSFLOAT_SUNANDSH2:
case SYSFLOAT_SUNDIR_FOR_PLANARSPECULAR:
case SYSFLOAT_SUN:
return (dirty_states&(C3DLOWSTATE_LIGHT|C3DLOWSTATE_TRANSFORMVIEWPROJ))!=0;
break;
case SYSFLOAT_SUNANDSH2_WORLD:
case SYSFLOAT_SUNDIR_FOR_PLANARSPECULAR_WORLD:
case SYSFLOAT_SUN_WORLD:
return (dirty_states&C3DLOWSTATE_LIGHT)!=0;
break;
case SYSFLOAT_SPECREF:
return (dirty_states&(C3DLOWSTATE_LIGHT|C3DLOWSTATE_REFLECTIONINTENSITY))!=0;
break;
case SYSFLOAT_LIGHT_DIFFUSE:
case SYSFLOAT_LIGHT_WATERLOW:
return (dirty_states&(C3DLOWSTATE_LIGHT))!=0;
break;
default:
#ifdef C3DLOW_DEBUG
OutputDebugStringA("StateManager::IsDirty : Not all param_type is handled.");
#endif
return true;
}
}
//updates vertex shader constants that depends on dirty C3DLOWSTATE_
void StateManager::ShaderParamUpdate()
{
int dirty_states = g_C3DLow.GetDirtyStates();
int i;
Profile_StartTimerFast("ShaderParamUpdate::Set");
if (dirty_states == C3DLOWSTATE_ALL)
{ //each state is dirty update each of them
for(i=0;i<m_VShaderParamStateCount;++i)
{
SetShaderConstantF(ST_VERTEX, m_VShaderParamStates[i].index,
m_VShaderParamStates[i].type);
}
for(i=0;i<m_PShaderParamStateCount;++i)
{
SetShaderConstantF(ST_PIXEL, m_PShaderParamStates[i].index,
m_PShaderParamStates[i].type);
}
}
else if (dirty_states!=0)
{
for(i=0;i<m_VShaderParamStateCount;++i)
{
if (IsDirty(m_VShaderParamStates[i].type))
SetShaderConstantF(ST_VERTEX, m_VShaderParamStates[i].index,
m_VShaderParamStates[i].type);
}
for(i=0;i<m_PShaderParamStateCount;++i)
{
if (IsDirty(m_PShaderParamStates[i].type))
SetShaderConstantF(ST_PIXEL, m_PShaderParamStates[i].index,
m_PShaderParamStates[i].type);
}
}
Profile_EndTimerFast("ShaderParamUpdate::Set");
Profile_StartTimerFast("ShaderParamUpdate::Apply");
Apply();
Profile_EndTimerFast("ShaderParamUpdate::Apply");
}
// *********************************************
// C3DLow material implementations
// *********************************************
int C3DLowInterface::MaterialBegin(CMaterial &mat, int mode)
{
Profile_AddToCounterFast("MaterialBegin" , 1)
int lod = m_MaterialLod;
switch(m_ParaboloidMode)
{
case C3DLOWPARABOLOIDMODE_FRONT:
mode = (mode == RENDERMODE_SLOT) ? RENDERMODE_INTOPARABOLOIDFRONT_SLOT : RENDERMODE_INTOPARABOLOIDFRONT;
lod = 100;
break;
case C3DLOWPARABOLOIDMODE_BACK:
mode = (mode == RENDERMODE_SLOT) ? RENDERMODE_INTOPARABOLOIDBACK_SLOT : RENDERMODE_INTOPARABOLOIDBACK;
lod = 100;
break;
}
#ifdef C3DLOW_DEBUG2
materials[material_count].mat = &mat;
materials[material_count].active = 1;
++material_count;
#endif
m_CurrentRenderMode = mode;
//select the appropriate implementation
CMaterialImpl *impl = mat.m_pImplList->SetLOD(lod);
#ifdef C3DLOW_DEBUG
{
static int log_mat_types = 0;
if (log_mat_types)
{
char str[128];
sprintf(str,"id:%x tex:%x\n",mat.GetType(),mat.GetTexture(MATPARAMTEX_DIFFUSE));
OutputDebugString(str);
}
}
#endif
mat.m_pActiveImpl = impl;
m_pCurrentMaterialImpl = impl;
int numpass = impl->Begin(mode);
m_DirtyStates = C3DLOWSTATE_ALL;
#ifdef SANITY_CHECK
if (mode==RENDERMODE_PRELIT && !(mat.m_MaterialMode&MATERIALMODE_PRELIT))
OutputDebugStringA("MaterialBegin: Invalid RenderMode\n");
#ifdef USE_STATEMANAGER
if (!g_pStateManager->CheckStateValidity())
{
g_pStateManager->CheckStateValidity();
}
#else
if (!g_C3DLow.IsD3DStateValid())
{
g_C3DLow.IsD3DStateValid();
}
#endif
#endif
if (numpass)
{
if (mat.m_AlphaTestValue!=0 && !m_AlphaTestEnabled)
{
g_pD3DDevice->SetRenderState(D3DRS_ALPHAREF, mat.m_AlphaTestValue);
g_pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
}
if (mat.m_MaterialMode & MATERIALMODE_CULLNONE)
{
g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
}
}
#ifdef C3DLOW_DEBUG
if ( (mode == RENDERMODE_PALSKINNED1 ||
mode == RENDERMODE_PALSKINNED2 ||
mode == RENDERMODE_PALSKINNED3 ||
mode == RENDERMODE_PALSKINNED4) &&
g_dontrender_palskinned )
return 0;
#endif
return numpass;
}
int C3DLowInterface::MaterialPass(CMaterial &mat, int pass_index)
{
Profile_AddToCounterFast("MaterialPass" , 1)
if (pass_index>=0)
g_pStateManager->ShaderParamClear();
g_C3DLow.m_CurrentPass = pass_index;
int rval = mat.m_pActiveImpl->Pass(pass_index);
return rval;
}
void C3DLowInterface::MaterialEnd(CMaterial &mat)
{
Profile_AddToCounterFast("MaterialEnd" , 1)
mat.m_pActiveImpl->Pass(-1);
g_pStateManager->ShaderParamClear();
if (mat.m_AlphaTestValue!=0 && !m_AlphaTestEnabled)
{
g_pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, g_C3DLow.m_AlphaTestEnabled);
}
if (mat.m_MaterialMode & MATERIALMODE_CULLNONE)
{
g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, m_CullMode);
}
#ifdef SANITY_CHECK
if (!g_C3DLow.IsD3DStateValid())
{
g_C3DLow.IsD3DStateValid();
}
#endif
m_pCurrentMaterialImpl = NULL;
m_CurrentRenderMode = RENDERMODE_INVALID;
}
// ***************************************************
// Vertex/Pixel Shader related functions
// ***************************************************
static class CIncludeManager : public ID3DXInclude
{
public:
STDMETHOD (Open)(D3DXINCLUDE_TYPE, LPCSTR, LPCVOID, LPCVOID *, UINT *);
STDMETHOD (Close)(LPCVOID);
} TheIncludeManager;
static MacroList __nomacros;
MacroList &NoMacros()
{
return __nomacros;
}
bool IsVSSupported(int major, int minor)
{
return g_C3DLow.m_dcaps.VertexShaderVersion >= D3DVS_VERSION(major,minor);
}
bool IsPSSupported(int major, int minor)
{
return g_C3DLow.m_dcaps.PixelShaderVersion >= D3DPS_VERSION(major,minor);
}
static unsigned char *ShaderLibData = NULL;
struct ShaderLibEntry
{
char *fname;
int offset;
int len;
ShaderLibEntry *m_pNext;
} * ShaderLibEntryHead = NULL;
typedef unsigned char* BUFPTR;
extern int LZW_expand(BUFPTR input, int length, BUFPTR output, int buflen, int CODE_BITS=11);
extern int LZW_expand_size(BUFPTR input, int length); //calculates the expanded size
void InitShaderLib()
{
#ifdef USE_SHADERLIB
ShaderLibEntryHead = NULL;
long filesize = 0;
unsigned char *tempdata = 0;
filesize = file_Load("renderengine/neoshader.dat", (char **)&tempdata);
if (filesize <= 0 || !tempdata)
{
if (tempdata)
free(tempdata);
return;
}
// decompress data
int data_size = LZW_expand_size(tempdata, filesize);
if (data_size > 0)
{
ShaderLibData = new unsigned char[data_size];
LZW_expand(tempdata, filesize, ShaderLibData, data_size);
free(tempdata);
}
else
{
data_size = filesize;
ShaderLibData = new unsigned char[data_size];
memcpy(ShaderLibData, tempdata, data_size);
free(tempdata);
}
{
// compute entries
unsigned char *rover = ShaderLibData;
unsigned char *rover_end = ShaderLibData + data_size;
char* id = "ISHD";
if (_strnicmp((char*)rover, id, 4))
{
fLog(LL_Error, LS_Render, 0, "Error: Invalid ShaderLib file!");
return;
}
rover += 4;
while (rover < rover_end)
{
ShaderLibEntry *entry = new ShaderLibEntry;
entry->m_pNext = ShaderLibEntryHead;
ShaderLibEntryHead = entry;
// get filename
int slen = strlen((char*)rover) + 1;
entry->fname = new char[slen];
strcpy_s(entry->fname, slen, (char*)rover);
rover += strlen(entry->fname) + 1;
// get len
entry->len = *((int*)rover);
rover += sizeof(int);
entry->offset = rover - ShaderLibData;
rover += entry->len;
}
}
#endif
}
void DestroyShaderLib()
{
#ifdef USE_SHADERLIB
ShaderLibEntry *rover = ShaderLibEntryHead;
while (rover)
{
ShaderLibEntry *temp = rover->m_pNext;
delete[] rover->fname;
delete rover;
rover = temp;
}
ShaderLibEntryHead = NULL;
delete ShaderLibData;
ShaderLibData = NULL;
#endif
}
char *ShaderLibGetData(const char *fname, int &len)
{
#ifdef USE_SHADERLIB
ShaderLibEntry *rover = ShaderLibEntryHead;
while (rover)
{
if (!_stricmp(fname, rover->fname))
{
len = rover->len;
return (char*)&ShaderLibData[rover->offset];
}
rover = rover->m_pNext;
}
len = 0;
return NULL;
#else
len = 0;
return NULL;
#endif
}
LPD3DXBUFFER AssembleShader(char *fname, MacroList &macros, bool valuedDefines)
{
LPD3DXBUFFER pCode = NULL;
LPD3DXBUFFER pErrorMsg = NULL;
D3DXMACRO d3dx_macro[20];
unsigned int i;
unsigned int macrosSize = (unsigned int)macros.size() / (valuedDefines ? 2 : 1);
for (i=0; i<macrosSize && i<19; ++i)
{
if (valuedDefines)
{
d3dx_macro[i].Name = macros.at(i*2).c_str();
d3dx_macro[i].Definition = macros.at(i*2 + 1).c_str();
}
else
{
d3dx_macro[i].Name = macros.at(i).c_str();
d3dx_macro[i].Definition = "1";
}
}
i = min(macrosSize, 19);
d3dx_macro[i].Name = NULL;
d3dx_macro[i].Definition = NULL;
int len;
char *shader = ShaderLibGetData(fname, len);
if (shader) // LOAD FROM LIBRARY
{
// Assemble the vertex shader from the file
#ifdef SHADER_ERRORS
D3DXAssembleShader(shader, len, d3dx_macro, &TheIncludeManager, 0, &pCode, &pErrorMsg);
#else
D3DXAssembleShader(shader, len, d3dx_macro, &TheIncludeManager, 0, &pCode, NULL);
#endif
}
#ifdef SHADER_ERRORS
if (pErrorMsg && pErrorMsg->GetBufferPointer())
{
char temp[2048];
sprintf_s(temp, "Error in shader %s.\n%s", fname, (char*)pErrorMsg->GetBufferPointer());
::MessageBoxA(NULL, temp, "Error", 0);
}
SAFE_RELEASE(pErrorMsg)
#endif
return pCode;
}
LPD3DXBUFFER CreateShader(const char *fname, const char *entrypoint, const char *profile, MacroList &macros, bool valuedDefines)
{
LPD3DXBUFFER pCode = NULL;
LPD3DXBUFFER pErrorMsg = NULL;
D3DXMACRO d3dx_macro[20];
unsigned int i;
unsigned int macrosSize = (unsigned int)macros.size() / (valuedDefines ? 2 : 1);
for (i=0; i<macrosSize && i<19; ++i)
{
if (valuedDefines)
{
d3dx_macro[i].Name = macros.at(i*2).c_str();
d3dx_macro[i].Definition = macros.at(i*2 + 1).c_str();
}
else
{
d3dx_macro[i].Name = macros.at(i).c_str();
d3dx_macro[i].Definition = "1";
}
}
i = min(macrosSize, 19);
d3dx_macro[i].Name = NULL;
d3dx_macro[i].Definition = NULL;
DWORD flags = 0;
#if D3DX_SDK_VERSION >= 31
flags = D3DXSHADER_USE_LEGACY_D3DX9_31_DLL;
#endif
int len;
char *shader = ShaderLibGetData(fname, len);
if (shader) // LOAD FROM LIBRARY
{
// Assemble the vertex shader from the file
#ifdef SHADER_ERRORS
D3DXCompileShader(shader, len, d3dx_macro, &TheIncludeManager, (LPCSTR)entrypoint,
(LPCSTR)profile, flags, &pCode, &pErrorMsg, NULL);
#else
D3DXCompileShader(shader, len, d3dx_macro, &TheIncludeManager, (LPCSTR)entrypoint,
(LPCSTR)profile, flags, &pCode, NULL, NULL);
#endif
}
#ifdef SHADER_ERRORS
// any errors?
if (pErrorMsg && pErrorMsg->GetBufferPointer())
{
//OutputDebugStringA((char*)pErrorMsg->GetBufferPointer());
char temp[2048];
sprintf_s(temp, "Error in shader %s.\n%s", fname, (char*)pErrorMsg->GetBufferPointer());
::MessageBoxA(NULL, temp, "Error", 0);
}
SAFE_RELEASE(pErrorMsg)
#endif
return pCode;
}
LPDIRECT3DVERTEXSHADER9 CreateVertexShader(char *fname, MacroList &macros, bool valuedDefines)
{
LPDIRECT3DVERTEXSHADER9 pVertexShader;
LPD3DXBUFFER pCode = AssembleShader(fname, macros, valuedDefines);
if (!pCode)
{
return NULL;
}
// Create the vertex shader
if (FAILED(g_pD3DDevice->CreateVertexShader((DWORD*)pCode->GetBufferPointer(), &pVertexShader)))
{
return NULL;
}
++g_C3DLow.m_VertexShaderCount;
return pVertexShader;
}
LPDIRECT3DVERTEXSHADER9 CreateVertexShader(char *fname, char* macro, char* macro2)
{
MacroList macros;
macros.clear();
std::string m1, m2;
m1.append(macro ? macro : "");
m2.append(macro2 ? macro2 : "");
macros.push_back(m1);
macros.push_back(m2);
return CreateVertexShader(fname, macros);
}
LPDIRECT3DVERTEXSHADER9 CreateVertexShader(const char *fname, const char *entrypoint, const char *profile,
MacroList &macros, bool valuedDefines)
{
LPDIRECT3DVERTEXSHADER9 pVertexShader;
LPD3DXBUFFER pCode = CreateShader(fname, entrypoint, profile, macros, valuedDefines);
if (!pCode)
{
return NULL;
}
// Create the vertex shader
if (FAILED(g_pD3DDevice->CreateVertexShader((DWORD*)pCode->GetBufferPointer(), &pVertexShader)))
{
return NULL;
}
++g_C3DLow.m_VertexShaderCount;
return pVertexShader;
}
void ReleaseVertexShader(LPDIRECT3DVERTEXSHADER9 vertexshader)
{
if (vertexshader==NULL) return;
if (vertexshader->Release()==0)
{//delete from list
--g_C3DLow.m_VertexShaderCount;
}
}
LPDIRECT3DPIXELSHADER9 CreatePixelShader(char *fname, MacroList &macros, bool valuedDefines)
{
//check if it is already created
LPDIRECT3DPIXELSHADER9 pPixelShader;
LPD3DXBUFFER pCode = AssembleShader(fname, macros, valuedDefines);
if (!pCode)
{
return NULL;
}
// Create the vertex shader
if (FAILED(g_pD3DDevice->CreatePixelShader((DWORD*)pCode->GetBufferPointer(), &pPixelShader)))
{
return NULL;
}
++g_C3DLow.m_PixelShaderCount;
return pPixelShader;
}
LPDIRECT3DPIXELSHADER9 CreatePixelShader(char *fname, char* macro, char* macro2)
{
MacroList macros;
macros.clear();
std::string m1, m2;
m1.append(macro ? macro : "");
m2.append(macro2 ? macro2 : "");
macros.push_back(m1);
macros.push_back(m2);
return CreatePixelShader(fname, macros);
}
LPDIRECT3DPIXELSHADER9 CreatePixelShader(const char *fname, const char *entrypoint, const char *profile,
MacroList &macros, bool valuedDefines)
{
LPDIRECT3DPIXELSHADER9 pPixelShader;
LPD3DXBUFFER pCode = CreateShader(fname, entrypoint, profile, macros, valuedDefines);
if (!pCode)
{
return NULL;
}
// Create the vertex shader
if (FAILED(g_pD3DDevice->CreatePixelShader((DWORD*)pCode->GetBufferPointer(), &pPixelShader)))
{
return NULL;
}
++g_C3DLow.m_PixelShaderCount;
return pPixelShader;
}
void ReleasePixelShader(LPDIRECT3DPIXELSHADER9 pixelshader)
{
if (pixelshader==NULL) return;
if (pixelshader->Release()==0)
{//delete from list
--g_C3DLow.m_PixelShaderCount;
}
}
LPD3DXFRAGMENTLINKER CreateFragmentLinker(char *fname, MacroList macros)
{
DWORD dwShaderFlags = 0; //D3DXSHADER_PARTIALPRECISION;
// Shader compilate and link flags
LPD3DXBUFFER pCompiledFragments = NULL;
LPD3DXBUFFER pErrorMsg = NULL;
D3DXMACRO d3dx_macro[10];
unsigned int i;
for (i=0; i<macros.size() && i<9; ++i)
{
d3dx_macro[i].Name = macros.at(i).c_str();
d3dx_macro[i].Definition = "1";
}
i = min(macros.size(), 9);
d3dx_macro[i].Name = NULL;
d3dx_macro[i].Definition = NULL;
LPD3DXFRAGMENTLINKER fragment_linker = NULL;
//check if it is already created
int len;
const char *shader = ShaderLibGetData(fname, len);
if (shader)
{
#ifdef SHADER_ERRORS
D3DXGatherFragments( shader, len, macros.size() ? d3dx_macro : NULL,
NULL, dwShaderFlags, &pCompiledFragments, &pErrorMsg);
#else
D3DXGatherFragments( shader, len, macros.size() ? d3dx_macro : NULL,
NULL, dwShaderFlags, &pCompiledFragments, NULL);
#endif
}
if (pErrorMsg && pErrorMsg->GetBufferPointer())
{
char temp[2048];
sprintf_s(temp, "Error in shader %s.\n%s", fname, (char*)pErrorMsg->GetBufferPointer());
#ifdef SHADER_ERRORS
::MessageBoxA(NULL, temp, "Error", 0);
#endif
fLog(LL_Error, LS_Render, 0, temp);
}
SAFE_RELEASE(pErrorMsg)
if (pCompiledFragments)
{
fragment_linker = NULL; // Fragment linker interface
// Create the fragment linker interface
D3DXCreateFragmentLinker( g_pD3DDevice, 0, &fragment_linker );
// Add the compiled fragments to a list
fragment_linker->AddFragments( (DWORD*)pCompiledFragments->GetBufferPointer() );
}
return fragment_linker;
}
LPD3DXFRAGMENTLINKER CreateFragmentLinker(char *fname)
{
MacroList temp;
temp.clear();
return CreateFragmentLinker(fname, temp);
}
LPD3DXFRAGMENTLINKER CreateFragmentLinker(char *fname, char *macro)
{
MacroList temp;
temp.clear();
temp.push_back(std::string(macro));
return CreateFragmentLinker(fname, temp);
}
void ReleaseFragmentLinker(LPD3DXFRAGMENTLINKER fragment_linker)
{
if (fragment_linker == NULL) return;
fragment_linker->Release();
}
#define SHADER_REGISTER_COUNT 32
static struct shader_register
{
bool c[4];
} shader_registers[SHADER_REGISTER_COUNT];
static struct shader_instruction
{
DWORD *p;
int parameter_count;
} shader_instructions[128];
void OptimizeShader(LPD3DXBUFFER shader)
{
DWORD* data = (DWORD*)shader->GetBufferPointer();
DWORD* data_end = (DWORD*)shader->GetBufferPointer() + shader->GetBufferSize() / 4;
DWORD* rover = data;
if (!data) return;
#ifdef C3DLOW_DEBUG
bool output_shader = false;
if (output_shader)
{
LPD3DXBUFFER pDisassembly;
D3DXDisassembleShader((ULONG*)data, FALSE, NULL,&pDisassembly);
if (pDisassembly)
{
char * str = (char*)pDisassembly->GetBufferPointer();
OutputDebugStringA(str);
FILE *f = fopen("shaders.txt","at");
fputs("\n\nOriginal\n\n",f);
fputs(str,f);
fclose(f);
pDisassembly->Release();
}
output_shader = false;
}
if (*rover != D3DPS_VERSION(2,0))
OutputDebugStringA("Not PS2.0 version\n");
#endif
rover++;
int instruction_count = 0;
while(rover<data_end)
{
DWORD code = *rover;
if (code==D3DPS_END())
{
}
else
{
if ( (code&0x80000000) == 0x80000000)
{
_asm nop; //should not happen
}
else
{
if ((code&0x0000ffff) == 0x0000fffe)
{ //comment
if (instruction_count!=0 &&
shader_instructions[instruction_count-1].parameter_count!=0)
OutputDebugStringA("Error: comment is inside instruction\n");
int len = ((code>>16)&0x7ffff);
rover+=len;
}
else
{
//skip dcl and def
if ( (code&0x0000ffffff) != D3DSIO_DCL &&
(code&0x0000ffffff) != D3DSIO_DEF &&
(code&0x0000ffffff) != D3DSIO_DEFB &&
(code&0x0000ffffff) != D3DSIO_DEFI )
{
shader_instructions[instruction_count].parameter_count = (code>>24)&0xf;
shader_instructions[instruction_count++].p = rover;
}
rover+= (code>>24)&0xf;
}
}
}
rover++;
}
int i,j,k;
for(i=0;i<SHADER_REGISTER_COUNT;++i)
{
shader_registers[i].c[0] =
shader_registers[i].c[1] =
shader_registers[i].c[2] =
shader_registers[i].c[3] = false;
}
int d;
//come from back to front
for(i=instruction_count-1;i>=0;--i)
{
if ( (*shader_instructions[i].p) == ((2<<24)|D3DSIO_MOV))
{
unsigned int idx[2]={0,1};
//replace registers if can
bool do_swap = true;
//remove instruction -> comment
for(d=0;d<2 && do_swap;++d)
{
DWORD param = *(shader_instructions[i].p+1+d);
if ( ( ((param&D3DSP_REGTYPE_MASK)>>D3DSP_REGTYPE_SHIFT) |
((param&D3DSP_REGTYPE_MASK2)>>D3DSP_REGTYPE_SHIFT2) )
== D3DSPR_TEMP)
{ //dest is a temporary register
if (d==0)
{
if ( ((param>>13)&0x1) != 0 || //relative addressing
((param>>24)&0xf) != 0 || //shift scale
//((param>>16)&0xf) != 0xf || //write mask
( (param&D3DSP_DSTMOD_MASK) != D3DSPDM_NONE &&
(param&D3DSP_DSTMOD_MASK) != D3DSPDM_PARTIALPRECISION)
)
{
do_swap = false;
}
}
else
{
if ( ((param>>13)&0x1) != 0 || //relative addressing
(param&D3DSP_SWIZZLE_MASK) != D3DVS_NOSWIZZLE || //swizzle
(param&D3DSP_SRCMOD_MASK) != D3DSPSM_NONE //srcmask
)
{
do_swap = false;
}
}
}
else
do_swap = false;
if (do_swap)
idx[d] = param&D3DSP_REGNUM_MASK;
}
DWORD param = *(shader_instructions[i].p+1+d);
if (do_swap)
{
bool remove = false;
if (idx[0]==idx[1])
remove = true;
else if ((( (*(shader_instructions[i].p+1)) >>16)&0xf) == 0xf && //no write mask
!shader_registers[idx[1]].c[0] &&
!shader_registers[idx[1]].c[1] &&
!shader_registers[idx[1]].c[2] &&
!shader_registers[idx[1]].c[3] )
{ //there was no need for the data for the second register
//swap idx2,idx1
for(k=i-1;k>=0;--k)
{
for(j=0;j<shader_instructions[k].parameter_count;++j)
{
DWORD param = *(shader_instructions[k].p+1+j);
if ( ( ((param&D3DSP_REGTYPE_MASK)>>D3DSP_REGTYPE_SHIFT) |
((param&D3DSP_REGTYPE_MASK2)>>D3DSP_REGTYPE_SHIFT2) )
== D3DSPR_TEMP)
{
if ((param&D3DSP_REGNUM_MASK)==idx[0])
{
*(shader_instructions[k].p+1+j) &= ~D3DSP_REGNUM_MASK;
*(shader_instructions[k].p+1+j) |= idx[1];
}
if ((param&D3DSP_REGNUM_MASK)==idx[1])
{
*(shader_instructions[k].p+1+j) &= ~D3DSP_REGNUM_MASK;
*(shader_instructions[k].p+1+j) |= idx[0];
}
}
}
remove = true;
}
}
if (remove)
{
*shader_instructions[i].p = D3DSHADER_COMMENT(shader_instructions[i].parameter_count);
for(d=0;d<shader_instructions[i].parameter_count;++d)
{
*(shader_instructions[i].p+d+1) = ('x'<<24) | ('x'<<16) | ('x'<<8) | 'x';
}
continue;
}
}
}
//update read flags
DWORD dest_param = *(shader_instructions[i].p+1);
//clear the bit for the written components
if ( ( ((dest_param&D3DSP_REGTYPE_MASK)>>D3DSP_REGTYPE_SHIFT) |
((dest_param&D3DSP_REGTYPE_MASK2)>>D3DSP_REGTYPE_SHIFT2) )
== D3DSPR_TEMP)
{ //dest is a temporary register
bool remove = true;
for(d = 0; d < 4; ++d)
{
if ( ((dest_param>>(16+d)) & 0x1) )
{
{
if (shader_registers[dest_param&D3DSP_REGNUM_MASK].c[d])
{
shader_registers[dest_param&D3DSP_REGNUM_MASK].c[d] = false;
remove = false;
}
}
}
}
if(remove)
{
//there was no need for the data it computed
*shader_instructions[i].p = D3DSHADER_COMMENT(shader_instructions[i].parameter_count);
for(d=0;d<shader_instructions[i].parameter_count;++d)
{
*(shader_instructions[i].p+d+1) = ('x'<<24) | ('x'<<16) | ('x'<<8) | 'x';
}
continue;
}
}
//write_mask
int instruction = (*shader_instructions[i].p) & 0xffff;
if ( instruction != D3DSIO_ABS &&
instruction != D3DSIO_ADD &&
instruction != D3DSIO_CMP &&
instruction != D3DSIO_LRP &&
instruction != D3DSIO_MAD &&
instruction != D3DSIO_MAX &&
instruction != D3DSIO_MIN &&
instruction != D3DSIO_MOV &&
instruction != D3DSIO_MUL &&
instruction != D3DSIO_SUB )
dest_param |= 0xf<<16;
// set the bit for the needed components
for(d = 0; d < 4; ++d)
{
if ( (dest_param>>(16+d)) & 0x1 )
{ //the component is used
for(j=1;j<shader_instructions[i].parameter_count;++j)
{
DWORD src_param = *(shader_instructions[i].p+1+j);
if ( ( ((src_param&D3DSP_REGTYPE_MASK)>>D3DSP_REGTYPE_SHIFT) |
((src_param&D3DSP_REGTYPE_MASK2)>>D3DSP_REGTYPE_SHIFT2) )
== D3DSPR_TEMP)
{
shader_registers[src_param&D3DSP_REGNUM_MASK].c[(src_param>>(16+(2*d)))&0x3] = true;
}
}
}
}
}
#ifdef C3DLOW_DEBUG
bool b_output_shader = false;
if (b_output_shader)
{
LPD3DXBUFFER pDisassembly;
D3DXDisassembleShader((ULONG*)data, FALSE, NULL,&pDisassembly);
if (pDisassembly)
{
char * str = (char*)pDisassembly->GetBufferPointer();
OutputDebugStringA(str);
FILE *f = fopen("shaders.txt","at");
fputs("\n\nOptimized\n\n",f);
fputs(str,f);
fclose(f);
pDisassembly->Release();
}
}
#endif
}
void OutputShaderSrc(LPDIRECT3DVERTEXSHADER9 vs)
{
#ifdef C3DLOW_DEBUG
bool b2_output_shader = false;
if (b2_output_shader)
{
if (vs)
{ //get sampler indices because we can't force them with register(s#)
LPD3DXBUFFER ppDisassembly;
UINT data_size;
char *data;
vs->GetFunction(NULL,&data_size);
data = new char[data_size];
vs->GetFunction(data,&data_size);
D3DXDisassembleShader((ULONG*)data, FALSE, NULL,&ppDisassembly);
char * str = (char*)ppDisassembly->GetBufferPointer();
OutputDebugStringA(str);
LPD3DXCONSTANTTABLE ppConstantTable;
D3DXGetShaderConstantTable( (DWORD*)data, &ppConstantTable );
D3DXCONSTANT_DESC desc;
UINT count = 1;
D3DXHANDLE handle = ppConstantTable->GetConstantByName(NULL,"WorldViewT");
if (handle)
ppConstantTable->GetConstantDesc( handle, &desc, &count);
delete[] data;
}
}
#endif
}
void OutputShaderSrc(LPDIRECT3DPIXELSHADER9 ps)
{
#ifdef C3DLOW_DEBUG
if (ps)
{ //get sampler indices because we can't force them with register(s#)
LPD3DXBUFFER ppDisassembly;
UINT data_size;
char *data;
ps->GetFunction(NULL,&data_size);
data = new char[data_size];
ps->GetFunction(data,&data_size);
D3DXDisassembleShader((ULONG*)data, FALSE, NULL,&ppDisassembly);
char * str = (char*)ppDisassembly->GetBufferPointer();
OutputDebugStringA(str);
delete data;
}
#endif
}
void CreateShaderPS20(shader_ps20 *sh, ID3DXFragmentLinker* pFragmentLinker,
D3DXHANDLE *vs_fragments, int vs_num_fragments,
D3DXHANDLE *ps_fragments, int ps_num_fragments)
{ //optimizes shaders too
DWORD dwShaderFlags = 0; // Shader link flags
LPD3DXBUFFER pErrorMsg = NULL;
if (sh->failed) return;
sh->failed = 1;
sh->vs = NULL;
sh->ps = NULL;
#ifdef C3DLOW_DEBUG
{
int i;
for(i=0;i<vs_num_fragments;++i)
if (vs_fragments[i]==NULL)
{
char str[128];
sprintf(str,"Fragment shader(%d) is NULL",i);
OutputDebugStringA(str);
}
}
#endif
HRESULT hres;
if (FAILED(hres = pFragmentLinker->LinkVertexShader( "vs_2_0", dwShaderFlags, vs_fragments, vs_num_fragments, &sh->vs, &pErrorMsg ) ) )
{
if (pErrorMsg && pErrorMsg->GetBufferPointer())
{
OutputDebugStringA((char*)pErrorMsg->GetBufferPointer());
pErrorMsg->Release();
}
}
else OutputShaderSrc(sh->vs);
//pixel shader
#ifdef C3DLOW_DEBUG
{
int i;
for(i=0;i<ps_num_fragments;++i)
if (ps_fragments[i]==NULL)
{
char str[128];
sprintf(str,"Fragment shader(%d) is NULL",i);
OutputDebugStringA(str);
}
}
#endif
LPD3DXBUFFER pCode = NULL;
if (FAILED ( pFragmentLinker->LinkShader( "ps_2_0", dwShaderFlags, ps_fragments, ps_num_fragments, &pCode, &pErrorMsg ) ) )
{
if (pErrorMsg && pErrorMsg->GetBufferPointer())
{
OutputDebugStringA((char*)pErrorMsg->GetBufferPointer());
pErrorMsg->Release();
}
}
// compile shader
if (pCode)
{
LPD3DXBUFFER pCodeOptim;
D3DXCreateBuffer(pCode->GetBufferSize(),&pCodeOptim);
memcpy(pCodeOptim->GetBufferPointer(),
pCode->GetBufferPointer(),
pCode->GetBufferSize());
OptimizeShader(pCodeOptim);
if (FAILED( g_pD3DDevice->CreatePixelShader( (DWORD*)pCodeOptim->GetBufferPointer(),&sh->ps )) )
{
OutputDebugStringA("Error : Optimized Pixel shader is invalid\n");
g_pD3DDevice->CreatePixelShader( (DWORD*)pCode->GetBufferPointer(),&sh->ps );
}
pCodeOptim->Release();
pCode->Release();
}
if (sh->ps)
{ //get sampler indices because we can't force them with register(s#)
UINT data_size;
char *data;
sh->ps->GetFunction(NULL,&data_size);
data = new char[data_size];
sh->ps->GetFunction(data,&data_size);
LPD3DXCONSTANTTABLE ppConstantTable;
D3DXGetShaderConstantTable( (DWORD*)data, &ppConstantTable );
D3DXCONSTANT_DESC desc;
UINT count = 1;
for(int i = 0; i<SAMPLER_COUNT; ++i)
{
char name[20];
sprintf_s(name, 20, "Sampler%d",i);
D3DXHANDLE handle = ppConstantTable->GetConstantByName(NULL,name);
if (handle)
{
ppConstantTable->GetConstantDesc( handle, &desc, &count);
sh->sampler_idx[i] = desc.RegisterIndex;
}
else
sh->sampler_idx[i] = -1;
}
delete[] data;
ppConstantTable->Release();
}
else
{
for(int i = 0; i<SAMPLER_COUNT; ++i)
{
sh->sampler_idx[i] = -1;
}
}
if (sh->vs)
++g_C3DLow.m_VertexShaderCount;
if (sh->ps)
++g_C3DLow.m_PixelShaderCount;
if ( ! ( (sh->vs==NULL && vs_fragments!=NULL) &&
(sh->ps==NULL && ps_fragments!=NULL) ) )
{
sh->failed = 0;
}
else
{
OutputDebugStringA("CreateShaderPS20 failed");
}
}
void CreateShader( LPCSTR vsver, LPCSTR psver,
shader_versioned *sh, ID3DXFragmentLinker* pFragmentLinker,
D3DXHANDLE *vs_fragments, int vs_num_fragments,
D3DXHANDLE *ps_fragments, int ps_num_fragments)
{ //optimizes shaders too
DWORD dwShaderFlags = 0; // Shader link flags
LPD3DXBUFFER pErrorMsg;
if (sh->failed) return;
sh->failed = 1;
sh->vs = NULL;
sh->ps = NULL;
#ifdef C3DLOW_DEBUG
{
int i;
for(i=0;i<vs_num_fragments;++i)
if (vs_fragments[i]==NULL)
{
char str[128];
sprintf(str,"Fragment shader(%d) is NULL",i);
OutputDebugStringA(str);
}
}
#endif
HRESULT hres;
if (FAILED(hres = pFragmentLinker->LinkVertexShader( vsver, dwShaderFlags, vs_fragments, vs_num_fragments, &sh->vs, &pErrorMsg ) ) )
{
if (pErrorMsg && pErrorMsg->GetBufferPointer())
{
OutputDebugStringA((char*)pErrorMsg->GetBufferPointer());
pErrorMsg->Release();
}
}
else OutputShaderSrc(sh->vs);
//pixel shader
#ifdef C3DLOW_DEBUG
{
int i;
for(i=0;i<ps_num_fragments;++i)
if (ps_fragments[i]==NULL)
{
char str[128];
sprintf(str,"Fragment shader(%d) is NULL",i);
OutputDebugStringA(str);
}
}
#endif
LPD3DXBUFFER pCode = NULL;
HRESULT ered;
ered = pFragmentLinker->LinkShader( psver, dwShaderFlags, ps_fragments, ps_num_fragments, &pCode, &pErrorMsg );
if (FAILED ( ered ) )
{
if (pErrorMsg && pErrorMsg->GetBufferPointer())
{
OutputDebugStringA((char*)pErrorMsg->GetBufferPointer());
pErrorMsg->Release();
}
}
// compile shader
if (pCode)
{
LPD3DXBUFFER pCodeOptim;
D3DXCreateBuffer(pCode->GetBufferSize(),&pCodeOptim);
memcpy(pCodeOptim->GetBufferPointer(),
pCode->GetBufferPointer(),
pCode->GetBufferSize());
OptimizeShader(pCodeOptim);
if (FAILED( g_pD3DDevice->CreatePixelShader( (DWORD*)pCodeOptim->GetBufferPointer(),&sh->ps )) )
{
OutputDebugStringA("Error : Optimized Pixel shader is invalid\n");
g_pD3DDevice->CreatePixelShader( (DWORD*)pCode->GetBufferPointer(),&sh->ps );
}
pCodeOptim->Release();
pCode->Release();
}
if (sh->ps)
{ //get sampler indices because we can't force them with register(s#)
UINT data_size;
char *data;
sh->ps->GetFunction(NULL,&data_size);
data = new char[data_size];
sh->ps->GetFunction(data,&data_size);
LPD3DXCONSTANTTABLE ppConstantTable;
D3DXGetShaderConstantTable( (DWORD*)data, &ppConstantTable );
D3DXCONSTANT_DESC desc;
UINT count = 1;
for(int i = 0; i<SAMPLER_COUNT; ++i)
{
char name[20];
sprintf_s(name, 20, "Sampler%d",i);
D3DXHANDLE handle = ppConstantTable->GetConstantByName(NULL,name);
if (handle)
{
ppConstantTable->GetConstantDesc( handle, &desc, &count);
sh->sampler_idx[i] = desc.RegisterIndex;
}
else
sh->sampler_idx[i] = -1;
}
delete[] data;
ppConstantTable->Release();
}
else
{
for(int i = 0; i<SAMPLER_COUNT; ++i)
{
sh->sampler_idx[i] = -1;
}
}
if (sh->vs)
++g_C3DLow.m_VertexShaderCount;
if (sh->ps)
++g_C3DLow.m_PixelShaderCount;
if ( ! ( (sh->vs==NULL && vs_fragments!=NULL) &&
(sh->ps==NULL && ps_fragments!=NULL) ) )
{
sh->failed = 0;
}
else
{
OutputDebugStringA("CreateShaderPS failed");
}
}
void GetShadowLightMatrix(C3DLowMatrix& m, bool eyeCentered)
{
float inv_depth = 1.0f / g_C3DLow.GetProjectedShadow()->GetShadowDepth();
//set special texture matrix for shadow mapping
extern float fBias;
D3DXMATRIX mbias( 0.5f, 0.0f, 0.0f, 0.0f,
0.0f, -0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, fBias * inv_depth, 1.0f );
D3DXMatrixMultiply((D3DXMATRIX*)&m, (D3DXMATRIX*)g_C3DLow.GetProjectedShadow()->GetLightMatrix(), &mbias);
C3DLowMatrix *invview = g_C3DLow.GetInvViewMatrix();
C3DLowVector eye = {invview->_41, invview->_42, invview->_43};
if (eyeCentered)
{
D3DXMATRIX eyem( 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
eye.x, eye.y, eye.z, 1.0f);
D3DXMatrixMultiply((D3DXMATRIX*)&m, &eyem, (D3DXMATRIX*)&m);
}
//.w cam direction scaled for z offset
//view z vector with scale
extern float fDistBias;
C3DLowMatrix *mat_view = g_C3DLow.GetViewMatrix();
float v4[4] = {fDistBias * inv_depth * mat_view->_13, fDistBias * inv_depth * mat_view->_23,
fDistBias * inv_depth * mat_view->_33, fDistBias * inv_depth * mat_view->_43};
m._14 = v4[0];
m._24 = v4[1];
m._34 = v4[2];
m._44 = v4[3] + (eyeCentered ? (v4[0] * eye.x + v4[1] * eye.y + v4[2] * eye.z) : 0.0f);
}
HRESULT CIncludeManager::Open(D3DXINCLUDE_TYPE, LPCSTR filename, LPCVOID, LPCVOID *data, UINT *size)
{
// shaderlib will give the pointer to the shaderfile
*data = (LPCVOID)ShaderLibGetData((const char *)filename, (int &)*size);
return S_OK;
}
HRESULT CIncludeManager::Close(LPCVOID pData)
{
// no need to free data - shaderlib will handle that later
return S_OK;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment