Last active
December 23, 2022 23:29
-
-
Save Jackster/20104b36871b28906026649f9e2a2346 to your computer and use it in GitHub Desktop.
C3DLow_dx9_MatUtil.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 ¶m) | |
{ | |
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 ¶m) | |
{ //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 ¯os, 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 ¯os, 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 ¯os, 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 ¯os, 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 ¯os, 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 ¯os, 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