Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.

This commit is contained in:
LFeenanEA
2025-02-27 17:34:39 +00:00
parent 2e338c00cb
commit 3d0ee53a05
6072 changed files with 2283311 additions and 0 deletions

View File

@@ -0,0 +1,238 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shd6bumpdiff.cpp $*
* *
* $Org Author:: Kenny_m
*
* $Author:: Kenny_m
*
* $Modtime:: 7/11/02 10:36p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "dx8fvf.h"
#include "dx8wrapper.h"
#include "assetmgr.h"
#include "rinfo.h"
#include "camera.h"
#include "shdbumpdiff.h"
#include "shd6bumpdiff.h"
#include "shd6bumpdiff_constants.h"
#include "shdclassids.h"
// shader code declarations
#include "shd6bumpdiff.vsh_code.h"
ShdHWVertexShader Shd6BumpDiffClass::Vertex_Shader;
Matrix4x4 Shd6BumpDiffClass::View_Projection_Matrix;
Shd6BumpDiffClass::Shd6BumpDiffClass(const ShdDefClass* def)
: ShdInterfaceClass(def,SHDDEF_CLASSID_BUMPDIFF),
Texture(NULL)
{
ShdBumpDiffDefClass* Definition=(ShdBumpDiffDefClass*)def;
Texture=WW3DAssetManager::Get_Instance()->Get_Texture
(
Definition->Get_Texture_Name()
);
const Vector3& a=Definition->Get_Ambient();
Ambient.Set(a.X,a.Y,a.Z,1.0f);
const Vector3& d=Definition->Get_Diffuse();
Diffuse.Set(d.X,d.Y,d.Z,1.0f);
}
Shd6BumpDiffClass::~Shd6BumpDiffClass()
{
REF_PTR_RELEASE(Texture);
}
void Shd6BumpDiffClass::Init()
{
// Create vertex shader
DWORD vertex_shader_declaration[]=
{
D3DVSD_STREAM(0),
(D3DVSD_REG(0, D3DVSDT_FLOAT3)), // vertex position
(D3DVSD_REG(1, D3DVSDT_FLOAT3)), // vertex normal
(D3DVSD_REG(2, D3DVSDT_D3DCOLOR)), // vertex color
(D3DVSD_REG(3, D3DVSDT_FLOAT2)), // vertex texture coords
D3DVSD_END()
};
Vertex_Shader.Create
(
shd6bumpdiff_vsh_code,
vertex_shader_declaration
);
}
void Shd6BumpDiffClass::Shutdown()
{
Vertex_Shader.Destroy();
}
/**********************************************************************************************
//! Apply shared states for 1 pass DX6 (no bump)
/*! 7/10/02 5:39p KJM Created
*/
void Shd6BumpDiffClass::Apply_Shared(int pass, RenderInfoClass& rinfo)
{
// vertex processing behavior
DX8Wrapper::Set_DX8_Render_State(D3DRS_SOFTWAREVERTEXPROCESSING,!Vertex_Shader.Is_Using_Hardware());
// fixed function uses pass through by default
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU);
// set vertex shader
DX8Wrapper::Set_Vertex_Shader(Vertex_Shader.Peek_Shader());
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
// set constants
DX8Wrapper::Set_Vertex_Shader_Constant(CV_CONST, D3DXVECTOR4(0.0f, 1.0f, 0.5f, 2.0f), 1);
// calculate shader view projection matrix
Matrix4x4 view_matrix;
DX8Wrapper::Get_Transform(D3DTS_VIEW, view_matrix);
Matrix4x4 proj_matrix;
DX8Wrapper::Get_Transform(D3DTS_PROJECTION, proj_matrix);
Matrix4x4::Multiply(proj_matrix, view_matrix, &View_Projection_Matrix);
}
//**********************************************************************************************
//! Apply per instance states for 1 pass DX6 specular with gloss map (no bump)
/*! 7/10/02 5:39p KJM Created
*/
void Shd6BumpDiffClass::Apply_Instance(int cur_pass, RenderInfoClass& rinfo)
{
DX8Wrapper::Set_Texture(0, Texture);
// set vertex shader constants
Matrix4x4 world;
DX8Wrapper::Get_Transform(D3DTS_WORLD, world);
Matrix4x4 world_view_proj_matrix;
Matrix4x4::Multiply(View_Projection_Matrix,world,&world_view_proj_matrix);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_WORLD_VIEW_PROJECTION, &world_view_proj_matrix, 4);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_WORLD, &world, 4);
ShdHWVertexShader::Light
(
rinfo,
Ambient,
Diffuse
);
}
unsigned Shd6BumpDiffClass::Get_Vertex_Stream_Count() const
{
return 1;
}
unsigned Shd6BumpDiffClass::Get_Vertex_Size(unsigned stream) const
{
return sizeof(VertexFormatXYZNDUV1);
}
void Shd6BumpDiffClass::Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
)
{
VertexFormatXYZNDUV1* verts=(VertexFormatXYZNDUV1*)dest_buffer;
for (unsigned i=0; i<vertex_count; ++i)
{
if (vss.Locations)
{
verts[i].x=vss.Locations[i][0];
verts[i].y=vss.Locations[i][1];
verts[i].z=vss.Locations[i][2];
}
else
{
verts[i].x=0.0f;
verts[i].y=0.0f;
verts[i].z=0.0f;
}
if (vss.DiffuseInt)
{
verts[i].diffuse=vss.DiffuseInt[i];
}
else
{
verts[i].diffuse=0xffffffff;
}
if (vss.Normals)
{
verts[i].nx=vss.Normals[i][0];
verts[i].ny=vss.Normals[i][1];
verts[i].nz=vss.Normals[i][2];
}
else
{
verts[i].nx=0.0f;
verts[i].ny=0.0f;
verts[i].nz=0.0f;
}
if (vss.UV[0])
{
verts[i].u1=vss.UV[0][i].U;
verts[i].v1=vss.UV[0][i].V;
}
else
{
verts[i].u1=0.0f;
verts[i].v1=0.0f;
}
}
}

View File

@@ -0,0 +1,90 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shd6bumpdiff.h $*
* *
* $Org Author:: Kenny_m
*
* $Author:: Kenny_m
*
* $Modtime:: 7/11/02 10:36p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHD6BUMPDIFF_H
#define SHD6BUMPDIFF_H
#ifndef SHDINTERFACE_H
#include "shdinterface.h"
#endif
#ifndef SHDHWSHADER_H
#include "shdhwshader.h"
#endif
class Shd6BumpDiffClass : public ShdInterfaceClass
{
public:
Shd6BumpDiffClass(const ShdDefClass* def);
virtual ~Shd6BumpDiffClass();
static void Init();
static void Shutdown();
virtual int Get_Pass_Count() { return 1; }
virtual int Get_Texture_Count() const { return 1; }
virtual TextureClass* Peek_Texture(int idx) const { return Texture; }
virtual void Apply_Shared(int cur_pass, RenderInfoClass& rinfo);
virtual void Apply_Instance(int cur_pass, RenderInfoClass& rinfo);
virtual unsigned Get_Vertex_Stream_Count() const;
virtual unsigned Get_Vertex_Size(unsigned stream) const;
virtual bool Use_HW_Vertex_Processing() const { return Vertex_Shader.Is_Using_Hardware(); }
virtual void Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
);
protected:
static ShdHWVertexShader Vertex_Shader;
static Matrix4x4 View_Projection_Matrix;
TextureClass* Texture;
Vector4 Ambient;
Vector4 Diffuse;
};
#endif // SHD6BUMPDIFF_H

View File

@@ -0,0 +1,84 @@
//
// Command & Conquer Generals Zero Hour(tm)
// Copyright 2025 Electronic Arts Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// DX6 vertex shader (no bump)
// Kenny Mitchell - Westwood Studios EA 2002
vs.1.1
#include "shdhw_constants.h"
#include "shd6bumpdiff_constants.h"
// In:
// v0 - object space vertex position
// v1 - object space normal
// v2 - color
// v3 - texture coords
// object space vertex position -> screen (early as possible for view clipping)
dp4 oPos.x, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_0]
dp4 oPos.y, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_1]
dp4 oPos.z, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_2]
dp4 oPos.w, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_3]
dp3 WORLD_NORMAL.x, V_NORMAL, c[CV_WORLD_0]
dp3 WORLD_NORMAL.y, V_NORMAL, c[CV_WORLD_1]
dp3 WORLD_NORMAL.z, V_NORMAL, c[CV_WORLD_2]
// Normalize the world normal vector
dp3 WORLD_NORMAL.w, WORLD_NORMAL, WORLD_NORMAL
rsq WORLD_NORMAL.w, WORLD_NORMAL.w
mul WORLD_NORMAL, WORLD_NORMAL, WORLD_NORMAL.w
// calculate light 0 factor
dp3 LIGHT_0.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_0] // L.N
max LIGHT_0.w, LIGHT_0.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_0.w, LIGHT_0.w, c[CV_LIGHT_COLOR_0].w // light attentuation factor
// calculate light 1 factor
dp3 LIGHT_1.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_1] // L.N
max LIGHT_1.w, LIGHT_1.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_1.w, LIGHT_1.w, c[CV_LIGHT_COLOR_1].w // light attentuation factor
// calculate light 2 factor
dp3 LIGHT_2.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_2] // L.N
max LIGHT_2.w, LIGHT_2.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_2.w, LIGHT_2.w, c[CV_LIGHT_COLOR_2].w // light attentuation factor
// calculate light 3 factor
dp3 LIGHT_3.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_3] // L.N
max LIGHT_3.w, LIGHT_3.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_3.w, LIGHT_3.w, c[CV_LIGHT_COLOR_3].w // light attentuation factor
// accumulate light colors
mul COL, c[CV_LIGHT_COLOR_0], LIGHT_0.w
mad COL, c[CV_LIGHT_COLOR_1], LIGHT_1.w, COL
mad COL, c[CV_LIGHT_COLOR_2], LIGHT_2.w, COL
mad COL, c[CV_LIGHT_COLOR_3], LIGHT_3.w, COL
// apply vertex color and diffuse and ambient material terms
mul COL, COL, V_DIFFUSE
mul COL, COL, c[CV_DIFFUSE]
add oD0, COL, c[CV_AMBIENT]
mov oT0, V_TEXTURE

View File

@@ -0,0 +1,100 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// bump diffuse shader constants (no bump)
// Kenny Mitchell - Westwood Studios EA 2002
#ifndef SHD6BUMPDIFF_CONSTANTS_H
#define SHD6BUMPDIFF_CONSTANTS_H
// vertex shader macros
#define CV_WORLD_VIEW_PROJECTION 1
#define CV_WORLD_VIEW_PROJECTION_0 1
#define CV_WORLD_VIEW_PROJECTION_1 2
#define CV_WORLD_VIEW_PROJECTION_2 3
#define CV_WORLD_VIEW_PROJECTION_3 4
//#define CV_WORLD_VIEW 5
//#define CV_WORLD_VIEW_0 5
//#define CV_WORLD_VIEW_1 6
//#define CV_WORLD_VIEW_2 7
//#define CV_WORLD_VIEW_3 8
//#define CV_WORLD_VIEW_INVERSE_TRANSPOSE 9
//#define CV_WORLD_VIEW_INVERSE_TRANSPOSE_0 9
//#define CV_WORLD_VIEW_INVERSE_TRANSPOSE_1 10
//#define CV_WORLD_VIEW_INVERSE_TRANSPOSE_2 11
#define CV_WORLD 12
#define CV_WORLD_0 12
#define CV_WORLD_1 13
#define CV_WORLD_2 14
#define CV_WORLD_3 15
// 16-26 lighting constants
#define CV_BUMPINESS 27
#define CV_EYE_WORLD 28
// inputs
#define V_POSITION v0
#define V_NORMAL v1
#define V_DIFFUSE v2
#define V_TEXTURE v3
#define V_S v4
#define V_T v5
#define V_SxT v6
// registers
#define HALF_ANGLE r0
#define S_WORLD r1
#define T_WORLD r2
#define SxT_WORLD r3
#define LIGHT_LOCAL r4
#define LIGHT_0 r5
#define LIGHT_1 r6
#define LIGHT_2 r7
#define LIGHT_3 r8
#define COL r9
#define WORLD_VERTEX r10
#define EYE_VECTOR r11
#define WORLD_NORMAL r1
#define OUTPUT_REG r0
// texture stages
#define TEX_CUBEMAP t0
#endif

View File

@@ -0,0 +1,280 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shd6bumpspec.cpp $*
* *
* $Org Author:: Kenny_m
*
* $Author:: Kenny_m
*
* $Modtime:: 7/11/02 10:36p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "dx8fvf.h"
#include "dx8wrapper.h"
#include "assetmgr.h"
#include "rinfo.h"
#include "camera.h"
#include "shdbumpspec.h"
#include "shd6bumpspec.h"
#include "shd6bumpspec_constants.h"
#include "shdclassids.h"
// shader code declarations
#include "shd6bumpspec.vsh_code.h"
ShdHWVertexShader Shd6BumpSpecClass::Vertex_Shader;
Matrix4x4 Shd6BumpSpecClass::View_Projection_Matrix;
Shd6BumpSpecClass::Shd6BumpSpecClass(const ShdDefClass* def)
: ShdInterfaceClass(def,SHDDEF_CLASSID_BUMPSPEC),
Texture(NULL)
{
ShdBumpSpecDefClass* Definition=(ShdBumpSpecDefClass*)def;
Texture=WW3DAssetManager::Get_Instance()->Get_Texture
(
Definition->Get_Texture_Name()
);
const Vector3& a=Definition->Get_Ambient();
Ambient.Set(a.X,a.Y,a.Z,1.0f);
const Vector3& d=Definition->Get_Diffuse();
Diffuse.Set(d.X,d.Y,d.Z,1.0f);
const Vector3& s=Definition->Get_Specular();
Specular.Set(s.X,s.Y,s.Z,1.0f);
}
Shd6BumpSpecClass::~Shd6BumpSpecClass()
{
REF_PTR_RELEASE(Texture);
}
void Shd6BumpSpecClass::Init()
{
// Create vertex shader
DWORD vertex_shader_declaration[]=
{
D3DVSD_STREAM(0),
(D3DVSD_REG(0, D3DVSDT_FLOAT3)), // vertex position
(D3DVSD_REG(1, D3DVSDT_FLOAT3)), // vertex normal
(D3DVSD_REG(2, D3DVSDT_D3DCOLOR)), // vertex color
(D3DVSD_REG(3, D3DVSDT_FLOAT2)), // vertex texture coords
D3DVSD_END()
};
Vertex_Shader.Create
(
shd6bumpspec_vsh_code,
vertex_shader_declaration
);
}
void Shd6BumpSpecClass::Shutdown()
{
Vertex_Shader.Destroy();
}
/**********************************************************************************************
//! Apply shared states for 1 pass DX6 specular with gloss map (no bump)
/*! 7/10/02 5:39p KJM Created
*/
void Shd6BumpSpecClass::Apply_Shared(int pass, RenderInfoClass& rinfo)
{
// vertex processing behavior
DX8Wrapper::Set_DX8_Render_State(D3DRS_SOFTWAREVERTEXPROCESSING,!Vertex_Shader.Is_Using_Hardware());
// fixed function uses pass through by default
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU);
// set vertex shader
DX8Wrapper::Set_Vertex_Shader(Vertex_Shader.Peek_Shader());
const Matrix3D& cam=rinfo.Camera.Get_Transform();
// set constants
DX8Wrapper::Set_Vertex_Shader_Constant
(
CV_EYE_WORLD,
D3DXVECTOR4
(
cam.Get_X_Translation(),
cam.Get_Y_Translation(),
cam.Get_Z_Translation(),
1.0f
),
1
);
// set texture stage settings
if (DX8Wrapper::Get_Current_Caps()->Support_ModAlphaAddClr())
{
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLORARG1, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLOROP, D3DTOP_MODULATEALPHA_ADDCOLOR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLORARG2, D3DTA_SPECULAR );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
}
else
{
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
}
// set constants
DX8Wrapper::Set_Vertex_Shader_Constant(CV_CONST, D3DXVECTOR4(0.0f, 1.0f, 0.5f, 2.0f), 1);
// calculate shader view projection matrix
Matrix4x4 view_matrix;
DX8Wrapper::Get_Transform(D3DTS_VIEW, view_matrix);
Matrix4x4 proj_matrix;
DX8Wrapper::Get_Transform(D3DTS_PROJECTION, proj_matrix);
Matrix4x4::Multiply(proj_matrix, view_matrix, &View_Projection_Matrix);
}
//**********************************************************************************************
//! Apply per instance states for 1 pass DX6 specular with gloss map (no bump)
/*! 7/10/02 5:39p KJM Created
*/
void Shd6BumpSpecClass::Apply_Instance(int cur_pass, RenderInfoClass& rinfo)
{
DX8Wrapper::Set_Texture(0, Texture);
// set vertex shader constants
Matrix4x4 world;
DX8Wrapper::Get_Transform(D3DTS_WORLD, world);
Matrix4x4 world_view_proj_matrix;
Matrix4x4::Multiply(View_Projection_Matrix,world,&world_view_proj_matrix);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_WORLD_VIEW_PROJECTION, &world_view_proj_matrix, 4);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_WORLD, &world, 4);
ShdHWVertexShader::Light
(
rinfo,
Ambient,
Diffuse,
Specular
);
}
unsigned Shd6BumpSpecClass::Get_Vertex_Stream_Count() const
{
return 1;
}
unsigned Shd6BumpSpecClass::Get_Vertex_Size(unsigned stream) const
{
return sizeof(VertexFormatXYZNDUV1);
}
void Shd6BumpSpecClass::Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
)
{
VertexFormatXYZNDUV1* verts=(VertexFormatXYZNDUV1*)dest_buffer;
for (unsigned i=0; i<vertex_count; ++i)
{
if (vss.Locations)
{
verts[i].x=vss.Locations[i][0];
verts[i].y=vss.Locations[i][1];
verts[i].z=vss.Locations[i][2];
}
else
{
verts[i].x=0.0f;
verts[i].y=0.0f;
verts[i].z=0.0f;
}
if (vss.DiffuseInt)
{
verts[i].diffuse=vss.DiffuseInt[i];
}
else
{
verts[i].diffuse=0xffffffff;
}
if (vss.Normals)
{
verts[i].nx=vss.Normals[i][0];
verts[i].ny=vss.Normals[i][1];
verts[i].nz=vss.Normals[i][2];
}
else
{
verts[i].nx=0.0f;
verts[i].ny=0.0f;
verts[i].nz=0.0f;
}
if (vss.UV[0])
{
verts[i].u1=vss.UV[0][i].U;
verts[i].v1=vss.UV[0][i].V;
}
else
{
verts[i].u1=0.0f;
verts[i].v1=0.0f;
}
}
}

View File

@@ -0,0 +1,91 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shd6bumpspec.h $*
* *
* $Org Author:: Kenny_m
*
* $Author:: Kenny_m
*
* $Modtime:: 7/11/02 10:36p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHD6BUMPSPEC_H
#define SHD6BUMPSPEC_H
#ifndef SHDINTERFACE_H
#include "shdinterface.h"
#endif
#ifndef SHDHWSHADER_H
#include "shdhwshader.h"
#endif
class Shd6BumpSpecClass : public ShdInterfaceClass
{
public:
Shd6BumpSpecClass(const ShdDefClass* def);
virtual ~Shd6BumpSpecClass();
static void Init();
static void Shutdown();
virtual int Get_Pass_Count() { return 1; }
virtual int Get_Texture_Count() const { return 1; }
virtual TextureClass* Peek_Texture(int idx) const { return Texture; }
virtual void Apply_Shared(int cur_pass, RenderInfoClass& rinfo);
virtual void Apply_Instance(int cur_pass, RenderInfoClass& rinfo);
virtual unsigned Get_Vertex_Stream_Count() const;
virtual unsigned Get_Vertex_Size(unsigned stream) const;
virtual bool Use_HW_Vertex_Processing() const { return Vertex_Shader.Is_Using_Hardware(); }
virtual void Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
);
protected:
static ShdHWVertexShader Vertex_Shader;
static Matrix4x4 View_Projection_Matrix;
TextureClass* Texture;
Vector4 Ambient;
Vector4 Diffuse;
Vector4 Specular;
};
#endif // SHD7BUMPSPEC_H

View File

@@ -0,0 +1,140 @@
//
// Command & Conquer Generals Zero Hour(tm)
// Copyright 2025 Electronic Arts Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// DX6 specular mask vertex shader (no bump)
// Kenny Mitchell - Westwood Studios EA 2002
vs.1.1
#include "shdhw_constants.h"
#include "shd6bumpspec_constants.h"
// In:
// v0 - object space vertex position
// v1 - object space normal
// v2 - color
// v3 - texture coords
// object space vertex position -> screen (early as possible for view clipping)
dp4 oPos.x, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_0]
dp4 oPos.y, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_1]
dp4 oPos.z, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_2]
dp4 oPos.w, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_3]
dp3 WORLD_NORMAL.x, V_NORMAL, c[CV_WORLD_0]
dp3 WORLD_NORMAL.y, V_NORMAL, c[CV_WORLD_1]
dp3 WORLD_NORMAL.z, V_NORMAL, c[CV_WORLD_2]
// Normalize the world normal vector
dp3 WORLD_NORMAL.w, WORLD_NORMAL, WORLD_NORMAL
rsq WORLD_NORMAL.w, WORLD_NORMAL.w
mul WORLD_NORMAL, WORLD_NORMAL, WORLD_NORMAL.w
// calculate light 0 factor
dp3 LIGHT_0.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_0] // L.N
max LIGHT_0.w, LIGHT_0.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_0.w, LIGHT_0.w, c[CV_LIGHT_COLOR_0].w // light attentuation factor
// calculate light 1 factor
dp3 LIGHT_1.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_1] // L.N
max LIGHT_1.w, LIGHT_1.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_1.w, LIGHT_1.w, c[CV_LIGHT_COLOR_1].w // light attentuation factor
// calculate light 2 factor
dp3 LIGHT_2.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_2] // L.N
max LIGHT_2.w, LIGHT_2.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_2.w, LIGHT_2.w, c[CV_LIGHT_COLOR_2].w // light attentuation factor
// calculate light 3 factor
dp3 LIGHT_3.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_3] // L.N
max LIGHT_3.w, LIGHT_3.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_3.w, LIGHT_3.w, c[CV_LIGHT_COLOR_3].w // light attentuation factor
// accumulate light colors
mul COL, c[CV_LIGHT_COLOR_0], LIGHT_0.w
mad COL, c[CV_LIGHT_COLOR_1], LIGHT_1.w, COL
mad COL, c[CV_LIGHT_COLOR_2], LIGHT_2.w, COL
mad COL, c[CV_LIGHT_COLOR_3], LIGHT_3.w, COL
// apply vertex color and diffuse and ambient material terms
mul COL, COL, V_DIFFUSE
mul COL, COL, c[CV_DIFFUSE]
add oD0, COL, c[CV_AMBIENT]
// calculate half angle
// transform vertex position to world space
// to calculate V, vector to viewer in world
// space.
dp4 WORLD_VERTEX.x, V_POSITION, c[CV_WORLD_0]
dp4 WORLD_VERTEX.y, V_POSITION, c[CV_WORLD_1]
dp4 WORLD_VERTEX.z, V_POSITION, c[CV_WORLD_2]
//dp4 WORLD_VERTEX.w, V_POSITION, c[CV_WORLD_3]
// Half angle vector is (L+V)/||L+V|| or Normalize( L+V )
// ||a|| is magnitude of a
// L = vec to light from vertex point
// V = vec to viewer from vertex point
// vertex position - eye position
// eye position - vertex position
add EYE_VECTOR, c[CV_EYE_WORLD], -WORLD_VERTEX.xyz
// Normalize the eye vector
dp3 EYE_VECTOR.w, EYE_VECTOR, EYE_VECTOR
rsq EYE_VECTOR.w, EYE_VECTOR.w
mul EYE_VECTOR, EYE_VECTOR, EYE_VECTOR.w
// Add them to average & create half angle vector
add HALF_ANGLE, c[CV_LIGHT_DIRECTION_0], EYE_VECTOR
// Normalize the half angle vector
dp3 HALF_ANGLE.w, HALF_ANGLE, HALF_ANGLE
rsq HALF_ANGLE.w, HALF_ANGLE.w
mul HALF_ANGLE, HALF_ANGLE, HALF_ANGLE.w
// calculate light 0 factor
dp3 WORLD_NORMAL.x, V_NORMAL, c[CV_WORLD_0]
dp3 WORLD_NORMAL.y, V_NORMAL, c[CV_WORLD_1]
dp3 WORLD_NORMAL.z, V_NORMAL, c[CV_WORLD_2]
// Normalize the world normal vector
dp3 WORLD_NORMAL.w, WORLD_NORMAL, WORLD_NORMAL
rsq WORLD_NORMAL.w, WORLD_NORMAL.w
mul WORLD_NORMAL, WORLD_NORMAL, WORLD_NORMAL.w
dp3 LIGHT_0.w, HALF_ANGLE, WORLD_NORMAL // N.H
max LIGHT_0.w, LIGHT_0.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_0.w, LIGHT_0.w, c[CV_LIGHT_COLOR_0].w // light attentuation factor
// raise to 8th power
mul LIGHT_0.w, LIGHT_0, LIGHT_0
mul LIGHT_0.w, LIGHT_0, LIGHT_0
mul LIGHT_0.w, LIGHT_0, LIGHT_0
// accumulate light colors
mul COL, c[CV_LIGHT_COLOR_0], LIGHT_0.w
mul oD1, COL, c[CV_SPECULAR]
mov oT0, V_TEXTURE

View File

@@ -0,0 +1,100 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// bump specular with gloss map shader constants (no bump)
// Kenny Mitchell - Westwood Studios EA 2002
#ifndef SHD6BUMPSPEC_CONSTANTS_H
#define SHD6BUMPSPEC_CONSTANTS_H
// vertex shader macros
#define CV_WORLD_VIEW_PROJECTION 1
#define CV_WORLD_VIEW_PROJECTION_0 1
#define CV_WORLD_VIEW_PROJECTION_1 2
#define CV_WORLD_VIEW_PROJECTION_2 3
#define CV_WORLD_VIEW_PROJECTION_3 4
//#define CV_WORLD_VIEW 5
//#define CV_WORLD_VIEW_0 5
//#define CV_WORLD_VIEW_1 6
//#define CV_WORLD_VIEW_2 7
//#define CV_WORLD_VIEW_3 8
//#define CV_WORLD_VIEW_INVERSE_TRANSPOSE 9
//#define CV_WORLD_VIEW_INVERSE_TRANSPOSE_0 9
//#define CV_WORLD_VIEW_INVERSE_TRANSPOSE_1 10
//#define CV_WORLD_VIEW_INVERSE_TRANSPOSE_2 11
#define CV_WORLD 12
#define CV_WORLD_0 12
#define CV_WORLD_1 13
#define CV_WORLD_2 14
#define CV_WORLD_3 15
// 16-26 lighting constants
#define CV_BUMPINESS 27
#define CV_EYE_WORLD 28
// inputs
#define V_POSITION v0
#define V_NORMAL v1
#define V_DIFFUSE v2
#define V_TEXTURE v3
#define V_S v4
#define V_T v5
#define V_SxT v6
// registers
#define HALF_ANGLE r0
#define S_WORLD r1
#define T_WORLD r2
#define SxT_WORLD r3
#define LIGHT_LOCAL r4
#define LIGHT_0 r5
#define LIGHT_1 r6
#define LIGHT_2 r7
#define LIGHT_3 r8
#define COL r9
#define WORLD_VERTEX r10
#define EYE_VECTOR r11
#define WORLD_NORMAL r1
#define OUTPUT_REG r0
// texture stages
#define TEX_CUBEMAP t0
#endif

View File

@@ -0,0 +1,350 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/shd7bumpdiff.cpp $*
* *
* $Author:: Kenny_m
*
* $Modtime:: 6/06/02 11:18p $*
* *
* $Revision:: 2 $*
* *
* 06/06/02 KM added software vertex shader fallback check
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "dx8fvf.h"
#include "dx8wrapper.h"
#include "assetmgr.h"
#include "rinfo.h"
#include "camera.h"
#include "shdhwshader.h"
#include "shdbumpdiff.h"
#include "shd7bumpdiff.h"
#include "shd7bumpdiff_constants.h"
#include "shdclassids.h"
// shader code declarations
#include "shd7bumpdiffpass0.vsh_code.h"
#include "shd7bumpdiffpass1.vsh_code.h"
ShdHWVertexShader Shd7BumpDiffClass::Pass_0_Vertex_Shader;
ShdHWVertexShader Shd7BumpDiffClass::Pass_1_Vertex_Shader;
Matrix4x4 Shd7BumpDiffClass::View_Projection_Matrix;
Shd7BumpDiffClass::Shd7BumpDiffClass(const ShdDefClass* def)
: ShdInterfaceClass(def,SHDDEF_CLASSID_BUMPDIFF),
Texture(NULL),
NormalMap(NULL)
{
ShdBumpDiffDefClass* Definition=(ShdBumpDiffDefClass*)def;
Texture=WW3DAssetManager::Get_Instance()->Get_Texture
(
Definition->Get_Texture_Name()
);
NormalMap=WW3DAssetManager::Get_Instance()->Get_Texture
(
Definition->Get_Bump_Map_Name()
);
const Vector3& a=Definition->Get_Ambient();
Ambient.Set(a.X,a.Y,a.Z,1.0f);
const Vector3& d=Definition->Get_Diffuse();
Diffuse.Set(d.X,d.Y,d.Z,1.0f);
const Vector2& db=Definition->Get_Diffuse_Bumpiness();
Bumpiness.Set(db.X,db.Y,0.0f,0.0f);
}
Shd7BumpDiffClass::~Shd7BumpDiffClass()
{
REF_PTR_RELEASE(Texture);
REF_PTR_RELEASE(NormalMap);
}
void Shd7BumpDiffClass::Init()
{
// Create vertex shader
DWORD vertex_shader_declaration[]=
{
D3DVSD_STREAM(0),
(D3DVSD_REG(0, D3DVSDT_FLOAT3)), // vertex position
(D3DVSD_REG(1, D3DVSDT_FLOAT3)), // vertex normal
(D3DVSD_REG(2, D3DVSDT_D3DCOLOR)), // vertex color
(D3DVSD_REG(3, D3DVSDT_FLOAT2)), // vertex texture coords
(D3DVSD_REG(4, D3DVSDT_FLOAT3)), // vertex S basis
(D3DVSD_REG(5, D3DVSDT_FLOAT3)), // vertex T basis
(D3DVSD_REG(6, D3DVSDT_FLOAT3)), // vertex SxT basis
D3DVSD_END()
};
Pass_0_Vertex_Shader.Create
(
shd7bumpdiffpass0_vsh_code,
vertex_shader_declaration
);
Pass_1_Vertex_Shader.Create
(
shd7bumpdiffpass1_vsh_code,
vertex_shader_declaration
);
}
void Shd7BumpDiffClass::Shutdown()
{
Pass_0_Vertex_Shader.Destroy();
Pass_1_Vertex_Shader.Destroy();
}
//**********************************************************************************************
//! Apply shared states for 2 pass DX7 bump diffuse
/*! 6/03/02 8:12a KJM Created
*/
void Shd7BumpDiffClass::Apply_Shared(int pass, RenderInfoClass& rinfo)
{
// vertex processing behavior
DX8Wrapper::Set_DX8_Render_State(D3DRS_SOFTWAREVERTEXPROCESSING,!Pass_0_Vertex_Shader.Is_Using_Hardware());
// fixed function uses pass through by default
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU);
if (pass==0)
{
// set vertex shader
DX8Wrapper::Set_Vertex_Shader(Pass_0_Vertex_Shader.Peek_Shader());
// set texture stage settings
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3 );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLORARG2, D3DTA_SPECULAR );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAOP, D3DTOP_ADDSMOOTH );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE, TRUE);
DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND, D3DBLEND_ZERO);
}
else
{
// set vertex shader
DX8Wrapper::Set_Vertex_Shader(Pass_1_Vertex_Shader.Peek_Shader());
// set texture stage settings
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3 );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLORARG2, D3DTA_SPECULAR );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE, TRUE);
DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND, D3DBLEND_ONE);
}
// set constants
DX8Wrapper::Set_Vertex_Shader_Constant(CV_CONST, D3DXVECTOR4(0.0f, 1.0f, 0.5f, 2.0f), 1);
// calculate shader view projection matrix
Matrix4x4 view_matrix;
DX8Wrapper::Get_Transform(D3DTS_VIEW, view_matrix);
Matrix4x4 proj_matrix;
DX8Wrapper::Get_Transform(D3DTS_PROJECTION, proj_matrix);
Matrix4x4::Multiply(proj_matrix, view_matrix, &View_Projection_Matrix);
}
//**********************************************************************************************
//! Apply per instance states for 2 pass DX7 bump diffuse
/*! 6/03/02 8:12a KJM Created
*/
void Shd7BumpDiffClass::Apply_Instance(int cur_pass, RenderInfoClass& rinfo)
{
DX8Wrapper::Set_Texture(0, NormalMap);
DX8Wrapper::Set_Texture(1, Texture);
// set vertex shader constants
Matrix4x4 world;
DX8Wrapper::Get_Transform(D3DTS_WORLD, world);
Matrix4x4 world_view_proj_matrix;
Matrix4x4::Multiply(View_Projection_Matrix,world,&world_view_proj_matrix);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_WORLD_VIEW_PROJECTION, &world_view_proj_matrix, 4);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_WORLD, &world, 4);
ShdHWVertexShader::Light
(
rinfo,
Ambient,
Diffuse
);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_BUMPINESS, &Bumpiness, 1);
}
unsigned Shd7BumpDiffClass::Get_Vertex_Stream_Count() const
{
return 1;
}
unsigned Shd7BumpDiffClass::Get_Vertex_Size(unsigned stream) const
{
return sizeof(VertexFormatXYZNDUV1TG3);
}
void Shd7BumpDiffClass::Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
)
{
VertexFormatXYZNDUV1TG3* verts=(VertexFormatXYZNDUV1TG3*)dest_buffer;
for (unsigned i=0; i<vertex_count; ++i)
{
if (vss.Locations)
{
verts[i].x=vss.Locations[i][0];
verts[i].y=vss.Locations[i][1];
verts[i].z=vss.Locations[i][2];
}
else
{
verts[i].x=0.0f;
verts[i].y=0.0f;
verts[i].z=0.0f;
}
if (vss.DiffuseInt)
{
verts[i].diffuse=vss.DiffuseInt[i];
}
else
{
verts[i].diffuse=0xffffffff;
}
if (vss.Normals)
{
verts[i].nx=vss.Normals[i][0];
verts[i].ny=vss.Normals[i][1];
verts[i].nz=vss.Normals[i][2];
}
else
{
verts[i].nx=0.0f;
verts[i].ny=0.0f;
verts[i].nz=0.0f;
}
if (vss.UV[0])
{
verts[i].u1=vss.UV[0][i].U;
verts[i].v1=vss.UV[0][i].V;
}
else
{
verts[i].u1=0.0f;
verts[i].v1=0.0f;
}
if (vss.S)
{
verts[i].Sx=vss.S[i].X;
verts[i].Sy=vss.S[i].Y;
verts[i].Sz=vss.S[i].Z;
}
else
{
verts[i].Sx=0.0f;
verts[i].Sy=0.0f;
verts[i].Sz=0.0f;
}
if (vss.T)
{
verts[i].Tx=vss.T[i].X;
verts[i].Ty=vss.T[i].Y;
verts[i].Tz=vss.T[i].Z;
}
else
{
verts[i].Tx=0.0f;
verts[i].Ty=0.0f;
verts[i].Tz=0.0f;
}
if (vss.SxT)
{
verts[i].SxTx=vss.SxT[i].X;
verts[i].SxTy=vss.SxT[i].Y;
verts[i].SxTz=vss.SxT[i].Z;
}
else
{
verts[i].SxTx=0.0f;
verts[i].SxTy=0.0f;
verts[i].SxTz=0.0f;
}
}
}

View File

@@ -0,0 +1,92 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/shd7bumpdiff.h $*
* *
* $Author:: Kenny_m
*
* $Modtime:: 6/03/02 8:12a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHD7BUMPDIFF_H
#define SHD7BUMPDIFF_H
#ifndef SHDINTERFACE_H
#include "shdinterface.h"
#endif
#ifndef SHDHWSHADER_H
#include "shdhwshader.h"
#endif
class Shd7BumpDiffClass : public ShdInterfaceClass
{
public:
Shd7BumpDiffClass(const ShdDefClass* def);
virtual ~Shd7BumpDiffClass();
static void Init();
static void Shutdown();
virtual int Get_Pass_Count() { return 2; }
virtual int Get_Texture_Count() const { return 2; }
virtual TextureClass* Peek_Texture(int idx) const { return idx==0 ? Texture : NormalMap; }
virtual void Apply_Shared(int cur_pass, RenderInfoClass& rinfo);
virtual void Apply_Instance(int cur_pass, RenderInfoClass& rinfo);
virtual unsigned Get_Vertex_Stream_Count() const;
virtual unsigned Get_Vertex_Size(unsigned stream) const;
virtual bool Use_HW_Vertex_Processing() const { return Pass_0_Vertex_Shader.Is_Using_Hardware(); }
virtual void Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
);
protected:
static ShdHWVertexShader Pass_0_Vertex_Shader;
static ShdHWVertexShader Pass_1_Vertex_Shader;
static Matrix4x4 View_Projection_Matrix;
TextureClass* Texture;
TextureClass* NormalMap;
Vector4 Ambient;
Vector4 Diffuse;
Vector4 Bumpiness;
};
#endif // SHD7BUMPDIFF_H

View File

@@ -0,0 +1,84 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// bump diffuse map shader constants
// Kenny Mitchell - Westwood Studios EA 2002
#ifndef SHD7BUMPDIFF_CONSTANTS_H
#define SHD7BUMPDIFF_CONSTANTS_H
// vertex shader macros
#define CV_WORLD_VIEW_PROJECTION 1
#define CV_WORLD_VIEW_PROJECTION_0 1
#define CV_WORLD_VIEW_PROJECTION_1 2
#define CV_WORLD_VIEW_PROJECTION_2 3
#define CV_WORLD_VIEW_PROJECTION_3 4
// 5-11 world view & world view inverse transpose
#define CV_WORLD 12
#define CV_WORLD_0 12
#define CV_WORLD_1 13
#define CV_WORLD_2 14
#define CV_WORLD_3 15
// 16-26 lighting constants
#define CV_BUMPINESS 27
#define CV_EYE_WORLD 28
// inputs
#define V_POSITION v0
#define V_NORMAL v1
#define V_DIFFUSE v2
#define V_TEXTURE v3
#define V_S v4
#define V_T v5
#define V_SxT v6
// registers
#define HALF_ANGLE r0
#define S_WORLD r1
#define T_WORLD r2
#define SxT_WORLD r3
#define LIGHT_LOCAL r4
#define LIGHT_0 r5
#define LIGHT_1 r6
#define LIGHT_2 r7
#define LIGHT_3 r8
#define COL r9
#define WORLD_VERTEX r10
#define EYE_VECTOR r11
#define WORLD_NORMAL r1
#define OUTPUT_REG r0
// texture stages
#define TEX_CUBEMAP t0
#endif

View File

@@ -0,0 +1,120 @@
//
// Command & Conquer Generals Zero Hour(tm)
// Copyright 2025 Electronic Arts Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// DX7 bump diffuse vertex shader pass 0
// Kenny Mitchell - Westwood Studios EA 2002
vs.1.1
#include "shdhw_constants.h"
#include "shd7bumpdiff_constants.h"
// In:
// v0 - object space vertex position
// v1 - object space normal
// v2 - color
// v3 - texture coords
// v4 - S basis
// v5 - T basis
// v6 - SxT
// object space vertex position -> screen (early as possible for view clipping)
dp4 oPos.x, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_0]
dp4 oPos.y, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_1]
dp4 oPos.z, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_2]
dp4 oPos.w, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_3]
// Transform basis vectors to world space
dp3 S_WORLD.x, V_S, c[CV_WORLD_0]
dp3 S_WORLD.y, V_S, c[CV_WORLD_1]
dp3 S_WORLD.z, V_S, c[CV_WORLD_2]
dp3 T_WORLD.x, V_T, c[CV_WORLD_0]
dp3 T_WORLD.y, V_T, c[CV_WORLD_1]
dp3 T_WORLD.z, V_T, c[CV_WORLD_2]
dp3 SxT_WORLD.x, V_SxT, c[CV_WORLD_0]
dp3 SxT_WORLD.y, V_SxT, c[CV_WORLD_1]
dp3 SxT_WORLD.z, V_SxT, c[CV_WORLD_2]
// transform light 0 by basis vectors to put it into texture space
dp3 LIGHT_LOCAL.x, S_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
dp3 LIGHT_LOCAL.y, T_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
dp3 LIGHT_LOCAL.z, SxT_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
// Normalize the light vector
dp3 LIGHT_LOCAL.w, LIGHT_LOCAL, LIGHT_LOCAL
rsq LIGHT_LOCAL.w, LIGHT_LOCAL.w
mul LIGHT_LOCAL, LIGHT_LOCAL, LIGHT_LOCAL.w
dp3 WORLD_NORMAL.x, V_NORMAL, c[CV_WORLD_0]
dp3 WORLD_NORMAL.y, V_NORMAL, c[CV_WORLD_1]
dp3 WORLD_NORMAL.z, V_NORMAL, c[CV_WORLD_2]
// Normalize the world normal vector
dp3 WORLD_NORMAL.w, WORLD_NORMAL, WORLD_NORMAL
rsq WORLD_NORMAL.w, WORLD_NORMAL.w
mul WORLD_NORMAL, WORLD_NORMAL, WORLD_NORMAL.w
// calculate light 0 factor
dp3 LIGHT_0.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_0] // L.N
max LIGHT_0.w, LIGHT_0.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_0.w, LIGHT_0.w, c[CV_LIGHT_COLOR_0].w // light attentuation factor
// calculate light 1 factor
dp3 LIGHT_1.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_1] // L.N
max LIGHT_1.w, LIGHT_1.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_1.w, LIGHT_1.w, c[CV_LIGHT_COLOR_1].w // light attentuation factor
// calculate light 2 factor
dp3 LIGHT_2.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_2] // L.N
max LIGHT_2.w, LIGHT_2.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_2.w, LIGHT_2.w, c[CV_LIGHT_COLOR_2].w // light attentuation factor
// calculate light 3 factor
dp3 LIGHT_3.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_3] // L.N
max LIGHT_3.w, LIGHT_3.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_3.w, LIGHT_3.w, c[CV_LIGHT_COLOR_3].w // light attentuation factor
// accumulate light colors
mul COL, c[CV_LIGHT_COLOR_0], LIGHT_0.w
mad COL, c[CV_LIGHT_COLOR_1], LIGHT_1.w, COL
mad COL, c[CV_LIGHT_COLOR_2], LIGHT_2.w, COL
mad COL, c[CV_LIGHT_COLOR_3], LIGHT_3.w, COL
// apply vertex color and diffuse and ambient material terms
mul COL, COL, V_DIFFUSE
mul COL, COL, c[CV_DIFFUSE]
add oD1, COL, c[CV_AMBIENT]
// Scale to 0-1
add LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].yyy
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].zzz
// apply bump scale and bias controls
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_BUMPINESS].xxx
add oD0, LIGHT_LOCAL, c[CV_BUMPINESS].yyy
// place negated bump light intensity in alpha channel
add oD0.w, c[CV_CONST].y, -LIGHT_0.w
mov oT0, V_TEXTURE
mov oT1, V_TEXTURE

View File

@@ -0,0 +1,120 @@
//
// Command & Conquer Generals Zero Hour(tm)
// Copyright 2025 Electronic Arts Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// DX7 bump diffuse vertex shader pass 1
// Kenny Mitchell - Westwood Studios EA 2002
vs.1.1
#include "shdhw_constants.h"
#include "shd7bumpdiff_constants.h"
// In:
// v0 - object space vertex position
// v1 - object space normal
// v2 - color
// v3 - texture coords
// v4 - S basis
// v5 - T basis
// v6 - SxT
// object space vertex position -> screen (early as possible for view clipping)
dp4 oPos.x, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_0]
dp4 oPos.y, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_1]
dp4 oPos.z, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_2]
dp4 oPos.w, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_3]
// Transform basis vectors to world space
dp3 S_WORLD.x, V_S, c[CV_WORLD_0]
dp3 S_WORLD.y, V_S, c[CV_WORLD_1]
dp3 S_WORLD.z, V_S, c[CV_WORLD_2]
dp3 T_WORLD.x, V_T, c[CV_WORLD_0]
dp3 T_WORLD.y, V_T, c[CV_WORLD_1]
dp3 T_WORLD.z, V_T, c[CV_WORLD_2]
dp3 SxT_WORLD.x, V_SxT, c[CV_WORLD_0]
dp3 SxT_WORLD.y, V_SxT, c[CV_WORLD_1]
dp3 SxT_WORLD.z, V_SxT, c[CV_WORLD_2]
// transform light 0 by basis vectors to put it into texture space
dp3 LIGHT_LOCAL.x, S_WORLD.xyz, -c[CV_LIGHT_DIRECTION_0]
dp3 LIGHT_LOCAL.y, T_WORLD.xyz, -c[CV_LIGHT_DIRECTION_0]
dp3 LIGHT_LOCAL.z, SxT_WORLD.xyz, -c[CV_LIGHT_DIRECTION_0]
// Normalize the light vector
dp3 LIGHT_LOCAL.w, LIGHT_LOCAL, LIGHT_LOCAL
rsq LIGHT_LOCAL.w, LIGHT_LOCAL.w
mul LIGHT_LOCAL, LIGHT_LOCAL, LIGHT_LOCAL.w
dp3 WORLD_NORMAL.x, V_NORMAL, c[CV_WORLD_0]
dp3 WORLD_NORMAL.y, V_NORMAL, c[CV_WORLD_1]
dp3 WORLD_NORMAL.z, V_NORMAL, c[CV_WORLD_2]
// Normalize the world normal vector
dp3 WORLD_NORMAL.w, WORLD_NORMAL, WORLD_NORMAL
rsq WORLD_NORMAL.w, WORLD_NORMAL.w
mul WORLD_NORMAL, WORLD_NORMAL, WORLD_NORMAL.w
// calculate light 0 factor
dp3 LIGHT_0.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_0] // L.N
max LIGHT_0.w, LIGHT_0.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_0.w, LIGHT_0.w, c[CV_LIGHT_COLOR_0].w // light attentuation factor
// calculate light 1 factor
dp3 LIGHT_1.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_1] // L.N
max LIGHT_1.w, LIGHT_1.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_1.w, LIGHT_1.w, c[CV_LIGHT_COLOR_1].w // light attentuation factor
// calculate light 2 factor
dp3 LIGHT_2.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_2] // L.N
max LIGHT_2.w, LIGHT_2.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_2.w, LIGHT_2.w, c[CV_LIGHT_COLOR_2].w // light attentuation factor
// calculate light 3 factor
dp3 LIGHT_3.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_3] // L.N
max LIGHT_3.w, LIGHT_3.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_3.w, LIGHT_3.w, c[CV_LIGHT_COLOR_3].w // light attentuation factor
// accumulate light colors
mul COL, c[CV_LIGHT_COLOR_0], LIGHT_0.w
mad COL, c[CV_LIGHT_COLOR_1], LIGHT_1.w, COL
mad COL, c[CV_LIGHT_COLOR_2], LIGHT_2.w, COL
mad COL, c[CV_LIGHT_COLOR_3], LIGHT_3.w, COL
// apply vertex color and diffuse and ambient material terms
mul COL, COL, V_DIFFUSE
mul COL, COL, c[CV_DIFFUSE]
add oD1, COL, c[CV_AMBIENT]
// Scale to 0-1
add LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].yyy
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].zzz
// apply bump scale and bias controls
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_BUMPINESS].xxx
add oD0, LIGHT_LOCAL, c[CV_BUMPINESS].yyy
// place negated bump light intensity in alpha channel
add oD0.w, c[CV_CONST].y, -LIGHT_0.w
mov oT0, V_TEXTURE
mov oT1, V_TEXTURE

View File

@@ -0,0 +1,374 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/shd7bumpspec.cpp $*
* *
* $Author:: Kenny_m
*
* $Modtime:: 6/06/02 11:18p $*
* *
* $Revision:: 3 $*
* *
* 06/06/02 KM added software vertex shader fallback check
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "dx8fvf.h"
#include "dx8wrapper.h"
#include "assetmgr.h"
#include "rinfo.h"
#include "camera.h"
#include "shdbumpspec.h"
#include "shd7bumpspec.h"
#include "shd7bumpspec_constants.h"
#include "shdclassids.h"
// shader code declarations
#include "shd7bumpspecpass0.vsh_code.h"
#include "shd7bumpspecpass1.vsh_code.h"
ShdHWVertexShader Shd7BumpSpecClass::Pass_0_Vertex_Shader;
ShdHWVertexShader Shd7BumpSpecClass::Pass_1_Vertex_Shader;
Matrix4x4 Shd7BumpSpecClass::View_Projection_Matrix;
Shd7BumpSpecClass::Shd7BumpSpecClass(const ShdDefClass* def)
: ShdInterfaceClass(def,SHDDEF_CLASSID_BUMPSPEC),
Texture(NULL),
NormalMap(NULL)
{
ShdBumpSpecDefClass* Definition=(ShdBumpSpecDefClass*)def;
Texture=WW3DAssetManager::Get_Instance()->Get_Texture
(
Definition->Get_Texture_Name()
);
NormalMap=WW3DAssetManager::Get_Instance()->Get_Texture
(
Definition->Get_Bump_Map_Name()
);
const Vector3& a=Definition->Get_Ambient();
Ambient.Set(a.X,a.Y,a.Z,1.0f);
const Vector3& d=Definition->Get_Diffuse();
Diffuse.Set(d.X,d.Y,d.Z,1.0f);
const Vector3& s=Definition->Get_Specular();
Specular.Set(s.X,s.Y,s.Z,1.0f);
const Vector2& db=Definition->Get_Diffuse_Bumpiness();
const Vector2& ds=Definition->Get_Specular_Bumpiness();
Bumpiness.Set(db.X,db.Y,ds.X,ds.Y);
}
Shd7BumpSpecClass::~Shd7BumpSpecClass()
{
REF_PTR_RELEASE(Texture);
REF_PTR_RELEASE(NormalMap);
}
void Shd7BumpSpecClass::Init()
{
// Create vertex shader
DWORD vertex_shader_declaration[]=
{
D3DVSD_STREAM(0),
(D3DVSD_REG(0, D3DVSDT_FLOAT3)), // vertex position
(D3DVSD_REG(1, D3DVSDT_FLOAT3)), // vertex normal
(D3DVSD_REG(2, D3DVSDT_D3DCOLOR)), // vertex color
(D3DVSD_REG(3, D3DVSDT_FLOAT2)), // vertex texture coords
(D3DVSD_REG(4, D3DVSDT_FLOAT3)), // vertex S basis
(D3DVSD_REG(5, D3DVSDT_FLOAT3)), // vertex T basis
(D3DVSD_REG(6, D3DVSDT_FLOAT3)), // vertex SxT basis
D3DVSD_END()
};
Pass_0_Vertex_Shader.Create
(
shd7bumpspecpass0_vsh_code,
vertex_shader_declaration
);
Pass_1_Vertex_Shader.Create
(
shd7bumpspecpass1_vsh_code,
vertex_shader_declaration
);
}
void Shd7BumpSpecClass::Shutdown()
{
Pass_0_Vertex_Shader.Destroy();
Pass_1_Vertex_Shader.Destroy();
}
//**********************************************************************************************
//! Apply shared states for 2 pass DX7 bump specular with gloss map
/*! 5/27/02 5:39p KJM Created
/*! 06/06/02 KM added software vertex shader fallback check
*/
void Shd7BumpSpecClass::Apply_Shared(int pass, RenderInfoClass& rinfo)
{
// vertex processing behavior
DX8Wrapper::Set_DX8_Render_State(D3DRS_SOFTWAREVERTEXPROCESSING,!Pass_0_Vertex_Shader.Is_Using_Hardware());
// fixed function uses pass through by default
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU);
if (pass==0)
{
// set vertex shader
DX8Wrapper::Set_Vertex_Shader(Pass_0_Vertex_Shader.Peek_Shader());
// set texture stage settings
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3 );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLORARG2, D3DTA_SPECULAR );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAOP, D3DTOP_ADDSMOOTH );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE, TRUE);
DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND, D3DBLEND_ZERO);
}
else
{
// specular pass
// set vertex shader
DX8Wrapper::Set_Vertex_Shader(Pass_1_Vertex_Shader.Peek_Shader());
const Matrix3D& cam=rinfo.Camera.Get_Transform();
// set constants
DX8Wrapper::Set_Vertex_Shader_Constant
(
CV_EYE_WORLD,
D3DXVECTOR4
(
cam.Get_X_Translation(),
cam.Get_Y_Translation(),
cam.Get_Z_Translation(),
1.0f
),
1
);
// set texture stage settings
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3 );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLORARG1, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLORARG2, D3DTA_SPECULAR );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE, TRUE);
DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND, D3DBLEND_ONE);
}
// set constants
DX8Wrapper::Set_Vertex_Shader_Constant(CV_CONST, D3DXVECTOR4(0.0f, 1.0f, 0.5f, 2.0f), 1);
// calculate shader view projection matrix
Matrix4x4 view_matrix;
DX8Wrapper::Get_Transform(D3DTS_VIEW, view_matrix);
Matrix4x4 proj_matrix;
DX8Wrapper::Get_Transform(D3DTS_PROJECTION, proj_matrix);
Matrix4x4::Multiply(proj_matrix, view_matrix, &View_Projection_Matrix);
}
//**********************************************************************************************
//! Apply per instance states for 2 pass DX7 bump specular with gloss map
/*! 5/27/02 5:39p KJM Created
*/
void Shd7BumpSpecClass::Apply_Instance(int cur_pass, RenderInfoClass& rinfo)
{
DX8Wrapper::Set_Texture(0, NormalMap);
DX8Wrapper::Set_Texture(1, Texture);
// set vertex shader constants
Matrix4x4 world;
DX8Wrapper::Get_Transform(D3DTS_WORLD, world);
Matrix4x4 world_view_proj_matrix;
Matrix4x4::Multiply(View_Projection_Matrix,world,&world_view_proj_matrix);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_WORLD_VIEW_PROJECTION, &world_view_proj_matrix, 4);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_WORLD, &world, 4);
ShdHWVertexShader::Light
(
rinfo,
Ambient,
Diffuse,
Specular
);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_BUMPINESS, &Bumpiness, 1);
}
unsigned Shd7BumpSpecClass::Get_Vertex_Stream_Count() const
{
return 1;
}
unsigned Shd7BumpSpecClass::Get_Vertex_Size(unsigned stream) const
{
return sizeof(VertexFormatXYZNDUV1TG3);
}
void Shd7BumpSpecClass::Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
)
{
VertexFormatXYZNDUV1TG3* verts=(VertexFormatXYZNDUV1TG3*)dest_buffer;
for (unsigned i=0; i<vertex_count; ++i)
{
if (vss.Locations)
{
verts[i].x=vss.Locations[i][0];
verts[i].y=vss.Locations[i][1];
verts[i].z=vss.Locations[i][2];
}
else
{
verts[i].x=0.0f;
verts[i].y=0.0f;
verts[i].z=0.0f;
}
if (vss.DiffuseInt)
{
verts[i].diffuse=vss.DiffuseInt[i];
}
else
{
verts[i].diffuse=0xffffffff;
}
if (vss.Normals)
{
verts[i].nx=vss.Normals[i][0];
verts[i].ny=vss.Normals[i][1];
verts[i].nz=vss.Normals[i][2];
}
else
{
verts[i].nx=0.0f;
verts[i].ny=0.0f;
verts[i].nz=0.0f;
}
if (vss.UV[0])
{
verts[i].u1=vss.UV[0][i].U;
verts[i].v1=vss.UV[0][i].V;
}
else
{
verts[i].u1=0.0f;
verts[i].v1=0.0f;
}
if (vss.S)
{
verts[i].Sx=vss.S[i].X;
verts[i].Sy=vss.S[i].Y;
verts[i].Sz=vss.S[i].Z;
}
else
{
verts[i].Sx=0.0f;
verts[i].Sy=0.0f;
verts[i].Sz=0.0f;
}
if (vss.T)
{
verts[i].Tx=vss.T[i].X;
verts[i].Ty=vss.T[i].Y;
verts[i].Tz=vss.T[i].Z;
}
else
{
verts[i].Tx=0.0f;
verts[i].Ty=0.0f;
verts[i].Tz=0.0f;
}
if (vss.SxT)
{
verts[i].SxTx=vss.SxT[i].X;
verts[i].SxTy=vss.SxT[i].Y;
verts[i].SxTz=vss.SxT[i].Z;
}
else
{
verts[i].SxTx=0.0f;
verts[i].SxTy=0.0f;
verts[i].SxTz=0.0f;
}
}
}

View File

@@ -0,0 +1,93 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/shd7bumpspec.h $*
* *
* $Author:: Kenny_m
*
* $Modtime:: 5/27/02 2:48p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHD7BUMPSPEC_H
#define SHD7BUMPSPEC_H
#ifndef SHDINTERFACE_H
#include "shdinterface.h"
#endif
#ifndef SHDHWSHADER_H
#include "shdhwshader.h"
#endif
class Shd7BumpSpecClass : public ShdInterfaceClass
{
public:
Shd7BumpSpecClass(const ShdDefClass* def);
virtual ~Shd7BumpSpecClass();
static void Init();
static void Shutdown();
virtual int Get_Pass_Count() { return 2; }
virtual int Get_Texture_Count() const { return 2; }
virtual TextureClass* Peek_Texture(int idx) const { return idx==0 ? Texture : NormalMap; }
virtual void Apply_Shared(int cur_pass, RenderInfoClass& rinfo);
virtual void Apply_Instance(int cur_pass, RenderInfoClass& rinfo);
virtual unsigned Get_Vertex_Stream_Count() const;
virtual unsigned Get_Vertex_Size(unsigned stream) const;
virtual bool Use_HW_Vertex_Processing() const { return Pass_0_Vertex_Shader.Is_Using_Hardware(); }
virtual void Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
);
protected:
static ShdHWVertexShader Pass_0_Vertex_Shader;
static ShdHWVertexShader Pass_1_Vertex_Shader;
static Matrix4x4 View_Projection_Matrix;
TextureClass* Texture;
TextureClass* NormalMap;
Vector4 Ambient;
Vector4 Diffuse;
Vector4 Specular;
Vector4 Bumpiness;
};
#endif // SHD7BUMPSPEC_H

View File

@@ -0,0 +1,100 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// bump specular with gloss map shader constants
// Kenny Mitchell - Westwood Studios EA 2002
#ifndef SHD7BUMPSPEC_CONSTANTS_H
#define SHD7BUMPSPEC_CONSTANTS_H
// vertex shader macros
#define CV_WORLD_VIEW_PROJECTION 1
#define CV_WORLD_VIEW_PROJECTION_0 1
#define CV_WORLD_VIEW_PROJECTION_1 2
#define CV_WORLD_VIEW_PROJECTION_2 3
#define CV_WORLD_VIEW_PROJECTION_3 4
//#define CV_WORLD_VIEW 5
//#define CV_WORLD_VIEW_0 5
//#define CV_WORLD_VIEW_1 6
//#define CV_WORLD_VIEW_2 7
//#define CV_WORLD_VIEW_3 8
//#define CV_WORLD_VIEW_INVERSE_TRANSPOSE 9
//#define CV_WORLD_VIEW_INVERSE_TRANSPOSE_0 9
//#define CV_WORLD_VIEW_INVERSE_TRANSPOSE_1 10
//#define CV_WORLD_VIEW_INVERSE_TRANSPOSE_2 11
#define CV_WORLD 12
#define CV_WORLD_0 12
#define CV_WORLD_1 13
#define CV_WORLD_2 14
#define CV_WORLD_3 15
// 16-26 lighting constants
#define CV_BUMPINESS 27
#define CV_EYE_WORLD 28
// inputs
#define V_POSITION v0
#define V_NORMAL v1
#define V_DIFFUSE v2
#define V_TEXTURE v3
#define V_S v4
#define V_T v5
#define V_SxT v6
// registers
#define HALF_ANGLE r0
#define S_WORLD r1
#define T_WORLD r2
#define SxT_WORLD r3
#define LIGHT_LOCAL r4
#define LIGHT_0 r5
#define LIGHT_1 r6
#define LIGHT_2 r7
#define LIGHT_3 r8
#define COL r9
#define WORLD_VERTEX r10
#define EYE_VECTOR r11
#define WORLD_NORMAL r1
#define OUTPUT_REG r0
// texture stages
#define TEX_CUBEMAP t0
#endif

View File

@@ -0,0 +1,122 @@
//
// Command & Conquer Generals Zero Hour(tm)
// Copyright 2025 Electronic Arts Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// DX7 bump specular mask vertex shader pass 0
// Kenny Mitchell - Westwood Studios EA 2002
vs.1.1
#include "shdhw_constants.h"
#include "shd7bumpspec_constants.h"
// In:
// v0 - object space vertex position
// v1 - object space normal
// v2 - color
// v3 - texture coords
// v4 - S basis
// v5 - T basis
// v6 - SxT
// object space vertex position -> screen (early as possible for view clipping)
dp4 oPos.x, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_0]
dp4 oPos.y, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_1]
dp4 oPos.z, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_2]
dp4 oPos.w, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_3]
// Transform basis vectors to world space
dp3 S_WORLD.x, V_S, c[CV_WORLD_0]
dp3 S_WORLD.y, V_S, c[CV_WORLD_1]
dp3 S_WORLD.z, V_S, c[CV_WORLD_2]
dp3 T_WORLD.x, V_T, c[CV_WORLD_0]
dp3 T_WORLD.y, V_T, c[CV_WORLD_1]
dp3 T_WORLD.z, V_T, c[CV_WORLD_2]
dp3 SxT_WORLD.x, V_SxT, c[CV_WORLD_0]
dp3 SxT_WORLD.y, V_SxT, c[CV_WORLD_1]
dp3 SxT_WORLD.z, V_SxT, c[CV_WORLD_2]
// transform light 0 by basis vectors to put it into texture space
dp3 LIGHT_LOCAL.x, S_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
dp3 LIGHT_LOCAL.y, T_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
dp3 LIGHT_LOCAL.z, SxT_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
// Normalize the light vector
dp3 LIGHT_LOCAL.w, LIGHT_LOCAL, LIGHT_LOCAL
rsq LIGHT_LOCAL.w, LIGHT_LOCAL.w
mul LIGHT_LOCAL, LIGHT_LOCAL, LIGHT_LOCAL.w
dp3 WORLD_NORMAL.x, V_NORMAL, c[CV_WORLD_0]
dp3 WORLD_NORMAL.y, V_NORMAL, c[CV_WORLD_1]
dp3 WORLD_NORMAL.z, V_NORMAL, c[CV_WORLD_2]
// Normalize the world normal vector
dp3 WORLD_NORMAL.w, WORLD_NORMAL, WORLD_NORMAL
rsq WORLD_NORMAL.w, WORLD_NORMAL.w
mul WORLD_NORMAL, WORLD_NORMAL, WORLD_NORMAL.w
// calculate light 0 factor
dp3 LIGHT_0.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_0] // L.N
max LIGHT_0.w, LIGHT_0.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_0.w, LIGHT_0.w, c[CV_LIGHT_COLOR_0].w // light attentuation factor
// calculate light 1 factor
dp3 LIGHT_1.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_1] // L.N
max LIGHT_1.w, LIGHT_1.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_1.w, LIGHT_1.w, c[CV_LIGHT_COLOR_1].w // light attentuation factor
// calculate light 2 factor
dp3 LIGHT_2.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_2] // L.N
max LIGHT_2.w, LIGHT_2.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_2.w, LIGHT_2.w, c[CV_LIGHT_COLOR_2].w // light attentuation factor
// calculate light 3 factor
dp3 LIGHT_3.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_3] // L.N
max LIGHT_3.w, LIGHT_3.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_3.w, LIGHT_3.w, c[CV_LIGHT_COLOR_3].w // light attentuation factor
// accumulate light colors
mul COL, c[CV_LIGHT_COLOR_0], LIGHT_0.w
mad COL, c[CV_LIGHT_COLOR_1], LIGHT_1.w, COL
mad COL, c[CV_LIGHT_COLOR_2], LIGHT_2.w, COL
mad COL, c[CV_LIGHT_COLOR_3], LIGHT_3.w, COL
// apply vertex color and diffuse and ambient material terms
mul COL, COL, V_DIFFUSE
mul COL, COL, c[CV_DIFFUSE]
add oD1, COL, c[CV_AMBIENT]
// Scale to 0-1
add LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].yyy
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].zzz
// apply bump scale and bias controls
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_BUMPINESS].xxx
add oD0, LIGHT_LOCAL, c[CV_BUMPINESS].yyy
// place negated bump light intensity in alpha channel
add oD0.w, c[CV_CONST].y, -LIGHT_0.w
mov oT0, V_TEXTURE
mov oT1, V_TEXTURE

View File

@@ -0,0 +1,159 @@
//
// Command & Conquer Generals Zero Hour(tm)
// Copyright 2025 Electronic Arts Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// DX7 bump specular with gloss map vertex shader pass 1
// Kenny Mitchell - Westwood Studios EA 2002
vs.1.1
#include "shdhw_constants.h"
#include "shd7bumpspec_constants.h"
// In:
// v0 - object space vertex position
// v1 - object space normal
// v2 - color
// v3 - texture coords
// v4 - S basis
// v5 - T basis
// v6 - SxT
// object space vertex position -> screen (early as possible for view clipping)
dp4 EYE_VECTOR.x, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_0]
dp4 EYE_VECTOR.y, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_1]
dp4 EYE_VECTOR.z, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_2]
dp4 EYE_VECTOR.w, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_3]
mov oPos, EYE_VECTOR
// Set alpha to 1
mov oD0.w, c[CV_CONST].y
mov oT0, V_TEXTURE
mov oT1, V_TEXTURE
// Transform basis vectors to world space
dp3 S_WORLD.x, V_S, c[CV_WORLD_0]
dp3 S_WORLD.y, V_S, c[CV_WORLD_1]
dp3 S_WORLD.z, V_S, c[CV_WORLD_2]
dp3 T_WORLD.x, V_T, c[CV_WORLD_0]
dp3 T_WORLD.y, V_T, c[CV_WORLD_1]
dp3 T_WORLD.z, V_T, c[CV_WORLD_2]
dp3 SxT_WORLD.x, V_SxT, c[CV_WORLD_0]
dp3 SxT_WORLD.y, V_SxT, c[CV_WORLD_1]
dp3 SxT_WORLD.z, V_SxT, c[CV_WORLD_2]
// calculate half angle
// transform vertex position to world space
// to calculate V, vector to viewer in world
// space.
dp4 WORLD_VERTEX.x, V_POSITION, c[CV_WORLD_0]
dp4 WORLD_VERTEX.y, V_POSITION, c[CV_WORLD_1]
dp4 WORLD_VERTEX.z, V_POSITION, c[CV_WORLD_2]
//dp4 WORLD_VERTEX.w, V_POSITION, c[CV_WORLD_3]
// Half angle vector is (L+V)/||L+V|| or Normalize( L+V )
// ||a|| is magnitude of a
// L = vec to light from vertex point
// V = vec to viewer from vertex point
// vertex position - eye position
// eye position - vertex position
add EYE_VECTOR, c[CV_EYE_WORLD], -WORLD_VERTEX.xyz
// Normalize the eye vector
dp3 EYE_VECTOR.w, EYE_VECTOR, EYE_VECTOR
rsq EYE_VECTOR.w, EYE_VECTOR.w
mul EYE_VECTOR, EYE_VECTOR, EYE_VECTOR.w
// Add them to average & create half angle vector
add HALF_ANGLE, c[CV_LIGHT_DIRECTION_0], EYE_VECTOR
// Normalize the half angle vector
dp3 HALF_ANGLE.w, HALF_ANGLE, HALF_ANGLE
rsq HALF_ANGLE.w, HALF_ANGLE.w
mul HALF_ANGLE, HALF_ANGLE, HALF_ANGLE.w
dp3 LIGHT_LOCAL.x, HALF_ANGLE, S_WORLD
dp3 LIGHT_LOCAL.y, HALF_ANGLE, T_WORLD
dp3 LIGHT_LOCAL.z, HALF_ANGLE, SxT_WORLD
// Normalize the half angle vector
dp3 LIGHT_LOCAL.w, LIGHT_LOCAL, LIGHT_LOCAL
rsq LIGHT_LOCAL.w, LIGHT_LOCAL.w
mul LIGHT_LOCAL, LIGHT_LOCAL, LIGHT_LOCAL.w
// calculate light 0 factor
dp3 WORLD_NORMAL.x, V_NORMAL, c[CV_WORLD_0]
dp3 WORLD_NORMAL.y, V_NORMAL, c[CV_WORLD_1]
dp3 WORLD_NORMAL.z, V_NORMAL, c[CV_WORLD_2]
// Normalize the world normal vector
dp3 WORLD_NORMAL.w, WORLD_NORMAL, WORLD_NORMAL
rsq WORLD_NORMAL.w, WORLD_NORMAL.w
mul WORLD_NORMAL, WORLD_NORMAL, WORLD_NORMAL.w
dp3 LIGHT_0.w, HALF_ANGLE, WORLD_NORMAL // N.H
max LIGHT_0.w, LIGHT_0.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_0.w, LIGHT_0.w, c[CV_LIGHT_COLOR_0].w // light attentuation factor
mul LIGHT_0.w, LIGHT_0, LIGHT_0
mul LIGHT_0.w, LIGHT_0, LIGHT_0
mul LIGHT_0.w, LIGHT_0, LIGHT_0
// calculate light 1 factor
//dp3 LIGHT_1.w, HALF_ANGLE, c[CV_LIGHT_DIRECTION_1] // L.H
//max LIGHT_1.w, LIGHT_1.w, c[CV_CONST].x // clamp 0-1
//mul LIGHT_1.w, LIGHT_1.w, c[CV_LIGHT_COLOR_1].w // light attentuation factor
//mul LIGHT_1.w, LIGHT_1, LIGHT_1
//mul LIGHT_1.w, LIGHT_1, LIGHT_1
//mul LIGHT_1.w, LIGHT_1, LIGHT_1
// calculate light 2 factor
//dp3 LIGHT_2.w, HALF_ANGLE, c[CV_LIGHT_DIRECTION_2] // L.H
//max LIGHT_2.w, LIGHT_2.w, c[CV_CONST].x // clamp 0-1
//mul LIGHT_2.w, LIGHT_2.w, c[CV_LIGHT_COLOR_2].w // light attentuation factor
//mul LIGHT_2.w, LIGHT_2, LIGHT_2
//mul LIGHT_2.w, LIGHT_2, LIGHT_2
//mul LIGHT_2.w, LIGHT_2, LIGHT_2
// accumulate light colors
mul COL, c[CV_LIGHT_COLOR_0], LIGHT_0.w
//mad COL, c[CV_LIGHT_COLOR_1], LIGHT_1.w, COL
//mad COL, c[CV_LIGHT_COLOR_2], LIGHT_2.w, COL
mul oD1, COL, c[CV_SPECULAR]
// Scale to 0-1
add LIGHT_LOCAL.xyz, LIGHT_LOCAL, c[CV_CONST].yyy
mul LIGHT_LOCAL.xyz, LIGHT_LOCAL, c[CV_CONST].zzz
// apply bump scale and bias controls
mul LIGHT_LOCAL.xyz, LIGHT_LOCAL, c[CV_BUMPINESS].zzz
add oD0.xyz, LIGHT_LOCAL, c[CV_BUMPINESS].www

View File

@@ -0,0 +1,382 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shd8bumpdiff.cpp $*
* *
* $Author:: Kenny_m
*
* $Modtime:: 07/08/02 3:40p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "dx8fvf.h"
#include "dx8wrapper.h"
#include "assetmgr.h"
#include "rinfo.h"
#include "camera.h"
#include "shdmesh.h"
#include "texproject.h"
#include "shdbumpdiff.h"
#include "shd8bumpdiff.h"
#include "shd8bumpdiff_constants.h"
#include "shdclassids.h"
// shader code declarations
#include "shd8bumpdiff.vsh_code.h"
#include "shd8bumpdiff.psh_code.h"
#include "shd8ssbumpdiff.vsh_code.h"
#include "shd8ssbumpdiff.psh_code.h"
ShdHWVertexShader Shd8BumpDiffClass::Vertex_Shader;
ShdHWPixelShader Shd8BumpDiffClass::Pixel_Shader;
ShdHWPixelShader Shd8BumpDiffClass::Self_Shadow_Pixel_Shader;
ShdHWVertexShader Shd8BumpDiffClass::Self_Shadow_Vertex_Shader;
Matrix4x4 Shd8BumpDiffClass::View_Projection_Matrix;
Shd8BumpDiffClass::Shd8BumpDiffClass(const ShdDefClass* def)
: ShdInterfaceClass(def,SHDDEF_CLASSID_BUMPDIFF),
Texture(NULL),
NormalMap(NULL)
{
ShdBumpDiffDefClass* Definition=(ShdBumpDiffDefClass*)def;
Texture=WW3DAssetManager::Get_Instance()->Get_Texture
(
Definition->Get_Texture_Name()
);
NormalMap=WW3DAssetManager::Get_Instance()->Get_Texture
(
Definition->Get_Bump_Map_Name()
);
const Vector3& a=Definition->Get_Ambient();
Ambient.Set(a.X,a.Y,a.Z,0.0f);
const Vector3& d=Definition->Get_Diffuse();
Diffuse.Set(d.X,d.Y,d.Z,0.0f);
const Vector2& db=Definition->Get_Diffuse_Bumpiness();
Bumpiness.Set(db.X,db.Y,0,0);
}
Shd8BumpDiffClass::~Shd8BumpDiffClass(void)
{
REF_PTR_RELEASE(Texture);
REF_PTR_RELEASE(NormalMap);
}
void Shd8BumpDiffClass::Init(void)
{
// Create vertex shader
DWORD vertex_shader_declaration[]=
{
D3DVSD_STREAM(0),
(D3DVSD_REG(0, D3DVSDT_FLOAT3)), // vertex position
(D3DVSD_REG(1, D3DVSDT_FLOAT3)), // vertex normal
(D3DVSD_REG(2, D3DVSDT_D3DCOLOR)), // vertex color
(D3DVSD_REG(3, D3DVSDT_FLOAT2)), // vertex texture coords
(D3DVSD_REG(4, D3DVSDT_FLOAT3)), // vertex S basis
(D3DVSD_REG(5, D3DVSDT_FLOAT3)), // vertex T basis
(D3DVSD_REG(6, D3DVSDT_FLOAT3)), // vertex SxT basis
D3DVSD_END()
};
Pixel_Shader.Create(shd8bumpdiff_psh_code);
Vertex_Shader.Create
(
shd8bumpdiff_vsh_code,
vertex_shader_declaration
);
Self_Shadow_Pixel_Shader.Create(shd8ssbumpdiff_psh_code);
Self_Shadow_Vertex_Shader.Create
(
shd8ssbumpdiff_vsh_code,
vertex_shader_declaration
);
}
void Shd8BumpDiffClass::Shutdown(void)
{
Vertex_Shader.Destroy();
Pixel_Shader.Destroy();
Self_Shadow_Pixel_Shader.Destroy();
Self_Shadow_Vertex_Shader.Destroy();
}
void Shd8BumpDiffClass::Apply_Shared(int cur_pass, RenderInfoClass& rinfo)
{
// set vertex shader
if (cur_pass==0)
{
DX8Wrapper::Set_Vertex_Shader(Vertex_Shader.Peek_Shader());
}
else
{
DX8Wrapper::Set_Vertex_Shader(Self_Shadow_Vertex_Shader.Peek_Shader());
}
// set vertex shader constants
DX8Wrapper::Set_Vertex_Shader_Constant(CV_CONST, D3DXVECTOR4(0.0f, 1.0f, 0.5f, 2.0f), 1);
// set pixel shader
if (cur_pass==0)
{
DX8Wrapper::Set_Pixel_Shader(Pixel_Shader.Peek_Shader());
}
else
{
DX8Wrapper::Set_Pixel_Shader(Self_Shadow_Pixel_Shader.Peek_Shader());
}
// set constants
DX8Wrapper::Set_Vertex_Shader_Constant(CV_CONST, D3DXVECTOR4(0.0f, 1.0f, 0.5f, 2.0f), 1);
// calculate shader view projection matrix
Matrix4x4 view_matrix;
DX8Wrapper::Get_Transform(D3DTS_VIEW, view_matrix);
Matrix4x4 proj_matrix;
DX8Wrapper::Get_Transform(D3DTS_PROJECTION, proj_matrix);
Matrix4x4::Multiply(proj_matrix, view_matrix, &View_Projection_Matrix);
}
void Shd8BumpDiffClass::Apply_Instance(int cur_pass, RenderInfoClass& rinfo)
{
if (cur_pass==0)
{
DX8Wrapper::Set_Texture(0, NormalMap);
DX8Wrapper::Set_Texture(1, Texture);
}
else
{
ZTextureClass* ztex=DX8Wrapper::Get_Shadow_Map(0);
DX8Wrapper::Set_Texture(0, Texture);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_TEXMAP,&Self_Shadow_Transform,4);
}
// set vertex shader constants
Matrix4x4 world;
DX8Wrapper::Get_Transform(D3DTS_WORLD, world);
Matrix4x4 world_view_proj_matrix;
Matrix4x4::Multiply(View_Projection_Matrix,world,&world_view_proj_matrix);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_WORLD_VIEW_PROJECTION, &world_view_proj_matrix, 4);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_WORLD, &world, 4);
ShdHWVertexShader::Light
(
rinfo,
Ambient,
Diffuse
);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_BUMPINESS, &Bumpiness, 1);
}
unsigned Shd8BumpDiffClass::Get_Vertex_Stream_Count() const
{
return 1;
}
unsigned Shd8BumpDiffClass::Get_Vertex_Size(unsigned stream) const
{
return sizeof(VertexFormatXYZNDUV1TG3);
}
void Shd8BumpDiffClass::Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
)
{
VertexFormatXYZNDUV1TG3* verts=(VertexFormatXYZNDUV1TG3*)dest_buffer;
for (unsigned i=0; i<vertex_count; ++i)
{
if (vss.Locations)
{
verts[i].x=vss.Locations[i][0];
verts[i].y=vss.Locations[i][1];
verts[i].z=vss.Locations[i][2];
}
else
{
verts[i].x=0.0f;
verts[i].y=0.0f;
verts[i].z=0.0f;
}
if (vss.DiffuseInt)
{
verts[i].diffuse=vss.DiffuseInt[i];
}
else
{
verts[i].diffuse=0xffffffff;
}
if (vss.Normals)
{
verts[i].nx=vss.Normals[i][0];
verts[i].ny=vss.Normals[i][1];
verts[i].nz=vss.Normals[i][2];
}
else
{
verts[i].nx=0.0f;
verts[i].ny=0.0f;
verts[i].nz=0.0f;
}
if (vss.UV[0])
{
verts[i].u1=vss.UV[0][i].U;
verts[i].v1=vss.UV[0][i].V;
}
else
{
verts[i].u1=0.0f;
verts[i].v1=0.0f;
}
if (vss.S)
{
verts[i].Sx=vss.S[i].X;
verts[i].Sy=vss.S[i].Y;
verts[i].Sz=vss.S[i].Z;
}
else
{
verts[i].Sx=0.0f;
verts[i].Sy=0.0f;
verts[i].Sz=0.0f;
}
if (vss.T)
{
verts[i].Tx=vss.T[i].X;
verts[i].Ty=vss.T[i].Y;
verts[i].Tz=vss.T[i].Z;
}
else
{
verts[i].Tx=0.0f;
verts[i].Ty=0.0f;
verts[i].Tz=0.0f;
}
if (vss.SxT)
{
verts[i].SxTx=vss.SxT[i].X;
verts[i].SxTy=vss.SxT[i].Y;
verts[i].SxTz=vss.SxT[i].Z;
}
else
{
verts[i].SxTx=0.0f;
verts[i].SxTy=0.0f;
verts[i].SxTz=0.0f;
}
}
}
bool Shd8BumpDiffClass::Pass_Selection
(
ShdMeshClass* mesh,
RenderInfoClass* rinfo,
int pass
)
{
if (mesh->Is_Applying_Shadow_Map())
{
if (pass==1) // just do once
{
// is rendering self shadowed object
Setup_Self_Shadow_Info(*mesh,*rinfo);
}
return (pass==1);
}
return (pass==0);
}
/**********************************************************************************************
//! Set up transform for shadow maps
/*! 06/07/02 KM created
*/
void Shd8BumpDiffClass::Setup_Self_Shadow_Info(ShdMeshClass& mesh, RenderInfoClass& rinfo)
{
Matrix4x4 tex_mat=mesh.Peek_Texture_Projector()->Peek_Mapper()->Get_Texture_Transform();
//set special texture matrix for shadow mapping
ZTextureClass* smap=DX8Wrapper::Get_Shadow_Map(0); // todo KJM assign shadow map from rinfo
if (!smap) return;
float off_x=0.5f+(0.5f/(float)smap->Get_Width());
float off_y=0.5f+(0.5f/(float)smap->Get_Height());
unsigned int bits=Get_Num_Depth_Bits(smap->Get_Texture_Format());
float range=(float)(0xFFFFFFFF>>(32-bits));
float bias=0.0f;//-0.001f*range;
Matrix4x4 sb_mat
(
Vector4(0.5f, 0.0f, 0.0f, 0.0f),
Vector4(0.0f, -0.5f, 0.0f, 0.0f),
Vector4(0.0f, 0.0f, range, 0.0f),
Vector4(off_x, off_y, bias, 1.0f)
);
Matrix4x4 view2tex;
Matrix4x4::Multiply(sb_mat,tex_mat,&view2tex);
Matrix4x4 world;
world.Init(mesh.Get_Transform());
Matrix4x4 view;
view.Init(rinfo.Camera.Get_View_Matrix());
Matrix4x4 vw_mat;
Matrix4x4::Multiply(world,view,&vw_mat);
Matrix4x4::Multiply(view2tex,vw_mat,&Self_Shadow_Transform);
}

View File

@@ -0,0 +1,99 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: /Commando/Code/ww3d2/shd8bumpdiff.h $*
* *
* $Author:: Kenny_m
*
* $Modtime:: 07/08/02 3:39p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHD8BUMPDIFF_H
#define SHD8BUMPDIFF_H
#ifndef SHDINTERFACE_H
#include "shdinterface.h"
#endif
#ifndef SHDHWSHADER_H
#include "shdhwshader.h"
#endif
class Shd8BumpDiffClass : public ShdInterfaceClass
{
public:
Shd8BumpDiffClass(const ShdDefClass* def);
virtual ~Shd8BumpDiffClass();
static void Init();
static void Shutdown();
virtual int Get_Pass_Count() { return 2; }
virtual bool Pass_Selection(ShdMeshClass*, RenderInfoClass*,int);
virtual int Get_Texture_Count() const { return 2; }
virtual TextureClass* Peek_Texture(int idx) const { return idx==0 ? Texture : NormalMap; }
virtual void Apply_Shared(int cur_pass, RenderInfoClass& rinfo);
virtual void Apply_Instance(int cur_pass, RenderInfoClass& rinfo);
virtual unsigned Get_Vertex_Stream_Count() const;
virtual unsigned Get_Vertex_Size(unsigned stream) const;
virtual bool Use_HW_Vertex_Processing() const { return Vertex_Shader.Is_Using_Hardware(); }
virtual void Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
);
protected:
void Setup_Self_Shadow_Info(ShdMeshClass& mesh, RenderInfoClass& rinfo);
static ShdHWVertexShader Vertex_Shader;
static ShdHWPixelShader Pixel_Shader;
static Matrix4x4 View_Projection_Matrix;
TextureClass* Texture;
TextureClass* NormalMap;
Vector4 Ambient;
Vector4 Diffuse;
Vector4 Bumpiness;
// self shadowing
static ShdHWPixelShader Self_Shadow_Pixel_Shader;
static ShdHWVertexShader Self_Shadow_Vertex_Shader;
Matrix4x4 Self_Shadow_Transform;
};
#endif // SHD8BUMPDIFF_H

View File

@@ -0,0 +1,46 @@
//
// Command & Conquer Generals Zero Hour(tm)
// Copyright 2025 Electronic Arts Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// DX8 bump diffuse shader
// Kenny Mitchell
#include "shd8bumpdiff_constants.h"
// pixel shader version 1.1
ps.1.1
tex TEX_NORMALMAP // normal map texture
tex TEX_DECAL // decal texture
// bumped normal
dp3 TEX_NORMALMAP, TEX_NORMALMAP_bx2, COL_LIGHT_bx2
// modulate texture and light color
mul TEX_DECAL.rgb, COL_DIFFUSE, TEX_DECAL
// apply bump color in reverse direction with saturation
mul_sat r1, TEX_DECAL, -TEX_NORMALMAP
// apply bump color in primary direction with saturation
mul_sat r0, TEX_DECAL, TEX_NORMALMAP
// add bump light contribution
add r0, r0, r1
// add key light contribution
mad r0, TEX_DECAL, COL_LIGHT.a, r0

View File

@@ -0,0 +1,134 @@
//
// Command & Conquer Generals Zero Hour(tm)
// Copyright 2025 Electronic Arts Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// DX8 bump diffuse vertex shader
// Kenny Mitchell - Westwood Studios EA 2002
vs.1.1
#include "shdhw_constants.h"
#include "shd8bumpdiff_constants.h"
// In:
// v0 - object space vertex position
// v1 - object space normal
// v2 - color
// v3 - texture coords
// v4 - S basis
// v5 - T basis
// v6 - SxT
// object space vertex position -> screen (early as possible for view clipping)
dp4 EYE_VECTOR.x, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_0]
dp4 EYE_VECTOR.y, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_1]
dp4 EYE_VECTOR.z, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_2]
dp4 EYE_VECTOR.w, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_3]
mov oPos, EYE_VECTOR
// Transform basis vectors to world space
dp3 S_WORLD.x, V_S, c[CV_WORLD_0]
dp3 S_WORLD.y, V_S, c[CV_WORLD_1]
dp3 S_WORLD.z, V_S, c[CV_WORLD_2]
dp3 T_WORLD.x, V_T, c[CV_WORLD_0]
dp3 T_WORLD.y, V_T, c[CV_WORLD_1]
dp3 T_WORLD.z, V_T, c[CV_WORLD_2]
dp3 SxT_WORLD.x, V_SxT, c[CV_WORLD_0]
dp3 SxT_WORLD.y, V_SxT, c[CV_WORLD_1]
dp3 SxT_WORLD.z, V_SxT, c[CV_WORLD_2]
// transform light 0 by basis vectors to put it into texture space
dp3 LIGHT_LOCAL.x, S_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
dp3 LIGHT_LOCAL.y, T_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
dp3 LIGHT_LOCAL.z, SxT_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
// Normalize the light vector
dp3 LIGHT_LOCAL.w, LIGHT_LOCAL, LIGHT_LOCAL
rsq LIGHT_LOCAL.w, LIGHT_LOCAL.w
mul LIGHT_LOCAL, LIGHT_LOCAL, LIGHT_LOCAL.w
dp3 WORLD_NORMAL.x, V_NORMAL, c[CV_WORLD_0]
dp3 WORLD_NORMAL.y, V_NORMAL, c[CV_WORLD_1]
dp3 WORLD_NORMAL.z, V_NORMAL, c[CV_WORLD_2]
// Normalize the world normal vector
dp3 WORLD_NORMAL.w, WORLD_NORMAL, WORLD_NORMAL
rsq WORLD_NORMAL.w, WORLD_NORMAL.w
mul WORLD_NORMAL, WORLD_NORMAL, WORLD_NORMAL.w
// calculate light 0 factor
dp3 LIGHT_0.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_0] // L.N
max LIGHT_0.w, LIGHT_0.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_0.w, LIGHT_0.w, c[CV_LIGHT_COLOR_0].w // light attentuation factor
// calculate light 1 factor
dp3 LIGHT_1.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_1] // L.N
max LIGHT_1.w, LIGHT_1.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_1.w, LIGHT_1.w, c[CV_LIGHT_COLOR_1].w // light attentuation factor
// calculate light 2 factor
dp3 LIGHT_2.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_2] // L.N
max LIGHT_2.w, LIGHT_2.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_2.w, LIGHT_2.w, c[CV_LIGHT_COLOR_2].w // light attentuation factor
// calculate light 3 factor
dp3 LIGHT_3.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_3] // L.N
max LIGHT_3.w, LIGHT_3.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_3.w, LIGHT_3.w, c[CV_LIGHT_COLOR_3].w // light attentuation factor
// accumulate light colors
mul COL, c[CV_LIGHT_COLOR_0], LIGHT_0.w
mad COL, c[CV_LIGHT_COLOR_1], LIGHT_1.w, COL
mad COL, c[CV_LIGHT_COLOR_2], LIGHT_2.w, COL
mad COL, c[CV_LIGHT_COLOR_3], LIGHT_3.w, COL
// apply vertex color and diffuse and ambient material terms
mul COL, COL, V_DIFFUSE
mul COL, COL, c[CV_DIFFUSE]
add oD1, COL, c[CV_AMBIENT]
// Scale to 0-1
add LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].yyy
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].zzz
// apply bump scale and bias controls
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_BUMPINESS].xxx
add oD0, LIGHT_LOCAL, c[CV_BUMPINESS].yyy
// calc light factor excluding bumped lights
add LIGHT_0.w, c[CV_CONST].y, -LIGHT_0.w
add LIGHT_1.w, c[CV_CONST].y, -LIGHT_1.w
mul LIGHT_0.w, c[CV_LIGHT_COLOR_0], LIGHT_0.w
mul LIGHT_1.w, c[CV_LIGHT_COLOR_1], LIGHT_1.w
add oD0.w, LIGHT_0.w, LIGHT_1.w
mov oT0, V_TEXTURE
mov oT1, V_TEXTURE

View File

@@ -0,0 +1,98 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// DX8 bump diffuse shader constants
// Kenny Mitchell - Westwood Studios EA 2002
#ifndef SHD8BUMPDIFF_CONSTANTS_H
#define SHD8BUMPDIFF_CONSTANTS_H
// vertex shader macros
#define CV_WORLD_VIEW_PROJECTION 1
#define CV_WORLD_VIEW_PROJECTION_0 1
#define CV_WORLD_VIEW_PROJECTION_1 2
#define CV_WORLD_VIEW_PROJECTION_2 3
#define CV_WORLD_VIEW_PROJECTION_3 4
#define CV_WORLD 12
#define CV_WORLD_0 12
#define CV_WORLD_1 13
#define CV_WORLD_2 14
#define CV_WORLD_3 15
// 16-26 lighting constants
#define CV_BUMPINESS 27
#define CV_EYE_WORLD 28
#define CV_TEXMAP 30
#define CV_TEXMAP_0 30
#define CV_TEXMAP_1 31
#define CV_TEXMAP_2 32
#define CV_TEXMAP_3 33
// inputs
#define V_POSITION v0
#define V_NORMAL v1
#define V_DIFFUSE v2
#define V_TEXTURE v3
#define V_S v4
#define V_T v5
#define V_SxT v6
// registers
#define HALF_ANGLE r0
#define S_WORLD r1
#define T_WORLD r2
#define SxT_WORLD r3
#define LIGHT_LOCAL r4
#define LIGHT_0 r5
#define LIGHT_1 r6
#define LIGHT_2 r7
#define LIGHT_3 r8
#define COL r9
#define WORLD_NORMAL r10
#define EYE_VECTOR r11
#define WORLD_VERTEX r11
// pixel shader constants
#define OUTPUT_REG r0
// texture stages
#define TEX_NORMALMAP t0
#define TEX_DECAL t1
#define COL_LIGHT v0
#define COL_DIFFUSE v1
#endif

View File

@@ -0,0 +1,408 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shd8bumpspec.cpp $*
* *
* $Author:: Kenny_m
*
* $Modtime:: 5/27/02 3:40p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "dx8fvf.h"
#include "dx8wrapper.h"
#include "assetmgr.h"
#include "rinfo.h"
#include "camera.h"
#include "shdmesh.h"
#include "texproject.h"
#include "shdbumpspec.h"
#include "shd8bumpspec.h"
#include "shd8bumpspec_constants.h"
#include "shdclassids.h"
// shader code declarations
#include "shd8bumpspec.vsh_code.h"
#include "shd8bumpspec.psh_code.h"
#include "shd8ssbumpspec.vsh_code.h"
#include "shd8ssbumpspec.psh_code.h"
ShdHWVertexShader Shd8BumpSpecClass::Vertex_Shader;
ShdHWPixelShader Shd8BumpSpecClass::Pixel_Shader;
ShdHWPixelShader Shd8BumpSpecClass::Self_Shadow_Pixel_Shader;
ShdHWVertexShader Shd8BumpSpecClass::Self_Shadow_Vertex_Shader;
Matrix4x4 Shd8BumpSpecClass::View_Projection_Matrix;
Shd8BumpSpecClass::Shd8BumpSpecClass(const ShdDefClass* def)
: ShdInterfaceClass(def,SHDDEF_CLASSID_BUMPSPEC),
Texture(NULL),
NormalMap(NULL)
{
ShdBumpSpecDefClass* Definition=(ShdBumpSpecDefClass*)def;
Texture=WW3DAssetManager::Get_Instance()->Get_Texture
(
Definition->Get_Texture_Name()
);
NormalMap=WW3DAssetManager::Get_Instance()->Get_Texture
(
Definition->Get_Bump_Map_Name()
);
const Vector3& a=Definition->Get_Ambient();
Ambient.Set(a.X,a.Y,a.Z,0.0f);
const Vector3& d=Definition->Get_Diffuse();
Diffuse.Set(d.X,d.Y,d.Z,0.0f);
const Vector3& s=Definition->Get_Specular();
Specular.Set(s.X,s.Y,s.Z,0.0f);
const Vector2& db=Definition->Get_Diffuse_Bumpiness();
const Vector2& ds=Definition->Get_Specular_Bumpiness();
Bumpiness.Set(db.X,db.Y,ds.X,ds.Y);
}
Shd8BumpSpecClass::~Shd8BumpSpecClass(void)
{
REF_PTR_RELEASE(Texture);
REF_PTR_RELEASE(NormalMap);
}
void Shd8BumpSpecClass::Init(void)
{
// Create vertex shader
DWORD vertex_shader_declaration[]=
{
D3DVSD_STREAM(0),
(D3DVSD_REG(0, D3DVSDT_FLOAT3)), // vertex position
(D3DVSD_REG(1, D3DVSDT_FLOAT3)), // vertex normal
(D3DVSD_REG(2, D3DVSDT_D3DCOLOR)), // vertex color
(D3DVSD_REG(3, D3DVSDT_FLOAT2)), // vertex texture coords
(D3DVSD_REG(4, D3DVSDT_FLOAT3)), // vertex S basis
(D3DVSD_REG(5, D3DVSDT_FLOAT3)), // vertex T basis
(D3DVSD_REG(6, D3DVSDT_FLOAT3)), // vertex SxT basis
D3DVSD_END()
};
Pixel_Shader.Create
(
shd8bumpspec_psh_code
);
Vertex_Shader.Create
(
shd8bumpspec_vsh_code,
vertex_shader_declaration
);
Self_Shadow_Pixel_Shader.Create
(
shd8ssbumpspec_psh_code
);
Self_Shadow_Vertex_Shader.Create
(
shd8ssbumpspec_vsh_code,
vertex_shader_declaration
);
}
void Shd8BumpSpecClass::Shutdown(void)
{
Vertex_Shader.Destroy();
Pixel_Shader.Destroy();
Self_Shadow_Pixel_Shader.Destroy();
Self_Shadow_Vertex_Shader.Destroy();
}
void Shd8BumpSpecClass::Apply_Shared(int cur_pass, RenderInfoClass& rinfo)
{
// set vertex shader
if (cur_pass==0)
{
DX8Wrapper::Set_Vertex_Shader(Vertex_Shader.Peek_Shader());
}
else
{
DX8Wrapper::Set_Vertex_Shader(Self_Shadow_Vertex_Shader.Peek_Shader());
}
// set vertex shader constants
DX8Wrapper::Set_Vertex_Shader_Constant(CV_CONST, D3DXVECTOR4(0.0f, 1.0f, 0.5f, 2.0f), 1);
const Matrix3D& cam=rinfo.Camera.Get_Transform();
// set constants
DX8Wrapper::Set_Vertex_Shader_Constant
(
CV_EYE_WORLD,
D3DXVECTOR4
(
cam.Get_X_Translation(),
cam.Get_Y_Translation(),
cam.Get_Z_Translation(),
1.0f
),
1
);
// set pixel shader
if (cur_pass==0)
{
DX8Wrapper::Set_Pixel_Shader(Pixel_Shader.Peek_Shader());
}
else
{
DX8Wrapper::Set_Pixel_Shader(Self_Shadow_Pixel_Shader.Peek_Shader());
}
// set constants
DX8Wrapper::Set_Vertex_Shader_Constant(CV_CONST, D3DXVECTOR4(0.0f, 1.0f, 0.5f, 2.0f), 1);
// calculate shader view projection matrix
Matrix4x4 view_matrix;
DX8Wrapper::Get_Transform(D3DTS_VIEW, view_matrix);
Matrix4x4 proj_matrix;
DX8Wrapper::Get_Transform(D3DTS_PROJECTION, proj_matrix);
Matrix4x4::Multiply(proj_matrix, view_matrix, &View_Projection_Matrix);
}
void Shd8BumpSpecClass::Apply_Instance(int cur_pass, RenderInfoClass& rinfo)
{
if (cur_pass==0)
{
DX8Wrapper::Set_Texture(0, NormalMap);
DX8Wrapper::Set_Texture(1, Texture);
}
else
{
ZTextureClass* ztex=DX8Wrapper::Get_Shadow_Map(0);
DX8Wrapper::Set_Texture(0, Texture);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_TEXMAP,&Self_Shadow_Transform,4);
}
// set vertex shader constants
Matrix4x4 world;
DX8Wrapper::Get_Transform(D3DTS_WORLD, world);
Matrix4x4 world_view_proj_matrix;
Matrix4x4::Multiply(View_Projection_Matrix,world,&world_view_proj_matrix);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_WORLD_VIEW_PROJECTION, &world_view_proj_matrix, 4);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_WORLD, &world, 4);
ShdHWVertexShader::Light
(
rinfo,
Ambient,
Diffuse,
Specular
);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_BUMPINESS, &Bumpiness, 1);
}
unsigned Shd8BumpSpecClass::Get_Vertex_Stream_Count() const
{
return 1;
}
unsigned Shd8BumpSpecClass::Get_Vertex_Size(unsigned stream) const
{
return sizeof(VertexFormatXYZNDUV1TG3);
}
void Shd8BumpSpecClass::Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
)
{
VertexFormatXYZNDUV1TG3* verts=(VertexFormatXYZNDUV1TG3*)dest_buffer;
for (unsigned i=0; i<vertex_count; ++i)
{
if (vss.Locations)
{
verts[i].x=vss.Locations[i][0];
verts[i].y=vss.Locations[i][1];
verts[i].z=vss.Locations[i][2];
}
else
{
verts[i].x=0.0f;
verts[i].y=0.0f;
verts[i].z=0.0f;
}
if (vss.DiffuseInt)
{
verts[i].diffuse=vss.DiffuseInt[i];
}
else
{
verts[i].diffuse=0xffffffff;
}
if (vss.Normals)
{
verts[i].nx=vss.Normals[i][0];
verts[i].ny=vss.Normals[i][1];
verts[i].nz=vss.Normals[i][2];
}
else
{
verts[i].nx=0.0f;
verts[i].ny=0.0f;
verts[i].nz=0.0f;
}
if (vss.UV[0])
{
verts[i].u1=vss.UV[0][i].U;
verts[i].v1=vss.UV[0][i].V;
}
else
{
verts[i].u1=0.0f;
verts[i].v1=0.0f;
}
if (vss.S)
{
verts[i].Sx=vss.S[i].X;
verts[i].Sy=vss.S[i].Y;
verts[i].Sz=vss.S[i].Z;
}
else
{
verts[i].Sx=0.0f;
verts[i].Sy=0.0f;
verts[i].Sz=0.0f;
}
if (vss.T)
{
verts[i].Tx=vss.T[i].X;
verts[i].Ty=vss.T[i].Y;
verts[i].Tz=vss.T[i].Z;
}
else
{
verts[i].Tx=0.0f;
verts[i].Ty=0.0f;
verts[i].Tz=0.0f;
}
if (vss.SxT)
{
verts[i].SxTx=vss.SxT[i].X;
verts[i].SxTy=vss.SxT[i].Y;
verts[i].SxTz=vss.SxT[i].Z;
}
else
{
verts[i].SxTx=0.0f;
verts[i].SxTy=0.0f;
verts[i].SxTz=0.0f;
}
}
}
bool Shd8BumpSpecClass::Pass_Selection
(
ShdMeshClass* mesh,
RenderInfoClass* rinfo,
int pass
)
{
if (mesh->Is_Applying_Shadow_Map())
{
if (pass==1) // just do once
{
// is rendering self shadowed object
Setup_Self_Shadow_Info(*mesh,*rinfo);
}
return (pass==1);
}
return (pass==0);
}
/**********************************************************************************************
//! Set up transform for shadow maps
/*! 06/07/02 KM created
*/
void Shd8BumpSpecClass::Setup_Self_Shadow_Info(ShdMeshClass& mesh, RenderInfoClass& rinfo)
{
Matrix4x4 tex_mat=mesh.Peek_Texture_Projector()->Peek_Mapper()->Get_Texture_Transform();
//set special texture matrix for shadow mapping
ZTextureClass* smap=DX8Wrapper::Get_Shadow_Map(0); // todo KJM assign shadow map from rinfo
if (!smap) return;
float off_x=0.5f+(0.5f/(float)smap->Get_Width());
float off_y=0.5f+(0.5f/(float)smap->Get_Height());
unsigned int bits=Get_Num_Depth_Bits(smap->Get_Texture_Format());
float range=(float)(0xFFFFFFFF>>(32-bits));
float bias=0.0f;//-0.001f*range;
Matrix4x4 sb_mat
(
Vector4(0.5f, 0.0f, 0.0f, 0.0f),
Vector4(0.0f, -0.5f, 0.0f, 0.0f),
Vector4(0.0f, 0.0f, range, 0.0f),
Vector4(off_x, off_y, bias, 1.0f)
);
Matrix4x4 view2tex;
Matrix4x4::Multiply(sb_mat,tex_mat,&view2tex);
Matrix4x4 world;
world.Init(mesh.Get_Transform());
Matrix4x4 view;
view.Init(rinfo.Camera.Get_View_Matrix());
Matrix4x4 vw_mat;
Matrix4x4::Multiply(world,view,&vw_mat);
Matrix4x4::Multiply(view2tex,vw_mat,&Self_Shadow_Transform);
}

View File

@@ -0,0 +1,100 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/shd8bumpspec.h $*
* *
* $Author:: Kenny_m
*
* $Modtime:: 5/27/02 3:39p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHD8BUMPSPEC_H
#define SHD8BUMPSPEC_H
#ifndef SHDINTERFACE_H
#include "shdinterface.h"
#endif
#ifndef SHDHWSHADER_H
#include "shdhwshader.h"
#endif
class Shd8BumpSpecClass : public ShdInterfaceClass
{
public:
Shd8BumpSpecClass(const ShdDefClass* def);
virtual ~Shd8BumpSpecClass();
static void Init();
static void Shutdown();
virtual int Get_Pass_Count() { return 2; }
virtual bool Pass_Selection(ShdMeshClass*, RenderInfoClass*,int);
virtual int Get_Texture_Count() const { return 2; }
virtual TextureClass* Peek_Texture(int idx) const { return idx==0 ? Texture : NormalMap; }
virtual void Apply_Shared(int cur_pass, RenderInfoClass& rinfo);
virtual void Apply_Instance(int cur_pass, RenderInfoClass& rinfo);
virtual unsigned Get_Vertex_Stream_Count() const;
virtual unsigned Get_Vertex_Size(unsigned stream) const;
virtual bool Use_HW_Vertex_Processing() const { return Vertex_Shader.Is_Using_Hardware(); }
virtual void Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
);
protected:
void Setup_Self_Shadow_Info(ShdMeshClass& mesh, RenderInfoClass& rinfo);
static ShdHWVertexShader Vertex_Shader;
static ShdHWPixelShader Pixel_Shader;
static Matrix4x4 View_Projection_Matrix;
TextureClass* Texture;
TextureClass* NormalMap;
Vector4 Ambient;
Vector4 Diffuse;
Vector4 Specular;
Vector4 Bumpiness;
// self shadowing
static ShdHWPixelShader Self_Shadow_Pixel_Shader;
static ShdHWVertexShader Self_Shadow_Vertex_Shader;
Matrix4x4 Self_Shadow_Transform;
};
#endif // SHD8BUMPSPEC_H

View File

@@ -0,0 +1,57 @@
//
// Command & Conquer Generals Zero Hour(tm)
// Copyright 2025 Electronic Arts Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// DX8 bump specular with gloss shader
// Kenny Mitchell
#include "shd8bumpspec_constants.h"
// pixel shader version 1.1
ps.1.1
tex TEX_NORMALMAP // normal map texture
tex TEX_DECAL // decal texture
texcoord TEX_SPECULAR // specular term
// bumped normal
dp3 TEX_NORMALMAP, TEX_NORMALMAP_bx2, COL_LIGHT_bx2
// modulate texture and light color
mul TEX_DECAL.rgb, COL_DIFFUSE, TEX_DECAL
// apply bump color in reverse direction with saturation
mul_sat r1, TEX_DECAL, -TEX_NORMALMAP
// apply bump color in primary direction with saturation
mul_sat r0, TEX_DECAL, TEX_NORMALMAP
// add bump light contribution
add r0, r0, r1
// add key light contribution
mad r0, TEX_DECAL, COL_LIGHT.a, r0
// specular section
// apply gloss map
mul_sat r1, TEX_DECAL.a, TEX_NORMALMAP
// apply specular power
mad r0, TEX_SPECULAR, r1, r0

View File

@@ -0,0 +1,183 @@
//
// Command & Conquer Generals Zero Hour(tm)
// Copyright 2025 Electronic Arts Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// DX8 bump specularwith gloss map vertex shader
// Kenny Mitchell - Westwood Studios EA 2002
vs.1.1
#include "shdhw_constants.h"
#include "shd8bumpspec_constants.h"
// In:
// v0 - object space vertex position
// v1 - object space normal
// v2 - color
// v3 - texture coords
// v4 - S basis
// v5 - T basis
// v6 - SxT
// object space vertex position -> screen (early as possible for view clipping)
dp4 EYE_VECTOR.x, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_0]
dp4 EYE_VECTOR.y, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_1]
dp4 EYE_VECTOR.z, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_2]
dp4 EYE_VECTOR.w, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_3]
mov oPos, EYE_VECTOR
// Transform basis vectors to world space
dp3 S_WORLD.x, V_S, c[CV_WORLD_0]
dp3 S_WORLD.y, V_S, c[CV_WORLD_1]
dp3 S_WORLD.z, V_S, c[CV_WORLD_2]
dp3 T_WORLD.x, V_T, c[CV_WORLD_0]
dp3 T_WORLD.y, V_T, c[CV_WORLD_1]
dp3 T_WORLD.z, V_T, c[CV_WORLD_2]
dp3 SxT_WORLD.x, V_SxT, c[CV_WORLD_0]
dp3 SxT_WORLD.y, V_SxT, c[CV_WORLD_1]
dp3 SxT_WORLD.z, V_SxT, c[CV_WORLD_2]
// transform light 0 by basis vectors to put it into texture space
dp3 LIGHT_LOCAL.x, S_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
dp3 LIGHT_LOCAL.y, T_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
dp3 LIGHT_LOCAL.z, SxT_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
// Normalize the light vector
dp3 LIGHT_LOCAL.w, LIGHT_LOCAL, LIGHT_LOCAL
rsq LIGHT_LOCAL.w, LIGHT_LOCAL.w
mul LIGHT_LOCAL, LIGHT_LOCAL, LIGHT_LOCAL.w
dp3 WORLD_NORMAL.x, V_NORMAL, c[CV_WORLD_0]
dp3 WORLD_NORMAL.y, V_NORMAL, c[CV_WORLD_1]
dp3 WORLD_NORMAL.z, V_NORMAL, c[CV_WORLD_2]
// Normalize the world normal vector
dp3 WORLD_NORMAL.w, WORLD_NORMAL, WORLD_NORMAL
rsq WORLD_NORMAL.w, WORLD_NORMAL.w
mul WORLD_NORMAL, WORLD_NORMAL, WORLD_NORMAL.w
// calculate light 0 factor
dp3 LIGHT_0.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_0] // L.N
max LIGHT_0.w, LIGHT_0.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_0.w, LIGHT_0.w, c[CV_LIGHT_COLOR_0].w // light attentuation factor
// calculate light 1 factor
dp3 LIGHT_1.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_1] // L.N
max LIGHT_1.w, LIGHT_1.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_1.w, LIGHT_1.w, c[CV_LIGHT_COLOR_1].w // light attentuation factor
// calculate light 2 factor
dp3 LIGHT_2.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_2] // L.N
max LIGHT_2.w, LIGHT_2.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_2.w, LIGHT_2.w, c[CV_LIGHT_COLOR_2].w // light attentuation factor
// calculate light 3 factor
dp3 LIGHT_3.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_3] // L.N
max LIGHT_3.w, LIGHT_3.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_3.w, LIGHT_3.w, c[CV_LIGHT_COLOR_3].w // light attentuation factor
// accumulate light colors
mul COL, c[CV_LIGHT_COLOR_0], LIGHT_0.w
mad COL, c[CV_LIGHT_COLOR_1], LIGHT_1.w, COL
mad COL, c[CV_LIGHT_COLOR_2], LIGHT_2.w, COL
mad COL, c[CV_LIGHT_COLOR_3], LIGHT_3.w, COL
// apply vertex color and diffuse and ambient material terms
mul COL, COL, V_DIFFUSE
mul COL, COL, c[CV_DIFFUSE]
add oD1, COL, c[CV_AMBIENT]
// Scale to 0-1
add LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].yyy
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].zzz
// apply bump scale and bias controls
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_BUMPINESS].xxx
add oD0, LIGHT_LOCAL, c[CV_BUMPINESS].yyy
// calc light factor excluding bumped lights
add LIGHT_0.w, c[CV_CONST].y, -LIGHT_0.w
add LIGHT_1.w, c[CV_CONST].y, -LIGHT_1.w
mul LIGHT_0.w, c[CV_LIGHT_COLOR_0], LIGHT_0.w
mul LIGHT_1.w, c[CV_LIGHT_COLOR_1], LIGHT_1.w
add oD0.w, LIGHT_0.w, LIGHT_1.w
// calculate specular term
// calculate half angle
// transform vertex position to world space
// to calculate V, vector to viewer in world
// space.
dp4 WORLD_VERTEX.x, V_POSITION, c[CV_WORLD_0]
dp4 WORLD_VERTEX.y, V_POSITION, c[CV_WORLD_1]
dp4 WORLD_VERTEX.z, V_POSITION, c[CV_WORLD_2]
//dp4 WORLD_VERTEX.w, V_POSITION, c[CV_WORLD_3]
// Half angle vector is (L+V)/||L+V|| or Normalize( L+V )
// ||a|| is magnitude of a
// L = vec to light from vertex point
// V = vec to viewer from vertex point
// vertex position - eye position
// eye position - vertex position
add EYE_VECTOR, c[CV_EYE_WORLD], -WORLD_VERTEX.xyz
// Normalize the eye vector
dp3 EYE_VECTOR.w, EYE_VECTOR, EYE_VECTOR
rsq EYE_VECTOR.w, EYE_VECTOR.w
mul EYE_VECTOR, EYE_VECTOR, EYE_VECTOR.w
// Add them to average & create half angle vector
add HALF_ANGLE, c[CV_LIGHT_DIRECTION_0], EYE_VECTOR
// Normalize the half angle vector
dp3 HALF_ANGLE.w, HALF_ANGLE, HALF_ANGLE
rsq HALF_ANGLE.w, HALF_ANGLE.w
mul HALF_ANGLE, HALF_ANGLE, HALF_ANGLE.w
// calculate light 0 factor
dp3 LIGHT_0.w, HALF_ANGLE, WORLD_NORMAL // N.H
max LIGHT_0.w, LIGHT_0.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_0.w, LIGHT_0.w, c[CV_LIGHT_COLOR_0].w // light attentuation factor
mul LIGHT_0.w, LIGHT_0, LIGHT_0
mul LIGHT_0.w, LIGHT_0, LIGHT_0
mul LIGHT_0.w, LIGHT_0, LIGHT_0
// accumulate light colors
mul COL, c[CV_LIGHT_COLOR_0], LIGHT_0.w
// output per vertex specular color
mul oT2, COL, c[CV_SPECULAR]
mov oT0, V_TEXTURE
mov oT1, V_TEXTURE

View File

@@ -0,0 +1,99 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// DX8 bump specular mask with gloss map shader constants
// Kenny Mitchell - Westwood Studios EA 2002
#ifndef SHD8BUMPSPEC_CONSTANTS_H
#define SHD8BUMPSPEC_CONSTANTS_H
// vertex shader macros
#define CV_WORLD_VIEW_PROJECTION 1
#define CV_WORLD_VIEW_PROJECTION_0 1
#define CV_WORLD_VIEW_PROJECTION_1 2
#define CV_WORLD_VIEW_PROJECTION_2 3
#define CV_WORLD_VIEW_PROJECTION_3 4
#define CV_WORLD 12
#define CV_WORLD_0 12
#define CV_WORLD_1 13
#define CV_WORLD_2 14
#define CV_WORLD_3 15
// 16-26 lighting constants
#define CV_BUMPINESS 27
#define CV_EYE_WORLD 28
#define CV_TEXMAP 30
#define CV_TEXMAP_0 30
#define CV_TEXMAP_1 31
#define CV_TEXMAP_2 32
#define CV_TEXMAP_3 33
// inputs
#define V_POSITION v0
#define V_NORMAL v1
#define V_DIFFUSE v2
#define V_TEXTURE v3
#define V_S v4
#define V_T v5
#define V_SxT v6
// registers
#define HALF_ANGLE r0
#define S_WORLD r1
#define T_WORLD r2
#define SxT_WORLD r3
#define LIGHT_LOCAL r4
#define LIGHT_0 r5
#define LIGHT_1 r6
#define LIGHT_2 r7
#define LIGHT_3 r8
#define COL r9
#define WORLD_NORMAL r10
#define EYE_VECTOR r11
#define WORLD_VERTEX r11
// pixel shader constants
#define OUTPUT_REG r0
// texture stages
#define TEX_NORMALMAP t0
#define TEX_DECAL t1
#define TEX_SPECULAR t2
#define COL_LIGHT v0
#define COL_DIFFUSE v1
#endif

View File

@@ -0,0 +1,57 @@
//
// Command & Conquer Generals Zero Hour(tm)
// Copyright 2025 Electronic Arts Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// DX8 self shadowed bump specular with gloss shader
// Kenny Mitchell
#include "shd8bumpspec_constants.h"
// pixel shader version 1.1
ps.1.1
tex TEX_NORMALMAP // normal map texture
//tex TEX_DECAL // decal texture
mov r0,TEX_NORMALMAP
//texcoord TEX_SPECULAR // specular term
//texcoord t3
// bumped normal
//dp3_sat r1, TEX_NORMALMAP_bx2, COL_LIGHT_bx2
// fill light normal
//add r1, COL_LIGHT.a, r1
// modulate texture and light color
//mul r0, COL_DIFFUSE, TEX_DECAL
// apply light intensity
//mul r0, r0, r1
// specular section
//dp3_sat r1, TEX_NORMALMAP_bx2, t3_bx2
//mul r1, r1, r1
//mul r1, r1, r1
// apply gloss map
//mul r1, TEX_DECAL.a, r1
//mad r0, TEX_SPECULAR, r1, r0

View File

@@ -0,0 +1,221 @@
//
// Command & Conquer Generals Zero Hour(tm)
// Copyright 2025 Electronic Arts Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// DX8 self shadowed bump specular with gloss map vertex shader
// Kenny Mitchell - Westwood Studios EA 2002
vs.1.1
#include "shdhw_constants.h"
#include "shd8bumpspec_constants.h"
// In:
// v0 - object space vertex position
// v1 - object space normal
// v2 - color
// v3 - texture coords
// v4 - S basis
// v5 - T basis
// v6 - SxT
// object space vertex position -> screen (early as possible for view clipping)
dp4 EYE_VECTOR.x, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_0]
dp4 EYE_VECTOR.y, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_1]
dp4 EYE_VECTOR.z, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_2]
dp4 EYE_VECTOR.w, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_3]
mov oPos, EYE_VECTOR
dp4 oT0.x, V_POSITION, c[CV_TEXMAP_0]
dp4 oT0.y, V_POSITION, c[CV_TEXMAP_1]
dp4 oT0.z, V_POSITION, c[CV_TEXMAP_2]
dp4 oT0.w, V_POSITION, c[CV_TEXMAP_3]
// Transform basis vectors to world space
dp3 S_WORLD.x, V_S, c[CV_WORLD_0]
dp3 S_WORLD.y, V_S, c[CV_WORLD_1]
dp3 S_WORLD.z, V_S, c[CV_WORLD_2]
dp3 T_WORLD.x, V_T, c[CV_WORLD_0]
dp3 T_WORLD.y, V_T, c[CV_WORLD_1]
dp3 T_WORLD.z, V_T, c[CV_WORLD_2]
dp3 SxT_WORLD.x, V_SxT, c[CV_WORLD_0]
dp3 SxT_WORLD.y, V_SxT, c[CV_WORLD_1]
dp3 SxT_WORLD.z, V_SxT, c[CV_WORLD_2]
// transform light 0 by basis vectors to put it into texture space
dp3 LIGHT_LOCAL.x, S_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
dp3 LIGHT_LOCAL.y, T_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
dp3 LIGHT_LOCAL.z, SxT_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
// Normalize the light vector
dp3 LIGHT_LOCAL.w, LIGHT_LOCAL, LIGHT_LOCAL
rsq LIGHT_LOCAL.w, LIGHT_LOCAL.w
mul LIGHT_LOCAL, LIGHT_LOCAL, LIGHT_LOCAL.w
dp3 WORLD_NORMAL.x, V_NORMAL, c[CV_WORLD_0]
dp3 WORLD_NORMAL.y, V_NORMAL, c[CV_WORLD_1]
dp3 WORLD_NORMAL.z, V_NORMAL, c[CV_WORLD_2]
// Normalize the world normal vector
dp3 WORLD_NORMAL.w, WORLD_NORMAL, WORLD_NORMAL
rsq WORLD_NORMAL.w, WORLD_NORMAL.w
mul WORLD_NORMAL, WORLD_NORMAL, WORLD_NORMAL.w
// calculate light 0 factor
dp3 LIGHT_0.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_0] // L.N
max LIGHT_0.w, LIGHT_0.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_0.w, LIGHT_0.w, c[CV_LIGHT_COLOR_0].w // light attentuation factor
// calculate light 1 factor
dp3 LIGHT_1.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_1] // L.N
max LIGHT_1.w, LIGHT_1.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_1.w, LIGHT_1.w, c[CV_LIGHT_COLOR_1].w // light attentuation factor
// calculate light 2 factor
dp3 LIGHT_2.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_2] // L.N
max LIGHT_2.w, LIGHT_2.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_2.w, LIGHT_2.w, c[CV_LIGHT_COLOR_2].w // light attentuation factor
// calculate light 3 factor
dp3 LIGHT_3.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_3] // L.N
max LIGHT_3.w, LIGHT_3.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_3.w, LIGHT_3.w, c[CV_LIGHT_COLOR_3].w // light attentuation factor
// accumulate light colors
mul COL, c[CV_LIGHT_COLOR_0], LIGHT_0.w
mad COL, c[CV_LIGHT_COLOR_1], LIGHT_1.w, COL
mad COL, c[CV_LIGHT_COLOR_2], LIGHT_2.w, COL
mad COL, c[CV_LIGHT_COLOR_3], LIGHT_3.w, COL
// apply vertex color and diffuse and ambient material terms
mul COL, COL, V_DIFFUSE
mul COL, COL, c[CV_DIFFUSE]
add oD1, COL, c[CV_AMBIENT]
// Scale to 0-1
add LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].yyy
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].zzz
// apply bump scale and bias controls
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_BUMPINESS].xxx
add oD0, LIGHT_LOCAL, c[CV_BUMPINESS].yyy
// set compliment of diffuse light factor
add oD0.w, c[CV_CONST].y, -LIGHT_0.w
// calculate specular term
// calculate half angle
// transform vertex position to world space
// to calculate V, vector to viewer in world
// space.
dp4 WORLD_VERTEX.x, V_POSITION, c[CV_WORLD_0]
dp4 WORLD_VERTEX.y, V_POSITION, c[CV_WORLD_1]
dp4 WORLD_VERTEX.z, V_POSITION, c[CV_WORLD_2]
//dp4 WORLD_VERTEX.w, V_POSITION, c[CV_WORLD_3]
// Half angle vector is (L+V)/||L+V|| or Normalize( L+V )
// ||a|| is magnitude of a
// L = vec to light from vertex point
// V = vec to viewer from vertex point
// vertex position - eye position
// eye position - vertex position
add EYE_VECTOR, c[CV_EYE_WORLD], -WORLD_VERTEX.xyz
// Normalize the eye vector
dp3 EYE_VECTOR.w, EYE_VECTOR, EYE_VECTOR
rsq EYE_VECTOR.w, EYE_VECTOR.w
mul EYE_VECTOR, EYE_VECTOR, EYE_VECTOR.w
// Add them to average & create half angle vector
add HALF_ANGLE, c[CV_LIGHT_DIRECTION_0], EYE_VECTOR
// Normalize the half angle vector
dp3 HALF_ANGLE.w, HALF_ANGLE, HALF_ANGLE
rsq HALF_ANGLE.w, HALF_ANGLE.w
mul HALF_ANGLE, HALF_ANGLE, HALF_ANGLE.w
dp3 LIGHT_LOCAL.x, S_WORLD.xyz, HALF_ANGLE
dp3 LIGHT_LOCAL.y, T_WORLD.xyz, HALF_ANGLE
dp3 LIGHT_LOCAL.z, SxT_WORLD.xyz, HALF_ANGLE
// Normalize the half angle vector
dp3 LIGHT_LOCAL.w, LIGHT_LOCAL, LIGHT_LOCAL
rsq LIGHT_LOCAL.w, LIGHT_LOCAL.w
mul LIGHT_LOCAL, LIGHT_LOCAL, LIGHT_LOCAL.w
// Scale to 0-1
//add LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].yyy
//mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].zzz
// apply bump scale and bias controls
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_BUMPINESS].zzz
//add oT3, LIGHT_LOCAL, c[CV_BUMPINESS].www
// calculate light 0 factor
dp3 LIGHT_0.w, HALF_ANGLE, WORLD_NORMAL // N.H
max LIGHT_0.w, LIGHT_0.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_0.w, LIGHT_0.w, c[CV_LIGHT_COLOR_0].w // light attentuation factor
mul LIGHT_0.w, LIGHT_0, LIGHT_0
mul LIGHT_0.w, LIGHT_0, LIGHT_0
mul LIGHT_0.w, LIGHT_0, LIGHT_0
// calculate light 1 factor
//dp3 LIGHT_1.w, HALF_ANGLE, c[CV_LIGHT_DIRECTION_1] // L.H
//max LIGHT_1.w, LIGHT_1.w, c[CV_CONST].x // clamp 0-1
//mul LIGHT_1.w, LIGHT_1.w, c[CV_LIGHT_COLOR_1].w // light attentuation factor
// calculate light 2 factor
//dp3 LIGHT_2.w, HALF_ANGLE, c[CV_LIGHT_DIRECTION_2] // L.H
//max LIGHT_2.w, LIGHT_2.w, c[CV_CONST].x // clamp 0-1
//mul LIGHT_2.w, LIGHT_2.w, c[CV_LIGHT_COLOR_2].w // light attentuation factor
// accumulate light colors
mul COL, c[CV_LIGHT_COLOR_0], LIGHT_0.w
//mad COL, c[CV_LIGHT_COLOR_1], LIGHT_1.w, COL
//mad COL, c[CV_LIGHT_COLOR_2], LIGHT_2.w, COL
//mul oT2, COL, c[CV_SPECULAR]
// Set alpha to 1
//add oT3.w, c[CV_CONST].y, -LIGHT_0.w
//mov oT0, V_TEXTURE
//mov oT1, V_TEXTURE

View File

@@ -0,0 +1,57 @@
//
// Command & Conquer Generals Zero Hour(tm)
// Copyright 2025 Electronic Arts Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// DX8 self shadowed bump specular with gloss shader
// Kenny Mitchell
#include "shd8bumpspec_constants.h"
// pixel shader version 1.1
ps.1.1
tex TEX_NORMALMAP // normal map texture
//tex TEX_DECAL // decal texture
mov r0,TEX_NORMALMAP
//texcoord TEX_SPECULAR // specular term
//texcoord t3
// bumped normal
//dp3_sat r1, TEX_NORMALMAP_bx2, COL_LIGHT_bx2
// fill light normal
//add r1, COL_LIGHT.a, r1
// modulate texture and light color
//mul r0, COL_DIFFUSE, TEX_DECAL
// apply light intensity
//mul r0, r0, r1
// specular section
//dp3_sat r1, TEX_NORMALMAP_bx2, t3_bx2
//mul r1, r1, r1
//mul r1, r1, r1
// apply gloss map
//mul r1, TEX_DECAL.a, r1
//mad r0, TEX_SPECULAR, r1, r0

View File

@@ -0,0 +1,221 @@
//
// Command & Conquer Generals Zero Hour(tm)
// Copyright 2025 Electronic Arts Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// DX8 self shadowed bump specular with gloss map vertex shader
// Kenny Mitchell - Westwood Studios EA 2002
vs.1.1
#include "shdhw_constants.h"
#include "shd8bumpspec_constants.h"
// In:
// v0 - object space vertex position
// v1 - object space normal
// v2 - color
// v3 - texture coords
// v4 - S basis
// v5 - T basis
// v6 - SxT
// object space vertex position -> screen (early as possible for view clipping)
dp4 EYE_VECTOR.x, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_0]
dp4 EYE_VECTOR.y, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_1]
dp4 EYE_VECTOR.z, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_2]
dp4 EYE_VECTOR.w, V_POSITION, c[CV_WORLD_VIEW_PROJECTION_3]
mov oPos, EYE_VECTOR
dp4 oT0.x, V_POSITION, c[CV_TEXMAP_0]
dp4 oT0.y, V_POSITION, c[CV_TEXMAP_1]
dp4 oT0.z, V_POSITION, c[CV_TEXMAP_2]
dp4 oT0.w, V_POSITION, c[CV_TEXMAP_3]
// Transform basis vectors to world space
dp3 S_WORLD.x, V_S, c[CV_WORLD_0]
dp3 S_WORLD.y, V_S, c[CV_WORLD_1]
dp3 S_WORLD.z, V_S, c[CV_WORLD_2]
dp3 T_WORLD.x, V_T, c[CV_WORLD_0]
dp3 T_WORLD.y, V_T, c[CV_WORLD_1]
dp3 T_WORLD.z, V_T, c[CV_WORLD_2]
dp3 SxT_WORLD.x, V_SxT, c[CV_WORLD_0]
dp3 SxT_WORLD.y, V_SxT, c[CV_WORLD_1]
dp3 SxT_WORLD.z, V_SxT, c[CV_WORLD_2]
// transform light 0 by basis vectors to put it into texture space
dp3 LIGHT_LOCAL.x, S_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
dp3 LIGHT_LOCAL.y, T_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
dp3 LIGHT_LOCAL.z, SxT_WORLD.xyz, c[CV_LIGHT_DIRECTION_0]
// Normalize the light vector
dp3 LIGHT_LOCAL.w, LIGHT_LOCAL, LIGHT_LOCAL
rsq LIGHT_LOCAL.w, LIGHT_LOCAL.w
mul LIGHT_LOCAL, LIGHT_LOCAL, LIGHT_LOCAL.w
dp3 WORLD_NORMAL.x, V_NORMAL, c[CV_WORLD_0]
dp3 WORLD_NORMAL.y, V_NORMAL, c[CV_WORLD_1]
dp3 WORLD_NORMAL.z, V_NORMAL, c[CV_WORLD_2]
// Normalize the world normal vector
dp3 WORLD_NORMAL.w, WORLD_NORMAL, WORLD_NORMAL
rsq WORLD_NORMAL.w, WORLD_NORMAL.w
mul WORLD_NORMAL, WORLD_NORMAL, WORLD_NORMAL.w
// calculate light 0 factor
dp3 LIGHT_0.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_0] // L.N
max LIGHT_0.w, LIGHT_0.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_0.w, LIGHT_0.w, c[CV_LIGHT_COLOR_0].w // light attentuation factor
// calculate light 1 factor
dp3 LIGHT_1.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_1] // L.N
max LIGHT_1.w, LIGHT_1.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_1.w, LIGHT_1.w, c[CV_LIGHT_COLOR_1].w // light attentuation factor
// calculate light 2 factor
dp3 LIGHT_2.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_2] // L.N
max LIGHT_2.w, LIGHT_2.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_2.w, LIGHT_2.w, c[CV_LIGHT_COLOR_2].w // light attentuation factor
// calculate light 3 factor
dp3 LIGHT_3.w, WORLD_NORMAL, c[CV_LIGHT_DIRECTION_3] // L.N
max LIGHT_3.w, LIGHT_3.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_3.w, LIGHT_3.w, c[CV_LIGHT_COLOR_3].w // light attentuation factor
// accumulate light colors
mul COL, c[CV_LIGHT_COLOR_0], LIGHT_0.w
mad COL, c[CV_LIGHT_COLOR_1], LIGHT_1.w, COL
mad COL, c[CV_LIGHT_COLOR_2], LIGHT_2.w, COL
mad COL, c[CV_LIGHT_COLOR_3], LIGHT_3.w, COL
// apply vertex color and diffuse and ambient material terms
mul COL, COL, V_DIFFUSE
mul COL, COL, c[CV_DIFFUSE]
add oD1, COL, c[CV_AMBIENT]
// Scale to 0-1
add LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].yyy
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].zzz
// apply bump scale and bias controls
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_BUMPINESS].xxx
add oD0, LIGHT_LOCAL, c[CV_BUMPINESS].yyy
// set compliment of diffuse light factor
add oD0.w, c[CV_CONST].y, -LIGHT_0.w
// calculate specular term
// calculate half angle
// transform vertex position to world space
// to calculate V, vector to viewer in world
// space.
dp4 WORLD_VERTEX.x, V_POSITION, c[CV_WORLD_0]
dp4 WORLD_VERTEX.y, V_POSITION, c[CV_WORLD_1]
dp4 WORLD_VERTEX.z, V_POSITION, c[CV_WORLD_2]
//dp4 WORLD_VERTEX.w, V_POSITION, c[CV_WORLD_3]
// Half angle vector is (L+V)/||L+V|| or Normalize( L+V )
// ||a|| is magnitude of a
// L = vec to light from vertex point
// V = vec to viewer from vertex point
// vertex position - eye position
// eye position - vertex position
add EYE_VECTOR, c[CV_EYE_WORLD], -WORLD_VERTEX.xyz
// Normalize the eye vector
dp3 EYE_VECTOR.w, EYE_VECTOR, EYE_VECTOR
rsq EYE_VECTOR.w, EYE_VECTOR.w
mul EYE_VECTOR, EYE_VECTOR, EYE_VECTOR.w
// Add them to average & create half angle vector
add HALF_ANGLE, c[CV_LIGHT_DIRECTION_0], EYE_VECTOR
// Normalize the half angle vector
dp3 HALF_ANGLE.w, HALF_ANGLE, HALF_ANGLE
rsq HALF_ANGLE.w, HALF_ANGLE.w
mul HALF_ANGLE, HALF_ANGLE, HALF_ANGLE.w
dp3 LIGHT_LOCAL.x, S_WORLD.xyz, HALF_ANGLE
dp3 LIGHT_LOCAL.y, T_WORLD.xyz, HALF_ANGLE
dp3 LIGHT_LOCAL.z, SxT_WORLD.xyz, HALF_ANGLE
// Normalize the half angle vector
dp3 LIGHT_LOCAL.w, LIGHT_LOCAL, LIGHT_LOCAL
rsq LIGHT_LOCAL.w, LIGHT_LOCAL.w
mul LIGHT_LOCAL, LIGHT_LOCAL, LIGHT_LOCAL.w
// Scale to 0-1
//add LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].yyy
//mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_CONST].zzz
// apply bump scale and bias controls
mul LIGHT_LOCAL, LIGHT_LOCAL, c[CV_BUMPINESS].zzz
//add oT3, LIGHT_LOCAL, c[CV_BUMPINESS].www
// calculate light 0 factor
dp3 LIGHT_0.w, HALF_ANGLE, WORLD_NORMAL // N.H
max LIGHT_0.w, LIGHT_0.w, c[CV_CONST].x // clamp 0-1
mul LIGHT_0.w, LIGHT_0.w, c[CV_LIGHT_COLOR_0].w // light attentuation factor
mul LIGHT_0.w, LIGHT_0, LIGHT_0
mul LIGHT_0.w, LIGHT_0, LIGHT_0
mul LIGHT_0.w, LIGHT_0, LIGHT_0
// calculate light 1 factor
//dp3 LIGHT_1.w, HALF_ANGLE, c[CV_LIGHT_DIRECTION_1] // L.H
//max LIGHT_1.w, LIGHT_1.w, c[CV_CONST].x // clamp 0-1
//mul LIGHT_1.w, LIGHT_1.w, c[CV_LIGHT_COLOR_1].w // light attentuation factor
// calculate light 2 factor
//dp3 LIGHT_2.w, HALF_ANGLE, c[CV_LIGHT_DIRECTION_2] // L.H
//max LIGHT_2.w, LIGHT_2.w, c[CV_CONST].x // clamp 0-1
//mul LIGHT_2.w, LIGHT_2.w, c[CV_LIGHT_COLOR_2].w // light attentuation factor
// accumulate light colors
mul COL, c[CV_LIGHT_COLOR_0], LIGHT_0.w
//mad COL, c[CV_LIGHT_COLOR_1], LIGHT_1.w, COL
//mad COL, c[CV_LIGHT_COLOR_2], LIGHT_2.w, COL
//mul oT2, COL, c[CV_SPECULAR]
// Set alpha to 1
//add oT3.w, c[CV_CONST].y, -LIGHT_0.w
//mov oT0, V_TEXTURE
//mov oT1, V_TEXTURE

View File

@@ -0,0 +1,224 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/shdbumpdiff.cpp $*
* *
* $Author:: Kenny_m
*
* $Modtime:: 6/03/02 8:12a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "dx8fvf.h"
#include "dx8wrapper.h"
#include "assetmgr.h"
#include "shdbumpdiff.h"
#include "shd6bumpdiff.h"
#include "shd7bumpdiff.h"
#include "shd8bumpdiff.h"
#include "editable.h"
#include "shdclassids.h"
#include "shddeffactory.h"
#include "shdinterface.h"
#include "persistfactory.h"
#include "wwhack.h"
DECLARE_FORCE_LINK(BumpDiffShader);
REGISTER_SHDDEF(ShdBumpDiffDefClass,SHDDEF_CLASSID_BUMPDIFF,"Bump Diffuse");
// static member
ShdVersion ShdBumpDiffDefClass::Version;
// Save-Load methods for ShdDefClass
enum
{
CHUNKID_VARIABLES = 0x16490450,
VARID_TEXTURE_NAME = 0x00,
VARID_BUMP_MAP_NAME,
VARID_AMBIENT_COLOR,
VARID_DIFFUSE_COLOR,
VARID_DIFFUSE_BUMPINESS,
};
ShdBumpDiffDefClass::ShdBumpDiffDefClass()
: ShdDefClass(SHDDEF_CLASSID_BUMPDIFF),
Ambient(1,1,1),
Diffuse(1,1,1),
Diffuse_Bumpiness(1,0)
{
NAMED_TEXTURE_FILENAME_PARAM(ShdBumpDiffDefClass, TextureName, "Base Map", "Targa Files", ".tga");
NAMED_TEXTURE_FILENAME_PARAM(ShdBumpDiffDefClass, BumpMapName, "Bump Map", "Targa Files", ".tga");
NAMED_EDITABLE_PARAM(ShdBumpDiffDefClass, ParameterClass::TYPE_COLOR, Ambient, "Ambient");
NAMED_EDITABLE_PARAM(ShdBumpDiffDefClass, ParameterClass::TYPE_COLOR, Diffuse, "Diffuse");
NAMED_EDITABLE_PARAM(ShdBumpDiffDefClass, ParameterClass::TYPE_FLOAT, Diffuse_Bumpiness.X, "Diffuse Bump Scale");
NAMED_EDITABLE_PARAM(ShdBumpDiffDefClass, ParameterClass::TYPE_FLOAT, Diffuse_Bumpiness.Y, "Diffuse Bump Bias");
}
ShdBumpDiffDefClass::ShdBumpDiffDefClass(const ShdBumpDiffDefClass& that)
: ShdDefClass(that),
Ambient(that.Ambient),
Diffuse(that.Diffuse),
Diffuse_Bumpiness(that.Diffuse_Bumpiness)
{
TextureName=that.TextureName;
BumpMapName=that.BumpMapName;
}
ShdBumpDiffDefClass::~ShdBumpDiffDefClass()
{
}
bool ShdBumpDiffDefClass::Is_Valid_Config(StringClass &message)
{
return true;
}
bool ShdBumpDiffDefClass::Save(ChunkSaveClass &csave)
{
ShdDefClass::Save(csave);
csave.Begin_Chunk(CHUNKID_VARIABLES);
bool retval = true;
// only save the file name
char fname[_MAX_PATH];
_splitpath(TextureName,NULL,NULL,fname,NULL);
strcat(fname,".tga");
TextureName=fname;
WRITE_MICRO_CHUNK_WWSTRING(csave, VARID_TEXTURE_NAME, TextureName);
_splitpath(BumpMapName,NULL,NULL,fname,NULL);
strcat(fname,".tga");
BumpMapName=fname;
WRITE_MICRO_CHUNK_WWSTRING(csave, VARID_BUMP_MAP_NAME, BumpMapName);
WRITE_MICRO_CHUNK(csave, VARID_AMBIENT_COLOR, Ambient);
WRITE_MICRO_CHUNK(csave, VARID_DIFFUSE_COLOR, Diffuse);
WRITE_MICRO_CHUNK(csave, VARID_DIFFUSE_BUMPINESS, Diffuse_Bumpiness);
csave.End_Chunk();
return retval;
}
bool ShdBumpDiffDefClass::Load(ChunkLoadClass &cload)
{
ShdDefClass::Load(cload);
// Loop through all the microchunks that define the variables
while (cload.Open_Chunk()) {
switch (cload.Cur_Chunk_ID())
{
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk())
{
switch (cload.Cur_Micro_Chunk_ID())
{
READ_MICRO_CHUNK_WWSTRING(cload, VARID_TEXTURE_NAME, TextureName);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_BUMP_MAP_NAME, BumpMapName);
READ_MICRO_CHUNK(cload, VARID_AMBIENT_COLOR, Ambient);
READ_MICRO_CHUNK(cload, VARID_DIFFUSE_COLOR, Diffuse);
READ_MICRO_CHUNK(cload, VARID_DIFFUSE_BUMPINESS, Diffuse_Bumpiness);
}
cload.Close_Micro_Chunk();
}
break;
default:
break;
}
cload.Close_Chunk();
}
return true;
}
void ShdBumpDiffDefClass::Init()
{
// select shader version
if ((DX8Wrapper::Get_Current_Caps()->Get_Pixel_Shader_Major_Version())==1 &&
(DX8Wrapper::Get_Current_Caps()->Get_Pixel_Shader_Minor_Version())>=1)
{
Version.Set(SHDVER_8);
}
else if (DX8Wrapper::Get_Current_Caps()->Support_Dot3())
{
Version.Set(SHDVER_7);
}
else
{
Version.Set(SHDVER_6);
}
switch (Version.Get())
{
case SHDVER_8 : Shd8BumpDiffClass::Init(); break;
case SHDVER_7 : Shd7BumpDiffClass::Init(); break;
case SHDVER_6 : Shd6BumpDiffClass::Init(); break;
}
}
void ShdBumpDiffDefClass::Shutdown()
{
switch (Version.Get())
{
case SHDVER_8 : Shd8BumpDiffClass::Shutdown(); break;
case SHDVER_7 : Shd7BumpDiffClass::Shutdown(); break;
case SHDVER_6 : Shd6BumpDiffClass::Shutdown(); break;
}
}
ShdInterfaceClass* ShdBumpDiffDefClass::Create() const
{
switch (Version.Get())
{
case SHDVER_8 : return new Shd8BumpDiffClass(this); break;
case SHDVER_7 : return new Shd7BumpDiffClass(this); break;
case SHDVER_6 : return new Shd6BumpDiffClass(this); break;
}
return NULL;
}

View File

@@ -0,0 +1,109 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/shdbumpdiff.h $*
* *
* $Author:: Kenny_m
*
* $Modtime:: 6/03/02 8:12a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHDBUMPDIFF_H
#define SHDBUMPDIFF_H
#include "shddef.h"
#include "saveload.h"
#include "shader.h"
class ShdBumpDiffDefClass : public ShdDefClass
{
public:
/////////////////////////////////////////////////////////////////////
// Editable interface requirements
/////////////////////////////////////////////////////////////////////
DECLARE_EDITABLE(ShdBumpDiffDefClass, ShdDefClass);
ShdBumpDiffDefClass();
ShdBumpDiffDefClass(const ShdBumpDiffDefClass& that);
virtual ~ShdBumpDiffDefClass();
virtual ShdDefClass* Clone() const { return new ShdBumpDiffDefClass(*this); }
// Shader Creation (should create a shader compatible with the current hardware/API)
virtual void Init();
virtual void Shutdown();
virtual ShdInterfaceClass* Create() const;
// Validation methods
virtual bool Is_Valid_Config(StringClass &message);
// Requirements
virtual bool Requires_Normals() const { return true; }
virtual bool Requires_Tangent_Space_Vectors() const { return true; }
virtual bool Requires_Sorting() const { return false; }
virtual int Static_Sort_Index() const { return 0; }
// From PersistClass
virtual bool Save(ChunkSaveClass &csave);
virtual bool Load(ChunkLoadClass &cload);
void Set_Texture_Name(const StringClass& name) { TextureName=name; }
const StringClass& Get_Texture_Name() const { return TextureName; }
void Set_Bump_Map_Name(const StringClass& name) { BumpMapName=name; }
const StringClass& Get_Bump_Map_Name() const { return BumpMapName; }
void Set_Ambient(const Vector3& ambient) { Ambient=ambient; }
const Vector3& Get_Ambient() const { return Ambient; }
void Set_Diffuse(const Vector3& diffuse) { Diffuse=diffuse; }
const Vector3& Get_Diffuse() const { return Diffuse; }
void Set_Diffuse_Bumpiness(const Vector2& diffuse_bumpiness) { Diffuse_Bumpiness=diffuse_bumpiness; }
const Vector2& Get_Diffuse_Bumpiness() const { return Diffuse_Bumpiness; }
private:
static ShdVersion Version;
bool Save_Variables(ChunkSaveClass &csave);
bool Load_Variables(ChunkLoadClass &cload);
StringClass TextureName;
StringClass BumpMapName;
Vector3 Ambient;
Vector3 Diffuse;
Vector2 Diffuse_Bumpiness;
};
#endif //SHDBUMPDIFF_H

View File

@@ -0,0 +1,236 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/shdbumpspec.cpp $*
* *
* $Author:: Kenny_m
*
* $Modtime:: 5/27/02 2:21p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "dx8fvf.h"
#include "dx8wrapper.h"
#include "assetmgr.h"
#include "shdbumpspec.h"
#include "shd6bumpspec.h"
#include "shd7bumpspec.h"
#include "shd8bumpspec.h"
#include "editable.h"
#include "shdclassids.h"
#include "shddeffactory.h"
#include "shdinterface.h"
#include "persistfactory.h"
#include "wwhack.h"
DECLARE_FORCE_LINK(BumpSpecShader);
REGISTER_SHDDEF(ShdBumpSpecDefClass,SHDDEF_CLASSID_BUMPSPEC,"Bump Specular");
// static member
ShdVersion ShdBumpSpecDefClass::Version;
// Save-Load methods for ShdDefClass
enum
{
CHUNKID_VARIABLES = 0x16490450,
VARID_TEXTURE_NAME = 0x00,
VARID_BUMP_MAP_NAME,
VARID_AMBIENT_COLOR,
VARID_DIFFUSE_COLOR,
VARID_SPECULAR_COLOR,
VARID_DIFFUSE_BUMPINESS,
VARID_SPECULAR_BUMPINESS
};
ShdBumpSpecDefClass::ShdBumpSpecDefClass()
: ShdDefClass(SHDDEF_CLASSID_BUMPSPEC),
Ambient(1,1,1),
Diffuse(1,1,1),
Specular(1,1,1),
Diffuse_Bumpiness(1,0),
Specular_Bumpiness(1,0)
{
NAMED_TEXTURE_FILENAME_PARAM(ShdBumpSpecDefClass, TextureName, "Base and Alpha Gloss Map", "Targa Files", ".tga");
NAMED_TEXTURE_FILENAME_PARAM(ShdBumpSpecDefClass, BumpMapName, "Bump Map", "Targa Files", ".tga");
NAMED_EDITABLE_PARAM(ShdBumpSpecDefClass, ParameterClass::TYPE_COLOR, Ambient, "Ambient");
NAMED_EDITABLE_PARAM(ShdBumpSpecDefClass, ParameterClass::TYPE_COLOR, Diffuse, "Diffuse");
NAMED_EDITABLE_PARAM(ShdBumpSpecDefClass, ParameterClass::TYPE_COLOR, Specular, "Specular");
NAMED_EDITABLE_PARAM(ShdBumpSpecDefClass, ParameterClass::TYPE_FLOAT, Diffuse_Bumpiness.X, "Diffuse Bump Scale");
NAMED_EDITABLE_PARAM(ShdBumpSpecDefClass, ParameterClass::TYPE_FLOAT, Diffuse_Bumpiness.Y, "Diffuse Bump Bias");
NAMED_EDITABLE_PARAM(ShdBumpSpecDefClass, ParameterClass::TYPE_FLOAT, Specular_Bumpiness.X, "Specular Bump Scale");
NAMED_EDITABLE_PARAM(ShdBumpSpecDefClass, ParameterClass::TYPE_FLOAT, Specular_Bumpiness.Y, "Specular Bump Bias");
}
ShdBumpSpecDefClass::ShdBumpSpecDefClass(const ShdBumpSpecDefClass& that)
: ShdDefClass(that),
Ambient(that.Ambient),
Diffuse(that.Diffuse),
Specular(that.Specular),
Diffuse_Bumpiness(that.Diffuse_Bumpiness),
Specular_Bumpiness(that.Specular_Bumpiness)
{
TextureName=that.TextureName;
BumpMapName=that.BumpMapName;
}
ShdBumpSpecDefClass::~ShdBumpSpecDefClass()
{
}
bool ShdBumpSpecDefClass::Is_Valid_Config(StringClass &message)
{
return true;
}
bool ShdBumpSpecDefClass::Save(ChunkSaveClass &csave)
{
ShdDefClass::Save(csave);
csave.Begin_Chunk(CHUNKID_VARIABLES);
bool retval = true;
// only save the file name
char fname[_MAX_PATH];
_splitpath(TextureName,NULL,NULL,fname,NULL);
strcat(fname,".tga");
TextureName=fname;
WRITE_MICRO_CHUNK_WWSTRING(csave, VARID_TEXTURE_NAME, TextureName);
_splitpath(BumpMapName,NULL,NULL,fname,NULL);
strcat(fname,".tga");
BumpMapName=fname;
WRITE_MICRO_CHUNK_WWSTRING(csave, VARID_BUMP_MAP_NAME, BumpMapName);
WRITE_MICRO_CHUNK(csave, VARID_AMBIENT_COLOR, Ambient);
WRITE_MICRO_CHUNK(csave, VARID_DIFFUSE_COLOR, Diffuse);
WRITE_MICRO_CHUNK(csave, VARID_SPECULAR_COLOR, Specular);
WRITE_MICRO_CHUNK(csave, VARID_DIFFUSE_BUMPINESS, Diffuse_Bumpiness);
WRITE_MICRO_CHUNK(csave, VARID_SPECULAR_BUMPINESS, Specular_Bumpiness);
csave.End_Chunk();
return retval;
}
bool ShdBumpSpecDefClass::Load(ChunkLoadClass &cload)
{
ShdDefClass::Load(cload);
// Loop through all the microchunks that define the variables
while (cload.Open_Chunk()) {
switch (cload.Cur_Chunk_ID())
{
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk())
{
switch (cload.Cur_Micro_Chunk_ID())
{
READ_MICRO_CHUNK_WWSTRING(cload, VARID_TEXTURE_NAME, TextureName);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_BUMP_MAP_NAME, BumpMapName);
READ_MICRO_CHUNK(cload, VARID_AMBIENT_COLOR, Ambient);
READ_MICRO_CHUNK(cload, VARID_DIFFUSE_COLOR, Diffuse);
READ_MICRO_CHUNK(cload, VARID_SPECULAR_COLOR, Specular);
READ_MICRO_CHUNK(cload, VARID_DIFFUSE_BUMPINESS, Diffuse_Bumpiness);
READ_MICRO_CHUNK(cload, VARID_SPECULAR_BUMPINESS, Specular_Bumpiness);
}
cload.Close_Micro_Chunk();
}
break;
default:
break;
}
cload.Close_Chunk();
}
return true;
}
void ShdBumpSpecDefClass::Init()
{
// select shader version
if ((DX8Wrapper::Get_Current_Caps()->Get_Pixel_Shader_Major_Version())==1 &&
(DX8Wrapper::Get_Current_Caps()->Get_Pixel_Shader_Minor_Version())>=1)
{
Version.Set(SHDVER_8);
}
else if (DX8Wrapper::Get_Current_Caps()->Support_Dot3())
{
Version.Set(SHDVER_7);
}
else
{
Version.Set(SHDVER_6);
}
switch (Version.Get())
{
case SHDVER_8 : Shd8BumpSpecClass::Init(); break;
case SHDVER_7 : Shd7BumpSpecClass::Init(); break;
case SHDVER_6 : Shd6BumpSpecClass::Init(); break;
}
}
void ShdBumpSpecDefClass::Shutdown()
{
switch (Version.Get())
{
case SHDVER_8 : Shd8BumpSpecClass::Shutdown(); break;
case SHDVER_7 : Shd7BumpSpecClass::Shutdown(); break;
case SHDVER_6 : Shd6BumpSpecClass::Shutdown(); break;
}
}
ShdInterfaceClass* ShdBumpSpecDefClass::Create() const
{
switch (Version.Get())
{
case SHDVER_8 : return new Shd8BumpSpecClass(this); break;
case SHDVER_7 : return new Shd7BumpSpecClass(this); break;
case SHDVER_6 : return new Shd6BumpSpecClass(this); break;
}
return NULL;
}

View File

@@ -0,0 +1,116 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/shdbumpspec.h $*
* *
* $Author:: Kenny_m
*
* $Modtime:: 5/27/02 2:21p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHDBUMPSPEC_H
#define SHDBUMPSPEC_H
#include "shddef.h"
#include "saveload.h"
class ShdBumpSpecDefClass : public ShdDefClass
{
public:
/////////////////////////////////////////////////////////////////////
// Editable interface requirements
/////////////////////////////////////////////////////////////////////
DECLARE_EDITABLE(ShdBumpSpecDefClass, ShdDefClass);
ShdBumpSpecDefClass();
ShdBumpSpecDefClass(const ShdBumpSpecDefClass& that);
virtual ~ShdBumpSpecDefClass();
virtual ShdDefClass* Clone() const { return new ShdBumpSpecDefClass(*this); }
// Shader Creation (should create a shader compatible with the current hardware/API)
virtual void Init();
virtual void Shutdown();
virtual ShdInterfaceClass* Create() const;
// Validation methods
virtual bool Is_Valid_Config(StringClass &message);
// Requirements
virtual bool Requires_Normals() const { return true; }
virtual bool Requires_Tangent_Space_Vectors() const { return true; }
virtual bool Requires_Sorting() const { return false; }
virtual int Static_Sort_Index() const { return 0; }
// From PersistClass
virtual bool Save(ChunkSaveClass &csave);
virtual bool Load(ChunkLoadClass &cload);
void Set_Texture_Name(const StringClass& name) { TextureName=name; }
const StringClass& Get_Texture_Name() const { return TextureName; }
void Set_Bump_Map_Name(const StringClass& name) { BumpMapName=name; }
const StringClass& Get_Bump_Map_Name() const { return BumpMapName; }
void Set_Ambient(const Vector3& ambient) { Ambient=ambient; }
const Vector3& Get_Ambient() const { return Ambient; }
void Set_Diffuse(const Vector3& diffuse) { Diffuse=diffuse; }
const Vector3& Get_Diffuse() const { return Diffuse; }
void Set_Specular(const Vector3& specular) { Specular=specular; }
const Vector3& Get_Specular() const { return Specular; }
void Set_Diffuse_Bumpiness(const Vector2& diffuse_bumpiness) { Diffuse_Bumpiness=diffuse_bumpiness; }
const Vector2& Get_Diffuse_Bumpiness() const { return Diffuse_Bumpiness; }
void Set_Specular_Bumpiness(const Vector2& specular_bumpiness) { Specular_Bumpiness=specular_bumpiness; }
const Vector2& Get_Specular_Bumpiness() const { return Specular_Bumpiness; }
private:
static ShdVersion Version;
bool Save_Variables(ChunkSaveClass &csave);
bool Load_Variables(ChunkLoadClass &cload);
StringClass TextureName;
StringClass BumpMapName;
Vector3 Ambient;
Vector3 Diffuse;
Vector3 Specular;
Vector2 Diffuse_Bumpiness;
Vector2 Specular_Bumpiness;
};
#endif //SHDBUMPSPEC_H

View File

@@ -0,0 +1,70 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shdclassids.h $*
* *
* $Org Author:: Jani_p
*
* $Author:: Kenny_m
*
* $Modtime:: 8/01/02 3:12p $*
* *
* $Revision:: 4 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHDCLASSIDS_H
#define SHDCLASSIDS_H
/*
** ClassID's for Shader Definitions
*/
enum
{
SHDDEF_CLASSID_DUMMY = 0,
SHDDEF_CLASSID_SIMPLE,
SHDDEF_CLASSID_GLOSSMASK,
SHDDEF_CLASSID_BUMPSPEC,
SHDDEF_CLASSID_BUMPDIFF,
SHDDEF_CLASSID_CUBEMAP,
SHDDEF_CLASSID_LEGACYW3D,
SHDDEF_CLASSID_LAST,
};
/*
** ClassID's for actual Shader Implementations (typically there will be several for each "type", one
** for each hardware configuration...)
*/
enum
{
SHD_CLASSID_DUMMY = 0,
SHD_CLASSID_LAST,
};
#endif //SHDCLASSIDS_H

View File

@@ -0,0 +1,328 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shdcubemap.cpp $*
* *
* $Org Author:: Kenny_m
*
* $Author:: Kenny_m
*
* $Modtime:: 8/01/02 3:12p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Currently unsupported due to cube map texture management needed by W3D
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <d3dx8math.h>
#include "dx8fvf.h"
#include "dx8wrapper.h"
#include "assetmgr.h"
#include "shdcubemap.h"
#include "editable.h"
#include "shdclassids.h"
#include "shddeffactory.h"
#include "shdinterface.h"
#include "shdhwshader.h"
#include "persistfactory.h"
#include "wwhack.h"
DECLARE_FORCE_LINK(CubeMapShader);
REGISTER_SHDDEF(ShdCubeMapDefClass,SHDDEF_CLASSID_CUBEMAP,"Cube Map");
// Save-Load methods for ShdDefClass
enum
{
CHUNKID_VARIABLES = 0x16490470,
VARID_TEXTURE_NAME = 0x00,
VARID_AMBIENT_COLOR,
VARID_DIFFUSE_COLOR,
VARID_SPECULAR_COLOR
};
ShdCubeMapDefClass::ShdCubeMapDefClass()
: ShdDefClass(SHDDEF_CLASSID_CUBEMAP),
Ambient(1,1,1),
Diffuse(1,1,1),
Specular(0,0,0)
{
NAMED_TEXTURE_FILENAME_PARAM(ShdCubeMapDefClass, TextureName, "Texture Name", "Targa Files", ".tga");
NAMED_EDITABLE_PARAM(ShdCubeMapDefClass, ParameterClass::TYPE_COLOR, Ambient, "Ambient");
NAMED_EDITABLE_PARAM(ShdCubeMapDefClass, ParameterClass::TYPE_COLOR, Diffuse, "Diffuse");
NAMED_EDITABLE_PARAM(ShdCubeMapDefClass, ParameterClass::TYPE_COLOR, Specular, "Specular");
}
ShdCubeMapDefClass::ShdCubeMapDefClass(const ShdCubeMapDefClass& that)
: ShdDefClass(that),
Ambient(that.Ambient),
Diffuse(that.Diffuse),
Specular(that.Specular)
{
TextureName=that.TextureName;
}
ShdCubeMapDefClass::~ShdCubeMapDefClass()
{
}
bool ShdCubeMapDefClass::Is_Valid_Config(StringClass &message)
{
return true;
}
bool ShdCubeMapDefClass::Save(ChunkSaveClass &csave)
{
ShdDefClass::Save(csave);
csave.Begin_Chunk(CHUNKID_VARIABLES);
bool retval = true;
// only save the file name
char fname[_MAX_PATH];
_splitpath(TextureName,NULL,NULL,fname,NULL);
strcat(fname,".dds");
TextureName=fname;
WRITE_MICRO_CHUNK_WWSTRING(csave, VARID_TEXTURE_NAME, TextureName);
WRITE_MICRO_CHUNK(csave, VARID_AMBIENT_COLOR, Ambient);
WRITE_MICRO_CHUNK(csave, VARID_DIFFUSE_COLOR, Diffuse);
WRITE_MICRO_CHUNK(csave, VARID_SPECULAR_COLOR, Specular);
csave.End_Chunk();
return retval;
}
bool ShdCubeMapDefClass::Load(ChunkLoadClass &cload)
{
ShdDefClass::Load(cload);
// Loop through all the microchunks that define the variables
while (cload.Open_Chunk()) {
switch (cload.Cur_Chunk_ID())
{
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk())
{
switch (cload.Cur_Micro_Chunk_ID())
{
READ_MICRO_CHUNK_WWSTRING(cload, VARID_TEXTURE_NAME, TextureName);
READ_MICRO_CHUNK(cload, VARID_AMBIENT_COLOR, Ambient);
READ_MICRO_CHUNK(cload, VARID_DIFFUSE_COLOR, Diffuse);
READ_MICRO_CHUNK(cload, VARID_SPECULAR_COLOR, Specular);
}
cload.Close_Micro_Chunk();
}
break;
default:
break;
}
cload.Close_Chunk();
}
return true;
}
void ShdCubeMapDefClass::Init()
{
Shd6CubeMapClass::Init();
}
void ShdCubeMapDefClass::Shutdown()
{
Shd6CubeMapClass::Shutdown();
}
ShdInterfaceClass* ShdCubeMapDefClass::Create() const
{
return new Shd6CubeMapClass(this);
}
Matrix4x4 Shd6CubeMapClass::View_Projection_Matrix;
Shd6CubeMapClass::Shd6CubeMapClass(const ShdDefClass* def)
: ShdInterfaceClass(def,SHDDEF_CLASSID_CUBEMAP),
Texture(NULL)
{
ShdCubeMapDefClass* Definition=(ShdCubeMapDefClass*)def;
Texture=WW3DAssetManager::Get_Instance()->Get_Texture
(
Definition->Get_Texture_Name(),
MIP_LEVELS_ALL,
WW3D_FORMAT_UNKNOWN,
true,
TextureBaseClass::TEX_CUBEMAP
);
const Vector3& a=Definition->Get_Ambient();
Ambient.Set(a.X,a.Y,a.Z,1.0f);
const Vector3& d=Definition->Get_Diffuse();
Diffuse.Set(d.X,d.Y,d.Z,1.0f);
const Vector3& s=Definition->Get_Specular();
Specular.Set(s.X,s.Y,s.Z,1.0f);
Material=new D3DMATERIAL8;
memset(Material,0,sizeof(D3DMATERIAL8));
Material->Ambient.r=a.X; Material->Ambient.g=a.Y; Material->Ambient.b=a.Z;
Material->Diffuse.r=d.X; Material->Diffuse.g=d.Y; Material->Diffuse.b=d.Z;
Material->Specular.r=s.X; Material->Specular.g=s.Y; Material->Specular.b=s.Z;
Material->Power=20;
}
Shd6CubeMapClass::~Shd6CubeMapClass()
{
REF_PTR_RELEASE(Texture);
}
void Shd6CubeMapClass::Init()
{
}
void Shd6CubeMapClass::Shutdown()
{
}
/**********************************************************************************************
//! Apply shared states for 1 pass DX6
/*! 7/12/02 3:39p KJM Created
*/
void Shd6CubeMapClass::Apply_Shared(int pass, RenderInfoClass& rinfo)
{
// fixed function uses pass through by default
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
// set vertex shader
DX8Wrapper::Set_Vertex_Shader(DX8_FVF_XYZNDCUBEMAP);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Render_State(D3DRS_LIGHTING, TRUE);
DX8Wrapper::Set_DX8_Render_State(D3DRS_SPECULARENABLE, TRUE);
DX8Wrapper::Set_DX8_Render_State(D3DRS_AMBIENTMATERIALSOURCE,D3DMCS_MATERIAL);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DIFFUSEMATERIALSOURCE,D3DMCS_MATERIAL);
DX8Wrapper::Set_DX8_Render_State(D3DRS_SPECULARMATERIALSOURCE,D3DMCS_MATERIAL);
DX8Wrapper::Set_DX8_Render_State(D3DRS_EMISSIVEMATERIALSOURCE,D3DMCS_MATERIAL);
DX8Wrapper::Set_DX8_Material(Material);
}
//**********************************************************************************************
//! Apply per instance states for 1 pass DX6
/*! 7/10/02 5:39p KJM Created
*/
void Shd6CubeMapClass::Apply_Instance(int cur_pass, RenderInfoClass& rinfo)
{
DX8Wrapper::Set_Texture(0, Texture);
}
unsigned Shd6CubeMapClass::Get_Vertex_Stream_Count() const
{
return 1;
}
unsigned Shd6CubeMapClass::Get_Vertex_Size(unsigned stream) const
{
return sizeof(VertexFormatXYZNDCUBEMAP);
}
void Shd6CubeMapClass::Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
)
{
VertexFormatXYZNDCUBEMAP* verts=(VertexFormatXYZNDCUBEMAP*)dest_buffer;
for (unsigned i=0; i<vertex_count; ++i)
{
if (vss.Locations)
{
verts[i].x=vss.Locations[i][0];
verts[i].y=vss.Locations[i][1];
verts[i].z=vss.Locations[i][2];
}
else
{
verts[i].x=0.0f;
verts[i].y=0.0f;
verts[i].z=0.0f;
}
if (vss.DiffuseInt)
{
verts[i].diffuse=vss.DiffuseInt[i];
}
else
{
verts[i].diffuse=0xffffffff;
}
if (vss.Normals)
{
verts[i].nx=vss.Normals[i][0];
verts[i].ny=vss.Normals[i][1];
verts[i].nz=vss.Normals[i][2];
}
else
{
verts[i].nx=0.0f;
verts[i].ny=0.0f;
verts[i].nz=0.0f;
}
}
}

View File

@@ -0,0 +1,152 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shdcubemap.cpp $*
* *
* $Org Author:: Kenny_m
*
* $Author:: Kenny_m
*
* $Modtime:: 8/01/02 3:12p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHDCUBEMAP_H
#define SHDCUBEMAP_H
#ifndef SHDINTERFACE_H
#include "shdinterface.h"
#endif
#include "shddef.h"
#include "saveload.h"
#include "shader.h"
class ShdCubeMapDefClass : public ShdDefClass
{
public:
/////////////////////////////////////////////////////////////////////
// Editable interface requirements
/////////////////////////////////////////////////////////////////////
DECLARE_EDITABLE(ShdCubeMapDefClass, ShdDefClass);
ShdCubeMapDefClass();
ShdCubeMapDefClass(const ShdCubeMapDefClass& that);
virtual ~ShdCubeMapDefClass();
virtual ShdDefClass* Clone() const { return new ShdCubeMapDefClass(*this); }
// Shader Creation (should create a shader compatible with the current hardware/API)
virtual void Init();
virtual void Shutdown();
virtual ShdInterfaceClass* Create() const;
// Validation methods
virtual bool Is_Valid_Config(StringClass &message);
// Requirements
virtual bool Requires_Normals() const { return true; }
virtual bool Requires_Tangent_Space_Vectors() const { return false; }
virtual bool Requires_Sorting() const { return false; }
virtual int Static_Sort_Index() const { return 0; }
// From PersistClass
virtual bool Save(ChunkSaveClass &csave);
virtual bool Load(ChunkLoadClass &cload);
void Set_Texture_Name(const StringClass& name) { TextureName=name; }
const StringClass& Get_Texture_Name() const { return TextureName; }
void Set_Ambient(const Vector3& ambient) { Ambient=ambient; }
const Vector3& Get_Ambient() const { return Ambient; }
void Set_Diffuse(const Vector3& diffuse) { Diffuse=diffuse; }
const Vector3& Get_Diffuse() const { return Diffuse; }
void Set_Specular(const Vector3& specular) { Specular=specular; }
const Vector3& Get_Specular() const { return Specular; }
private:
bool Save_Variables(ChunkSaveClass &csave);
bool Load_Variables(ChunkLoadClass &cload);
StringClass TextureName;
Vector3 Ambient;
Vector3 Diffuse;
Vector3 Specular;
};
class Shd6CubeMapClass : public ShdInterfaceClass
{
public:
Shd6CubeMapClass(const ShdDefClass* def);
virtual ~Shd6CubeMapClass();
static void Init();
static void Shutdown();
virtual int Get_Pass_Count() { return 1; }
virtual int Get_Texture_Count() const { return 1; }
virtual TextureClass* Peek_Texture(int idx) const { return NULL; }
virtual void Apply_Shared(int cur_pass, RenderInfoClass& rinfo);
virtual void Apply_Instance(int cur_pass, RenderInfoClass& rinfo);
virtual unsigned Get_Vertex_Stream_Count() const;
virtual unsigned Get_Vertex_Size(unsigned stream) const;
virtual bool Use_HW_Vertex_Processing() const { return true; }
virtual void Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
);
protected:
static Matrix4x4 View_Projection_Matrix;
D3DMATERIAL8* Material;
TextureClass* Texture;
Vector4 Ambient;
Vector4 Diffuse;
Vector4 Specular;
};
#endif //SHDCUBEMAP_H

View File

@@ -0,0 +1,216 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shddef.cpp $*
* *
* $Org Author:: Jani_p
*
* $Author:: Kenny_m
*
* $Modtime:: 6/07/02 3:12p $*
* *
* $Revision:: 2 $*
* *
* 6/07/02 KJM : Added validation enum
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "shddef.h"
#include "chunkio.h"
#include "w3d_file.h"
ShdDefClass::ShdDefClass(uint32 classid) :
ClassID(classid),
Name("UnNamed"),
SurfaceType(0)
{
ENUM_PARAM (
ShdDefClass, SurfaceType,
(
"Light Metal", SURFACE_TYPE_LIGHT_METAL,
"Heavy Metal", SURFACE_TYPE_HEAVY_METAL,
"Water", SURFACE_TYPE_WATER,
"Sand", SURFACE_TYPE_SAND,
"Dirt", SURFACE_TYPE_DIRT,
"Mud", SURFACE_TYPE_MUD,
"Grass", SURFACE_TYPE_GRASS,
"Wood", SURFACE_TYPE_WOOD,
"Concrete", SURFACE_TYPE_CONCRETE,
"Flesh", SURFACE_TYPE_FLESH,
"Rock", SURFACE_TYPE_ROCK,
"Snow", SURFACE_TYPE_SNOW,
"Ice", SURFACE_TYPE_ICE,
"Default", SURFACE_TYPE_DEFAULT,
"Glass", SURFACE_TYPE_GLASS,
"Cloth", SURFACE_TYPE_CLOTH,
"Tiberium Field", SURFACE_TYPE_TIBERIUM_FIELD,
"Foliage Permeable", SURFACE_TYPE_FOLIAGE_PERMEABLE,
"Glass Permeable", SURFACE_TYPE_GLASS_PERMEABLE,
"Ice Permeable", SURFACE_TYPE_ICE_PERMEABLE,
"Cloth Permeable", SURFACE_TYPE_CLOTH_PERMEABLE,
"Electrical", SURFACE_TYPE_ELECTRICAL,
"Electrical Permeable", SURFACE_TYPE_ELECTRICAL_PERMEABLE,
"Flammable", SURFACE_TYPE_FLAMMABLE,
"Flammable Permeable", SURFACE_TYPE_FLAMMABLE_PERMEABLE ,
"Steam", SURFACE_TYPE_STEAM,
"Steam Permeable", SURFACE_TYPE_STEAM_PERMEABLE,
"Water Permeable", SURFACE_TYPE_WATER_PERMEABLE,
"Tiberium Water", SURFACE_TYPE_TIBERIUM_WATER,
"Tiberium Water Permeable", SURFACE_TYPE_TIBERIUM_WATER_PERMEABLE,
"Underwater Dirt", SURFACE_TYPE_UNDERWATER_DIRT,
"Underwater Tiberium Dirt", SURFACE_TYPE_UNDERWATER_TIBERIUM_DIRT,
NULL
)
);
}
ShdDefClass::ShdDefClass(const ShdDefClass & that):
ClassID(that.ClassID),
Name(that.Name),
SurfaceType(that.SurfaceType)
{
}
ShdDefClass::~ShdDefClass(void)
{
}
const char * ShdDefClass::Get_Name (void) const
{
return Name;
}
void ShdDefClass::Set_Name (const char *new_name)
{
Name = new_name;
}
void ShdDefClass::Reset(void)
{
SurfaceType = 0;
}
/*******************************************************************************
**
** Save-Load methods for ShdDefClass
**
*******************************************************************************/
enum
{
CHUNKID_VARIABLES = 0x16490430,
VARID_NAME = 0x00,
VARID_SURFACETYPE,
};
//**********************************************************************************************
//! Serialize this ShdDef into a chunk saver
/*!
@param csave - ChunkSave object to write into
*/
bool ShdDefClass::Save (ChunkSaveClass &csave)
{
bool retval=true;
csave.Begin_Chunk(CHUNKID_VARIABLES);
retval=Save_Variables(csave);
csave.End_Chunk ();
return retval;
}
//**********************************************************************************************
//! Load this ShdDef from a chunk loader
/*!
@param cload - ChunkLoad object to read from
*/
bool ShdDefClass::Load (ChunkLoadClass &cload)
{
bool retval = true;
cload.Open_Chunk();
retval=cload.Cur_Chunk_ID()==CHUNKID_VARIABLES;
Load_Variables(cload);
cload.Close_Chunk();
return retval;
}
//**********************************************************************************************
//! Save the variables for this object
/*!
Each variable is stored in its own "micro-chunk" for flexibility.
@param csave - chunk saver to write to.
*/
bool ShdDefClass::Save_Variables (ChunkSaveClass &csave)
{
bool retval = true;
WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_NAME, Name);
WRITE_MICRO_CHUNK (csave, VARID_SURFACETYPE, SurfaceType);
return retval;
}
//**********************************************************************************************
//! Load the variables for this object from a chunk
/*!
@param cload - chunk loader to read from
*/
bool ShdDefClass::Load_Variables (ChunkLoadClass &cload)
{
bool retval = true;
//
// Loop through all the microchunks that define the variables
//
while (cload.Open_Micro_Chunk ())
{
switch (cload.Cur_Micro_Chunk_ID ())
{
READ_MICRO_CHUNK_WWSTRING (cload, VARID_NAME, Name);
READ_MICRO_CHUNK (cload, VARID_SURFACETYPE, SurfaceType);
}
cload.Close_Micro_Chunk();
}
return retval;
}

View File

@@ -0,0 +1,140 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shddef.h $*
* *
* $Org Author:: Jani_p
*
* $Author:: Kenny_m
*
* $Modtime:: 6/07/02 3:12p $*
* *
* $Revision:: 2 $*
* *
* 6/07/02 KJM : Added validation enum
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHDDEF_H
#define SHDDEF_H
#include "always.h"
#include "editable.h"
#include "refcount.h"
class ShdInterfaceClass;
enum SHDVER
{
SHDVER_UNDEFINED=0,
SHDVER_6,
SHDVER_7,
SHDVER_8
};
class ShdVersion
{
public:
ShdVersion() : Version(SHDVER_UNDEFINED) {}
void Set(const SHDVER ver) { Version=ver; }
SHDVER Get() const { return Version; }
private:
SHDVER Version;
};
/**
** ShdDefClass - This class is the base class for all shader "definition" objects.
**
** A shader definition object has two responsibilities.
**
** - It contains a "generic" description (chars, ints, floats, etc) of all of the user-settable parameters used
** by an instance of this type of shader (e.g. what textures it uses, colors, etc).
**
** - It contains a virtual "Create" function which can create an actual shader for you. This function is an
** abstract factory which creates a shader implementation compatible with the current hardware the application
** is running on.
*/
class ShdDefClass : public EditableClass, public RefCountClass
{
public:
DECLARE_EDITABLE(ShdDefClass, EditableClass);
ShdDefClass(uint32 class_id);
ShdDefClass(const ShdDefClass & that);
virtual ~ShdDefClass(void);
virtual ShdDefClass * Clone(void) const = 0;
virtual void Reset(void);
// Run-Time Type identification (ID's defined in "shdclassids.h")
WWINLINE uint32 Get_Class_ID (void) const { return ClassID; }
// Shader Management & Creation (should create a shader compatible with the current hardware/API)
virtual void Init()=0;
virtual void Shutdown()=0;
virtual ShdInterfaceClass * Create (void) const = 0;
// Name methods
const char * Get_Name (void) const;
void Set_Name (const char *new_name);
// Surface type, used for decal, sound, and emitter creation
int Get_Surface_Type(void) const { return SurfaceType; }
void Set_Surface_Type(int t) { SurfaceType = t; }
// Validation methods
virtual bool Is_Valid_Config (StringClass &message) { return true; }
// Requirements PRELIMINARY, NEED TO VALIDATE THIS PART OF THE INTERFACE!!!
virtual bool Uses_Vertex_Alpha(void) const { return false; }
virtual bool Uses_UV_Channel(int i) const { return (i==0); }
virtual bool Uses_Vertex_Colors(void) const { return false; }
virtual bool Requires_Normals(void) const { return false; }
virtual bool Requires_Tangent_Space_Vectors(void) const { return false; }
virtual bool Requires_Sorting(void) const { return false; }
virtual int Static_Sort_Index(void) const { return 0; }
// From PersistClass
virtual bool Save (ChunkSaveClass &csave);
virtual bool Load (ChunkLoadClass &cload);
private:
bool Save_Variables (ChunkSaveClass &csave);
bool Load_Variables (ChunkLoadClass &cload);
uint32 ClassID;
StringClass Name;
int SurfaceType;
};
#endif //SHDDEF_H

View File

@@ -0,0 +1,74 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shddeffactory.cpp $*
* *
* $Org Author:: Jani_p
*
* $Author:: Kenny_m
*
* $Modtime:: 6/01/02 3:12p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "shddeffactory.h"
#include "shddefmanager.h"
/*
**
** ShdDefFactory Implementation
**
*/
//**********************************************************************************************
//! Constructor for ShdDefFactoryClass
/*!
Automatically registers this instance of the ShdDefFactory with the manager.
*/
ShdDefFactoryClass::ShdDefFactoryClass (void) :
NextFactory(NULL),
PrevFactory(NULL)
{
ShdDefManagerClass::Register_Factory (this);
}
//**********************************************************************************************
//! Destructor for ShdDefFactoryClass
/*!
Automatically un-registers this instance of a ShdDefFactory from the manager.
*/
ShdDefFactoryClass::~ShdDefFactoryClass (void)
{
ShdDefManagerClass::Unregister_Factory (this);
}

View File

@@ -0,0 +1,115 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shddeffactory.h $*
* *
* $Org Author:: Jani_p
*
* $Author:: Kenny_m
*
* $Modtime:: 6/01/02 3:12p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHDDEFFACTORY_H
#define SHDDEFFACTORY_H
#include "always.h"
#include "bittype.h"
class ShdDefClass;
/*
** NOTE: For most users, the only thing you need from this module is the REGISTER_SHDDEF(T,ID,NAME) macro
*/
/**
** ShdDefFactoryClass - An instance of this class is used to automatically register
** each unique type of ShdDefClass with the system. This object is responsible for
** creating shader definitions. All existing 'DefFactories' can be iterated over
** and presented to the user in a menu.
*/
class ShdDefFactoryClass
{
public:
ShdDefFactoryClass (void);
virtual ~ShdDefFactoryClass (void);
//////////////////////////////////////////////////////////////
// Public methods
//////////////////////////////////////////////////////////////
virtual ShdDefClass * Create (void) const = 0;
virtual const char * Get_Name (void) const = 0;
virtual uint32 Get_Class_ID (void) const = 0;
protected:
//////////////////////////////////////////////////////////////
// Protected member data
//////////////////////////////////////////////////////////////
ShdDefFactoryClass * NextFactory;
ShdDefFactoryClass * PrevFactory;
friend class ShdDefManagerClass;
};
/**
** SimpleShdDefFactoryClass - This template automates the process of creating a ShdDefFactory.
** For complete ease of use, the associated REGISTER_SHDDEF macro can be used in the cpp file
** of your shader definition.
** Macro useage example (in the cpp file for your shader definition):
** REGISTER_SHDDEF(MyShdDefClass, MYSHDDEF_CLASSID, "Greg's super-fancy shader");
*/
template<class T, int class_id, char *name> class SimpleShdDefFactoryClass : public ShdDefFactoryClass
{
public:
SimpleShdDefFactoryClass (void) { }
virtual ~SimpleShdDefFactoryClass (void) { }
//////////////////////////////////////////////////////////////
// Public methods
//////////////////////////////////////////////////////////////
virtual ShdDefClass * Create (void) const { return new T; }
virtual const char * Get_Name (void) const { return name; }
virtual uint32 Get_Class_ID (void) const { return class_id; }
};
/*
** Use this macro in the .CPP file for your shader definition to automatically link it
** into the shader editing system.
*/
#define REGISTER_SHDDEF(T,ID,NAME) \
char T ## Name[] = NAME; \
SimpleShdDefFactoryClass<T,ID,T ## Name> T ## Factory \
#endif //SHDDEFFACTORY_H

View File

@@ -0,0 +1,250 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shddefmanager.cpp $*
* *
* $Org Author:: Jani_p
*
* $Author:: Kenny_m
*
* $Modtime:: 5/20/02 3:12p $*
* *
* $Revision:: 2 $*
* *
* 5/20/02 KM Added save load behavior
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "w3d_file.h"
#include "chunkio.h"
#include "shddef.h"
#include "shddefmanager.h"
#include "shddeffactory.h"
#include "wwdebug.h"
#include "string.h"
/*
** Static head of the factory list
*/
ShdDefFactoryClass *ShdDefManagerClass::_FactoryListHead = NULL;
//**********************************************************************************************
//! Used to look up the ShdDefFactory for a given class id
/*!
@param class_id - class id to look up the factory for
@returns the factory if it is found or NULL
*/
ShdDefFactoryClass *
ShdDefManagerClass::Find_Factory (uint32 class_id)
{
ShdDefFactoryClass *factory = 0;
//
// Loop through all the factories and see if we can
// find the one who owns the corresponding class-id.
//
for ( ShdDefFactoryClass *curr_factory = _FactoryListHead;
(factory == 0) && (curr_factory != 0);
curr_factory = curr_factory->NextFactory)
{
//
// Is this the factory we were looking for?
//
if (curr_factory->Get_Class_ID () == class_id) {
factory = curr_factory;
}
}
return factory;
}
//**********************************************************************************************
//! Used to look up the ShdDefFactory for a given named shader def
/*!
@param name - name of the desired shader def
@returns the factory if it is found or NULL if not
*/
ShdDefFactoryClass * ShdDefManagerClass::Find_Factory (const char *name)
{
ShdDefFactoryClass * factory = 0;
//
// Loop through all the factories and see if we can
// find the one who owns the corresponding class-id.
//
for ( ShdDefFactoryClass *curr_factory = _FactoryListHead;
(factory == 0) && (curr_factory != 0);
curr_factory = curr_factory->NextFactory) {
//
// Is this the factory we were looking for?
//
if (::stricmp (curr_factory->Get_Name (), name) == 0) {
factory = curr_factory;
}
}
return factory;
}
//**********************************************************************************************
//! Registers a factory with the system
/*!
@param factory - the factory to register
*/
void ShdDefManagerClass::Register_Factory (ShdDefFactoryClass *factory)
{
WWASSERT (factory->NextFactory == 0);
WWASSERT (factory->PrevFactory == 0);
Link_Factory (factory);
}
//**********************************************************************************************
//! removes a factory from the system
/*!
@param factory - the factory to unregister
*/
void ShdDefManagerClass::Unregister_Factory (ShdDefFactoryClass *factory)
{
WWASSERT (factory != 0);
Unlink_Factory (factory);
return ;
}
ShdDefFactoryClass * ShdDefManagerClass::Get_First (void)
{
return _FactoryListHead;
}
ShdDefFactoryClass * ShdDefManagerClass::Get_Next (ShdDefFactoryClass *current)
{
//
// Simply return the next factory in the chain
//
if (current != NULL) {
return current->NextFactory;
}
return _FactoryListHead;
}
void ShdDefManagerClass::Link_Factory (ShdDefFactoryClass *factory)
{
WWASSERT (factory->NextFactory == 0);
WWASSERT (factory->PrevFactory == 0);
// Adding this factory in front of the current head of the list
factory->NextFactory = _FactoryListHead;
// If the list wasn't empty, link the next factory back to this factory
if (factory->NextFactory != 0) {
factory->NextFactory->PrevFactory = factory;
}
// Point the head of the list at this factory now
_FactoryListHead = factory;
return ;
}
void ShdDefManagerClass::Unlink_Factory (ShdDefFactoryClass *factory)
{
WWASSERT(factory != 0);
// Handle the factory's prev pointer:
if (factory->PrevFactory == 0) {
// this factory is the head
WWASSERT (_FactoryListHead == factory);
_FactoryListHead = factory->NextFactory;
} else {
// link it's prev with it's next
factory->PrevFactory->NextFactory = factory->NextFactory;
}
// Handle the factory's next pointer if its not at the end of the list:
if (factory->NextFactory != 0) {
factory->NextFactory->PrevFactory = factory->PrevFactory;
}
// factory is now un-linked
factory->NextFactory = 0;
factory->PrevFactory = 0;
return ;
}
ShdDefClass* ShdDefManagerClass::Create_ShdDefClass_Instance(uint32 class_id)
{
// first look up the factory for this classid
ShdDefFactoryClass * factory = Find_Factory (class_id);
if (factory != NULL)
{
return factory->Create();
}
else
{
return NULL;
}
}
void ShdDefManagerClass::Save_Shader(ChunkSaveClass& csave, ShdDefClass* shddef)
{
csave.Begin_Chunk(W3D_CHUNK_SHDSUBMESH_SHADER_CLASSID);
uint32 id=shddef->Get_Class_ID();
csave.Write(&id,sizeof(uint32));
csave.End_Chunk();
csave.Begin_Chunk(W3D_CHUNK_SHDSUBMESH_SHADER_DEF);
shddef->Save(csave);
csave.End_Chunk();
}
void ShdDefManagerClass::Load_Shader(ChunkLoadClass& cload, ShdDefClass** shddef)
{
uint32 id;
cload.Open_Chunk();
cload.Read(&id,sizeof(uint32));
cload.Close_Chunk();
*shddef=Create_ShdDefClass_Instance(id);
cload.Open_Chunk();
(*shddef)->Load(cload);
cload.Close_Chunk();
}

View File

@@ -0,0 +1,91 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shddefmanager.h $*
* *
* $Org Author:: Jani_p
*
* $Author:: Kenny_m
*
* $Modtime:: 5/20/02 3:12p $*
* *
* $Revision:: 2 $*
* *
* 5/20/02 KM Added save load behavior
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHDDEFMANAGER_H
#define SHDDEFMANAGER_H
#include "always.h"
#include "bittype.h"
class ShdDefClass;
class ShdDefFactoryClass;
class ChunkSaveClass;
class ChunkLoadClass;
/**
** ShdDefManagerClass - This class contains a list of all constructed ShdDefFactories.
** This class is used to iterate through the shader definition factories in the material
** editor for example.
*/
class ShdDefManagerClass
{
public:
static ShdDefFactoryClass * Find_Factory (uint32 class_id);
static ShdDefFactoryClass * Find_Factory (const char *name);
static void Register_Factory (ShdDefFactoryClass *factory);
static void Unregister_Factory (ShdDefFactoryClass *factory);
// Class enumeration
static ShdDefFactoryClass * Get_First (uint32 superclass_id);
static ShdDefFactoryClass * Get_Next (ShdDefFactoryClass *current, uint32 superclass_id);
// Factory enumeration
static ShdDefFactoryClass * Get_First (void);
static ShdDefFactoryClass * Get_Next (ShdDefFactoryClass *current);
// Construction
static ShdDefClass * Create_ShdDefClass_Instance(uint32 class_id);
// save/load
static void Save_Shader(ChunkSaveClass& csave, ShdDefClass* shddef);
static void Load_Shader(ChunkLoadClass& cload, ShdDefClass** shddef);
private:
static void Link_Factory (ShdDefFactoryClass *factory);
static void Unlink_Factory (ShdDefFactoryClass *factory);
static ShdDefFactoryClass * _FactoryListHead;
};
#endif SHDDEFMANAGER_H

View File

@@ -0,0 +1,70 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shddump.h $*
* *
* $Org Author:: Kenny_m
*
* $Author:: Kenny_m
*
* $Modtime:: 8/05/02 3:12p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
// header file for use in wdump util only
#ifndef SHDDUMP_H
#define SHDDUMP_H
#ifndef SHDCLASSIDS_H
#include "shdclassids.h"
#endif
const char* Shader_ClassIDs[SHDDEF_CLASSID_LAST]=
{
"SHDDEF_CLASSID_DUMMY",
"SHDDEF_CLASSID_SIMPLE",
"SHDDEF_CLASSID_GLOSSMASK",
"SHDDEF_CLASSID_BUMPSPEC",
"SHDDEF_CLASSID_BUMPDIFF",
"SHDDEF_CLASSID_CUBEMAP"
};
struct ShdDef_ChunkStruct
{
DWORD DefChunkId;
char Pad0[6];
char DefName[8];
char Pad1[2];
int SurfaceType;
DWORD ShdChunkId;
char Pad2[6];
char TexName[];
};
#endif //SHDDUMP_H

View File

@@ -0,0 +1,62 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : wwshade *
* *
* $Archive:: \code\wwshade\shdforcelinks.cpp $*
* *
* Org Author:: Patrick Smith *
* *
* Author:: Kenny Mitchell *
* *
* $Modtime:: 6/27/2002 4:28p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "shdforcelinks.h"
#include "wwhack.h"
/////////////////////////////////////////////////////////////////////////////
//
// SHD_Force_Links
//
/////////////////////////////////////////////////////////////////////////////
void SHD_Force_Links ()
{
//
// Force-link those modules that would be "linked-out" of the static lib
// because they are not directly referenced.
//
FORCE_LINK (SimpleShader);
FORCE_LINK (GlossMaskShader);
FORCE_LINK (BumpSpecShader);
FORCE_LINK (BumpDiffShader);
FORCE_LINK (CubeMapShader);
FORCE_LINK (LegacyW3DShader);
return ;
}

View File

@@ -0,0 +1,53 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : wwshade *
* *
* $Archive:: \code\wwshade\shdforcelinks.h $*
* *
* Org Author:: Patrick Smith *
* *
* Author:: Kenny Mitchell *
* *
* $Modtime:: 6/27/2002 4:28p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __SHDFORCELINKS_H
#define __SHDFORCELINKS_H
//////////////////////////////////////////////////////////////////////
// Function prototypes
//////////////////////////////////////////////////////////////////////
void SHD_Force_Links();
#endif //__SHDFORCELINKS_H

View File

@@ -0,0 +1,363 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shdglossmask.cpp $*
* *
* $Org Author:: Kenny_m
*
* $Author:: Kenny_m
*
* $Modtime:: 8/01/02 11:39a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <d3dx8math.h>
#include "dx8fvf.h"
#include "dx8wrapper.h"
#include "assetmgr.h"
#include "shdglossmask.h"
#include "editable.h"
#include "shdclassids.h"
#include "shddeffactory.h"
#include "shdinterface.h"
#include "shdhwshader.h"
#include "persistfactory.h"
#include "wwhack.h"
DECLARE_FORCE_LINK(GlossMaskShader);
REGISTER_SHDDEF(ShdGlossMaskDefClass,SHDDEF_CLASSID_GLOSSMASK,"Gloss Mask");
// Save-Load methods for ShdDefClass
enum
{
CHUNKID_VARIABLES = 0x16490460,
VARID_TEXTURE_NAME = 0x00,
VARID_AMBIENT_COLOR,
VARID_DIFFUSE_COLOR,
VARID_SPECULAR_COLOR
};
ShdGlossMaskDefClass::ShdGlossMaskDefClass()
: ShdDefClass(SHDDEF_CLASSID_GLOSSMASK),
Ambient(1,1,1),
Diffuse(1,1,1),
Specular(1,1,1)
{
NAMED_TEXTURE_FILENAME_PARAM(ShdGlossMaskDefClass, TextureName, "Texture Name", "Targa Files", ".tga");
NAMED_EDITABLE_PARAM(ShdGlossMaskDefClass, ParameterClass::TYPE_COLOR, Ambient, "Ambient");
NAMED_EDITABLE_PARAM(ShdGlossMaskDefClass, ParameterClass::TYPE_COLOR, Diffuse, "Diffuse");
NAMED_EDITABLE_PARAM(ShdGlossMaskDefClass, ParameterClass::TYPE_COLOR, Specular, "Specular");
}
ShdGlossMaskDefClass::ShdGlossMaskDefClass(const ShdGlossMaskDefClass& that)
: ShdDefClass(that),
Ambient(that.Ambient),
Diffuse(that.Diffuse),
Specular(that.Specular)
{
TextureName=that.TextureName;
}
ShdGlossMaskDefClass::~ShdGlossMaskDefClass()
{
}
bool ShdGlossMaskDefClass::Is_Valid_Config(StringClass &message)
{
return true;
}
bool ShdGlossMaskDefClass::Save(ChunkSaveClass &csave)
{
ShdDefClass::Save(csave);
csave.Begin_Chunk(CHUNKID_VARIABLES);
bool retval = true;
// only save the file name
char fname[_MAX_PATH];
_splitpath(TextureName,NULL,NULL,fname,NULL);
strcat(fname,".tga");
TextureName=fname;
WRITE_MICRO_CHUNK_WWSTRING(csave, VARID_TEXTURE_NAME, TextureName);
WRITE_MICRO_CHUNK(csave, VARID_AMBIENT_COLOR, Ambient);
WRITE_MICRO_CHUNK(csave, VARID_DIFFUSE_COLOR, Diffuse);
WRITE_MICRO_CHUNK(csave, VARID_SPECULAR_COLOR, Specular);
csave.End_Chunk();
return retval;
}
bool ShdGlossMaskDefClass::Load(ChunkLoadClass &cload)
{
ShdDefClass::Load(cload);
// Loop through all the microchunks that define the variables
while (cload.Open_Chunk()) {
switch (cload.Cur_Chunk_ID())
{
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk())
{
switch (cload.Cur_Micro_Chunk_ID())
{
READ_MICRO_CHUNK_WWSTRING(cload, VARID_TEXTURE_NAME, TextureName);
READ_MICRO_CHUNK(cload, VARID_AMBIENT_COLOR, Ambient);
READ_MICRO_CHUNK(cload, VARID_DIFFUSE_COLOR, Diffuse);
READ_MICRO_CHUNK(cload, VARID_SPECULAR_COLOR, Specular);
}
cload.Close_Micro_Chunk();
}
break;
default:
break;
}
cload.Close_Chunk();
}
return true;
}
void ShdGlossMaskDefClass::Init()
{
Shd6GlossMaskClass::Init();
}
void ShdGlossMaskDefClass::Shutdown()
{
Shd6GlossMaskClass::Shutdown();
}
ShdInterfaceClass* ShdGlossMaskDefClass::Create() const
{
return new Shd6GlossMaskClass(this);
}
Matrix4x4 Shd6GlossMaskClass::View_Projection_Matrix;
Shd6GlossMaskClass::Shd6GlossMaskClass(const ShdDefClass* def)
: ShdInterfaceClass(def,SHDDEF_CLASSID_GLOSSMASK),
Texture(NULL)
{
ShdGlossMaskDefClass* Definition=(ShdGlossMaskDefClass*)def;
Texture=WW3DAssetManager::Get_Instance()->Get_Texture
(
Definition->Get_Texture_Name()
);
const Vector3& a=Definition->Get_Ambient();
Ambient.Set(a.X,a.Y,a.Z,1.0f);
const Vector3& d=Definition->Get_Diffuse();
Diffuse.Set(d.X,d.Y,d.Z,1.0f);
const Vector3& s=Definition->Get_Specular();
Specular.Set(s.X,s.Y,s.Z,1.0f);
Material=new D3DMATERIAL8;
memset(Material,0,sizeof(D3DMATERIAL8));
Material->Ambient.r=a.X; Material->Ambient.g=a.Y; Material->Ambient.b=a.Z;
Material->Diffuse.r=d.X; Material->Diffuse.g=d.Y; Material->Diffuse.b=d.Z;
Material->Specular.r=s.X; Material->Specular.g=s.Y; Material->Specular.b=s.Z;
Material->Power=20;
}
Shd6GlossMaskClass::~Shd6GlossMaskClass()
{
REF_PTR_RELEASE(Texture);
}
void Shd6GlossMaskClass::Init()
{
}
void Shd6GlossMaskClass::Shutdown()
{
}
/**********************************************************************************************
//! Apply shared states for 1 pass DX6
/*! 7/12/02 3:39p KJM Created
*/
void Shd6GlossMaskClass::Apply_Shared(int pass, RenderInfoClass& rinfo)
{
// fixed function uses pass through by default
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU);
// set vertex shader
DX8Wrapper::Set_Vertex_Shader(DX8_FVF_XYZNDUV1);
// set texture stage settings
if (DX8Wrapper::Get_Current_Caps()->Support_ModAlphaAddClr())
{
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLORARG1, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLOROP, D3DTOP_MODULATEALPHA_ADDCOLOR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLORARG2, D3DTA_SPECULAR );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
}
else
{
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
}
DX8Wrapper::Set_DX8_Render_State(D3DRS_LIGHTING, TRUE);
DX8Wrapper::Set_DX8_Render_State(D3DRS_AMBIENTMATERIALSOURCE,D3DMCS_MATERIAL);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DIFFUSEMATERIALSOURCE,D3DMCS_MATERIAL);
DX8Wrapper::Set_DX8_Render_State(D3DRS_SPECULARMATERIALSOURCE,D3DMCS_MATERIAL);
DX8Wrapper::Set_DX8_Render_State(D3DRS_EMISSIVEMATERIALSOURCE,D3DMCS_MATERIAL);
DX8Wrapper::Set_DX8_Material(Material);
}
//**********************************************************************************************
//! Apply per instance states for 1 pass DX6
/*! 7/10/02 5:39p KJM Created
*/
void Shd6GlossMaskClass::Apply_Instance(int cur_pass, RenderInfoClass& rinfo)
{
DX8Wrapper::Set_Texture(0, Texture);
if (DX8Wrapper::Get_Current_Caps()->Support_ModAlphaAddClr())
{
DX8Wrapper::Set_Texture(1, Texture);
}
DX8Wrapper::Set_DX8_Material(Material);
}
unsigned Shd6GlossMaskClass::Get_Vertex_Stream_Count() const
{
return 1;
}
unsigned Shd6GlossMaskClass::Get_Vertex_Size(unsigned stream) const
{
return sizeof(VertexFormatXYZNDUV1);
}
void Shd6GlossMaskClass::Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
)
{
VertexFormatXYZNDUV1* verts=(VertexFormatXYZNDUV1*)dest_buffer;
for (unsigned i=0; i<vertex_count; ++i)
{
if (vss.Locations)
{
verts[i].x=vss.Locations[i][0];
verts[i].y=vss.Locations[i][1];
verts[i].z=vss.Locations[i][2];
}
else
{
verts[i].x=0.0f;
verts[i].y=0.0f;
verts[i].z=0.0f;
}
if (vss.DiffuseInt)
{
verts[i].diffuse=vss.DiffuseInt[i];
}
else
{
verts[i].diffuse=0xffffffff;
}
if (vss.Normals)
{
verts[i].nx=vss.Normals[i][0];
verts[i].ny=vss.Normals[i][1];
verts[i].nz=vss.Normals[i][2];
}
else
{
verts[i].nx=0.0f;
verts[i].ny=0.0f;
verts[i].nz=0.0f;
}
if (vss.UV[0])
{
verts[i].u1=vss.UV[0][i].U;
verts[i].v1=vss.UV[0][i].V;
}
else
{
verts[i].u1=0.0f;
verts[i].v1=0.0f;
}
}
}

View File

@@ -0,0 +1,152 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shdglossmask.cpp $*
* *
* $Org Author:: Kenny_m
*
* $Author:: Kenny_m
*
* $Modtime:: 8/01/02 11:39a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHDGLOSSMASK_H
#define SHDGLOSSMASK_H
#ifndef SHDINTERFACE_H
#include "shdinterface.h"
#endif
#include "shddef.h"
#include "saveload.h"
#include "shader.h"
class ShdGlossMaskDefClass : public ShdDefClass
{
public:
/////////////////////////////////////////////////////////////////////
// Editable interface requirements
/////////////////////////////////////////////////////////////////////
DECLARE_EDITABLE(ShdGlossMaskDefClass, ShdDefClass);
ShdGlossMaskDefClass();
ShdGlossMaskDefClass(const ShdGlossMaskDefClass& that);
virtual ~ShdGlossMaskDefClass();
virtual ShdDefClass* Clone() const { return new ShdGlossMaskDefClass(*this); }
// Shader Creation (should create a shader compatible with the current hardware/API)
virtual void Init();
virtual void Shutdown();
virtual ShdInterfaceClass* Create() const;
// Validation methods
virtual bool Is_Valid_Config(StringClass &message);
// Requirements
virtual bool Requires_Normals() const { return true; }
virtual bool Requires_Tangent_Space_Vectors() const { return false; }
virtual bool Requires_Sorting() const { return false; }
virtual int Static_Sort_Index() const { return 0; }
// From PersistClass
virtual bool Save(ChunkSaveClass &csave);
virtual bool Load(ChunkLoadClass &cload);
void Set_Texture_Name(const StringClass& name) { TextureName=name; }
const StringClass& Get_Texture_Name() const { return TextureName; }
void Set_Ambient(const Vector3& ambient) { Ambient=ambient; }
const Vector3& Get_Ambient() const { return Ambient; }
void Set_Diffuse(const Vector3& diffuse) { Diffuse=diffuse; }
const Vector3& Get_Diffuse() const { return Diffuse; }
void Set_Specular(const Vector3& specular) { Specular=specular; }
const Vector3& Get_Specular() const { return Specular; }
private:
bool Save_Variables(ChunkSaveClass &csave);
bool Load_Variables(ChunkLoadClass &cload);
StringClass TextureName;
Vector3 Ambient;
Vector3 Diffuse;
Vector3 Specular;
};
class Shd6GlossMaskClass : public ShdInterfaceClass
{
public:
Shd6GlossMaskClass(const ShdDefClass* def);
virtual ~Shd6GlossMaskClass();
static void Init();
static void Shutdown();
virtual int Get_Pass_Count() { return 1; }
virtual int Get_Texture_Count() const { return 1; }
virtual TextureClass* Peek_Texture(int idx) const { return Texture; }
virtual void Apply_Shared(int cur_pass, RenderInfoClass& rinfo);
virtual void Apply_Instance(int cur_pass, RenderInfoClass& rinfo);
virtual unsigned Get_Vertex_Stream_Count() const;
virtual unsigned Get_Vertex_Size(unsigned stream) const;
virtual bool Use_HW_Vertex_Processing() const { return true; }
virtual void Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
);
protected:
static Matrix4x4 View_Projection_Matrix;
D3DMATERIAL8* Material;
TextureClass* Texture;
Vector4 Ambient;
Vector4 Diffuse;
Vector4 Specular;
};
#endif //SHDGLOSSMASK_H

View File

@@ -0,0 +1,43 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// generic shaders constants
// Kenny Mitchell - Westwood Studios EA 2002
#ifndef SHDHW_CONSTANTS_H
#define SHDHW_CONSTANTS_H
// constants (0,1,0.5,2.0)
#define CV_CONST 0
// lighting constants
#define CV_LIGHT_DIRECTION_0 16
#define CV_LIGHT_DIRECTION_1 17
#define CV_LIGHT_DIRECTION_2 18
#define CV_LIGHT_DIRECTION_3 19
#define CV_LIGHT_COLOR_0 20
#define CV_LIGHT_COLOR_1 21
#define CV_LIGHT_COLOR_2 22
#define CV_LIGHT_COLOR_3 23
#define CV_AMBIENT 24
#define CV_DIFFUSE 25
#define CV_SPECULAR 26
#endif

View File

@@ -0,0 +1,510 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/shdhwshader.cpp $*
* *
* $Org Author:: Kenny_m
* *
* $Author:: Kenny_m
*
* $Modtime:: 07/07/02 12:18p $*
* *
* $Revision:: 3 $*
* *
* 06/06/02 KM added software vertex shader fallback check
* 07/07/02 KM Generic shader functions for factoring HW shader code
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <stdio.h>
#include "shdhwshader.h"
#include "dx8wrapper.h"
#include "rinfo.h"
#include "shdhw_constants.h"
//**********************************************************************************************
//! Execute and wait for a hidden shell command
/*! 5/27/02 5:39p KJM Created
*/
void ShdHWShader::Shell_Run(char* cmd)
{
int result;
#ifdef WIN32
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(pi));
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags=STARTF_USESHOWWINDOW;
si.wShowWindow=SW_HIDE;
static bool found=false;
static char work_dir[_MAX_PATH];
if (!found)
{
char* shader_path="\\shaders\\";
::GetCurrentDirectory(_MAX_PATH,work_dir);
strcat(work_dir,shader_path);
}
result=CreateProcess(0,cmd,0,0,0,0,0,work_dir,&si,&pi);
if (result)
{
WaitForSingleObject(pi.hThread, INFINITE);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
found=true;
}
else
{
int err=GetLastError();
MessageBox
(
NULL,
"Failed to execute preprocessor on shader\n"
"Ensure shaders folder is in application subdirectory\n",
"Shader Asset Error",
MB_OK
);
WWASSERT_PRINT(result,"Failed to execute preprocessor on shader (ensure shaders folder is in application subdirectory)");
}
#else
result=system(cmd);
#endif
}
//**********************************************************************************************
//! Preprocess and assemble a HW shader from file
/*! 5/27/02 5:39p KJM Created
*/
void ShdHWShader::Preprocess_And_Assemble_Shader_From_File
(
char* file_name,
LPD3DXBUFFER* constants,
LPD3DXBUFFER* shader_code
)
{
char shell_command[_MAX_PATH];
char temp_path[_MAX_PATH];
char temp_file[_MAX_PATH];
GetTempPath(_MAX_PATH, temp_path);
GetTempFileName(temp_path,"shd",1,temp_file);
_snprintf
(
shell_command,
sizeof(shell_command),
"shaders\\rspp %s %s",
file_name,
temp_file
);
LPD3DXBUFFER* errors=NULL;
Shell_Run(shell_command);
HRESULT result=D3DXAssembleShaderFromFile
(
temp_file,
NULL,
constants,
shader_code,
errors
);
WWASSERT_PRINT(result==D3D_OK,"Failed to assemble shader from file");
}
// 06/06/02 KM added software vertex shader fallback check
bool ShdHWVertexShader::Using_Hardware=true;
//**********************************************************************************************
//! Destruct this vertex shader
/*! 5/27/02 5:39p KJM Created
*/
ShdHWVertexShader::~ShdHWVertexShader()
{
Destroy();
}
//**********************************************************************************************
//! Destroy this vertex shader
/*! 5/27/02 5:39p KJM Created
*/
void ShdHWVertexShader::Destroy()
{
if (Shader)
{
DX8Wrapper::_Get_D3D_Device8()->SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE);
DX8Wrapper::_Get_D3D_Device8()->DeleteVertexShader(Shader);
Shader=0;
}
}
//**********************************************************************************************
//! Create Vertex Shader from a file and vertex stream declaration
/*! 05/27/02 5:39p KJM Created
/*! 06/06/02 KM added software vertex shader fallback check
*/
DWORD ShdHWVertexShader::Create
(
char* file_name,
DWORD* vertex_shader_declaration
)
{
// Create vertex shader
LPD3DXBUFFER shader_code=NULL;
Preprocess_And_Assemble_Shader_From_File
(
file_name,
NULL,
&shader_code
);
// try hardware first
Using_Hardware=true;
HRESULT result=DX8Wrapper::_Get_D3D_Device8()->CreateVertexShader
(
(DWORD*)vertex_shader_declaration,
(DWORD*)shader_code->GetBufferPointer(),
(DWORD*)&Shader,
0
);
if (result!=D3D_OK)
{
// try software
Using_Hardware=false;
result=DX8Wrapper::_Get_D3D_Device8()->CreateVertexShader
(
(DWORD*)vertex_shader_declaration,
(DWORD*)shader_code->GetBufferPointer(),
(DWORD*)&Shader,
D3DUSAGE_SOFTWAREPROCESSING
);
WWASSERT_PRINT(result==D3D_OK,"Failed to create vertex shader");
}
if (shader_code) shader_code->Release();
return Shader;
}
//**********************************************************************************************
//! Create Vertex Shader from a dword constant and vertex stream declaration
/*! 07/19/02 3:39p KJM Created
*/
DWORD ShdHWVertexShader::Create
(
DWORD* shader_code_str,
DWORD* vertex_shader_declaration
)
{
HRESULT result;
LPD3DXBUFFER shader_code=NULL;
LPD3DXBUFFER errors=NULL;
result=D3DXAssembleShader
(
shader_code_str,
strlen((char*)shader_code_str),
NULL,//D3DXASM_DEBUG,
NULL,
&shader_code,
&errors
);
if (result!=D3D_OK)
{
OutputDebugString((char*)errors->GetBufferPointer());
WWASSERT_PRINT(result==D3D_OK,"Failed to assemble shader");
}
// try hardware first
Using_Hardware=true;
result=DX8Wrapper::_Get_D3D_Device8()->CreateVertexShader
(
(DWORD*)vertex_shader_declaration,
(DWORD*)shader_code->GetBufferPointer(),
(DWORD*)&Shader,
0
);
if (result!=D3D_OK)
{
// try software
Using_Hardware=false;
result=DX8Wrapper::_Get_D3D_Device8()->CreateVertexShader
(
(DWORD*)vertex_shader_declaration,
(DWORD*)shader_code->GetBufferPointer(),
(DWORD*)&Shader,
D3DUSAGE_SOFTWAREPROCESSING
);
WWASSERT_PRINT(result==D3D_OK,"Failed to create vertex shader");
if (result!=D3D_OK)
{
OutputDebugString((char*)shader_code_str);
}
}
return Shader;
}
//**********************************************************************************************
//! Destruct this pixel shader
/*! 5/27/02 5:39p KJM Created
*/
ShdHWPixelShader::~ShdHWPixelShader()
{
Destroy();
}
//**********************************************************************************************
//! Destroy this pixel shader
/*! 5/27/02 5:39p KJM Created
*/
void ShdHWPixelShader::Destroy()
{
if (Shader)
{
DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(0);
DX8Wrapper::_Get_D3D_Device8()->DeletePixelShader(Shader);
Shader=0;
}
}
//**********************************************************************************************
//! Create Pixel Shader from a file
/*! 5/27/02 5:39p KJM Created
*/
DWORD ShdHWPixelShader::Create(char* file_name)
{
// Create pixel shader
LPD3DXBUFFER shader_code=NULL;
Preprocess_And_Assemble_Shader_From_File
(
file_name,
NULL,
&shader_code
);
HRESULT result=DX8Wrapper::_Get_D3D_Device8()->CreatePixelShader
(
(DWORD*)shader_code->GetBufferPointer(),
(DWORD*)&Shader
);
WWASSERT_PRINT(result==D3D_OK,"Failed to create pixel shader");
return Shader;
}
//**********************************************************************************************
//! Create Pixel Shader from a dword constant
/*! 07/19/02 3:39p KJM Created
*/
DWORD ShdHWPixelShader::Create(DWORD* shader_code_str)
{
HRESULT result;
LPD3DXBUFFER shader_code=NULL;
LPD3DXBUFFER errors;
result=D3DXAssembleShader
(
shader_code_str,
strlen((char*)shader_code_str),
NULL,
NULL,
&shader_code,
&errors
);
if (result!=D3D_OK)
{
OutputDebugString((char*)errors->GetBufferPointer());
WWASSERT_PRINT(result==D3D_OK,"Failed to assemble shader");
}
result=DX8Wrapper::_Get_D3D_Device8()->CreatePixelShader
(
(DWORD*)shader_code->GetBufferPointer(),
(DWORD*)&Shader
);
WWASSERT_PRINT(result==D3D_OK,"Failed to create pixel shader");
return Shader;
}
//**********************************************************************************************
//! Apply generic lighting
/*! 07/07/02 12:23p KJM Created
*/
void ShdHWVertexShader::Light
(
RenderInfoClass& rinfo,
Vector4& ambient,
Vector4& diffuse,
Vector4& specular
)
{
LightEnvironmentClass* lenv=rinfo.light_environment;
Vector4 light_ambient(1,1,1,1);
if (lenv)
{
int num_lights=lenv->Get_Light_Count();
// most cases set up and use the light environment
if (num_lights)
{
const Vector3& amb=lenv->Get_Equivalent_Ambient();
light_ambient.Set
(
amb.X,
amb.Y,
amb.Z,
0
);
int i;
int max=LightEnvironmentClass::Get_Max_Lights();
if (num_lights>max) num_lights=max;
Vector4 cdir, ccol;
for (i=0;i<max;i++)
{
if (i<num_lights)
{
Vector3 rot;
const Vector3& dir=lenv->Get_Light_Direction(i);
const Vector3& col=lenv->Get_Light_Diffuse(i);
cdir.Set(dir.X,dir.Y,dir.Z,1.0f);
ccol.Set(col.X,col.Y,col.Z,1.0f);
}
else
{
// if no light just set color to zero
ccol.Set(0,0,0,0);
}
DX8Wrapper::Set_Vertex_Shader_Constant(CV_LIGHT_DIRECTION_0+i, &cdir, 1);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_LIGHT_COLOR_0+i, &ccol, 1);
}
}
else
{
const Vector3& amb_col=DX8Wrapper::Get_Ambient();
light_ambient.X=amb_col.X;
light_ambient.Y=amb_col.Y;
light_ambient.Z=amb_col.Z;
// otherwise have to extract light from render state
int max=LightEnvironmentClass::Get_Max_Lights();
int i;
RenderStateStruct state;
DX8Wrapper::Get_Render_State(state);
Vector4 cdir, ccol;
for (i=0;i<max;i++)
{
if (state.LightEnable[i])
{
D3DLIGHT8& light=state.Lights[i];
// handle directional and positional lights
if (light.Type==D3DLIGHT_DIRECTIONAL)
{
const D3DXVECTOR3& dir=state.Lights[i].Direction;
cdir.Set(-dir.x,-dir.y,-dir.z,0.0f);
}
else
{
const D3DXVECTOR3& pos=state.Lights[i].Position;
// just normalise the light position for now (as only appears to be used in w3dview)
cdir.Set(pos.x,pos.y,pos.z,0.0f);
}
cdir.Normalize();
ccol.Set
(
state.Lights[i].Diffuse.r,
state.Lights[i].Diffuse.g,
state.Lights[i].Diffuse.b,
1.0f
);
}
else
{
// if no light just set color to zero
ccol.Set(0,0,0,0);
}
DX8Wrapper::Set_Vertex_Shader_Constant(CV_LIGHT_DIRECTION_0+i, &cdir, 1);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_LIGHT_COLOR_0+i, &ccol, 1);
}
}
}
light_ambient.X*=ambient.X;
light_ambient.Y*=ambient.Y;
light_ambient.Z*=ambient.Z;
DX8Wrapper::Set_Vertex_Shader_Constant(CV_AMBIENT, &light_ambient, 1);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_DIFFUSE, &diffuse, 1);
DX8Wrapper::Set_Vertex_Shader_Constant(CV_SPECULAR, &specular, 1);
}
//**********************************************************************************************
//! Apply generic lighting (no specular supplied)
/*! 07/07/02 12:23p KJM Created
*/
void ShdHWVertexShader::Light
(
RenderInfoClass& rinfo,
Vector4& ambient,
Vector4& diffuse
)
{
Vector4 specular(0,0,0,0);
Light(rinfo,ambient,diffuse,specular);
}

View File

@@ -0,0 +1,133 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/shdhwshader.h $*
* *
* $Org Author:: Kenny_m
* *
* $Author:: Kenny_m
*
* $Modtime:: 07/07/02 11:18p $*
* *
* $Revision:: 3 $*
* *
* 06/06/02 KM added software vertex shader fallback check
* 07/07/02 KM Generic shader functions for factoring HW shader code
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHDHWSHADER_H
#define SHDHWSHADER_H
#ifndef _D3D8_H_
#include <d3d8.h>
#endif
#ifndef __D3DX8_H__
#include <d3dx8.h>
#endif
#ifndef SHDHW_CONSTANTS_H
#include "shdhw_constants.h"
#endif
class RenderInfoClass;
class Vector4;
class ShdHWShader
{
public:
ShdHWShader() : Shader(0) {}
virtual ~ShdHWShader() {}
DWORD Peek_Shader() const { return Shader; }
protected:
void Shell_Run(char* cmd);
void Preprocess_And_Assemble_Shader_From_File
(
char* file_name,
LPD3DXBUFFER* constants,
LPD3DXBUFFER* shader_code
);
DWORD Shader;
};
class ShdHWVertexShader : public ShdHWShader
{
public:
virtual ~ShdHWVertexShader();
DWORD Create
(
char* file_name,
DWORD* vertex_shader_declaration
);
DWORD Create
(
DWORD* shader_code,
DWORD* vertex_shader_declaration
);
void Destroy();
static bool Is_Using_Hardware() { return Using_Hardware; }
static void Light
(
RenderInfoClass& rinfo,
Vector4& ambient,
Vector4& diffuse,
Vector4& specular
);
static void Light
(
RenderInfoClass& rinfo,
Vector4& ambient,
Vector4& diffuse
);
private:
static bool Using_Hardware;
};
class ShdHWPixelShader : public ShdHWShader
{
public:
virtual ~ShdHWPixelShader();
DWORD Create(char* file_name);
DWORD Create(DWORD* shader_code);
void Destroy();
};
#endif

View File

@@ -0,0 +1,78 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shdinterface.cpp $*
* *
* $Org Author:: Jani_p
*
* $Author:: Kenny_m
*
* $Modtime:: 6/05/02 3:12p $*
* *
* $Revision:: 2 $*
* *
* 6/05/02 KJM : Added texture info functions
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "shdinterface.h"
#include "shddef.h"
//**********************************************************************************************
//! Constructor
/*!
Base class constructor for shaders. Saves a pointer to the definition for this shader.
@param
*/
ShdInterfaceClass::ShdInterfaceClass(const ShdDefClass * def, int class_id) :
Definition(NULL),
ClassID(class_id)
{
REF_PTR_SET(Definition,def);
}
//**********************************************************************************************
//! Destructor
/*!
Destructor for ShdInterfaceClass, releases the definition.
*/
ShdInterfaceClass::~ShdInterfaceClass(void)
{
REF_PTR_RELEASE(Definition);
}
//**********************************************************************************************
//! returns a pointer to the definition for this shader
/*!
@returns
*/
const ShdDefClass * ShdInterfaceClass::Peek_Definition(void)
{
return Definition;
}

View File

@@ -0,0 +1,142 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shdinterface.h $*
* *
* $Org Author:: Jani_p
*
* $Author:: Kenny_m
*
* $Modtime:: 6/05/02 3:12p $*
* *
* $Revision:: 2 $*
* *
* 6/05/02 KJM : Added texture info functions
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHDINTERFACE_H
#define SHDINTERFACE_H
#include "always.h"
#include "refcount.h"
#include "dx8wrapper.h"
class ShdDefClass;
class ShdMeshClass;
class RenderInfoClass;
class TextureClass;
/*
** Maximum passes allowed for any shader implementation!
*/
const int SHD_MAX_PASSES = 4;
/**
** Utility structure for passing in streams to the shader. Those streams that are not available will be NULL,
** and the shader should ASSERT that it is passed everything it needs in its Copy_Vertex_Stream() function.
** The caller of the Copy_Vertex_Stream() should use query functions (such as Requires_Normals()) in the definition
** to determine which streams the shader needs.
*/
struct VertexStreamStruct
{
VertexStreamStruct()
: Locations(0),
Normals(0),
DiffuseInt(0),
DiffuseFloat(0)
{
for (int i=0;i<MAX_TEXTURE_STAGES;++i)
{
UV[i]=0;
}
}
const Vector3* Locations;
const Vector3* Normals;
const Vector2* UV[MAX_TEXTURE_STAGES];
const unsigned* DiffuseInt;
const Vector4* DiffuseFloat;
const Vector3* S;
const Vector3* T;
const Vector3* SxT;
};
/**
** ShdInterfaceClass - This class is the virtual interface for all shaders. A derived shader's job is to
** set up the D3D render states for a particular rendering operation. Instances of shaders are
** are created by an associated ShdDefClass.
*/
class ShdInterfaceClass : public RefCountClass
{
public:
ShdInterfaceClass(const ShdDefClass * def,int class_id);
virtual ~ShdInterfaceClass(void);
const ShdDefClass * Peek_Definition(void);
WWINLINE int Get_Class_ID() const { return ClassID; }
// For rendering efficiency, all shaders should implement comparison operator that the renderer
// can use to sort the meshes.
virtual bool Greater_Than (const ShdInterfaceClass& s,int pass) const { return true; }
virtual bool Similar_Enough (const ShdInterfaceClass& s,int pass) const { return true; }
virtual int Get_Pass_Count(void) = 0;
virtual bool Pass_Selection(ShdMeshClass*, RenderInfoClass*,int) { return true; }
virtual void Apply_Shared(int cur_pass, RenderInfoClass& rinfo) = 0;
virtual void Apply_Instance(int cur_pass, RenderInfoClass& rinfo) = 0;
// The shader needs to tell how many vertex streams it needs and what are the sizes of vertices
// in each stream.
virtual unsigned Get_Vertex_Stream_Count() const = 0;
virtual unsigned Get_Vertex_Size(unsigned stream) const = 0;
virtual bool Use_HW_Vertex_Processing() const = 0;
virtual int Get_Texture_Count() const = 0;
virtual TextureClass* Peek_Texture(int idx) const = 0;
// The shader needs to construct each vertex stream as requested. The data comes in a standard
// VertexStreamStruct, and the shader can format it as it wishes (nothing else will be using
// the buffer than the shader itself.
virtual void Copy_Vertex_Stream(unsigned stream, void* dest_buffer, const VertexStreamStruct& vss, unsigned vertex_count) = 0;
// Return whether this shader is opaque. This property is used to determine whether
// geometric shadows should be cast from an object for example. Alpha-Test shaders should
// return false to Is_Opaque.
virtual bool Is_Opaque(void) const { return true; }
protected:
const ShdDefClass * Definition;
int ClassID;
};
#endif //SHDINTERFACE_H

View File

@@ -0,0 +1,615 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shdlegacyw3d.cpp $*
* *
* $Org Author:: Jani_p
*
* $Author:: Jani_p
*
* $Modtime:: 7/12/02 3:12p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <d3dx8math.h>
#include "dx8fvf.h"
#include "dx8wrapper.h"
#include "assetmgr.h"
#include "shdlegacyw3d.h"
#include "editable.h"
#include "chunkio.h"
#include "w3d_util.h"
#include "persistfactory.h"
#include "wwhack.h"
#include "shdclassids.h"
#include "shddeffactory.h"
#include "shdinterface.h"
#include "shdhwshader.h"
DECLARE_FORCE_LINK(LegacyW3DShader);
REGISTER_SHDDEF(ShdLegacyW3DDefClass,SHDDEF_CLASSID_LEGACYW3D,"LegacyW3D");
// Save-Load methods for ShdDefClass
enum
{
SHDLEGACY_CHUNKID_VARIABLES = 0x11070958,
SHDLEGACY_CHUNKID_TEXTURE_NAME00,
SHDLEGACY_CHUNKID_TEXTURE_NAME01,
SHDLEGACY_CHUNKID_TEXTURE_NAME10,
SHDLEGACY_CHUNKID_TEXTURE_NAME11,
SHDLEGACY_CHUNKID_TEXTURE_NAME20,
SHDLEGACY_CHUNKID_TEXTURE_NAME21,
SHDLEGACY_CHUNKID_TEXTURE_NAME30,
SHDLEGACY_CHUNKID_TEXTURE_NAME31,
SHDLEGACY_CHUNKID_MAPPERARGS00,
SHDLEGACY_CHUNKID_MAPPERARGS01,
SHDLEGACY_CHUNKID_MAPPERARGS10,
SHDLEGACY_CHUNKID_MAPPERARGS11,
SHDLEGACY_CHUNKID_MAPPERARGS20,
SHDLEGACY_CHUNKID_MAPPERARGS21,
SHDLEGACY_CHUNKID_MAPPERARGS30,
SHDLEGACY_CHUNKID_MAPPERARGS31,
VARID_PASS_COUNT = 0x00,
VARID_SHADER0,
VARID_SHADER1,
VARID_SHADER2,
VARID_SHADER3,
VARID_MATERIAL0,
VARID_MATERIAL1,
VARID_MATERIAL2,
VARID_MATERIAL3,
VARID_TEXTURE_ATTRIBUTES00,
VARID_TEXTURE_ATTRIBUTES01,
VARID_TEXTURE_ATTRIBUTES10,
VARID_TEXTURE_ATTRIBUTES11,
VARID_TEXTURE_ATTRIBUTES20,
VARID_TEXTURE_ATTRIBUTES21,
VARID_TEXTURE_ATTRIBUTES30,
VARID_TEXTURE_ATTRIBUTES31,
VARID_MAPCHANNEL00,
VARID_MAPCHANNEL01,
VARID_MAPCHANNEL10,
VARID_MAPCHANNEL11,
VARID_MAPCHANNEL20,
VARID_MAPCHANNEL21,
VARID_MAPCHANNEL30,
VARID_MAPCHANNEL31,
VARID_AMBIENT_COLOR,
VARID_DIFFUSE_COLOR
};
ShdLegacyW3DDefClass::ShdLegacyW3DDefClass()
: ShdDefClass(SHDDEF_CLASSID_LEGACYW3D),
PassCount(0)
{
// init defaults
for (int pass_index=0; pass_index < MeshMatDescClass::MAX_PASSES; pass_index++) {
memset(&(Shaders[pass_index]),0,sizeof(W3dShaderStruct));
memset(&(Materials[pass_index]),0,sizeof(W3dVertexMaterialStruct));
for (int stage_index=0; stage_index < MeshMatDescClass::MAX_TEX_STAGES; stage_index++) {
TextureAttributes[pass_index][stage_index] = 0;
MapChannel[pass_index][stage_index] = 0;
}
}
}
ShdLegacyW3DDefClass::ShdLegacyW3DDefClass(const ShdLegacyW3DDefClass& that)
: ShdDefClass(that),
PassCount(that.PassCount)
{
// init defaults
for (int pass_index=0; pass_index < MeshMatDescClass::MAX_PASSES; pass_index++) {
memset(&(Shaders[pass_index]),0,sizeof(W3dShaderStruct));
memset(&(Materials[pass_index]),0,sizeof(W3dVertexMaterialStruct));
for (int stage_index=0; stage_index < MeshMatDescClass::MAX_TEX_STAGES; stage_index++) {
TextureAttributes[pass_index][stage_index] = 0;
MapChannel[pass_index][stage_index] = 0;
}
}
for (int pass=0;pass<PassCount;++pass) {
for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
TextureNames[pass][stage]=that.TextureNames[pass][stage];
}
// Shaders[pass]=that.Shaders[pass];
// Materials[pass]=that.Materials[pass];
}
}
ShdLegacyW3DDefClass::~ShdLegacyW3DDefClass()
{
}
bool ShdLegacyW3DDefClass::Is_Valid_Config(StringClass &message)
{
return true;
}
bool ShdLegacyW3DDefClass::Uses_UV_Channel(int i) const
{
for (int pass=0; pass<PassCount; pass++) {
for (int stage=0; stage<MeshMatDescClass::MAX_TEX_STAGES; stage++) {
if (MapChannel[pass][stage] == i) {
return true;
}
}
}
return false;
}
bool ShdLegacyW3DDefClass::Save(ChunkSaveClass &csave)
{
// Call parent class
ShdDefClass::Save(csave);
// Save our variables
csave.Begin_Chunk(SHDLEGACY_CHUNKID_VARIABLES);
Save_Variables(csave);
csave.End_Chunk();
// Save any mapper args and texture names present
for (int pass_index=0; pass_index<PassCount; pass_index++) {
for (int stage_index=0; stage_index<2; stage_index++) {
// Write the texture name
if (!TextureNames[pass_index][stage_index].Is_Empty()) {
/* (gth) need to save entire path for Max to work properly right???
char fname[_MAX_PATH];
char extension[_MAX_PATH];
_splitpath(TextureNames[pass_index][stage_index].Peek_Buffer(),NULL,NULL,fname,extension);
strcat(fname,extension);
*/
int chunk_id = SHDLEGACY_CHUNKID_TEXTURE_NAME00 + pass_index * 2 + stage_index;
WRITE_WWSTRING_CHUNK(csave,chunk_id,TextureNames[pass_index][stage_index]);
}
// Write the mapper args
if (!MapperArgs[pass_index][stage_index].Is_Empty()) {
int chunk_id = SHDLEGACY_CHUNKID_MAPPERARGS00 + pass_index * 2 + stage_index;
WRITE_WWSTRING_CHUNK(csave,chunk_id,MapperArgs[pass_index][stage_index])
}
}
}
return false;
}
bool ShdLegacyW3DDefClass::Load(ChunkLoadClass &cload)
{
int offset = 0;
int pass = 0;
int stage = 0;
// Call parent class
ShdDefClass::Load(cload);
// Read in the chunks
while (cload.Open_Chunk()) {
switch (cload.Cur_Chunk_ID())
{
case SHDLEGACY_CHUNKID_VARIABLES:
Load_Variables(cload);
break;
case SHDLEGACY_CHUNKID_TEXTURE_NAME00:
case SHDLEGACY_CHUNKID_TEXTURE_NAME01:
case SHDLEGACY_CHUNKID_TEXTURE_NAME10:
case SHDLEGACY_CHUNKID_TEXTURE_NAME11:
case SHDLEGACY_CHUNKID_TEXTURE_NAME20:
case SHDLEGACY_CHUNKID_TEXTURE_NAME21:
case SHDLEGACY_CHUNKID_TEXTURE_NAME30:
case SHDLEGACY_CHUNKID_TEXTURE_NAME31:
offset = cload.Cur_Chunk_ID() - SHDLEGACY_CHUNKID_TEXTURE_NAME00;
pass = offset / 2;
stage = offset % 2;
cload.Read(TextureNames[pass][stage].Get_Buffer(cload.Cur_Chunk_Length()),cload.Cur_Chunk_Length());
break;
case SHDLEGACY_CHUNKID_MAPPERARGS00:
case SHDLEGACY_CHUNKID_MAPPERARGS01:
case SHDLEGACY_CHUNKID_MAPPERARGS10:
case SHDLEGACY_CHUNKID_MAPPERARGS11:
case SHDLEGACY_CHUNKID_MAPPERARGS20:
case SHDLEGACY_CHUNKID_MAPPERARGS21:
case SHDLEGACY_CHUNKID_MAPPERARGS30:
case SHDLEGACY_CHUNKID_MAPPERARGS31:
offset = cload.Cur_Chunk_ID() - SHDLEGACY_CHUNKID_MAPPERARGS00;
pass = offset / 2;
stage = offset % 2;
cload.Read(MapperArgs[pass][stage].Get_Buffer(cload.Cur_Chunk_Length()),cload.Cur_Chunk_Length());
break;
default:
break;
}
cload.Close_Chunk();
}
return true;
}
bool ShdLegacyW3DDefClass::Save_Variables(ChunkSaveClass &csave)
{
WRITE_MICRO_CHUNK(csave, VARID_PASS_COUNT, PassCount);
for (int pass_index=0; pass_index<PassCount; pass_index++) {
// Write the shader and vertex material
WRITE_MICRO_CHUNK(csave, VARID_SHADER0 + pass_index, Shaders[pass_index]);
WRITE_MICRO_CHUNK(csave, VARID_MATERIAL0 + pass_index, Materials[pass_index]);
for (int stage_index=0; stage_index<2; stage_index++) {
// Write the texture attributes
if (TextureAttributes[pass_index][stage_index] != 0) {
WRITE_MICRO_CHUNK(csave, VARID_TEXTURE_ATTRIBUTES00 + pass_index*2 + stage_index, TextureAttributes[pass_index][stage_index]);
}
// Write the map channels
if (MapChannel[pass_index][stage_index] != 0) {
WRITE_MICRO_CHUNK(csave, VARID_MAPCHANNEL00 + pass_index*2 + stage_index, MapChannel[pass_index][stage_index]);
}
}
}
return true;
}
bool ShdLegacyW3DDefClass::Load_Variables(ChunkLoadClass &cload)
{
int offset = 0;
int pass = 0;
int stage = 0;
while (cload.Open_Micro_Chunk())
{
switch (cload.Cur_Micro_Chunk_ID())
{
READ_MICRO_CHUNK(cload, VARID_PASS_COUNT, PassCount);
case VARID_SHADER0:
case VARID_SHADER1:
case VARID_SHADER2:
case VARID_SHADER3:
pass = cload.Cur_Micro_Chunk_ID() - VARID_SHADER0;
cload.Read(&Shaders[pass],sizeof(Shaders[pass]));
break;
case VARID_MATERIAL0:
case VARID_MATERIAL1:
case VARID_MATERIAL2:
case VARID_MATERIAL3:
pass = cload.Cur_Micro_Chunk_ID() - VARID_MATERIAL0;
cload.Read(&Materials[pass],sizeof(Materials[pass]));
break;
case VARID_TEXTURE_ATTRIBUTES00:
case VARID_TEXTURE_ATTRIBUTES01:
case VARID_TEXTURE_ATTRIBUTES10:
case VARID_TEXTURE_ATTRIBUTES11:
case VARID_TEXTURE_ATTRIBUTES20:
case VARID_TEXTURE_ATTRIBUTES21:
case VARID_TEXTURE_ATTRIBUTES30:
case VARID_TEXTURE_ATTRIBUTES31:
offset = cload.Cur_Micro_Chunk_ID() - VARID_TEXTURE_ATTRIBUTES00;
pass = offset / 2;
stage = offset % 2;
cload.Read(&TextureAttributes[pass][stage],sizeof(TextureAttributes[pass][stage]));
break;
case VARID_MAPCHANNEL00:
case VARID_MAPCHANNEL01:
case VARID_MAPCHANNEL10:
case VARID_MAPCHANNEL11:
case VARID_MAPCHANNEL20:
case VARID_MAPCHANNEL21:
case VARID_MAPCHANNEL30:
case VARID_MAPCHANNEL31:
offset = cload.Cur_Micro_Chunk_ID() - VARID_MAPCHANNEL00;
pass = offset / 2;
stage = offset % 2;
cload.Read(&MapChannel[pass][stage],sizeof(MapChannel[pass][stage]));
break;
}
cload.Close_Micro_Chunk();
}
return true;
}
void ShdLegacyW3DDefClass::Init()
{
Shd6LegacyW3DClass::Init();
}
void ShdLegacyW3DDefClass::Shutdown()
{
Shd6LegacyW3DClass::Shutdown();
}
ShdInterfaceClass* ShdLegacyW3DDefClass::Create() const
{
return NEW_REF(Shd6LegacyW3DClass,(this));
}
Shd6LegacyW3DClass::Shd6LegacyW3DClass(const ShdDefClass* def)
: ShdInterfaceClass(def,SHDDEF_CLASSID_LEGACYW3D),
PassCount(0)
{
int pass;
int stage;
for (pass=0;pass<MeshMatDescClass::MAX_PASSES;++pass) {
Materials[pass]=NULL;
for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
Textures[pass][stage]=NULL;
}
}
ShdLegacyW3DDefClass* Definition=(ShdLegacyW3DDefClass*)def;
PassCount=Definition->Get_Pass_Count();
for (pass=0;pass<PassCount;++pass) {
// Set up the shaders
W3dUtilityClass::Convert_Shader(Definition->Get_Shader(pass),&(Shaders[pass]));
// Set up the vertex materials
VertexMaterialClass * vmat = NEW_REF(VertexMaterialClass,());
vmat->Parse_W3dVertexMaterialStruct(Definition->Get_Material(pass));
char * map0_args = NULL;
char * map1_args = NULL;
if (!Definition->Get_Mapper_Args(pass,0).Is_Empty()) {
map0_args = Definition->Get_Mapper_Args(pass,0).Peek_Buffer();
}
if (!Definition->Get_Mapper_Args(pass,1).Is_Empty()) {
map1_args = Definition->Get_Mapper_Args(pass,1).Peek_Buffer();
}
vmat->Parse_Mapping_Args(Definition->Get_Material(pass),map0_args,map1_args);
vmat->Set_UV_Source(0,Definition->Get_Map_Channel(pass,0));
vmat->Set_UV_Source(1,Definition->Get_Map_Channel(pass,1));
vmat->Set_Lighting(true);
REF_PTR_SET(Materials[pass],vmat);
REF_PTR_RELEASE(vmat);
// Set up the textures
for (stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
StringClass tex_name=Definition->Get_Texture_Name(pass,stage);
if (tex_name!="") {
Textures[pass][stage]=WW3DAssetManager::Get_Instance()->Get_Texture(tex_name);
}
else {
Textures[pass][stage]=NULL;
}
}
}
}
Shd6LegacyW3DClass::~Shd6LegacyW3DClass()
{
for (int pass=0;pass<PassCount;++pass) {
for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
REF_PTR_RELEASE(Textures[pass][stage]);
}
REF_PTR_RELEASE(Materials[pass]);
}
}
void Shd6LegacyW3DClass::Init()
{
}
void Shd6LegacyW3DClass::Shutdown()
{
}
bool Shd6LegacyW3DClass::Greater_Than(const ShdInterfaceClass& s,int pass) const
{
// By class
if (s.Get_Class_ID()!=Get_Class_ID()) {
return s.Get_Class_ID()>Get_Class_ID();
}
const Shd6LegacyW3DClass* src=static_cast<const Shd6LegacyW3DClass*>(&s);
// If same class, sort by textures
if (src->Textures[pass][0]!=Textures[pass][0]) {
return src->Textures[pass][0]>Textures[pass][0];
}
// If same texture, sort by materials
if (src->Materials[pass]!=Materials[pass]) {
return src->Materials[pass]>Materials[pass];
}
// If same material, sort by shaders
if (src->Shaders[pass].Get_Bits()!=(unsigned)Shaders[pass].Get_Bits()) {
return src->Shaders[pass].Get_Bits()>Shaders[pass].Get_Bits();
}
return false;
}
/**********************************************************************************************
//! Apply shared states for 1 pass DX6
/*! 7/12/02 3:39p KJM Created
*/
void Shd6LegacyW3DClass::Apply_Shared(int pass, RenderInfoClass& rinfo)
{
SNAPSHOT_SAY(("Shd6LegacyW3DClass::Apply_Shared(pass: %d)\n",pass));
// fixed function uses pass through by default
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU);
}
//**********************************************************************************************
//! Apply per instance states for 1 pass DX6
/*! 7/10/02 5:39p KJM Created
*/
void Shd6LegacyW3DClass::Apply_Instance(int cur_pass, RenderInfoClass& rinfo)
{
SNAPSHOT_SAY(("Shd6LegacyW3DClass::Apply_Instance(pass: %d)\n",cur_pass));
// set vertex shader
StringClass str;
SNAPSHOT_SAY(("legacyshader:DX8Wrapper::Set_Shader(%s)\n",Shaders[cur_pass].Get_Description(str)));
DX8Wrapper::Set_Shader(Shaders[cur_pass]);
DX8Wrapper::Set_Vertex_Shader(FVF);
SNAPSHOT_SAY(("legacyshader:DX8Wrapper::Set_Material(%s)\n",Materials[cur_pass] ? Materials[cur_pass]->Get_Name() : "NULL"));
DX8Wrapper::Set_Material(Materials[cur_pass]);
for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
SNAPSHOT_SAY(("legacyshader:DX8Wrapper::Set_Texture(%d,%s)\n",stage,Textures[cur_pass][stage] ? Textures[cur_pass][stage]->Get_Full_Path() : "NULL"));
DX8Wrapper::Set_Texture(stage, Textures[cur_pass][stage]);
}
}
unsigned Shd6LegacyW3DClass::Get_Vertex_Stream_Count() const
{
return 1;
}
unsigned Shd6LegacyW3DClass::Get_Vertex_Size(unsigned stream) const
{
FVFInfoClass fvf_info(FVF);
return fvf_info.Get_FVF_Size();
}
void Shd6LegacyW3DClass::Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
)
{
FVFInfoClass fi(FVF);
/*
** Append the UV coordinates to the vertex buffer
*/
int uvcount = 0;
if ((FVF&D3DFVF_TEX1) == D3DFVF_TEX1) {
uvcount = 1;
}
if ((FVF&D3DFVF_TEX2) == D3DFVF_TEX2) {
uvcount = 2;
}
if ((FVF&D3DFVF_TEX3) == D3DFVF_TEX3) {
uvcount = 3;
}
if ((FVF&D3DFVF_TEX4) == D3DFVF_TEX4) {
uvcount = 4;
}
if ((FVF&D3DFVF_TEX5) == D3DFVF_TEX5) {
uvcount = 5;
}
if ((FVF&D3DFVF_TEX6) == D3DFVF_TEX6) {
uvcount = 6;
}
if ((FVF&D3DFVF_TEX7) == D3DFVF_TEX7) {
uvcount = 7;
}
if ((FVF&D3DFVF_TEX8) == D3DFVF_TEX8) {
uvcount = 8;
}
unsigned char* vb=(unsigned char*)dest_buffer;
for (unsigned i=0; i<vertex_count; ++i)
{
if ((FVF&D3DFVF_XYZ)==D3DFVF_XYZ) {
if (vss.Locations)
{
*(Vector3*)(vb+fi.Get_Location_Offset())=vss.Locations[i];
}
else
{
*(Vector3*)(vb+fi.Get_Location_Offset())=Vector3(0.0f,0.0f,0.0f);
}
}
if ((FVF&D3DFVF_DIFFUSE)==D3DFVF_DIFFUSE) {
if (vss.DiffuseInt)
{
*(unsigned int*)(vb+fi.Get_Diffuse_Offset())=vss.DiffuseInt[i];
}
else
{
*(unsigned int*)(vb+fi.Get_Diffuse_Offset())=0xffffffff;
}
}
if ((FVF&D3DFVF_NORMAL)==D3DFVF_NORMAL) {
if (vss.Normals)
{
*(Vector3*)(vb+fi.Get_Normal_Offset())=vss.Normals[i];
}
else
{
*(Vector3*)(vb+fi.Get_Normal_Offset())=Vector3(0.0f,0.0f,0.0f);
}
}
for (int j=0; j<uvcount; j++) {
const Vector2*uvs=vss.UV[j];
if (uvs) {
*(Vector2*)(vb+fi.Get_Tex_Offset(j))=uvs[i];
}
else {
*(Vector2*)(vb+fi.Get_Tex_Offset(j))=Vector2(0.0f,0.0f);
}
}
vb+=fi.Get_FVF_Size();
}
}

View File

@@ -0,0 +1,160 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SHDLEGACYW3D_H
#define SHDLEGACYW3D_H
#include "shdinterface.h"
#include "shddef.h"
#include "meshmatdesc.h"
/**
** ShdLegacyW3DDefClass - This ShaderDef's sole purpose for existance is to let us make the
** transition to using shaders for all of our materials. This shader will wrap the old
** material system completely. The plan is to eventually have a full set of "real" shaders and
** not need to use this at all.
*/
class ShdLegacyW3DDefClass : public ShdDefClass
{
public:
/////////////////////////////////////////////////////////////////////
// Editable interface requirements
/////////////////////////////////////////////////////////////////////
DECLARE_EDITABLE(ShdLegacyW3DDefClass, ShdDefClass);
ShdLegacyW3DDefClass();
ShdLegacyW3DDefClass(const ShdLegacyW3DDefClass& that);
virtual ~ShdLegacyW3DDefClass();
virtual ShdDefClass* Clone() const { return new ShdLegacyW3DDefClass(*this); }
// Shader Creation (should create a shader compatible with the current hardware/API)
virtual void Init();
virtual void Shutdown();
virtual ShdInterfaceClass* Create() const;
// Validation methods
virtual bool Is_Valid_Config(StringClass &message);
// Requirements
virtual bool Requires_Normals() const { return true; }
virtual bool Requires_Tangent_Space_Vectors() const { return false; }
virtual bool Requires_Sorting() const { return false; }
virtual int Static_Sort_Index() const { return 0; }
virtual bool Uses_UV_Channel(int i) const;
// From PersistClass
virtual bool Save(ChunkSaveClass &csave);
virtual bool Load(ChunkLoadClass &cload);
// Accessors
int Get_Pass_Count() { return PassCount; }
const StringClass& Get_Texture_Name(int pass, int stage) { return TextureNames[pass][stage]; }
int Get_Texture_Attributes(int pass,int stage) { return TextureAttributes[pass][stage]; }
const W3dShaderStruct& Get_Shader(int pass) { return Shaders[pass]; }
const W3dVertexMaterialStruct & Get_Material(int pass) { return Materials[pass]; }
StringClass & Get_Mapper_Args(int pass,int stage) { return MapperArgs[pass][stage]; }
int Get_Map_Channel(int pass,int stage) { return MapChannel[pass][stage]; }
void Set_Pass_Count(int passes) { PassCount=passes; }
void Set_Texture_Name(int pass, int stage, const StringClass& name) { TextureNames[pass][stage]=name; }
void Set_Texture_Attributes(int pass, int stage, unsigned int attributes) { TextureAttributes[pass][stage] = attributes; }
void Set_Shader(int pass, const W3dShaderStruct& shader) { Shaders[pass] = shader; }
void Set_Material(int pass, const W3dVertexMaterialStruct& mat) { Materials[pass] = mat; }
void Set_Mapper_Args(int pass, int stage,const char * args) { MapperArgs[pass][stage] = args; }
void Set_Map_Channel(int pass, int stage, int channel) { MapChannel[pass][stage] = channel; }
private:
bool Save_Variables(ChunkSaveClass &csave);
bool Load_Variables(ChunkLoadClass &cload);
int PassCount;
// Textures
StringClass TextureNames[MeshMatDescClass::MAX_PASSES][MeshMatDescClass::MAX_TEX_STAGES];
unsigned int TextureAttributes[MeshMatDescClass::MAX_PASSES][MeshMatDescClass::MAX_TEX_STAGES];
// Shaders
W3dShaderStruct Shaders[MeshMatDescClass::MAX_PASSES];
// Materials
W3dVertexMaterialStruct Materials[MeshMatDescClass::MAX_PASSES];
StringClass MapperArgs[MeshMatDescClass::MAX_PASSES][MeshMatDescClass::MAX_TEX_STAGES];
int MapChannel[MeshMatDescClass::MAX_PASSES][MeshMatDescClass::MAX_TEX_STAGES];
};
class Shd6LegacyW3DClass : public ShdInterfaceClass
{
public:
Shd6LegacyW3DClass(const ShdDefClass* def);
virtual ~Shd6LegacyW3DClass();
static void Init();
static void Shutdown();
virtual bool Greater_Than(const ShdInterfaceClass& s,int pass) const;
virtual int Get_Pass_Count() { return PassCount; }
void Set_Pass_Count(int pass_count) { PassCount=pass_count; }
virtual int Get_Texture_Count() const { return 0; }
virtual TextureClass* Peek_Texture(int idx) const { return NULL; }
virtual void Apply_Shared(int cur_pass, RenderInfoClass& rinfo);
virtual void Apply_Instance(int cur_pass, RenderInfoClass& rinfo);
virtual unsigned Get_Vertex_Stream_Count() const;
virtual unsigned Get_Vertex_Size(unsigned stream) const;
virtual bool Use_HW_Vertex_Processing() const { return true; }
virtual void Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
);
virtual bool Is_Opaque(void) const { return (Shaders[0].Get_Dst_Blend_Func() == ShaderClass::DSTBLEND_ZERO); }
// Shd6LegacyW3DClass Accessors
VertexMaterialClass* Get_Material(int pass) { if (Materials[pass]) Materials[pass]->Add_Ref(); return Materials[pass]; }
void Set_Material(int pass,VertexMaterialClass* mat) { REF_PTR_SET(Materials[pass],mat); }
const ShaderClass& Get_Shader(int pass) { return Shaders[pass]; }
void Set_Shader(int pass,const ShaderClass& shader) { Shaders[pass]=shader; }
void Set_Texture(int pass,int stage,TextureClass* texture) { REF_PTR_SET(Textures[pass][stage],texture); }
void Set_FVF(unsigned fvf) { FVF=fvf; }
protected:
unsigned FVF;
int PassCount;
TextureClass* Textures[MeshMatDescClass::MAX_PASSES][MeshMatDescClass::MAX_TEX_STAGES];
ShaderClass Shaders[MeshMatDescClass::MAX_PASSES];
VertexMaterialClass* Materials[MeshMatDescClass::MAX_PASSES];
};
#endif //SHDLEGACYW3D_H

View File

@@ -0,0 +1,75 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWShade *
* *
* $Archive:: /Commando/Code/wwshade/shdlib.cpp $*
* *
* Org Author:: Kenny Mitchell *
* *
* Author : Kenny Mitchell *
* *
* $Modtime:: 07/01/02 10:31a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* WWShade.lib library interface *
*---------------------------------------------------------------------------------------------*/
#include "shdlib.h"
#include "assetmgr.h"
#include "shdloader.h"
#include "shdrenderer.h"
void SHD_Init()
{
ShdRendererClass::Peek_Instance()->Init();
}
void SHD_Shutdown()
{
ShdRendererClass::Peek_Instance()->Shutdown();
}
void SHD_Init_Shaders()
{
ShdRendererClass::Init_Shaders();
}
void SHD_Shutdown_Shaders()
{
ShdRendererClass::Shutdown_Shaders();
}
void SHD_Flush()
{
ShdRendererClass::Peek_Instance()->Flush();
}
void SHD_Register_Loader()
{
WW3DAssetManager::Get_Instance()->Register_Prototype_Loader(&_ShdMeshLoader);
// WW3DAssetManager::Get_Instance()->Register_Prototype_Loader(&_ShdMeshLegacyLoader);
WW3DAssetManager::Get_Instance()->Register_Prototype_Loader(&_MeshLoader);
}

View File

@@ -0,0 +1,108 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWShade *
* *
* $Archive:: /Commando/Code/wwshade/shdloader.cpp $*
* *
* Org Author:: Kenny Mitchell *
* *
* Author : Kenny Mitchell *
* *
* $Modtime:: 06/27/02 3:51p $*
* *
* $Revision:: 1 $*
* *
* 06/26/02 KM Abstracting shader system
*---------------------------------------------------------------------------------------------*/
#include "shdloader.h"
#include "shdmesh.h"
#include "mesh.h"
ShdMeshLoaderClass _ShdMeshLoader;
ShdMeshLegacyLoaderClass _ShdMeshLegacyLoader;
/***********************************************************************************************
* ShdMeshLoaderClass::Load -- reads in a shader mesh and creates a prototype for it *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/21/02 KJM : Created. *
*=============================================================================================*/
PrototypeClass* ShdMeshLoaderClass::Load_W3D(ChunkLoadClass& cload)
{
ShdMeshClass* mesh=NEW_REF(ShdMeshClass, ());
if (mesh==NULL)
{
return NULL;
}
if (mesh->Load_W3D(cload)!=WW3D_ERROR_OK)
{
// if the load failed, delete the mesh
assert(mesh->Num_Refs() == 1);
mesh->Release_Ref();
return NULL;
}
// create the prototype and add it to the lists
PrimitivePrototypeClass * newproto = new PrimitivePrototypeClass(mesh);
mesh->Release_Ref();
return newproto;
}
PrototypeClass * ShdMeshLegacyLoaderClass::Load_W3D(ChunkLoadClass & cload)
{
MeshClass * mesh = NEW_REF( MeshClass, () );
if (mesh == NULL) {
return NULL;
}
if (mesh->Load_W3D(cload) != WW3D_ERROR_OK) {
// if the load failed, delete the mesh
assert(mesh->Num_Refs() == 1);
mesh->Release_Ref();
return NULL;
} else {
ShdMeshClass* shdmesh=NEW_REF( ShdMeshClass, () );
shdmesh->Init_From_Legacy_Mesh(mesh);
mesh->Release_Ref();
// create the prototype and add it to the lists
PrimitivePrototypeClass * newproto = W3DNEW PrimitivePrototypeClass(shdmesh);
shdmesh->Release_Ref();
return newproto;
}
}

View File

@@ -0,0 +1,68 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWShade *
* *
* $Archive:: /Commando/Code/wwshade/shdloader.h $*
* *
* Org Author:: Kenny Mitchell *
* *
* Author : Kenny Mitchell *
* *
* $Modtime:: 06/27/02 3:51p $*
* *
* $Revision:: 1 $*
* *
* 06/26/02 KM Integrating shader system
*---------------------------------------------------------------------------------------------*/
#ifndef SHDLOADER_H
#define SHDLOADER_H
#ifndef PROTO_H
#include "proto.h"
#endif
class ShdMeshLoaderClass : public PrototypeLoaderClass
{
public:
virtual int Chunk_Type(void) { return W3D_CHUNK_SHDMESH; }
virtual PrototypeClass* Load_W3D(ChunkLoadClass& cload);
};
/*
** Prototype loader that converts legacy meshes into Shader meshes
*/
class ShdMeshLegacyLoaderClass : public PrototypeLoaderClass
{
public:
virtual int Chunk_Type(void) { return W3D_CHUNK_MESH; }
virtual PrototypeClass * Load_W3D(ChunkLoadClass & cload);
};
extern ShdMeshLoaderClass _ShdMeshLoader;
extern ShdMeshLegacyLoaderClass _ShdMeshLegacyLoader;
#endif

View File

@@ -0,0 +1,681 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWShade *
* *
* $Archive:: wwshade/shdmesh.cpp $*
* *
* Org Author:: Jani P *
* *
* Author : Kenny Mitchell *
* *
* $Modtime:: 07/12/02 10:31a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
*---------------------------------------------------------------------------------------------*/
#include "shdmesh.h"
#include "shdsubmesh.h"
#include "shdrenderer.h"
#include "rinfo.h"
#include "camera.h"
#include "dx8wrapper.h"
#include "wwdebug.h"
#include "wwprofile.h"
#include "mesh.h"
#include "meshmdl.h"
ShdMeshClass::ShdMeshClass()
: Name("UnNamed"),
LightEnvironment(NULL),
Applying_Shadow_Map(false)
{
}
ShdMeshClass::ShdMeshClass(const ShdMeshClass & src)
: RenderObjClass(src),
Name(src.Name),
LightEnvironment(NULL),
Applying_Shadow_Map(false)
{
Free();
SubMeshes.Resize(src.SubMeshes.Length());
for (int i=0;i<SubMeshes.Length();++i)
{
SubMeshes[i].Mesh=NULL;
SubMeshes[i].Renderer=NULL;
REF_PTR_SET(SubMeshes[i].Mesh,src.SubMeshes[i].Mesh);
}
}
ShdMeshClass::~ShdMeshClass()
{
Free();
// TODO TODO TODO!!!!!
}
RenderObjClass * ShdMeshClass::Clone() const
{
return new ShdMeshClass(*this);
}
const char * ShdMeshClass::Get_Name() const
{
return Name;
}
void ShdMeshClass::Set_Name(const char * name)
{
Name = name;
}
/***********************************************************************************************
* ShdMeshClass::Free -- Releases all memory/assets in use by this mesh *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/6/98 GTH : Created. *
*=============================================================================================*/
void ShdMeshClass::Free()
{
for (int i=0;i<SubMeshes.Length();++i)
{
REF_PTR_RELEASE(SubMeshes[i].Mesh);
if (SubMeshes[i].Renderer)
{
delete SubMeshes[i].Renderer;
SubMeshes[i].Renderer=NULL;
}
}
}
int ShdMeshClass::Get_Num_Polys() const
{
int count = 0;
for (int i=0; i<SubMeshes.Length(); i++)
{
count+= SubMeshes[i].Mesh->Get_Polygon_Count();
}
return count;
}
int ShdMeshClass::Get_Num_Vertices(void) const
{
int count = 0;
for (int i=0; i<SubMeshes.Length(); i++)
{
count+= SubMeshes[i].Mesh->Get_Vertex_Count();
}
return count;
}
void ShdMeshClass::Render(RenderInfoClass& rinfo)
{
WWPROFILE("ShdMeshClass::Render");
if (Is_Not_Hidden_At_All() == false)
{
return;
}
// DX8_RECORD_MESH_RENDER();
// TODO: Static sort lists
Set_Lighting_Environment(rinfo.light_environment);
const FrustumClass & frustum=rinfo.Camera.Get_Frustum();
// if rendering shadow remember camera info
if ((rinfo.Current_Override_Flags()&RenderInfoClass::RINFO_OVERRIDE_SHADOW_RENDERING))
{
// is generating shadow map
Set_Is_Self_Shadowed();
// set texture projector
Texture_Projector=rinfo.Texture_Projector;
Unset_Is_Applying_Shadow_Map();
}
else if (Is_Self_Shadowed())
{
// is applying shadow map
Set_Is_Applying_Shadow_Map();
Unset_Is_Self_Shadowed();
}
else
{
Unset_Is_Applying_Shadow_Map();
}
// TODO: What to do with SKINS?
if (1)//CollisionMath::Overlap_Test(frustum,Get_Bounding_Box())!=CollisionMath::OUTSIDE )
{
// bool rendered_something = false;
// TODO: Override flags, decals and material passes (probably in the submesh rendering)
for (int i=0;i<SubMeshes.Length();++i)
{
if (!SubMeshes[i].Renderer)
{
SubMeshes[i].Renderer=ShdRendererClass::Peek_Instance()->Register_Mesh(this,SubMeshes[i].Mesh);
}
SubMeshes[i].Renderer->Render(rinfo);
}
// TODO: RendererDebugger
}
}
//void ShdMeshClass::Render_Material_Pass(MaterialPassClass * pass,IndexBufferClass * ib)
//{
//
//}
void ShdMeshClass::Special_Render(SpecialRenderInfoClass & rinfo)
{
}
/***********************************************************************************************
* ShdMeshClass::Cast_Ray -- compute a ray intersection with this mesh *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 6/17/98 GTH : Created. *
*=============================================================================================*/
bool ShdMeshClass::Cast_Ray(RayCollisionTestClass & raytest)
{
if ((Get_Collision_Type() & raytest.CollisionType) == 0) return false;
if ((Is_Translucent()!=0) && (!raytest.CheckTranslucent)) return false;
if (Is_Animation_Hidden()) return false;
if (raytest.Result->StartBad) return false;
Matrix3D world_to_obj;
Matrix3D world=Get_Transform();
// if aligned or oriented rotate the mesh so that it's aligned to the ray
/* if (Model->Get_Flag(MeshModelClass::ALIGNED)) {
Vector3 mesh_position;
world.Get_Translation(&mesh_position);
world.Obj_Look_At(mesh_position,mesh_position - raytest.Ray.Get_Dir(),0.0f);
} else if (Model->Get_Flag(MeshModelClass::ORIENTED)) {
Vector3 mesh_position;
world.Get_Translation(&mesh_position);
world.Obj_Look_At(mesh_position,raytest.Ray.Get_P0(),0.0f);
}
*/
world.Get_Orthogonal_Inverse(world_to_obj);
RayCollisionTestClass objray(raytest,world_to_obj);
for (int i=0;i<SubMeshes.Length();++i) {
if (SubMeshes[i].Mesh->Cast_Ray(objray)) {
// transform result back into original coordinate system
raytest.CollidedRenderObj = this;
Matrix3D::Rotate_Vector(world,raytest.Result->Normal, &(raytest.Result->Normal));
if (raytest.Result->ComputeContactPoint) {
Matrix3D::Transform_Vector(world,raytest.Result->ContactPoint, &(raytest.Result->ContactPoint));
}
return true;
}
}
return false;
}
/***********************************************************************************************
* ShdMeshClass::Cast_AABox -- cast an AABox against this mesh *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 6/17/98 GTH : Created. *
*=============================================================================================*/
bool ShdMeshClass::Cast_AABox(AABoxCollisionTestClass & boxtest)
{
if ((Get_Collision_Type() & boxtest.CollisionType) == 0) return false;
if (boxtest.Result->StartBad) return false;
for (int i=0;i<SubMeshes.Length();++i) {
// This function analyses the tranform to call optimized functions in certain cases
if (SubMeshes[i].Mesh->Cast_World_Space_AABox(boxtest, Get_Transform())) {
boxtest.CollidedRenderObj = this;
return true;
}
}
return false;
}
/***********************************************************************************************
* Cast_OBBox -- Cast an obbox against this mesh *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 6/17/98 GTH : Created. *
*=============================================================================================*/
bool ShdMeshClass::Cast_OBBox(OBBoxCollisionTestClass & boxtest)
{
if ((Get_Collision_Type() & boxtest.CollisionType) == 0) return false;
if (boxtest.Result->StartBad) return false;
/*
** transform into the local coordinate system of the mesh.
*/
const Matrix3D & tm = Get_Transform();
Matrix3D world_to_obj;
tm.Get_Orthogonal_Inverse(world_to_obj);
OBBoxCollisionTestClass localtest(boxtest,world_to_obj);
for (int i=0;i<SubMeshes.Length();++i) {
if (SubMeshes[i].Mesh->Cast_OBBox(localtest)) {
/*
** If we hit, transform the result of the test back to the original coordinate system.
*/
boxtest.CollidedRenderObj = this;
Matrix3D::Rotate_Vector(tm,boxtest.Result->Normal, &(boxtest.Result->Normal));
if (boxtest.Result->ComputeContactPoint) {
Matrix3D::Transform_Vector(tm,boxtest.Result->ContactPoint, &(boxtest.Result->ContactPoint));
}
return true;
}
}
return false;
}
/***********************************************************************************************
* ShdMeshClass::Intersect_AABox -- test for intersection with given AABox *
* *
* The AAbox given is assumed to be in world space. Since meshes aren't generally in world *
* space, the test must be transformed into our local coordinate system (which turns it into *
* an OBBox...) *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/19/00 gth : Created. *
*=============================================================================================*/
bool ShdMeshClass::Intersect_AABox(AABoxIntersectionTestClass & boxtest)
{
if ((Get_Collision_Type() & boxtest.CollisionType) == 0) return false;
Matrix3D inv_tm;
Get_Transform().Get_Orthogonal_Inverse(inv_tm);
OBBoxIntersectionTestClass local_test(boxtest,inv_tm);
for (int i=0;i<SubMeshes.Length();++i) {
if (SubMeshes[i].Mesh->Intersect_OBBox(local_test)) return true;
}
return false;
}
/***********************************************************************************************
* ShdMeshClass::Intersect_OBBox -- test for intersection with the given OBBox *
* *
* The given OBBox is assumed to be in world space so we need to transform it into the mesh's *
* local coordinate system. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/19/00 gth : Created. *
*=============================================================================================*/
bool ShdMeshClass::Intersect_OBBox(OBBoxIntersectionTestClass & boxtest)
{
if ((Get_Collision_Type() & boxtest.CollisionType) == 0) return false;
Matrix3D inv_tm;
Get_Transform().Get_Orthogonal_Inverse(inv_tm);
OBBoxIntersectionTestClass local_test(boxtest,inv_tm);
for (int i=0;i<SubMeshes.Length();++i) {
if (SubMeshes[i].Mesh->Intersect_OBBox(local_test)) return true;
}
return false;
}
/***********************************************************************************************
* ShdMeshClass::Add_Dependencies_To_List -- Add dependent files to the list. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 3/18/99 PDS : Created. *
* 6/05/02 KJM : Added dependency calculation for shader system
*=============================================================================================*/
void ShdMeshClass::Add_Dependencies_To_List
(
DynamicVectorClass<StringClass> &file_list,
bool textures_only
)
{
// loop through sub meshes
for (int i=0;i<SubMeshes.Length();i++)
{
ShdInterfaceClass* shd=SubMeshes[i].Mesh->Peek_Shader();
for (int tidx=0;tidx<shd->Get_Texture_Count();tidx++)
{
TextureClass* texture=shd->Peek_Texture(tidx);
if (texture)
{
file_list.Add(texture->Get_Full_Path());
}
}
}
RenderObjClass::Add_Dependencies_To_List (file_list, textures_only);
return ;
}
/***********************************************************************************************
* ShdMeshClass::Update_Cached_Bounding_Volumes -- default collision sphere. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/14/2001 NH : Created. *
*=============================================================================================*/
void ShdMeshClass::Update_Cached_Bounding_Volumes(void) const
{
Get_Obj_Space_Bounding_Sphere(CachedBoundingSphere);
Matrix3D::Transform_Vector(Get_Transform(),CachedBoundingSphere.Center,&CachedBoundingSphere.Center);
// If we are camera-aligned or -oriented, we don't know which way we are facing at this point,
// so the box we return needs to contain the sphere. Otherewise do the normal computation.
/* if (Model->Get_Flag(MeshModelClass::ALIGNED) || Model->Get_Flag(MeshModelClass::ORIENTED)) {
CachedBoundingBox.Center = CachedBoundingSphere.Center;
CachedBoundingBox.Extent.Set(CachedBoundingSphere.Radius, CachedBoundingSphere.Radius, CachedBoundingSphere.Radius);
} else {
*/ Get_Obj_Space_Bounding_Box(CachedBoundingBox);
CachedBoundingBox.Transform(Get_Transform());
// }
Validate_Cached_Bounding_Volumes();
}
/***********************************************************************************************
* ShdMeshClass::Get_Obj_Space_Bounding_Sphere -- returns obj-space bounding sphere *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/19/00 gth : Created. *
*=============================================================================================*/
void ShdMeshClass::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
{
if (SubMeshes.Length()) {
SubMeshes[0].Mesh->Get_Bounding_Sphere(&sphere);
// If there are more than one submesh, merge all bounding spheres
for (int i=1;i<SubMeshes.Length();++i) {
SphereClass tmp_s;
SubMeshes[i].Mesh->Get_Bounding_Sphere(&tmp_s);
sphere+=tmp_s;
}
}
else {
sphere.Center.Set(0,0,0);
sphere.Radius = 1.0f;
}
}
/***********************************************************************************************
* ShdMeshClass::Get_Obj_Space_Bounding_Box -- returns the obj-space bounding box *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/19/00 gth : Created. *
*=============================================================================================*/
void ShdMeshClass::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
{
if (SubMeshes.Length()) {
SubMeshes[0].Mesh->Get_Bounding_Box(&box);
// If there are more than one submesh, merge all bounding boxes
for (int i=1;i<SubMeshes.Length();++i) {
AABoxClass tmp_b;
SubMeshes[i].Mesh->Get_Bounding_Box(&tmp_b);
box.Add_Box(tmp_b);
}
}
else {
box.Init(Vector3(0,0,0),Vector3(1,1,1));
}
}
void ShdMeshClass::Init_From_Legacy_Mesh(MeshClass* mesh)
{
Set_Name(mesh->Get_Name());
MeshModelClass* model=mesh->Peek_Model();
if (model)
{
int first_poly=0;
int sub_mesh_count=0;
while (first_poly<model->Get_Polygon_Count()) {
sub_mesh_count++;
ShdSubMeshClass * sub_mesh = NEW_REF( ShdSubMeshClass, () );
sub_mesh->Init_From_Legacy_Mesh_Model(model,first_poly);
SubMeshes.Resize(sub_mesh_count);
SubMeshes[sub_mesh_count-1].Mesh=sub_mesh;
SubMeshes[sub_mesh_count-1].Renderer=NULL;
if (sub_mesh->Get_Visible_Polygon_Count()==0) break;
first_poly+=sub_mesh->Get_Visible_Polygon_Count();
}
}
// Pull interesting stuff out of the w3d attributes bits
Set_Collision_Type(mesh->Get_Collision_Type());
Set_Hidden(mesh->Is_Hidden());
Set_Translucent(mesh->Is_Translucent());
}
/***********************************************************************************************
* ShdMeshClass::Load -- creates a shader mesh out of a shader mesh chunk in a .w3d file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 05/21/2002 KM : Created. *
*=============================================================================================*/
WW3DErrorType ShdMeshClass::Load_W3D(ChunkLoadClass& cload)
{
// Open the first chunk, it should be the shader mesh name
cload.Open_Chunk();
if (cload.Cur_Chunk_ID()!=W3D_CHUNK_SHDMESH_NAME)
{
WWDEBUG_SAY(("Invalid format shader mesh.\n"));
return WW3D_ERROR_LOAD_FAILED;
}
// read name
char buf[MAX_PATH];
cload.Read(buf,cload.Cur_Chunk_Length());
cload.Close_Chunk();
Set_Name(buf);
// open header
W3dShdMeshHeaderStruct hdr;
cload.Open_Chunk();
if
(
cload.Read
(
&hdr,
sizeof(W3dShdMeshHeaderStruct)
)!=sizeof(W3dShdMeshHeaderStruct)
)
{
return WW3D_ERROR_LOAD_FAILED;
}
cload.Close_Chunk();
// Process the header
// Set Bounding Info
Vector3 min(hdr.BoxMin.X,hdr.BoxMin.Y,hdr.BoxMin.Z);
Vector3 max(hdr.BoxMax.X,hdr.BoxMax.Y,hdr.BoxMax.Z);
CachedBoundingBox.Init_Min_Max(min,max);
Vector3 cntr(hdr.SphCenter.X,hdr.SphCenter.Y,hdr.SphCenter.Z);
CachedBoundingSphere.Init(cntr,hdr.SphRadius);
// Flags (todo)
// user text
// next are the sub meshes
Free();
SubMeshes.Resize(hdr.NumSubMeshes);
for (int i=0;i<SubMeshes.Length(); )
{
cload.Open_Chunk();
if (cload.Cur_Chunk_ID()==W3D_CHUNK_SHDMESH_USER_TEXT)
{
// todo
cload.Read(buf,cload.Cur_Chunk_Length());
}
else
{
ShdSubMeshClass* ssmesh=NEW_REF(ShdSubMeshClass,());
if (ssmesh==NULL)
{
WWDEBUG_SAY(("ShdMeshClass::Load_W3D - Failed to allocate sub mesh\r\n"));
return WW3D_ERROR_LOAD_FAILED;
}
SubMeshes[i].Mesh=ssmesh;
SubMeshes[i].Renderer=NULL;
REF_PTR_SET(SubMeshes[i].Mesh,SubMeshes[i].Mesh);
ssmesh->Load_W3D(cload);
// assign each sub-mesh with a name in the format: <parentmesh>.<index>
StringClass tmp;
tmp.Format("%s.%d",Name,i);
ssmesh->Set_Name(tmp);
i++;
}
cload.Close_Chunk();
}
// Pull interesting stuff out of the w3d attributes bits
int col_bits = (hdr.Attributes & W3D_MESH_FLAG_COLLISION_TYPE_MASK) >> W3D_MESH_FLAG_COLLISION_TYPE_SHIFT;
Set_Collision_Type( col_bits << 1 );
Set_Hidden(hdr.Attributes & W3D_MESH_FLAG_HIDDEN);
for (i=0;i<SubMeshes.Length(); i++) {
bool shadow = (hdr.Attributes & W3D_MESH_FLAG_CAST_SHADOW) == W3D_MESH_FLAG_CAST_SHADOW;
SubMeshes[i].Mesh->Set_Flag(MeshGeometryClass::CAST_SHADOW,shadow);
}
// Indicate whether this mesh is translucent. The mesh is considered translucent
// if sorting has been enabled (alpha blending on pass 0) or if pass0 contains alpha-test.
// This flag is used to determine if the mesh can cast a geometric shadow.
bool is_translucent = false;
for (i=0;i<SubMeshes.Length(); i++) {
if (SubMeshes[i].Mesh) {
if (SubMeshes[i].Mesh->Is_Sorting()) {
Set_Translucent(true);
}
ShdInterfaceClass * shader = SubMeshes[i].Mesh->Peek_Shader();
if ((shader) && (!shader->Is_Opaque())) {
Set_Translucent(true);
}
}
}
return WW3D_ERROR_OK;
}
int ShdMeshClass::Get_Sub_Mesh_Count(void) const
{
return SubMeshes.Length();
}
ShdSubMeshClass * ShdMeshClass::Peek_Sub_Mesh(int i) const
{
return SubMeshes[i].Mesh;
}

View File

@@ -0,0 +1,186 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWShade *
* *
* $Archive:: wwshade/shdmesh.h $*
* *
* Org Author:: Jani P *
* *
* Author : Kenny Mitchell *
* *
* $Modtime:: 07/12/02 10:31a $*
* *
* $Revision:: 2 $*
* *
* 07/12/02 KM Removed legacy mesh conversion *
*---------------------------------------------------------------------------------------------*
*---------------------------------------------------------------------------------------------*/
#ifndef SHDMESH_H
#define SHDMESH_H
#include "rendobj.h"
#include "wwstring.h"
#include "simplevec.h"
#include "w3derr.h"
#include "matrix4.h"
class ChunkLoadClass;
class LightEnvironmentClass;
class MaterialPassClass;
class ShdSubMeshClass;
class ShdRendererNodeClass;
class MeshClass;
class TexProjectClass;
struct ShdSubMeshStruct
{
ShdSubMeshClass* Mesh;
ShdRendererNodeClass* Renderer;
};
/**
** ShdMeshClass - Mesh which uses the new shader system. This is a render object which
** has the following characteristics:
** - It uses the new shader system
** - It contains one or more sub-meshes which each use only a single shader (unlike the old mesh system)
*/
class ShdMeshClass : public RenderObjClass
{
public:
ShdMeshClass(void);
ShdMeshClass(const ShdMeshClass & src);
virtual ~ShdMeshClass(void);
/////////////////////////////////////////////////////////////////////////////
// Render Object Interface
/////////////////////////////////////////////////////////////////////////////
virtual RenderObjClass * Clone(void) const;
virtual int Class_ID(void) const { return CLASSID_SHDMESH; }
virtual const char * Get_Name(void) const;
virtual void Set_Name(const char * name);
virtual int Get_Num_Polys(void) const;
int Get_Num_Vertices(void) const;
virtual void Render(RenderInfoClass & rinfo);
// void Render_Material_Pass(MaterialPassClass * pass,IndexBufferClass * ib);
virtual void Special_Render(SpecialRenderInfoClass & rinfo);
/////////////////////////////////////////////////////////////////////////////
// Render Object Interface - Collision Detection
/////////////////////////////////////////////////////////////////////////////
virtual bool Cast_Ray(RayCollisionTestClass & raytest);
virtual bool Cast_AABox(AABoxCollisionTestClass & boxtest);
virtual bool Cast_OBBox(OBBoxCollisionTestClass & boxtest);
virtual bool Intersect_AABox(AABoxIntersectionTestClass & boxtest);
virtual bool Intersect_OBBox(OBBoxIntersectionTestClass & boxtest);
/////////////////////////////////////////////////////////////////////////////
// Render Object Interface - Bounding Volumes
/////////////////////////////////////////////////////////////////////////////
virtual void Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const;
virtual void Get_Obj_Space_Bounding_Box(AABoxClass & box) const;
/////////////////////////////////////////////////////////////////////////////
// Render Object Interface - Attributes, Options, Properties, etc
/////////////////////////////////////////////////////////////////////////////
// virtual int Get_Sort_Level(void) const;
// virtual void Set_Sort_Level(int level);
/////////////////////////////////////////////////////////////////////////////
// Render Object Interface - Decals
/////////////////////////////////////////////////////////////////////////////
// virtual void Create_Decal(DecalGeneratorClass * generator);
// virtual void Delete_Decal(uint32 decal_id);
/////////////////////////////////////////////////////////////////////////////
// MeshClass Interface
/////////////////////////////////////////////////////////////////////////////
void Init_From_Legacy_Mesh(MeshClass* mesh);
// WW3DErrorType Init(const MeshBuilderClass & builder,MaterialInfoClass * matinfo,const char * name,const char * hmodelname);
WW3DErrorType Load_W3D(ChunkLoadClass & cload);
void Generate_Culling_Tree(void);
// MeshModelClass * Get_Model(void);
// MeshModelClass * Peek_Model(void);
uint32 Get_W3D_Flags(void);
const char * Get_User_Text(void) const;
bool Contains(const Vector3 &point);
void Get_Deformed_Vertices(Vector3 *dst_vert, Vector3 *dst_norm);
void Get_Deformed_Vertices(Vector3 *dst_vert);
void Set_Lighting_Environment(LightEnvironmentClass * light_env) { LightEnvironment = light_env; }
LightEnvironmentClass * Get_Lighting_Environment(void) { return LightEnvironment; }
// void Set_Next_Visible_Skin(MeshClass * next_visible) { NextVisibleSkin = next_visible; }
// MeshClass * Peek_Next_Visible_Skin(void) { return NextVisibleSkin; }
//
// void Set_Base_Vertex_Offset(int base) { BaseVertexOffset = base; }
// int Get_Base_Vertex_Offset(void) { return BaseVertexOffset; }
// Do old .w3d mesh files get fog turned on or off?
static bool Legacy_Meshes_Fogged;
// void Replace_Texture(TextureClass* texture,TextureClass* new_texture);
// void Replace_VertexMaterial(VertexMaterialClass* vmat,VertexMaterialClass* new_vmat);
void Make_Unique();
// unsigned Get_Debug_Id() const { return MeshDebugId; }
//
// void Set_Debugger_Disable(bool b) { IsDisabledByDebugger=b; }
// bool Is_Disabled_By_Debugger() const { return IsDisabledByDebugger; }
/*
** User Lighting feature, meshes can have a user lighting array.
*/
// void Install_User_Lighting_Array(Vector4 * lighting);
// unsigned int * Get_User_Lighting_Array(bool alloc = false);
//
// virtual void Save_User_Lighting (ChunkSaveClass & csave);
// virtual void Load_User_Lighting (ChunkLoadClass & cload);
void Set_Is_Applying_Shadow_Map() { Applying_Shadow_Map=true; }
void Unset_Is_Applying_Shadow_Map() { Applying_Shadow_Map=false; }
bool Is_Applying_Shadow_Map() const { return Applying_Shadow_Map; }
TexProjectClass* Peek_Texture_Projector() const { return Texture_Projector; }
// ShdMesh Accessors
int Get_Sub_Mesh_Count(void) const;
ShdSubMeshClass * Peek_Sub_Mesh(int i) const;
protected:
void Free(void);
virtual void Add_Dependencies_To_List (DynamicVectorClass<StringClass> &file_list, bool textures_only = false);
virtual void Update_Cached_Bounding_Volumes(void) const;
StringClass Name;
SimpleVecClass<ShdSubMeshStruct> SubMeshes;
LightEnvironmentClass * LightEnvironment; // cached pointer to the light environment for this mesh
bool Applying_Shadow_Map;
TexProjectClass* Texture_Projector;
};
#endif //SHDMESH_H

View File

@@ -0,0 +1,708 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/shdrenderer.cpp $*
*
* Org Author:: Jani_p
* *
* $Author:: Kenny_m
*
* $Modtime:: 7/29/02 1:50p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* 6/02/02 5:59p KM Added render info and light environment support $*
* 7/29/02 1:50p KM Added VB and IB usage flags for software vertex shaders
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "shdrenderer.h"
#include "shdforcelinks.h"
#include "shdmesh.h"
#include "shdsubmesh.h"
#include "shddef.h"
#include "shddefmanager.h"
#include "shdclassids.h"
#include "wwdebug.h"
#include "dx8vertexbuffer.h"
#include "dx8indexbuffer.h"
#include "dx8wrapper.h"
#include "rinfo.h"
#include "camera.h"
#include "texture.h"
#include "ww3dformat.h"
#include "wwprofile.h"
#include "sortingrenderer.h"
#include "meshmatdesc.h"
static DynamicVectorClass<Vector3> _TempVertexBuffer;
static DynamicVectorClass<Vector3> _TempNormalBuffer;
ShdRendererClass* ShdRendererClass::ShdRenderer=NULL;
ShdRendererClass::ShdRendererClass()
{
}
ShdRendererClass::~ShdRendererClass()
{
}
/////////////////////////////////////////////////////////////////////////////////////
// Initialize the rendering system. This is the place to create different versions
// (such as DX8, DX9, OGL) of the rendering system, if needed.
/////////////////////////////////////////////////////////////////////////////////////
void ShdRendererClass::Init()
{
SHD_Force_Links();
WWASSERT(!ShdRenderer);
ShdRenderer=new ShdDX8RendererClass();
Init_Shaders();
}
void ShdRendererClass::Init_Shaders()
{
ShdDefClass* def;
for (int i=SHDDEF_CLASSID_DUMMY+1; i<SHDDEF_CLASSID_LAST; i++)
{
def=ShdDefManagerClass::Create_ShdDefClass_Instance(i);
if (def != NULL) {
def->Init();
REF_PTR_RELEASE(def);
}
}
}
/////////////////////////////////////////////////////////////////////////////////////
// Release the renderer system. At this point, all the meshes must have been
// unregistered.
/////////////////////////////////////////////////////////////////////////////////////
void ShdRendererClass::Shutdown()
{
Shutdown_Shaders();
WWASSERT(ShdRenderer);
delete ShdRenderer;
ShdRenderer=0;
}
void ShdRendererClass::Shutdown_Shaders()
{
ShdDefClass* def;
for (int i=SHDDEF_CLASSID_DUMMY+1; i<SHDDEF_CLASSID_LAST; i++)
{
def=ShdDefManagerClass::Create_ShdDefClass_Instance(i);
if (def) {
def->Shutdown();
REF_PTR_RELEASE(def);
}
}
}
/////////////////////////////////////////////////////////////////////////////////////
// DirectX8 renderer utility class declaration
/////////////////////////////////////////////////////////////////////////////////////
RendererListContainerClass::RendererListContainerClass(int pass) : Pass(pass)
{
}
RendererListContainerClass::~RendererListContainerClass()
{
Unregister_All();
}
void RendererListContainerClass::Register_Renderer(ShdRendererNodeClass* node)
{
WWASSERT(node);
node->Add_Ref();
node->Set_Renderer_List_Container(this,Pass);
LinkedNodes.Add_Tail(node);
}
void RendererListContainerClass::Unregister_All()
{
while (!LinkedNodes.Is_Empty()) {
ShdRendererNodeClass* node=LinkedNodes.Remove_Head();
// REF_PTR_RELEASE(node);
delete node;
}
}
void RendererListContainerClass::Flush()
{
ShdRendererNodeClass* prev_node=NULL;
while (!VisibleNodes.Is_Empty())
{
ShdRendererNodeClass* node=VisibleNodes.Remove_Head();
node->Apply_Shared_Shader_Settings(prev_node,Pass);
node->Flush(Pass);
prev_node=node;
}
}
class ShdDX8RendererClass::MeshContainerClass : public RefCountClass
{
public:
MeshContainerClass();
virtual ~MeshContainerClass();
ShdRendererNodeClass* Register_Mesh(ShdMeshClass* mesh,ShdSubMeshClass* sub_mesh);
// void Add_Visible_Node(ShdRendererNodeClass* node,int pass);
void Flush();
private:
// ShdRendererNodeList VisibleNodeList[SHD_MAX_PASSES];
RendererListContainerList RendererListContainers[SHD_MAX_PASSES];
};
/**
** ShdDX8RendererNode
*/
class ShdDX8RendererNodeClass : public ShdRendererNodeClass
{
public:
ShdDX8RendererNodeClass(ShdDX8RendererClass::MeshContainerClass* container, ShdMeshClass* mesh,ShdSubMeshClass* sub_mesh);
virtual ~ShdDX8RendererNodeClass();
virtual void Render(RenderInfoClass& rinfo);
virtual void Flush(int pass);
virtual void Apply_Shared_Shader_Settings(ShdRendererNodeClass* prev,int pass);
virtual bool Greater_Than(const ShdRendererNodeClass&, int pass) const;
virtual bool Similar_Enough(const ShdRendererNodeClass&, int pass) const;
private:
ShdDX8RendererClass::MeshContainerClass* Container;
ShdMeshClass* Mesh;
ShdSubMeshClass* SubMesh;
VertexBufferClass** VertexBuffers;
IndexBufferClass* IndexBuffer;
LightEnvironmentClass LightEnvironment; // todo KJM optimize for output lights
RenderInfoClass* RenderInfo;
};
/////////////////////////////////////////////////////////////////////////////////////
// DirectX8 renderer implementation
/////////////////////////////////////////////////////////////////////////////////////
ShdDX8RendererClass::ShdDX8RendererClass()
{
MeshCategories=new MeshContainerClass*[SHDDEF_CLASSID_LAST];
for (int i=0;i<SHDDEF_CLASSID_LAST;++i)
{
MeshCategories[i]=0;
}
}
ShdDX8RendererClass::~ShdDX8RendererClass()
{
for (int i=0;i<SHDDEF_CLASSID_LAST;++i)
{
if (MeshCategories[i])
{
REF_PTR_RELEASE(MeshCategories[i]);
delete MeshCategories[i];
MeshCategories[i]=0;
}
}
delete[] MeshCategories;
MeshCategories=0;
}
bool ShdDX8RendererNodeClass::Greater_Than(const ShdRendererNodeClass& s, int pass) const
{
// Danger! Assuming ShdDX8RendererNodeClass!
const ShdDX8RendererNodeClass* src=static_cast<const ShdDX8RendererNodeClass*>(&s);
WWASSERT(SubMesh && src->SubMesh);
return SubMesh->Peek_Shader()->Greater_Than(*src->SubMesh->Peek_Shader(),pass);
}
bool ShdDX8RendererNodeClass::Similar_Enough(const ShdRendererNodeClass& s, int pass) const
{
// Danger! Assuming ShdDX8RendererNodeClass!
const ShdDX8RendererNodeClass* src=static_cast<const ShdDX8RendererNodeClass*>(&s);
WWASSERT(SubMesh && src->SubMesh);
return SubMesh->Peek_Shader()->Similar_Enough(*src->SubMesh->Peek_Shader(),pass);
}
/////////////////////////////////////////////////////////////////////////////////////
// Register mesh to the rendering system
/////////////////////////////////////////////////////////////////////////////////////
ShdRendererNodeClass* ShdDX8RendererClass::Register_Mesh
(
ShdMeshClass* mesh,
ShdSubMeshClass* sub_mesh
)
{
ShdInterfaceClass* shd=sub_mesh->Peek_Shader();
const ShdDefClass* def=shd->Peek_Definition();
uint32 class_id=def->Get_Class_ID();
WWASSERT(class_id<SHDDEF_CLASSID_LAST);
if (!MeshCategories[class_id])
{
MeshCategories[class_id]=new MeshContainerClass();
}
return MeshCategories[class_id]->Register_Mesh(mesh,sub_mesh);
}
/////////////////////////////////////////////////////////////////////////////////////
// Flush the list of visible meshes
/////////////////////////////////////////////////////////////////////////////////////
void ShdDX8RendererClass::Flush()
{
WWPROFILE("ShdDX8RendererClass::Flush");
DX8Wrapper::Apply_Render_State_Changes();
DX8Wrapper::Invalidate_Cached_Render_States();
DX8Wrapper::Apply_Default_State();
SNAPSHOT_SAY(("ShdDX8RendererClass::Flush()\n"));
for (int i=0;i<SHDDEF_CLASSID_LAST;++i)
{
if (MeshCategories[i])
{
MeshCategories[i]->Flush();
}
}
DX8Wrapper::Invalidate_Cached_Render_States();
DX8Wrapper::Apply_Default_State();
}
/////////////////////////////////////////////////////////////////////////////////////
// MeshContiner is used for each shader type. Meshes are assigned to a container
// when they're first rendered and they link themselves to container's visible list
// each frame they're visible.
/////////////////////////////////////////////////////////////////////////////////////
ShdDX8RendererClass::MeshContainerClass::MeshContainerClass()
{
}
ShdDX8RendererClass::MeshContainerClass::~MeshContainerClass()
{
for (int pass=0; pass<SHD_MAX_PASSES; pass++)
{
while (!RendererListContainers[pass].Is_Empty()) {
RendererListContainerClass* cont=RendererListContainers[pass].Remove_Head();
cont->Unregister_All();
REF_PTR_RELEASE(cont);
}
}
}
/////////////////////////////////////////////////////////////////////////////////////
// RendererNodeClass acts as a link between ShdMeshClass, ShdSubMeshClass and the
// rendering system.
/////////////////////////////////////////////////////////////////////////////////////
ShdRendererNodeClass* ShdDX8RendererClass::MeshContainerClass::Register_Mesh
(
ShdMeshClass* mesh,
ShdSubMeshClass* sub_mesh
)
{
ShdDX8RendererNodeClass* node=new ShdDX8RendererNodeClass(this,mesh,sub_mesh);
ShdInterfaceClass* shdi=sub_mesh->Peek_Shader();
WWASSERT(shdi);
for (int pass=0; pass<shdi->Get_Pass_Count(); pass++)
{
RendererListContainerIterator ite(&RendererListContainers[pass]);
ite.Last();
while (!ite.Is_Done()) {
RendererListContainerClass* cont=ite.Peek_Obj();
if (cont) {
ShdRendererNodeListIterator ite2(&cont->Peek_Linked_Nodes());
ite2.First();
// Container should delete itself when the last node is removed, so we must
// never have an empty node.
WWASSERT(!ite2.Is_Done());
ShdRendererNodeClass* obj=ite2.Peek_Obj();
if (obj) {
if (node->Greater_Than(*obj,pass)) {
// If similar enough, add to the same renderer container, otherwise create a new one
if (node->Similar_Enough(*obj,pass)) {
cont->Register_Renderer(node);
}
else {
RendererListContainerClass* new_cont=new RendererListContainerClass(pass);
new_cont->Register_Renderer(node);
RendererListContainers[pass].Add_After(new_cont,new_cont);
}
break;
}
}
}
ite.Prev();
}
if (ite.Is_Done()) {
RendererListContainerClass* new_cont=new RendererListContainerClass(pass);
new_cont->Register_Renderer(node);
RendererListContainers[pass].Add(new_cont);
}
}
return node;
}
/////////////////////////////////////////////////////////////////////////////////////
// Render all visible nodes and clear the visible list.
/////////////////////////////////////////////////////////////////////////////////////
void ShdDX8RendererClass::MeshContainerClass::Flush()
{
SNAPSHOT_SAY(("ShdDX8RendererClass::MeshContainerClass::Flush()\n"));
for (int pass=0; pass<SHD_MAX_PASSES; pass++)
{
RendererListContainerIterator ite(&RendererListContainers[pass]);
ite.First();
while (!ite.Is_Done()) {
RendererListContainerClass* cont=ite.Peek_Obj();
cont->Flush();
ite.Next();
}
}
}
/***********************************************************************************************
* ShdDX8RendererNodeClass::ShdDX8RendererNodeClass --
* Init the mesh for rendering... this node is used for all subsequent rendering of
* the particular mesh.
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 4/20/2002 jp : Created
* 5/26/2002 kjm : Updated stream handling for per-pixel shaders *
* 6/02/2002 kjm : Added light environment handling
* 7/29/2002 kjm : Added VB and IB usage flags for software vertex shaders
*=============================================================================================*/
ShdDX8RendererNodeClass::ShdDX8RendererNodeClass
(
ShdDX8RendererClass::MeshContainerClass* container,
ShdMeshClass* mesh,
ShdSubMeshClass* sub_mesh
)
: Container(container),
Mesh(NULL),
SubMesh(NULL),
VertexBuffers(NULL),
IndexBuffer(NULL)
{
REF_PTR_SET(Container,container);
REF_PTR_SET(Mesh,mesh);
REF_PTR_SET(SubMesh,sub_mesh);
// create usage depending on associated shader's processing behaviour KM
DX8IndexBufferClass::UsageType ib_usage=DX8IndexBufferClass::USAGE_DEFAULT;
if (!SubMesh->Peek_Shader()->Use_HW_Vertex_Processing())
{
ib_usage=DX8IndexBufferClass::USAGE_SOFTWAREPROCESSING;
}
int count=SubMesh->Get_Visible_Polygon_Count();
if (!count) count=SubMesh->Get_Polygon_Count();
unsigned index_count=count*3;
if (SubMesh->Is_Sorting()) {
IndexBuffer=new SortingIndexBufferClass(index_count);
}
else {
IndexBuffer=new DX8IndexBufferClass(index_count,ib_usage);
}
IndexBufferClass::WriteLockClass ilock(IndexBuffer);
const TriIndex* indices=SubMesh->Get_Polygon_Array();
int i;
int j=0;
for (i=SubMesh->Get_First_Visible_Polygon();i<count+SubMesh->Get_First_Visible_Polygon();++i)
{
ilock.Get_Index_Array()[j++]=indices[i][0];
ilock.Get_Index_Array()[j++]=indices[i][1];
ilock.Get_Index_Array()[j++]=indices[i][2];
}
// Don't use static vertex buffers if skin
if (SubMesh->Get_Flag(MeshGeometryClass::SKIN)) {
return;
}
// Compose the vertex and index buffers
VertexStreamStruct vss;
vss.Locations=SubMesh->Get_Vertex_Array();
vss.Normals=SubMesh->Get_Vertex_Normal_Array();
for (unsigned stage=0;stage<MAX_TEXTURE_STAGES;++stage)
{
vss.UV[stage]=SubMesh->Get_UV_Array(stage);
}
vss.DiffuseInt=SubMesh->Get_Diffuse_Array();
vss.S=SubMesh->Get_Tangent_Basis_S_Array();
vss.T=SubMesh->Get_Tangent_Basis_T_Array();
vss.SxT=SubMesh->Get_Tangent_Basis_SxT_Array();
unsigned vertex_count=SubMesh->Get_Vertex_Count();
unsigned stream_count=SubMesh->Peek_Shader()->Get_Vertex_Stream_Count();
WWASSERT(stream_count>0);
// create usage depending on associated shader's processing behaviour KM
DX8VertexBufferClass::UsageType vb_usage=DX8VertexBufferClass::USAGE_DEFAULT;
if (!SubMesh->Peek_Shader()->Use_HW_Vertex_Processing())
{
vb_usage=DX8VertexBufferClass::USAGE_SOFTWAREPROCESSING;
}
VertexBuffers=new VertexBufferClass*[stream_count];
unsigned n;
for (n=0;n<stream_count;++n)
{
unsigned vertex_size=SubMesh->Peek_Shader()->Get_Vertex_Size(n);
if (SubMesh->Is_Sorting()) {
VertexBuffers[n]=
new SortingVertexBufferClass(vertex_count);
}
else {
VertexBuffers[n]=
new DX8VertexBufferClass
(
0,
vertex_count,
vb_usage,
vertex_size
);
}
VertexBufferClass::WriteLockClass vlock(VertexBuffers[n]);
SubMesh->Peek_Shader()->Copy_Vertex_Stream
(
n,
vlock.Get_Vertex_Array(),
vss,
SubMesh->Get_Vertex_Count()
);
}
}
ShdDX8RendererNodeClass::~ShdDX8RendererNodeClass()
{
unsigned stream_count=SubMesh->Peek_Shader()->Get_Vertex_Stream_Count();
unsigned n;
for (n=0;n<stream_count;++n)
{
REF_PTR_RELEASE(VertexBuffers[n]);
}
delete[] VertexBuffers;
VertexBuffers=NULL;
REF_PTR_RELEASE(IndexBuffer);
REF_PTR_RELEASE(Mesh);
REF_PTR_RELEASE(SubMesh);
REF_PTR_RELEASE(Container);
}
/***********************************************************************************************
* ShdDX8RendererNodeClass::Render -- Render node
*
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 4/20/2002 jp : Created
* 6/02/2002 kjm : Added light environment handling
*=============================================================================================*/
void ShdDX8RendererNodeClass::Render(RenderInfoClass& rinfo)
{
RenderInfo=&rinfo;
if (rinfo.light_environment)
{
memcpy(&LightEnvironment,rinfo.light_environment,sizeof(LightEnvironmentClass));
}
else {
LightEnvironment.Reset(Vector3(0.0f,0.0f,0.0f),Vector3(0.0f,0.0f,0.0f));
}
Connect();
}
bool enable_rnd=true;
void ShdDX8RendererNodeClass::Flush(int cur_pass)
{
WWASSERT(RenderInfo);
// pass selection for this instance
if (!SubMesh->Peek_Shader()->Pass_Selection(Mesh,RenderInfo,cur_pass))
{
return;
}
SNAPSHOT_SAY(("ShdDX8RendererNodeClass::Flush(%d) - %s\n",cur_pass,SubMesh->Get_Name()));
// BEGIN OF SKIN CODE
if (SubMesh->Get_Flag(MeshGeometryClass::SKIN)) {
DX8Wrapper::Set_Vertex_Buffer(NULL); // Free up the reference to the current vertex buffer
// (in case it is the dynamic, which may have to be resized)
unsigned vertex_count=SubMesh->Get_Vertex_Count();
unsigned stream_count=SubMesh->Peek_Shader()->Get_Vertex_Stream_Count();
WWASSERT(stream_count>0);
// For now there are restrictions in vertex buffer format with skinning
FVFInfoClass fi(dynamic_fvf_type);
WWASSERT(SubMesh->Peek_Shader()->Get_Vertex_Size(0)==fi.Get_FVF_Size());
DynamicVBAccessClass vb(
SubMesh->Is_Sorting() ? BUFFER_TYPE_DYNAMIC_SORTING : BUFFER_TYPE_DYNAMIC_DX8,
dynamic_fvf_type,
vertex_count);
SNAPSHOT_SAY(("DynamicVBAccess - %s - %d vertices\n",SubMesh->Is_Sorting() ? "sorting" : "non-sorting",vertex_count));
if (_TempVertexBuffer.Length() < (int)vertex_count) _TempVertexBuffer.Resize(vertex_count);
if (_TempNormalBuffer.Length() < (int)vertex_count) _TempNormalBuffer.Resize(vertex_count);
Vector3* loc=&(_TempVertexBuffer[0]);
Vector3* norm=&(_TempNormalBuffer[0]);
WWASSERT(Mesh->Get_Container());
SubMesh->Get_Deformed_Vertices(loc,norm,Mesh->Get_Container()->Get_HTree());
// Compose the vertex and index buffers
VertexStreamStruct vss;
vss.Locations=loc;
vss.Normals=norm;
for (unsigned stage=0;stage<MAX_TEXTURE_STAGES;++stage)
{
vss.UV[stage]=SubMesh->Get_UV_Array(stage);
}
vss.DiffuseInt=SubMesh->Get_Diffuse_Array();
vss.S=SubMesh->Get_Tangent_Basis_S_Array();
vss.T=SubMesh->Get_Tangent_Basis_T_Array();
vss.SxT=SubMesh->Get_Tangent_Basis_SxT_Array();
WWASSERT(stream_count==1);
{
DynamicVBAccessClass::WriteLockClass vlock(&vb);
SubMesh->Peek_Shader()->Copy_Vertex_Stream
(
0,//stream
vlock.Get_Formatted_Vertex_Array(),
vss,
SubMesh->Get_Vertex_Count()
);
}
DX8Wrapper::Set_Vertex_Buffer(vb);//stream 0
DX8Wrapper::Set_Index_Buffer(IndexBuffer,0);
DX8Wrapper::Set_Transform(D3DTS_WORLD,Matrix3D(true));//Mesh->Get_Transform());
DX8Wrapper::Set_Light_Environment(&LightEnvironment);
SubMesh->Peek_Shader()->Apply_Instance(cur_pass, *RenderInfo);
if (SubMesh->Is_Sorting()) {
SortingRendererClass::Insert_Triangles
(
0,
SubMesh->Get_Visible_Polygon_Count() ? SubMesh->Get_Visible_Polygon_Count() : SubMesh->Get_Polygon_Count(),
0,
SubMesh->Get_Vertex_Count()
);
}
else {
DX8Wrapper::Draw_Triangles
(
0,
SubMesh->Get_Visible_Polygon_Count() ? SubMesh->Get_Visible_Polygon_Count() : SubMesh->Get_Polygon_Count(),
0,
SubMesh->Get_Vertex_Count()
);
}
return;
}
// END OF SKIN CODE
for (unsigned n=0;n<SubMesh->Peek_Shader()->Get_Vertex_Stream_Count();++n)
{
DX8Wrapper::Set_Vertex_Buffer(VertexBuffers[n],n);
}
DX8Wrapper::Set_Index_Buffer(IndexBuffer,0);
DX8Wrapper::Set_Transform(D3DTS_WORLD,Mesh->Get_Transform());
DX8Wrapper::Set_Light_Environment(&LightEnvironment);
SubMesh->Peek_Shader()->Apply_Instance(cur_pass, *RenderInfo);
if (SubMesh->Is_Sorting()) {
SortingRendererClass::Insert_Triangles
(
0,
SubMesh->Get_Visible_Polygon_Count() ? SubMesh->Get_Visible_Polygon_Count() : SubMesh->Get_Polygon_Count(),
0,
SubMesh->Get_Vertex_Count()
);
}
else {
DX8Wrapper::Draw_Triangles
(
0,
SubMesh->Get_Visible_Polygon_Count() ? SubMesh->Get_Visible_Polygon_Count() : SubMesh->Get_Polygon_Count(),
0,
SubMesh->Get_Vertex_Count()
);
}
}
void ShdDX8RendererNodeClass::Apply_Shared_Shader_Settings(ShdRendererNodeClass* prev_node, int pass)
{
// If the previously set shader is not the same type as this, we need to set
// all render states to default state.
if (prev_node) {
ShdDX8RendererNodeClass* prev_dx8_node=static_cast<ShdDX8RendererNodeClass*>(prev_node); // Illegal to pass another type!
ShdInterfaceClass* shd=prev_dx8_node->SubMesh->Peek_Shader();
if (shd->Get_Class_ID()!=SubMesh->Peek_Shader()->Get_Class_ID()) {
DX8Wrapper::Apply_Default_State();
}
}
SubMesh->Peek_Shader()->Apply_Shared(pass, *RenderInfo);
}

View File

@@ -0,0 +1,191 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/shdrenderer.h $*
*
* Org Author:: Jani_p
* *
* $Author:: Kenny_m
*
* $Modtime:: 6/06/02 3:04p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* 6/02/02 5:59p KM Added render info and light environment support $*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHDRENDERER_H
#define SHDRENDERER_H
#include "multilist.h"
#include "refcount.h"
#include "shdinterface.h"
class ShdSubMeshClass;
class ShdMeshClass;
class RenderInfoClass;
class ShdRendererNodeClass;
class RendererListContainerClass;
typedef MultiListClass<ShdRendererNodeClass> ShdRendererNodeList;
typedef MultiListIterator<ShdRendererNodeClass> ShdRendererNodeListIterator;
typedef MultiListClass<RendererListContainerClass> RendererListContainerList;
typedef MultiListIterator<RendererListContainerClass> RendererListContainerIterator;
class RendererListContainerClass : public MultiListObjectClass, public RefCountClass
{
int Pass;
ShdRendererNodeList LinkedNodes;
ShdRendererNodeList VisibleNodes;
public:
RendererListContainerClass(int pass);
virtual ~RendererListContainerClass();
void Add_Visible_Node(ShdRendererNodeClass* node) {
VisibleNodes.Add_Tail(node);
}
ShdRendererNodeList& Peek_Linked_Nodes() { return LinkedNodes; }
void Flush();
void Register_Renderer(ShdRendererNodeClass* node);
void Unregister_All();
};
/**
** ShdRendererNode
** RendererNodeClass acts as a link between ShdMeshClass, ShdSubMeshClass and the
** rendering system. Rendering API specific implementations are expected.
*/
class ShdRendererNodeClass : public MultiListObjectClass, public RefCountClass
{
RendererListContainerClass* RendererListContainer[SHD_MAX_PASSES];
int MaxPass;
public:
ShdRendererNodeClass() : MaxPass(0)
{
for (int a=0;a<SHD_MAX_PASSES;++a) {
RendererListContainer[a]=0;
}
}
virtual ~ShdRendererNodeClass()
{
for (int a=0;a<SHD_MAX_PASSES;++a) {
REF_PTR_RELEASE(RendererListContainer[a]);
}
}
virtual void Render(RenderInfoClass& rinfo)=0;
virtual void Flush(int pass)=0;
virtual void Apply_Shared_Shader_Settings(ShdRendererNodeClass* prev_node, int pass)=0;
virtual bool Greater_Than(const ShdRendererNodeClass&, int pass) const =0;
void Connect()
{
for (int pass=0;pass<=MaxPass;++pass) {
WWASSERT(RendererListContainer[pass]);
if (RendererListContainer[pass]) RendererListContainer[pass]->Add_Visible_Node(this);
}
}
void Set_Renderer_List_Container(RendererListContainerClass* cont,int pass)
{
REF_PTR_SET(RendererListContainer[pass],cont);
if (cont) MaxPass=max(MaxPass,pass);
}
RendererListContainerClass* Peek_Renderer_List_Container(int pass) { return RendererListContainer[pass]; }
};
/**
** ShdRenderer
*/
class ShdRendererClass
{
static ShdRendererClass* ShdRenderer;
protected:
ShdRendererClass();
virtual ~ShdRendererClass();
public:
/////////////////////////////////////////////////////////////////////////////////////
// Init must be called before any objects can be rendered and Release() must be called
// at the end to release all references to the rendering API. Working through a static
// pointer instead of calling static functions will later allow us to switch to another
// rendering API implementation of the renderer.
/////////////////////////////////////////////////////////////////////////////////////
static void Init();
static void Shutdown();
static void Init_Shaders();
static void Shutdown_Shaders();
static ShdRendererClass* Peek_Instance() { return ShdRenderer; }
/////////////////////////////////////////////////////////////////////////////////////
// Register initialized a mesh for rendering.
/////////////////////////////////////////////////////////////////////////////////////
virtual ShdRendererNodeClass* Register_Mesh(ShdMeshClass* mesh,ShdSubMeshClass* sub_mesh)=0;
/////////////////////////////////////////////////////////////////////////////////////
// Flush all linked meshes to the rendering system
/////////////////////////////////////////////////////////////////////////////////////
virtual void Flush()=0;
};
/**
** ShdDX8Renderer
*/
class ShdDX8RendererClass : public ShdRendererClass
{
public:
ShdDX8RendererClass();
virtual ~ShdDX8RendererClass();
/////////////////////////////////////////////////////////////////////////////////////
// Register initialized a mesh for rendering. Note, these will need to be virtual
// if new types of renderers are created.
/////////////////////////////////////////////////////////////////////////////////////
virtual ShdRendererNodeClass* Register_Mesh(ShdMeshClass* mesh,ShdSubMeshClass* sub_mesh);
/////////////////////////////////////////////////////////////////////////////////////
// Flush all linked meshes to the rendering system
/////////////////////////////////////////////////////////////////////////////////////
virtual void Flush();
class MeshContainerClass;
private:
MeshContainerClass** MeshCategories;
};
#endif //SHDRENDERER_H

View File

@@ -0,0 +1,325 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shdsimple.cpp $*
* *
* $Org Author:: Kenny_m
*
* $Author:: Kenny_m
*
* $Modtime:: 7/12/02 3:12p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <d3dx8math.h>
#include "dx8fvf.h"
#include "dx8wrapper.h"
#include "assetmgr.h"
#include "shdsimple.h"
#include "editable.h"
#include "shdclassids.h"
#include "shddeffactory.h"
#include "shdinterface.h"
#include "shdhwshader.h"
#include "persistfactory.h"
#include "wwhack.h"
DECLARE_FORCE_LINK(SimpleShader);
REGISTER_SHDDEF(ShdSimpleDefClass,SHDDEF_CLASSID_SIMPLE,"Simple");
// Save-Load methods for ShdDefClass
enum
{
CHUNKID_VARIABLES = 0x16490450,
VARID_TEXTURE_NAME = 0x00,
VARID_AMBIENT_COLOR,
VARID_DIFFUSE_COLOR
};
ShdSimpleDefClass::ShdSimpleDefClass()
: ShdDefClass(SHDDEF_CLASSID_SIMPLE),
Ambient(1,1,1),
Diffuse(1,1,1)
{
NAMED_TEXTURE_FILENAME_PARAM(ShdSimpleDefClass, TextureName, "Texture Name", "Targa Files", ".tga");
NAMED_EDITABLE_PARAM(ShdSimpleDefClass, ParameterClass::TYPE_COLOR, Ambient, "Ambient");
NAMED_EDITABLE_PARAM(ShdSimpleDefClass, ParameterClass::TYPE_COLOR, Diffuse, "Diffuse");
}
ShdSimpleDefClass::ShdSimpleDefClass(const ShdSimpleDefClass& that)
: ShdDefClass(that),
Ambient(0,0,0),
Diffuse(1,1,1)
{
TextureName=that.TextureName;
Ambient=that.Ambient;
Diffuse=that.Diffuse;
}
ShdSimpleDefClass::~ShdSimpleDefClass()
{
}
bool ShdSimpleDefClass::Is_Valid_Config(StringClass &message)
{
return true;
}
bool ShdSimpleDefClass::Save(ChunkSaveClass &csave)
{
ShdDefClass::Save(csave);
csave.Begin_Chunk(CHUNKID_VARIABLES);
bool retval = true;
// only save the file name
char fname[_MAX_PATH];
_splitpath(TextureName,NULL,NULL,fname,NULL);
strcat(fname,".tga");
TextureName=fname;
WRITE_MICRO_CHUNK_WWSTRING(csave, VARID_TEXTURE_NAME, TextureName);
WRITE_MICRO_CHUNK(csave, VARID_AMBIENT_COLOR, Ambient);
WRITE_MICRO_CHUNK(csave, VARID_DIFFUSE_COLOR, Diffuse);
csave.End_Chunk();
return retval;
}
bool ShdSimpleDefClass::Load(ChunkLoadClass &cload)
{
ShdDefClass::Load(cload);
// Loop through all the microchunks that define the variables
while (cload.Open_Chunk()) {
switch (cload.Cur_Chunk_ID())
{
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk())
{
switch (cload.Cur_Micro_Chunk_ID())
{
READ_MICRO_CHUNK_WWSTRING(cload, VARID_TEXTURE_NAME, TextureName);
READ_MICRO_CHUNK(cload, VARID_AMBIENT_COLOR, Ambient);
READ_MICRO_CHUNK(cload, VARID_DIFFUSE_COLOR, Diffuse);
}
cload.Close_Micro_Chunk();
}
break;
default:
break;
}
cload.Close_Chunk();
}
return true;
}
void ShdSimpleDefClass::Init()
{
Shd6SimpleClass::Init();
}
void ShdSimpleDefClass::Shutdown()
{
Shd6SimpleClass::Shutdown();
}
ShdInterfaceClass* ShdSimpleDefClass::Create() const
{
return new Shd6SimpleClass(this);
}
Matrix4x4 Shd6SimpleClass::View_Projection_Matrix;
Shd6SimpleClass::Shd6SimpleClass(const ShdDefClass* def)
: ShdInterfaceClass(def,SHDDEF_CLASSID_SIMPLE),
Texture(NULL)
{
ShdSimpleDefClass* Definition=(ShdSimpleDefClass*)def;
Texture=WW3DAssetManager::Get_Instance()->Get_Texture
(
Definition->Get_Texture_Name()
);
const Vector3& a=Definition->Get_Ambient();
Ambient.Set(a.X,a.Y,a.Z,1.0f);
const Vector3& d=Definition->Get_Diffuse();
Diffuse.Set(d.X,d.Y,d.Z,1.0f);
Material=new D3DMATERIAL8;
memset(Material,0,sizeof(D3DMATERIAL8));
Material->Ambient.r=a.X; Material->Ambient.g=a.Y; Material->Ambient.b=a.Z;
Material->Diffuse.r=d.X; Material->Diffuse.g=d.Y; Material->Diffuse.b=d.Z;
}
Shd6SimpleClass::~Shd6SimpleClass()
{
REF_PTR_RELEASE(Texture);
}
void Shd6SimpleClass::Init()
{
}
void Shd6SimpleClass::Shutdown()
{
}
/**********************************************************************************************
//! Apply shared states for 1 pass DX6
/*! 7/12/02 3:39p KJM Created
*/
void Shd6SimpleClass::Apply_Shared(int pass, RenderInfoClass& rinfo)
{
// fixed function uses pass through by default
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU);
// set vertex shader
DX8Wrapper::Set_Vertex_Shader(DX8_FVF_XYZNDUV1);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Render_State(D3DRS_LIGHTING, TRUE);
DX8Wrapper::Set_DX8_Render_State(D3DRS_AMBIENTMATERIALSOURCE,D3DMCS_MATERIAL);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DIFFUSEMATERIALSOURCE,D3DMCS_MATERIAL);
DX8Wrapper::Set_DX8_Render_State(D3DRS_SPECULARMATERIALSOURCE,D3DMCS_MATERIAL);
DX8Wrapper::Set_DX8_Render_State(D3DRS_EMISSIVEMATERIALSOURCE,D3DMCS_MATERIAL);
}
//**********************************************************************************************
//! Apply per instance states for 1 pass DX6
/*! 7/10/02 5:39p KJM Created
*/
void Shd6SimpleClass::Apply_Instance(int cur_pass, RenderInfoClass& rinfo)
{
DX8Wrapper::Set_DX8_Material(Material);
DX8Wrapper::Set_Texture(0, Texture);
}
unsigned Shd6SimpleClass::Get_Vertex_Stream_Count() const
{
return 1;
}
unsigned Shd6SimpleClass::Get_Vertex_Size(unsigned stream) const
{
return sizeof(VertexFormatXYZNDUV1);
}
void Shd6SimpleClass::Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
)
{
VertexFormatXYZNDUV1* verts=(VertexFormatXYZNDUV1*)dest_buffer;
for (unsigned i=0; i<vertex_count; ++i)
{
if (vss.Locations)
{
verts[i].x=vss.Locations[i][0];
verts[i].y=vss.Locations[i][1];
verts[i].z=vss.Locations[i][2];
}
else
{
verts[i].x=0.0f;
verts[i].y=0.0f;
verts[i].z=0.0f;
}
if (vss.DiffuseInt)
{
verts[i].diffuse=vss.DiffuseInt[i];
}
else
{
verts[i].diffuse=0xffffffff;
}
if (vss.Normals)
{
verts[i].nx=vss.Normals[i][0];
verts[i].ny=vss.Normals[i][1];
verts[i].nz=vss.Normals[i][2];
}
else
{
verts[i].nx=0.0f;
verts[i].ny=0.0f;
verts[i].nz=0.0f;
}
if (vss.UV[0])
{
verts[i].u1=vss.UV[0][i].U;
verts[i].v1=vss.UV[0][i].V;
}
else
{
verts[i].u1=0.0f;
verts[i].v1=0.0f;
}
}
}

View File

@@ -0,0 +1,146 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWSHADE *
* *
* $Archive:: wwshade/shdsimple.cpp $*
* *
* $Org Author:: Kenny_m
*
* $Author:: Kenny_m
*
* $Modtime:: 7/12/02 3:12p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SHDSIMPLE_H
#define SHDSIMPLE_H
#ifndef SHDINTERFACE_H
#include "shdinterface.h"
#endif
#include "shddef.h"
class ShdSimpleDefClass : public ShdDefClass
{
public:
/////////////////////////////////////////////////////////////////////
// Editable interface requirements
/////////////////////////////////////////////////////////////////////
DECLARE_EDITABLE(ShdSimpleDefClass, ShdDefClass);
ShdSimpleDefClass();
ShdSimpleDefClass(const ShdSimpleDefClass& that);
virtual ~ShdSimpleDefClass();
virtual ShdDefClass* Clone() const { return new ShdSimpleDefClass(*this); }
// Shader Creation (should create a shader compatible with the current hardware/API)
virtual void Init();
virtual void Shutdown();
virtual ShdInterfaceClass* Create() const;
// Validation methods
virtual bool Is_Valid_Config(StringClass &message);
// Requirements
virtual bool Requires_Normals() const { return true; }
virtual bool Requires_Tangent_Space_Vectors() const { return false; }
virtual bool Requires_Sorting() const { return false; }
virtual int Static_Sort_Index() const { return 0; }
// From PersistClass
virtual bool Save(ChunkSaveClass &csave);
virtual bool Load(ChunkLoadClass &cload);
void Set_Texture_Name(const StringClass& name) { TextureName=name; }
const StringClass& Get_Texture_Name() const { return TextureName; }
void Set_Ambient(const Vector3& ambient) { Ambient=ambient; }
const Vector3& Get_Ambient() const { return Ambient; }
void Set_Diffuse(const Vector3& diffuse) { Diffuse=diffuse; }
const Vector3& Get_Diffuse() const { return Diffuse; }
private:
bool Save_Variables(ChunkSaveClass &csave);
bool Load_Variables(ChunkLoadClass &cload);
StringClass TextureName;
Vector3 Ambient;
Vector3 Diffuse;
};
class Shd6SimpleClass : public ShdInterfaceClass
{
public:
Shd6SimpleClass(const ShdDefClass* def);
virtual ~Shd6SimpleClass();
static void Init();
static void Shutdown();
virtual int Get_Pass_Count() { return 1; }
virtual int Get_Texture_Count() const { return 1; }
virtual TextureClass* Peek_Texture(int idx) const { return Texture; }
virtual void Apply_Shared(int cur_pass, RenderInfoClass& rinfo);
virtual void Apply_Instance(int cur_pass, RenderInfoClass& rinfo);
virtual unsigned Get_Vertex_Stream_Count() const;
virtual unsigned Get_Vertex_Size(unsigned stream) const;
virtual bool Use_HW_Vertex_Processing() const { return true; }
virtual void Copy_Vertex_Stream
(
unsigned stream,
void* dest_buffer,
const VertexStreamStruct& vss,
unsigned vertex_count
);
protected:
static Matrix4x4 View_Projection_Matrix;
D3DMATERIAL8* Material;
TextureClass* Texture;
Vector4 Ambient;
Vector4 Diffuse;
};
#endif //SHDSIMPLE_H

View File

@@ -0,0 +1,917 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWShade *
* *
* $Archive:: wwshade/shdsubmesh.cpp $*
* *
* Org Author:: Jani P *
* *
* Author : Kenny Mitchell *
* *
* $Modtime:: 07/12/02 10:31a $*
* *
* $Revision:: 1 $*
* *
* 07/12/02 KM Removed legacy mesh conversion *
*---------------------------------------------------------------------------------------------*
*---------------------------------------------------------------------------------------------*/
#include "shddefmanager.h"
#include "shdsubmesh.h"
#include "shdrenderer.h"
#include "shdlegacyw3d.h"
#include "shdclassids.h"
#include "chunkio.h"
#include "texture.h"
#include "w3d_file.h"
#include "ww3d.h"
#include "dx8fvf.h"
#include "dx8wrapper.h"
#include "meshmdl.h"
#include "texture.h"
#include "aabtree.h"
#include "sharebuf.h"
ShdSubMeshClass::ShdSubMeshClass(void)
:
Shader(NULL),
S(NULL),
T(NULL),
SxT(NULL),
Diffuse(NULL),
FirstVisiblePolygon(0),
VisiblePolygonCount(0),
Sorting(false)
{
for (int i=0;i<MAX_TEXTURE_STAGES;++i)
{
UV[i]=NULL;
}
}
ShdSubMeshClass::ShdSubMeshClass(const ShdSubMeshClass& that)
:
Shader(NULL),
S(NULL),
T(NULL),
SxT(NULL),
Diffuse(NULL),
FirstVisiblePolygon(that.FirstVisiblePolygon),
VisiblePolygonCount(that.VisiblePolygonCount),
Sorting(false)
{
for (int i=0;i<MAX_TEXTURE_STAGES;++i)
{
UV[i]=NULL;
}
*this = that;
}
ShdSubMeshClass & ShdSubMeshClass::operator = (const ShdSubMeshClass & that)
{
if (this != &that)
{
FirstVisiblePolygon=that.FirstVisiblePolygon;
VisiblePolygonCount=that.VisiblePolygonCount;
Sorting=that.Sorting;
REF_PTR_SET(Shader,that.Shader);
for (int i=0;i<MAX_TEXTURE_STAGES;++i)
{
REF_PTR_SET(UV[i],that.UV[i]);
}
REF_PTR_SET(S,that.S);
REF_PTR_SET(T,that.T);
REF_PTR_SET(SxT,that.SxT);
REF_PTR_SET(Diffuse,that.Diffuse);
MeshGeometryClass::operator =(that);
}
return * this;
}
ShdSubMeshClass::~ShdSubMeshClass(void)
{
REF_PTR_RELEASE(Shader);
for (int i=0;i<MAX_TEXTURE_STAGES;++i)
{
REF_PTR_RELEASE(UV[i]);
}
REF_PTR_RELEASE(S);
REF_PTR_RELEASE(T);
REF_PTR_RELEASE(SxT);
REF_PTR_RELEASE(Diffuse);
}
// The legacy renderer is FVF-based so we need to figure out what FVF format to use
static unsigned Define_FVF(MeshModelClass* mmc,bool enable_lighting)
{
if (mmc->Get_Flag(MeshGeometryClass::SKIN)) {
return dynamic_fvf_type;
}
if ((!!mmc->Get_Flag(MeshGeometryClass::SORT)) && WW3D::Is_Sorting_Enabled()) {
return dynamic_fvf_type;
}
unsigned fvf=D3DFVF_XYZ;
int tex_coord_count=mmc->Get_UV_Array_Count();
if (mmc->Get_Color_Array(0,false)) {
fvf|=D3DFVF_DIFFUSE;
}
if (mmc->Get_Color_Array(1,false)) {
fvf|=D3DFVF_SPECULAR;
}
switch (tex_coord_count) {
default:
case 0:
break;
case 1: fvf|=D3DFVF_TEX1; break;
case 2: fvf|=D3DFVF_TEX2; break;
case 3: fvf|=D3DFVF_TEX3; break;
case 4: fvf|=D3DFVF_TEX4; break;
case 5: fvf|=D3DFVF_TEX5; break;
case 6: fvf|=D3DFVF_TEX6; break;
case 7: fvf|=D3DFVF_TEX7; break;
case 8: fvf|=D3DFVF_TEX8; break;
}
if (!mmc->Needs_Vertex_Normals()) { //enable_lighting || mmc->Get_Flag(MeshModelClass::PRELIT_MASK)) {
return fvf;
}
fvf|=D3DFVF_NORMAL; // Realtime-lit
return fvf;
}
// The legacy renderer is FVF-based so we need to figure out what FVF format to use
static unsigned Define_FVF(ShdSubMeshClass* ssm,bool enable_lighting)
{
if (ssm->Get_Flag(MeshGeometryClass::SKIN)) {
return dynamic_fvf_type;
}
if ((!!ssm->Get_Flag(MeshGeometryClass::SORT)) && WW3D::Is_Sorting_Enabled()) {
return dynamic_fvf_type;
}
unsigned fvf=D3DFVF_XYZ;
int tex_coord_count=0;
for (tex_coord_count=0;tex_coord_count < MeshMatDescClass::MAX_TEX_STAGES; tex_coord_count++) {
if (ssm->Get_UV_Array(tex_coord_count) == NULL) {
break;
}
}
if (ssm->Get_Diffuse_Array() != NULL) {
fvf|=D3DFVF_DIFFUSE;
}
switch (tex_coord_count) {
default:
case 0:
break;
case 1: fvf|=D3DFVF_TEX1; break;
case 2: fvf|=D3DFVF_TEX2; break;
case 3: fvf|=D3DFVF_TEX3; break;
case 4: fvf|=D3DFVF_TEX4; break;
case 5: fvf|=D3DFVF_TEX5; break;
case 6: fvf|=D3DFVF_TEX6; break;
case 7: fvf|=D3DFVF_TEX7; break;
case 8: fvf|=D3DFVF_TEX8; break;
}
if (ssm->Get_Vertex_Normal_Array() != NULL) {
fvf|=D3DFVF_NORMAL; // Realtime-lit
}
return fvf;
}
void ShdSubMeshClass::Init_From_Legacy_Mesh_Model(MeshModelClass* model,int first_polygon)
{
WWASSERT(first_polygon<model->Get_Polygon_Count());
Sorting=!!model->Get_Flag(MeshGeometryClass::SORT) && WW3D::Is_Sorting_Enabled();
int pass;
// Figure out how many polygons we can use
int active_polygon_count=0;
bool arrays_used=false;
for (pass=0;pass<model->Get_Pass_Count() && !arrays_used;++pass) {
if (model->Has_Shader_Array(pass) || model->Has_Material_Array(pass)) {
arrays_used=true;
break;
}
for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
TextureClass* texture=NULL;
if (model->Has_Texture_Array(pass,stage)) {
arrays_used=true;
break;
}
}
}
// If any arrays are used by the mesh, count how many polygons we have that share properties.
if (arrays_used) {
bool stop=false;
active_polygon_count=0;
for (int poly=first_polygon;poly<model->Get_Polygon_Count() && !stop;++poly) {
for (pass=0;pass<model->Get_Pass_Count();++pass) {
if (model->Has_Shader_Array(pass)) {
if (model->Get_Shader(first_polygon,pass)!=model->Get_Shader(poly,pass)) {
stop=true;
break;
}
}
if (model->Has_Material_Array(pass)) {
TriIndex first_tri=model->Get_Polygon_Array()[first_polygon];
TriIndex cur_tri=model->Get_Polygon_Array()[poly];
if (model->Peek_Material(first_tri[0],pass)!=model->Peek_Material(cur_tri[0],pass) ||
model->Peek_Material(first_tri[1],pass)!=model->Peek_Material(cur_tri[1],pass) ||
model->Peek_Material(first_tri[2],pass)!=model->Peek_Material(cur_tri[2],pass)) {
stop=true;
break;
}
}
for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
if (model->Has_Texture_Array(pass,stage)) {
if (model->Peek_Texture(first_polygon,pass,stage)!=model->Peek_Texture(poly,pass,stage)) {
stop=true;
break;
}
}
}
}
active_polygon_count++;
}
}
FirstVisiblePolygon=first_polygon;
VisiblePolygonCount=active_polygon_count;
if (FirstVisiblePolygon!=0 && VisiblePolygonCount==0) {
VisiblePolygonCount=model->Get_Polygon_Count()-FirstVisiblePolygon;
}
WWASSERT(FirstVisiblePolygon+VisiblePolygonCount<=model->Get_Polygon_Count());
// Now that the definition is initialized, create a shader instance (there's really
// only one def/instance pair with the legacy meshes, no optimization planned currently)
ShdLegacyW3DDefClass* shader_def=NEW_REF( ShdLegacyW3DDefClass, () );
Shader=shader_def->Create();
REF_PTR_RELEASE(shader_def);
// Danger! We're assuming Shd6LegacyW3DClass is the only type created by legacy shader!!!
((Shd6LegacyW3DClass*)Shader)->Set_FVF(Define_FVF(model,true));
((Shd6LegacyW3DClass*)Shader)->Set_Pass_Count(model->Get_Pass_Count());
for (pass=0;pass<model->Get_Pass_Count();++pass) {
ShaderClass legacy_shader=ShaderClass::_PresetOpaqueShader;
if (model->Has_Shader_Array(pass)) {
legacy_shader=model->Get_Shader(first_polygon,pass);
}
else {
legacy_shader=model->Get_Single_Shader(pass);
}
VertexMaterialClass* legacy_material=NULL;
if (model->Has_Material_Array(pass)) {
TriIndex first_tri=model->Get_Polygon_Array()[first_polygon];
legacy_material=model->Get_Material(first_tri[0],pass);
}
else {
legacy_material=model->Get_Single_Material(pass);
}
for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
TextureClass* texture=NULL;
if (model->Has_Texture_Array(pass,stage)) {
texture=model->Get_Texture(first_polygon,pass,stage);
}
else {
texture=model->Get_Single_Texture(pass,stage);
}
if (texture) {
// StringClass texture_name=texture->Get_Full_Path();
// texture->Release_Ref();
// shader_def->Set_Texture_Name(pass,stage,texture_name);
((Shd6LegacyW3DClass*)Shader)->Set_Texture(pass,stage,texture);
texture->Release_Ref();
}
}
((Shd6LegacyW3DClass*)Shader)->Set_Shader(pass,legacy_shader);
((Shd6LegacyW3DClass*)Shader)->Set_Material(pass,legacy_material);
}
*(MeshGeometryClass*)this = *(MeshGeometryClass*)model;
if (CullTree)
CullTree->Set_Mesh(this);
// Copy texture coordinates
int uv_array_count=model->Get_UV_Array_Count();
WWASSERT(uv_array_count<=MAX_TEXTURE_STAGES);
for (int uvi=0;uvi<uv_array_count;++uvi) {
const Vector2 *uv=model->Get_UV_Array_By_Index(uvi);
if (uv) {
UV[uvi]=NEW_REF(ShareBufferClass<Vector2>,(model->Get_Vertex_Count(),"ShdSubMeshClass::UVCoords"));
memcpy(UV[uvi]->Get_Array(),uv,sizeof(Vector2)*model->Get_Vertex_Count());
}
}
// Copy vertex color array
const unsigned* diffuse=model->Get_DCG_Array(0);
if (diffuse) {
Diffuse=NEW_REF(ShareBufferClass<unsigned>,(model->Get_Vertex_Count(),"ShdSubMeshClass::Diffuse"));
memcpy(Diffuse->Get_Array(),diffuse,sizeof(unsigned)*model->Get_Vertex_Count());
}
}
WW3DErrorType ShdSubMeshClass::Load_W3D(ChunkLoadClass& cload)
{
// read header
W3dShdSubMeshHeaderStruct hdr;
cload.Open_Chunk();
if
(
cload.Read
(
&hdr,
sizeof(W3dShdSubMeshHeaderStruct)
)!=sizeof(W3dShdSubMeshHeaderStruct)
)
{
return WW3D_ERROR_LOAD_FAILED;
}
cload.Close_Chunk();
// process header
PolyCount=hdr.NumTris;
VertexCount=hdr.NumVertices;
if ((PolyCount!=0) && (VertexCount!=0))
{
Poly = NEW_REF(ShareBufferClass<TriIndex>,(PolyCount,"ShdSubMesh::Poly"));
PolySurfaceType = NEW_REF(ShareBufferClass<uint8>,(PolyCount,"ShdSubMesh::PolySurfaceType"));
Vertex = NEW_REF(ShareBufferClass<Vector3>,(VertexCount,"ShdSubMesh::Vertex"));
Poly->Clear();
PolySurfaceType->Clear();
Vertex->Clear();
#if (!OPTIMIZE_VNORM_RAM)
VertexNorm =NEW_REF(ShareBufferClass<Vector3>,(VertexCount,"ShdSubMesh::VertexNorm"));
VertexNorm->Clear();
#endif
}
BoundBoxMin.Set(hdr.BoxMin.X,hdr.BoxMin.Y,hdr.BoxMin.Z);
BoundBoxMax.Set(hdr.BoxMax.X,hdr.BoxMax.Y,hdr.BoxMax.Z);
BoundSphereCenter.Set(hdr.SphCenter.X,hdr.SphCenter.Y,hdr.SphCenter.Z);
BoundSphereRadius=hdr.SphRadius;
read_chunks(cload);
if ((Shader->Peek_Definition() != NULL) && (Shader->Peek_Definition()->Get_Class_ID() == SHDDEF_CLASSID_LEGACYW3D)) {
// Danger! We're assuming Shd6LegacyW3DClass is the only type created by legacy shader!!!
Shd6LegacyW3DClass * legacy_shader = (Shd6LegacyW3DClass*)Shader;
legacy_shader->Set_FVF(Define_FVF(this,true));
if (!legacy_shader->Is_Opaque()) {
Set_Flag(MeshGeometryClass::SORT,true);
}
}
return WW3D_ERROR_OK;
}
/***********************************************************************************************
* ShdSubMeshClass::read_chunks -- read w3d chunks *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/21/2002 kjm : Created. *
*=============================================================================================*/
WW3DErrorType ShdSubMeshClass::read_chunks(ChunkLoadClass& cload)
{
// If there are no more chunks within the mesh chunk,
// we are done.
while (cload.Open_Chunk())
{
// Process the chunk
WW3DErrorType error=WW3D_ERROR_OK;
switch (cload.Cur_Chunk_ID())
{
case W3D_CHUNK_SHDSUBMESH_VERTICES : error=read_vertices(cload); break;
case W3D_CHUNK_SHDSUBMESH_VERTEX_NORMALS : error=read_vertex_normals(cload); break;
case W3D_CHUNK_SHDSUBMESH_UV0 : error=read_uv0(cload); break;
case W3D_CHUNK_SHDSUBMESH_UV1 : error=read_uv1(cload); break;
case W3D_CHUNK_SHDSUBMESH_TANGENT_BASIS_S : error=read_tangent_basis_s(cload); break;
case W3D_CHUNK_SHDSUBMESH_TANGENT_BASIS_T : error=read_tangent_basis_t(cload); break;
case W3D_CHUNK_SHDSUBMESH_TANGENT_BASIS_SxT : error=read_tangent_basis_sxt(cload); break;
case W3D_CHUNK_SHDSUBMESH_TRIANGLES : error=read_triangles(cload); break;
case W3D_CHUNK_SHDSUBMESH_VERTEX_SHADE_INDICES : error=read_vertex_shade_indices(cload); break;
case W3D_CHUNK_SHDSUBMESH_SHADER : error=read_shader(cload); break;
case W3D_CHUNK_SHDSUBMESH_VERTEX_INFLUENCES : error=read_vertex_influences(cload); break;
default: break;
}
cload.Close_Chunk();
if (error!=WW3D_ERROR_OK)
{
return error;
}
}
return WW3D_ERROR_OK;
}
/***********************************************************************************************
* ShdSubMeshClass::read_vertices -- read the vertex chunk from a W3D file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/21/2002 kjm : Created. *
*=============================================================================================*/
WW3DErrorType ShdSubMeshClass::read_vertices(ChunkLoadClass& cload)
{
W3dVectorStruct vert;
Vector3* loc=Vertex->Get_Array();
assert(loc);
for (int i=0; i<Get_Vertex_Count(); i++)
{
if (cload.Read(&vert,sizeof(W3dVectorStruct)) != sizeof(W3dVectorStruct))
{
return WW3D_ERROR_LOAD_FAILED;
}
loc[i].X=vert.X;
loc[i].Y=vert.Y;
loc[i].Z=vert.Z;
}
return WW3D_ERROR_OK;
}
/***********************************************************************************************
* ShdSubMeshClass::read_vertex_normals -- read the vertex normals chunk from a w3d file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/21/2002 kjm : Created. *
*=============================================================================================*/
WW3DErrorType ShdSubMeshClass::read_vertex_normals(ChunkLoadClass& cload)
{
W3dVectorStruct norm;
Vector3 * mdlnorms=get_vert_normals();
WWASSERT(mdlnorms);
for (int i=0; i<VertexCount; i++)
{
if (cload.Read(&norm,sizeof(W3dVectorStruct)) != sizeof(W3dVectorStruct))
{
return WW3D_ERROR_LOAD_FAILED;
}
mdlnorms[i].Set(norm.X,norm.Y,norm.Z);
}
return WW3D_ERROR_OK;
}
/***********************************************************************************************
* ShdSubMeshClass::read_uv0 -- read the texture coords chunk from a w3d file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/26/2002 kjm : Created. *
*=============================================================================================*/
WW3DErrorType ShdSubMeshClass::read_uv0(ChunkLoadClass& cload)
{
UV[0]=NEW_REF(ShareBufferClass<Vector2>,(VertexCount,"ShdSubMeshClass::UV"));
UV[0]->Clear();
Vector2* uv=UV[0]->Get_Array();
for (int i=0; i<VertexCount; i++)
{
if
(
cload.Read
(
uv++,
sizeof(Vector2)
)!=sizeof(Vector2)
)
{
return WW3D_ERROR_LOAD_FAILED;
}
}
return WW3D_ERROR_OK;
}
/***********************************************************************************************
* ShdSubMeshClass::read_uv1 -- read the texture coords chunk from a w3d file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/26/2002 kjm : Created. *
*=============================================================================================*/
WW3DErrorType ShdSubMeshClass::read_uv1(ChunkLoadClass& cload)
{
UV[1]=NEW_REF(ShareBufferClass<Vector2>,(VertexCount,"ShdSubMeshClass::UV"));
UV[1]->Clear();
Vector2* uv=UV[1]->Get_Array();
for (int i=0; i<VertexCount; i++)
{
if
(
cload.Read
(
uv++,
sizeof(Vector2)
)!=sizeof(Vector2)
)
{
return WW3D_ERROR_LOAD_FAILED;
}
}
return WW3D_ERROR_OK;
}
/***********************************************************************************************
* ShdSubMeshClass::read_tangent_basis_s -- read the tangent basis chunk from a w3d file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/26/2002 kjm : Created. *
*=============================================================================================*/
WW3DErrorType ShdSubMeshClass::read_tangent_basis_s(ChunkLoadClass& cload)
{
S=NEW_REF(ShareBufferClass<Vector3>,(VertexCount,"ShdSubMeshClass::S"));
S->Clear();
Vector3* t=S->Get_Array();
for (int i=0; i<VertexCount; i++)
{
if
(
cload.Read
(
t++,
sizeof(Vector3)
)!=sizeof(Vector3)
)
{
return WW3D_ERROR_LOAD_FAILED;
}
}
return WW3D_ERROR_OK;
}
/***********************************************************************************************
* ShdSubMeshClass::read_tangent_basis_t -- read the tangent basis chunk from a w3d file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/26/2002 kjm : Created. *
*=============================================================================================*/
WW3DErrorType ShdSubMeshClass::read_tangent_basis_t(ChunkLoadClass& cload)
{
T=NEW_REF(ShareBufferClass<Vector3>,(VertexCount,"ShdSubMeshClass::T"));
T->Clear();
Vector3* t=T->Get_Array();
for (int i=0; i<VertexCount; i++)
{
if
(
cload.Read
(
t++,
sizeof(Vector3)
)!=sizeof(Vector3)
)
{
return WW3D_ERROR_LOAD_FAILED;
}
}
return WW3D_ERROR_OK;
}
/***********************************************************************************************
* ShdSubMeshClass::read_tangent_basis_sxt -- read the tangent basis chunk from a w3d file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/26/2002 kjm : Created. *
*=============================================================================================*/
WW3DErrorType ShdSubMeshClass::read_tangent_basis_sxt(ChunkLoadClass& cload)
{
SxT=NEW_REF(ShareBufferClass<Vector3>,(VertexCount,"ShdSubMeshClass::SxT"));
SxT->Clear();
Vector3* t=SxT->Get_Array();
for (int i=0; i<VertexCount; i++)
{
if
(
cload.Read
(
t++,
sizeof(Vector3)
)!=sizeof(Vector3)
)
{
return WW3D_ERROR_LOAD_FAILED;
}
}
return WW3D_ERROR_OK;
}
/***********************************************************************************************
* ShdSubMeshClass::read_vertex_influences -- read the vertex bone links from a w3d file *
* *
* This is for WWSKin support, presumably when we implement HW skining this may become obsolete*
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 11/07/2002 gth: Created *
*=============================================================================================*/
WW3DErrorType ShdSubMeshClass::read_vertex_influences(ChunkLoadClass& cload)
{
uint16 * bone_links = get_bone_links();
for (int i=0; i<VertexCount; i++)
{
if
(
cload.Read
(
bone_links++,
sizeof(uint8)
)!=sizeof(uint8)
)
{
return WW3D_ERROR_LOAD_FAILED;
}
}
Set_Flag(SKIN,true);
return WW3D_ERROR_OK;
}
/***********************************************************************************************
* ShdSubMeshClass::read_triangles -- read the triangles chunk from a w3d file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/21/2002 kjm : Created. *
*=============================================================================================*/
WW3DErrorType ShdSubMeshClass::read_triangles(ChunkLoadClass & cload)
{
unsigned short tri[3];
// cache pointers to various arrays in the surrender mesh
TriIndex * vi = get_polys();
Set_Flag(DIRTY_PLANES,false);
// Vector4 * peq = get_planes();
// uint8 * surface_types = Get_Poly_Surface_Type_Array();
// read in each polygon one by one
for (int i=0; i<Get_Polygon_Count(); i++)
{
if
(
cload.Read
(
tri,
sizeof(unsigned short)*3
)!=sizeof(unsigned short)*3
)
{
return WW3D_ERROR_LOAD_FAILED;
}
// set the vertex indices
vi[i].I = tri[0];
vi[i].J = tri[1];
vi[i].K = tri[2];
// set the normal
/*peq[i].X = tri.Normal.X;
peq[i].Y = tri.Normal.Y;
peq[i].Z = tri.Normal.Z;
peq[i].W = -tri.Dist;
// set the surface type
WWASSERT(tri.Attributes < 256);
surface_types[i] = (uint8)(tri.Attributes);*/
}
return WW3D_ERROR_OK;
}
/***********************************************************************************************
* ShdSubMeshClass::read_vertex_shade_indices -- read the vertex shade indices chunk *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/21/2002 kjm : Created. *
*=============================================================================================*/
WW3DErrorType ShdSubMeshClass::read_vertex_shade_indices(ChunkLoadClass & cload)
{
uint32 * shade_index = get_shade_indices(true);
uint32 si;
for (int i=0; i<Get_Vertex_Count(); i++)
{
if (cload.Read(&si,sizeof(uint32)) != sizeof(uint32))
{
return WW3D_ERROR_LOAD_FAILED;
}
shade_index[i] = si;
}
return WW3D_ERROR_OK;
}
/***********************************************************************************************
* ShdSubMeshClass::read_shader -- read the shader chunk *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 5/21/2002 kjm : Created. *
*=============================================================================================*/
WW3DErrorType ShdSubMeshClass::read_shader(ChunkLoadClass& cload)
{
// load the shader definition
ShdDefClass* shddef=NULL;
ShdDefManagerClass::Load_Shader(cload, &shddef);
// create the shader interface
Shader=shddef->Create();
REF_PTR_RELEASE(shddef);
return WW3D_ERROR_OK;
}
/***********************************************************************************************
* ShdSubMesh::Get_Deformed_Vertices -- Gets the deformed vertices for a skin *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 3/4/2001 gth : Created. *
*=============================================================================================*/
void ShdSubMeshClass::Get_Deformed_Vertices(Vector3 *dst_vert, Vector3 *dst_norm, const HTreeClass* htree)
{
WWASSERT(Get_Flag(MeshGeometryClass::SKIN));
WWASSERT(htree);
get_deformed_vertices(dst_vert,dst_norm,htree);
}
/***********************************************************************************************
* ShdSubMeshClass::Get_Deformed_Vertices -- Gets the deformed vertices for a skin *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 3/4/2001 gth : Created. *
*=============================================================================================*/
void ShdSubMeshClass::Get_Deformed_Vertices(Vector3 *dst_vert,const HTreeClass* htree)
{
WWASSERT(Get_Flag(MeshGeometryClass::SKIN));
WWASSERT(htree);
get_deformed_vertices(dst_vert,htree);
}

View File

@@ -0,0 +1,173 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWShade *
* *
* $Archive:: wwshade/shdsubmesh.h $*
* *
* Org Author:: Jani P *
* *
* Author : Kenny Mitchell *
* *
* $Modtime:: 07/12/02 10:31a $*
* *
* $Revision:: 1 $*
* *
* 07/12/02 KM Removed legacy mesh conversion *
*---------------------------------------------------------------------------------------------*
*---------------------------------------------------------------------------------------------*/
#ifndef SHDSUBMESH_H
#define SHDSUBMESH_H
#include "always.h"
#include "meshgeometry.h"
#include "shdinterface.h"
#include "dx8wrapper.h"
#include "sharebuf.h"
class DecalGeneratorClass;
class ShdInterfaceClass;
class RenderInfoClass;
class MeshModelClass;
class HTreeClass;
/**
** ShdSubMeshClass - A single ShdMeshClass instance will contain one or more ShdSubMeshClass.
** The "sub-mesh" is a collection of polygons who all use the same shader.
*/
class ShdSubMeshClass : public MeshGeometryClass
{
public:
W3DMPO_GLUE(ShdSubMeshClass);
ShdSubMeshClass(void);
ShdSubMeshClass(const ShdSubMeshClass & that);
~ShdSubMeshClass(void);
ShdSubMeshClass & operator = (const ShdSubMeshClass & that);
void Reset(int polycount,int vertcount);
// unsigned Get_Vertex_Stream_Count();
// unsigned Get_Vertex_Size(unsigned stream);
// void Copy_Vertex_Stream(unsigned stream, void* buffer);
/////////////////////////////////////////////////////////////////////////////////////
// Material interface, All of these functions call through to the current
// material decription.
/////////////////////////////////////////////////////////////////////////////////////
void Set_Shader(ShdInterfaceClass * shader) { REF_PTR_SET(Shader,shader); }
ShdInterfaceClass * Peek_Shader(void) const { return Shader; }
/////////////////////////////////////////////////////////////////////////////////////
// Decal interface
/////////////////////////////////////////////////////////////////////////////////////
void Create_Decal(DecalGeneratorClass * generator);
void Delete_Decal(uint32 decal_id);
void Init_From_Legacy_Mesh_Model(MeshModelClass* model,int first_polygon);
/////////////////////////////////////////////////////////////////////////////////////
// Load from a W3D File
/////////////////////////////////////////////////////////////////////////////////////
WW3DErrorType Load_W3D(ChunkLoadClass& cload);
const Vector2* Get_UV_Array(unsigned stage) { return UV[stage] ? UV[stage]->Get_Array() : NULL; }
const unsigned* Get_Diffuse_Array() { return Diffuse ? Diffuse->Get_Array() : NULL; }
const Vector3* Get_Tangent_Basis_S_Array() { return S ? S->Get_Array() : NULL; }
const Vector3* Get_Tangent_Basis_T_Array() { return T ? T->Get_Array() : NULL; }
const Vector3* Get_Tangent_Basis_SxT_Array() { return SxT ? SxT->Get_Array() : NULL; }
// First and last visible polygon. Default is both zero, which means that all polygons
// are visible.
int Get_First_Visible_Polygon() const { return FirstVisiblePolygon; }
int Get_Visible_Polygon_Count() const { return VisiblePolygonCount; }
bool Is_Sorting() const { return Sorting; }
void Get_Deformed_Vertices(Vector3 *dst_vert, Vector3 *dst_norm, const HTreeClass* htree);
void Get_Deformed_Vertices(Vector3 *dst_vert, const HTreeClass* htree);
protected:
ShareBufferClass<Vector2> * UV[MAX_TEXTURE_STAGES];
ShareBufferClass<unsigned> * Diffuse;
ShareBufferClass<Vector3>* S;
ShareBufferClass<Vector3>* T;
ShareBufferClass<Vector3>* SxT;
int FirstVisiblePolygon;
int VisiblePolygonCount;
bool Sorting;
// MeshClass will set this for skins so that they can get the bone transforms
// void Set_HTree(const HTreeClass * htree);
protected:
// functions to compute the deformed vertices of skins.
// Destination pointers MUST point to arrays large enough to hold all vertices
// void get_deformed_vertices(Vector3 *dst_vert, Vector3 *dst_norm, const HTreeClass * htree);
// void get_deformed_vertices(Vector3 *dst_vert, const HTreeClass * htree);
// void get_deformed_screenspace_vertices(Vector4 *dst_vert,const RenderInfoClass & rinfo,const Matrix3D & mesh_tm,const HTreeClass * htree);
// loading
WW3DErrorType read_chunks(ChunkLoadClass& cload);
WW3DErrorType read_vertices(ChunkLoadClass& cload);
WW3DErrorType read_vertex_normals(ChunkLoadClass& cload);
WW3DErrorType read_uv0(ChunkLoadClass& cload);
WW3DErrorType read_uv1(ChunkLoadClass& cload);
WW3DErrorType read_tangent_basis_s(ChunkLoadClass& cload);
WW3DErrorType read_tangent_basis_t(ChunkLoadClass& cload);
WW3DErrorType read_tangent_basis_sxt(ChunkLoadClass& cload);
WW3DErrorType read_vertex_influences(ChunkLoadClass& cload);
WW3DErrorType read_triangles(ChunkLoadClass& cload);
WW3DErrorType read_vertex_shade_indices(ChunkLoadClass& cload);
WW3DErrorType read_shader(ChunkLoadClass& cload);
// WW3DErrorType read_texcoords(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_materials(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_v2_materials(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_v3_materials(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_per_tri_materials(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_vertex_colors(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_material_info(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_shaders(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_vertex_materials(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_textures(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_material_pass(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_vertex_material_ids(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_shader_ids(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_scg(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_dig(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_dcg(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_texture_stage(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_texture_ids(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_stage_texcoords(ChunkLoadClass & cload,ShdMeshLoadContextClass * context);
// WW3DErrorType read_per_face_texcoord_ids (ChunkLoadClass &cload, ShdMeshLoadContextClass *context);
// WW3DErrorType read_prelit_material (ChunkLoadClass &cload, ShdMeshLoadContextClass *context);
ShdInterfaceClass * Shader;
};
#endif //SHDSUBMESH_H

File diff suppressed because it is too large Load Diff