4796 lines
143 KiB
C++
4796 lines
143 KiB
C++
/*=============================================================================
|
|
D3DRendPipeline.cpp : Direct3D specific rendering using shaders pipeline.
|
|
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
|
|
|
Revision history:
|
|
* Created by Honitch Andrey
|
|
|
|
=============================================================================*/
|
|
|
|
#include "stdafx.h"
|
|
#include "DriverD3D8.h"
|
|
#include "..\common\shadow_renderer.h"
|
|
#include "D3DPShaders.h"
|
|
#include "D3DCGVProgram.h"
|
|
#include "I3dengine.h"
|
|
#include "CryHeaders.h"
|
|
|
|
//============================================================================================
|
|
// Shaders rendering
|
|
//============================================================================================
|
|
|
|
//============================================================================================
|
|
// Init Shaders rendering
|
|
|
|
void CD3D8Renderer::EF_InitRandTables()
|
|
{
|
|
int i;
|
|
float f;
|
|
|
|
for (i=0; i<256; i++)
|
|
{
|
|
f = (float)rand() / 32767.0f;
|
|
m_RP.m_tRandFloats[i] = f + f - 1.0f;
|
|
|
|
m_RP.m_tRandBytes[i] = (byte)((float)rand() / 32767.0f * 255.0f);
|
|
}
|
|
}
|
|
|
|
void CD3D8Renderer::EF_InitWaveTables()
|
|
{
|
|
int i;
|
|
|
|
//Init wave Tables
|
|
for (i=0; i<1024; i++)
|
|
{
|
|
float f = (float)i;
|
|
|
|
m_RP.m_tSinTable[i] = (float)sin(f * (360.0/1023.0) * M_PI / 180.0);
|
|
m_RP.m_tHalfSinTable[i] = (float)sin(f * (360.0/1023.0) * M_PI / 180.0);
|
|
if (m_RP.m_tHalfSinTable[i] < 0)
|
|
m_RP.m_tHalfSinTable[i] = 0;
|
|
m_RP.m_tCosTable[i] = (float)cos(f * (360.0/1023.0) * M_PI / 180.0);
|
|
m_RP.m_tHillTable[i] = (float)sin(f * (180.0/1023.0) * M_PI / 180.0);
|
|
|
|
if (i < 512)
|
|
m_RP.m_tSquareTable[i] = 1.0f;
|
|
else
|
|
m_RP.m_tSquareTable[i] = -1.0f;
|
|
|
|
m_RP.m_tSawtoothTable[i] = f / 1024.0f;
|
|
m_RP.m_tInvSawtoothTable[i] = 1.0f - m_RP.m_tSawtoothTable[i];
|
|
|
|
if (i < 512)
|
|
{
|
|
if (i < 256)
|
|
m_RP.m_tTriTable[i] = f / 256.0f;
|
|
else
|
|
m_RP.m_tTriTable[i] = 1.0f - m_RP.m_tTriTable[i-256];
|
|
}
|
|
else
|
|
m_RP.m_tTriTable[i] = 1.0f - m_RP.m_tTriTable[i-512];
|
|
}
|
|
}
|
|
|
|
void CD3D8Renderer::EF_InitEvalFuncs(int num)
|
|
{
|
|
switch(num)
|
|
{
|
|
case 0:
|
|
m_RP.m_pCurFuncs = &m_RP.m_EvalFuncs_C;
|
|
break;
|
|
default:
|
|
case 1:
|
|
m_RP.m_pCurFuncs = &m_RP.m_EvalFuncs_RE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
int CD3D8Renderer::EF_RegisterFogVolume(float fMaxFogDist, float fFogLayerZ, CFColor color)
|
|
{
|
|
SMFog Fog;
|
|
memset(&Fog,0,sizeof(Fog));
|
|
|
|
Fog.m_fMaxDist = fMaxFogDist;
|
|
Fog.m_FogInfo.m_FogColor = color;
|
|
Fog.m_Dist = fFogLayerZ;
|
|
Fog.m_Color = color;
|
|
Fog.m_Color.a = 1.0f;
|
|
//Fog.m_FogInfo.m_FogColor = m_FogColor;
|
|
Fog.m_Normal = Vec3d(0,0,1);
|
|
|
|
m_RP.m_FogVolumes.AddElem(Fog);
|
|
|
|
return m_RP.m_FogVolumes.Num()-1;
|
|
}
|
|
|
|
void CD3D8Renderer::EF_InitFogVolumes()
|
|
{
|
|
SMFog Fog;
|
|
memset(&Fog,0,sizeof(Fog));
|
|
m_RP.m_FogVolumes.AddElem(Fog); // register fake zero element
|
|
}
|
|
|
|
|
|
struct SVB
|
|
{
|
|
int Stride;
|
|
int OffsD;
|
|
int OffsT;
|
|
int OffsN;
|
|
int FVF;
|
|
UStaticVB mVB;
|
|
};
|
|
|
|
|
|
static SVB sSVB[] =
|
|
{
|
|
{STRIDE_D_1T, 12, 16, 0, D3DFVF_VERTEX_D_1T},
|
|
{STRIDE_D_2T, 12, 16, 0, D3DFVF_VERTEX_D_2T},
|
|
{STRIDE_D_3T, 12, 16, 0, D3DFVF_VERTEX_D_3T},
|
|
{STRIDE_D_4T, 12, 16, 0, D3DFVF_VERTEX_D_4T},
|
|
{STRIDE_N_D_1T, 24, 28, 12, D3DFVF_VERTEX_N_D_1T},
|
|
{STRIDE_N_D_2T, 24, 28, 12, D3DFVF_VERTEX_N_D_2T},
|
|
{STRIDE_N_D_3T, 24, 28, 12, D3DFVF_VERTEX_N_D_3T},
|
|
{STRIDE_N_D_4T, 24, 28, 12, D3DFVF_VERTEX_N_D_4T},
|
|
{STRIDE_TR_D_1T, 16, 24, 0, D3DFVF_TRVERTEX_D_1T},
|
|
{STRIDE_TR_D_2T, 16, 24, 0, D3DFVF_TRVERTEX_D_2T},
|
|
{STRIDE_TR_D_3T, 16, 24, 0, D3DFVF_TRVERTEX_D_3T},
|
|
{STRIDE_TR_D_4T, 16, 24, 0, D3DFVF_TRVERTEX_D_4T},
|
|
{0}
|
|
};
|
|
|
|
void CD3D8Renderer::EF_InitD3DFixedPipeline()
|
|
{
|
|
if (m_RP.m_D3DFixedPipeline[0][0].m_Declaration.Num())
|
|
return;
|
|
|
|
int n = 0;
|
|
{
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = sSVB[0].FVF;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT4)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = sSVB[1].FVF;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT4)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT4)); // texture coords 1
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = sSVB[2].FVF;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT4)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT4)); // texture coords 1
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD2, D3DVSDT_FLOAT4)); // texture coords 2
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = sSVB[3].FVF;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT4)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT4)); // texture coords 1
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD2, D3DVSDT_FLOAT4)); // texture coords 2
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD3, D3DVSDT_FLOAT4)); // texture coords 3
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = sSVB[4].FVF;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3)); // normal
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT4)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = sSVB[5].FVF;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3)); // normal
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT4)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT4)); // texture coords 1
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = sSVB[6].FVF;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3)); // normal
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT4)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT4)); // texture coords 1
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD2, D3DVSDT_FLOAT4)); // texture coords 2
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = sSVB[7].FVF;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3)); // normal
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT4)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT4)); // texture coords 1
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD2, D3DVSDT_FLOAT4)); // texture coords 2
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD3, D3DVSDT_FLOAT4)); // texture coords 3
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = sSVB[8].FVF;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT4)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT4)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = sSVB[9].FVF;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT4)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT4)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT4)); // texture coords 1
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = sSVB[10].FVF;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT4)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT4)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT4)); // texture coords 1
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD2, D3DVSDT_FLOAT4)); // texture coords 2
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = sSVB[11].FVF;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT4)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT4)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT4)); // texture coords 1
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD2, D3DVSDT_FLOAT4)); // texture coords 2
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD3, D3DVSDT_FLOAT4)); // texture coords 3
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
|
|
// base formats declarations (stream 0)
|
|
n = 16;
|
|
{
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = 0;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{ // VERTEX_FORMAT_P3F
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = D3DFVF_XYZ;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{ // VERTEX_FORMAT_P3F_COL4UB
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = D3DFVF_XYZ | D3DFVF_DIFFUSE;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{ // VERTEX_FORMAT_P3F_TEX2F
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = D3DFVF_XYZ | D3DFVF_TEX1;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{ // VERTEX_FORMAT_P3F_COL4UB_TEX2F
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{ // VERTEX_FORMAT_TRP3F_COL4UB_TEX2F
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT4)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{ // VERTEX_FORMAT_P3F_COL4UB_COL4UB
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_SPECULAR, D3DVSDT_D3DCOLOR)); // specular
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{ // VERTEX_FORMAT_P3F_N
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = D3DFVF_XYZ | D3DFVF_NORMAL;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3)); // normal
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{ // VERTEX_FORMAT_P3F_N_COL4UB
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3)); // normal
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{ // VERTEX_FORMAT_P3F_N_TEX2F
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3)); // normal
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
{ // VERTEX_FORMAT_P3F_N_COL4UB_TEX2F
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Handle = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_STREAM(0));
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3)); // position
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3)); // normal
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR)); // diffuse
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2)); // texture coords 0
|
|
m_RP.m_D3DFixedPipeline[0][n].m_Declaration.AddElem(D3DVSD_END());
|
|
n++;
|
|
}
|
|
|
|
// Additional streams:
|
|
// stream 1 (tangent vectors)
|
|
for (int i=0; i<32; i++)
|
|
{
|
|
if (!m_RP.m_D3DFixedPipeline[0][i].m_Declaration.Num())
|
|
continue;
|
|
m_RP.m_D3DFixedPipeline[1][i].m_Handle = m_RP.m_D3DFixedPipeline[0][i].m_Handle;
|
|
for (int j=0; j<m_RP.m_D3DFixedPipeline[0][i].m_Declaration.Num()-1; j++)
|
|
{
|
|
m_RP.m_D3DFixedPipeline[1][i].m_Declaration.AddElem(m_RP.m_D3DFixedPipeline[0][i].m_Declaration[j]);
|
|
}
|
|
m_RP.m_D3DFixedPipeline[1][i].m_Declaration.AddElem(D3DVSD_STREAM(1));
|
|
m_RP.m_D3DFixedPipeline[1][i].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD2, D3DVSDT_FLOAT3)); // tangent
|
|
m_RP.m_D3DFixedPipeline[1][i].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD3, D3DVSDT_FLOAT3)); // binormals
|
|
m_RP.m_D3DFixedPipeline[1][i].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_BLENDWEIGHT, D3DVSDT_FLOAT3)); // tnormals
|
|
m_RP.m_D3DFixedPipeline[1][i].m_Declaration.AddElem(D3DVSD_END());
|
|
}
|
|
|
|
// stream 2 (LM texcoords)
|
|
for (int i=0; i<32; i++)
|
|
{
|
|
if (!m_RP.m_D3DFixedPipeline[0][i].m_Declaration.Num())
|
|
continue;
|
|
for (int j=0; j<m_RP.m_D3DFixedPipeline[0][i].m_Declaration.Num()-1; j++)
|
|
{
|
|
m_RP.m_D3DFixedPipeline[2][i].m_Declaration.AddElem(m_RP.m_D3DFixedPipeline[0][i].m_Declaration[j]);
|
|
}
|
|
m_RP.m_D3DFixedPipeline[2][i].m_Declaration.AddElem(D3DVSD_STREAM(2));
|
|
m_RP.m_D3DFixedPipeline[2][i].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT2)); // LM texcoords
|
|
m_RP.m_D3DFixedPipeline[2][i].m_Declaration.AddElem(D3DVSD_END());
|
|
}
|
|
|
|
// stream 1 and 2 (tangent vectors and LM texcoords)
|
|
for (int i=0; i<32; i++)
|
|
{
|
|
if (!m_RP.m_D3DFixedPipeline[0][i].m_Declaration.Num())
|
|
continue;
|
|
for (int j=0; j<m_RP.m_D3DFixedPipeline[0][i].m_Declaration.Num()-1; j++)
|
|
{
|
|
m_RP.m_D3DFixedPipeline[3][i].m_Declaration.AddElem(m_RP.m_D3DFixedPipeline[0][i].m_Declaration[j]);
|
|
}
|
|
m_RP.m_D3DFixedPipeline[3][i].m_Declaration.AddElem(D3DVSD_STREAM(1));
|
|
m_RP.m_D3DFixedPipeline[3][i].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD2, D3DVSDT_FLOAT3)); // tangent
|
|
m_RP.m_D3DFixedPipeline[3][i].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD3, D3DVSDT_FLOAT3)); // binormals
|
|
m_RP.m_D3DFixedPipeline[3][i].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_BLENDWEIGHT, D3DVSDT_FLOAT3)); // tnormals
|
|
m_RP.m_D3DFixedPipeline[3][i].m_Declaration.AddElem(D3DVSD_STREAM(2));
|
|
m_RP.m_D3DFixedPipeline[3][i].m_Declaration.AddElem(D3DVSD_REG(D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT2)); // LM texcoord
|
|
m_RP.m_D3DFixedPipeline[3][i].m_Declaration.AddElem(D3DVSD_END());
|
|
}
|
|
|
|
m_MaxVertBufferSize = (int)10*1024*1024;
|
|
m_CurVertBufferSize = 0;
|
|
}
|
|
|
|
_inline static void *sAlign0x20(byte *vrts)
|
|
{
|
|
int b = (int)vrts;
|
|
|
|
if (!(b & 0x1f))
|
|
return vrts;
|
|
|
|
b = (b+0x20)&0xffffffe0;
|
|
|
|
return (void *)b;
|
|
}
|
|
|
|
void CD3D8Renderer::EF_Init()
|
|
{
|
|
bool nv = 0;
|
|
|
|
m_RP.m_pCurFuncs = NULL;
|
|
m_RP.m_MaxVerts = CV_d3d8_rb_verts;
|
|
m_RP.m_MaxTris = CV_d3d8_rb_tris;
|
|
|
|
iLog->Log("\nAllocate render buffer (%d verts, %d tris)...\n", m_RP.m_MaxVerts, m_RP.m_MaxTris);
|
|
|
|
int n = 0;
|
|
|
|
n += STRIDE_N_D_4T * m_RP.m_MaxVerts + 32;
|
|
|
|
//m_RP.mFogVertValues
|
|
n += sizeof(float)*m_RP.m_MaxVerts+32;
|
|
//m_RP.mBaseTexCoordPointer
|
|
n += sizeof(SMRendTexVert)*m_RP.m_MaxVerts+32;
|
|
//m_RP.mLMTexCoordPointer
|
|
n += sizeof(SMRendTexVert)*m_RP.m_MaxVerts+32;
|
|
//m_RP.mClientColors
|
|
n += sizeof(bvec4)*m_RP.m_MaxVerts+32;
|
|
|
|
//m_RP.mRendIndices;
|
|
n += sizeof(ushort)*3*m_RP.m_MaxTris+32;
|
|
|
|
int i;
|
|
if (GetFeatures() & RFT_BUMP_DOT3)
|
|
{
|
|
//m_RP.mBinormals
|
|
n += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
//m_RP.mTangents
|
|
n += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
//m_RP.mTNormals
|
|
n += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
for (i=0; i<4; i++)
|
|
{
|
|
//m_RP.mHalfAngleVectors
|
|
n += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
//m_RP.mLightVectors
|
|
n += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
}
|
|
//m_RP.mAttenuation
|
|
n += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
//m_RP.mLAttenSpec0
|
|
n += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
//m_RP.mLAttenSpec1
|
|
n += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
}
|
|
|
|
byte *buf = new byte [n];
|
|
m_SysArray = buf;
|
|
if (!buf)
|
|
iConsole->Exit("Can't allocate buffers for RB");
|
|
|
|
memset(buf, 0, n);
|
|
|
|
m_RP.m_Ptr.Ptr = sAlign0x20(buf);
|
|
buf += STRIDE_N_D_4T * m_RP.m_MaxVerts + 32;
|
|
m_RP.m_RendIndices = (ushort *)sAlign0x20(buf);
|
|
buf += sizeof(ushort)*3*m_RP.m_MaxTris+32;
|
|
m_RP.m_pClientColors = (bvec4 *)sAlign0x20(buf);
|
|
buf += sizeof(bvec4)*m_RP.m_MaxVerts+32;
|
|
m_RP.m_pBaseTexCoordPointer = (SMRendTexVert *)sAlign0x20(buf);
|
|
buf += sizeof(SMRendTexVert)*m_RP.m_MaxVerts+32;
|
|
m_RP.m_pLMTexCoordPointer = (SMRendTexVert *)sAlign0x20(buf);
|
|
buf += sizeof(SMRendTexVert)*m_RP.m_MaxVerts+32;
|
|
m_RP.m_pFogVertValues = (float *)sAlign0x20(buf);
|
|
buf += sizeof(float)*m_RP.m_MaxVerts+32;
|
|
if (GetFeatures() & RFT_BUMP_DOT3)
|
|
{
|
|
m_RP.m_pBinormals = (Vec3d *)sAlign0x20(buf);
|
|
buf += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
m_RP.m_pTangents = (Vec3d *)sAlign0x20(buf);
|
|
buf += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
m_RP.m_pTNormals = (Vec3d *)sAlign0x20(buf);
|
|
buf += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
for (i=0; i<4; i++)
|
|
{
|
|
m_RP.m_pLightVectors[i] = (Vec3d *)sAlign0x20(buf);
|
|
buf += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
m_RP.m_pHalfAngleVectors[i] = (Vec3d *)sAlign0x20(buf);
|
|
buf += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
}
|
|
m_RP.m_pAttenuation = (Vec3d *)sAlign0x20(buf);
|
|
buf += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
m_RP.m_pLAttenSpec0 = (Vec3d *)sAlign0x20(buf);
|
|
buf += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
m_RP.m_pLAttenSpec1 = (Vec3d *)sAlign0x20(buf);
|
|
buf += sizeof(Vec3d)*m_RP.m_MaxVerts+32;
|
|
}
|
|
m_RP.m_IndexBuf = new StaticIB <ushort>(m_pd3dDevice, m_RP.m_MaxTris*3);
|
|
|
|
sSVB[0].mVB.VBPtr_D_1T = new StaticVB <SPipeVertex_D_1T>(m_pd3dDevice, D3DFVF_VERTEX_D_1T, m_RP.m_MaxVerts);
|
|
sSVB[1].mVB.VBPtr_D_2T = new StaticVB <SPipeVertex_D_2T>(m_pd3dDevice, D3DFVF_VERTEX_D_2T, m_RP.m_MaxVerts);
|
|
sSVB[2].mVB.VBPtr_D_3T = new StaticVB <SPipeVertex_D_3T>(m_pd3dDevice, D3DFVF_VERTEX_D_3T, m_RP.m_MaxVerts);
|
|
sSVB[3].mVB.VBPtr_D_4T = new StaticVB <SPipeVertex_D_4T>(m_pd3dDevice, D3DFVF_VERTEX_D_4T, m_RP.m_MaxVerts);
|
|
sSVB[4].mVB.VBPtr_N_D_1T = new StaticVB <SPipeVertex_N_D_1T>(m_pd3dDevice, D3DFVF_VERTEX_N_D_1T, m_RP.m_MaxVerts);
|
|
sSVB[5].mVB.VBPtr_N_D_2T = new StaticVB <SPipeVertex_N_D_2T>(m_pd3dDevice, D3DFVF_VERTEX_N_D_2T, m_RP.m_MaxVerts);
|
|
sSVB[6].mVB.VBPtr_N_D_3T = new StaticVB <SPipeVertex_N_D_3T>(m_pd3dDevice, D3DFVF_VERTEX_N_D_3T, m_RP.m_MaxVerts);
|
|
sSVB[7].mVB.VBPtr_N_D_4T = new StaticVB <SPipeVertex_N_D_4T>(m_pd3dDevice, D3DFVF_VERTEX_N_D_4T, m_RP.m_MaxVerts);
|
|
sSVB[8].mVB.VBPtr_TR_D_1T = new StaticVB <SPipeTRVertex_D_1T>(m_pd3dDevice, D3DFVF_TRVERTEX_D_1T, m_RP.m_MaxVerts);
|
|
sSVB[9].mVB.VBPtr_TR_D_2T = new StaticVB <SPipeTRVertex_D_2T>(m_pd3dDevice, D3DFVF_TRVERTEX_D_2T, m_RP.m_MaxVerts);
|
|
sSVB[10].mVB.VBPtr_TR_D_3T = new StaticVB <SPipeTRVertex_D_3T>(m_pd3dDevice, D3DFVF_TRVERTEX_D_3T, m_RP.m_MaxVerts);
|
|
sSVB[11].mVB.VBPtr_TR_D_4T = new StaticVB <SPipeTRVertex_D_4T>(m_pd3dDevice, D3DFVF_TRVERTEX_D_4T, m_RP.m_MaxVerts);
|
|
|
|
// Used for sprites
|
|
m_RP.m_VBSprites.VBPtr_D_T2F = new StaticVB <struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F>(m_pd3dDevice, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, m_RP.m_MaxVerts);
|
|
|
|
EF_InitWaveTables();
|
|
EF_InitRandTables();
|
|
EF_InitEvalFuncs(0);
|
|
EF_InitFogVolumes();
|
|
EF_InitD3DFixedPipeline();
|
|
|
|
for (int i=0; i<VERTEX_FORMAT_NUMS; i++)
|
|
{
|
|
for (int j=0; j<VERTEX_FORMAT_NUMS; j++)
|
|
{
|
|
SVertBufComps Cps[2];
|
|
GetVertBufComps(&Cps[0], i);
|
|
GetVertBufComps(&Cps[1], j);
|
|
|
|
bool bNeedTC = Cps[1].m_bHasTC | Cps[0].m_bHasTC;
|
|
bool bNeedCol = Cps[1].m_bHasColors | Cps[0].m_bHasColors;
|
|
bool bNeedSecCol = Cps[1].m_bHasSecColors | Cps[0].m_bHasSecColors;
|
|
bool bNeedNormals = Cps[1].m_bHasNormals | Cps[0].m_bHasNormals;
|
|
m_RP.m_VFormatsMerge[i][j] = VertFormatForComponents(bNeedCol, bNeedSecCol, bNeedNormals, bNeedTC);
|
|
}
|
|
}
|
|
|
|
//==================================================
|
|
|
|
CCObject::m_Waves.Create(32);
|
|
m_RP.m_VisObjects = new CCObject *[MAX_REND_OBJECTS];
|
|
|
|
if (!m_RP.m_TempObjects.Num())
|
|
m_RP.m_TempObjects.Reserve(MAX_REND_OBJECTS);
|
|
if (!m_RP.m_Objects.Num())
|
|
{
|
|
m_RP.m_Objects.Reserve(MAX_REND_OBJECTS);
|
|
m_RP.m_Objects.SetUse(1);
|
|
SAFE_DELETE_ARRAY(m_RP.m_ObjectsPool);
|
|
m_RP.m_nNumObjectsInPool = 384;
|
|
m_RP.m_ObjectsPool = new CCObject[m_RP.m_nNumObjectsInPool];
|
|
for (int i=0; i<m_RP.m_nNumObjectsInPool; i++)
|
|
{
|
|
m_RP.m_TempObjects[i] = &m_RP.m_ObjectsPool[i];
|
|
m_RP.m_TempObjects[i]->Init();
|
|
m_RP.m_TempObjects[i]->m_Color = Col_White;
|
|
m_RP.m_TempObjects[i]->m_ObjFlags = 0;
|
|
m_RP.m_TempObjects[i]->m_Matrix.Identity();
|
|
m_RP.m_TempObjects[i]->m_RenderState = 0;
|
|
}
|
|
m_RP.m_VisObjects[0] = &m_RP.m_ObjectsPool[0];
|
|
}
|
|
|
|
m_RP.m_DLights.Create(64);
|
|
m_RP.m_DLights.SetUse(0);
|
|
|
|
m_RP.m_pREGlare = (CREGlare *)EF_CreateRE(eDATA_Glare);
|
|
}
|
|
|
|
void CD3D8Renderer::EF_PipelineShutdown()
|
|
{
|
|
int i, j;
|
|
|
|
i = 0;
|
|
while (sSVB[i].Stride)
|
|
{
|
|
SAFE_DELETE (sSVB[i].mVB.VBPtr_D_1T);
|
|
i++;
|
|
}
|
|
CCObject::m_Waves.Free();
|
|
SAFE_DELETE_ARRAY(m_RP.m_VisObjects);
|
|
SAFE_DELETE_ARRAY(m_SysArray);
|
|
|
|
m_RP.m_DLights.Free();
|
|
m_RP.m_FogVolumes.Free();
|
|
SAFE_RELEASE(m_RP.m_pREGlare);
|
|
|
|
for (i=0; i<CREClientPoly2D::mPolysStorage.GetSize(); i++)
|
|
{
|
|
SAFE_RELEASE(CREClientPoly2D::mPolysStorage[i]);
|
|
}
|
|
CREClientPoly2D::mPolysStorage.Free();
|
|
|
|
for (j=0; j<4; j++)
|
|
{
|
|
for (i=0; i<CREClientPoly::mPolysStorage[j].GetSize(); i++)
|
|
{
|
|
SAFE_RELEASE(CREClientPoly::mPolysStorage[j][i]);
|
|
}
|
|
CREClientPoly::mPolysStorage[j].Free();
|
|
}
|
|
|
|
EF_Release(EFRF_VSHADERS);
|
|
CCGVProgram_D3D::mfDeleteSharedScripts();
|
|
}
|
|
|
|
void CD3D8Renderer::EF_Release(int nFlags)
|
|
{
|
|
int i;
|
|
|
|
if (nFlags & EFRF_VSHADERS)
|
|
{
|
|
for (i=0; i<CVProgram::m_VPrograms.Num(); i++)
|
|
{
|
|
CVProgram::m_VPrograms[i]->mfReset();
|
|
}
|
|
}
|
|
if (nFlags & EFRF_PSHADERS)
|
|
{
|
|
for (i=0; i<CPShader::m_PShaders.Num(); i++)
|
|
{
|
|
CPShader::m_PShaders[i]->mfReset();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CD3D8Renderer::EF_ClearBuffer(bool bForce, float *Colors)
|
|
{
|
|
if (m_bWasCleared && !bForce)
|
|
return;
|
|
|
|
m_bWasCleared = true;
|
|
|
|
DWORD cColor;
|
|
if (Colors)
|
|
cColor = D3DRGBA(Colors[0], Colors[1], Colors[2], Colors[3]);
|
|
else
|
|
if(m_polygon_mode==R_WIREFRAME_MODE)
|
|
{
|
|
m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
|
|
cColor = D3DRGBA(0.25,0.5,1,0);
|
|
}
|
|
else
|
|
{
|
|
m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
|
|
cColor = D3DRGBA(m_vClearColor[0], m_vClearColor[1], m_vClearColor[2], 0);
|
|
}
|
|
|
|
if (m_sbpp)
|
|
m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, cColor, 1.0f, 0);
|
|
else
|
|
m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, cColor, 1.0f, 0);
|
|
|
|
}
|
|
|
|
//==========================================================================
|
|
|
|
void CD3D8Renderer::EF_SetCameraInfo()
|
|
{
|
|
m_RP.m_ViewOrg = m_cam.GetPos();
|
|
|
|
float fm[16];
|
|
GetModelViewMatrix(fm);
|
|
m_ViewMatrix = Matrix(fm);
|
|
m_CameraMatrix = m_ViewMatrix;
|
|
Matrix m = m_CameraMatrix;
|
|
m.Transpose();
|
|
|
|
m_RP.m_CamVecs[0][0] = -m(2,0);
|
|
m_RP.m_CamVecs[0][1] = -m(2,1);
|
|
m_RP.m_CamVecs[0][2] = -m(2,2);
|
|
|
|
m_RP.m_CamVecs[1][0] = m(1,0);
|
|
m_RP.m_CamVecs[1][1] = m(1,1);
|
|
m_RP.m_CamVecs[1][2] = m(1,2);
|
|
|
|
m_RP.m_CamVecs[2][0] = m(0,0);
|
|
m_RP.m_CamVecs[2][1] = m(0,1);
|
|
m_RP.m_CamVecs[2][2] = m(0,2);
|
|
|
|
GetProjectionMatrix(&m_ProjMatrix(0,0));
|
|
}
|
|
|
|
void CCObject::CalcInvertMatrix()
|
|
{
|
|
if (m_InvMatrixId)
|
|
return;
|
|
int n = m_InvMatrices.Num();
|
|
m_InvMatrices.AddIndex(1);
|
|
m_InvMatrixId = n;
|
|
|
|
CRenderer *rd = gRenDev;
|
|
Matrix44 &m = m_InvMatrices[m_InvMatrixId];
|
|
|
|
if (m_ObjFlags & FOB_TRANS_USEROTATE)
|
|
{
|
|
D3DXMatrixInverse((D3DXMATRIX *)m.GetData(), NULL, (D3DXMATRIX *)m_Matrix.GetData());
|
|
}
|
|
else
|
|
if (m_ObjFlags & FOB_TRANS_USESCALE)
|
|
{
|
|
m = m_Matrix;
|
|
float fiScaleX = 1.0f / m(0,0);
|
|
float fiScaleY = 1.0f / m(1,1);
|
|
float fiScaleZ = 1.0f / m(2,2);
|
|
m(0,0) = fiScaleX;
|
|
m(1,1) = fiScaleY;
|
|
m(2,2) = fiScaleZ;
|
|
m(3,0) = -m(3,0) * fiScaleX;
|
|
m(3,1) = -m(3,1) * fiScaleY;
|
|
m(3,2) = -m(3,2) * fiScaleZ;
|
|
}
|
|
else
|
|
if (m_ObjFlags & FOB_TRANS_USETRANSLATE)
|
|
{
|
|
m = m_Matrix;
|
|
m(3,0) = -m(3,0);
|
|
m(3,1) = -m(3,1);
|
|
m(3,2) = -m(3,2);
|
|
}
|
|
else
|
|
m = m_Matrix;
|
|
}
|
|
|
|
|
|
void CCObject::CalcMatrix()
|
|
{
|
|
if (m_ObjFlags & FOB_MATRIXCALCULATED)
|
|
return;
|
|
m_ObjFlags |= FOB_MATRIXCALCULATED;
|
|
if (m_ObjFlags & FOB_USEMATRIX)
|
|
{
|
|
m_ObjFlags |= FOB_TRANS_MASK;
|
|
return;
|
|
}
|
|
m_ObjFlags &= ~FOB_TRANS_MASK;
|
|
|
|
D3DXMATRIX mat, ma;
|
|
D3DXMatrixIdentity(&ma);
|
|
//if (obj->m_Scale != Vec3d(1.f,1.f,1.f))
|
|
if ( !IsEquivalent(m_Scale,Vec3d(1.f,1.f,1.f)) )
|
|
{
|
|
m_ObjFlags |= FOB_TRANS_USESCALE;
|
|
D3DXMatrixScaling(&mat, m_Scale.x, m_Scale.y, m_Scale.z);
|
|
D3DXMatrixMultiply(&ma, &ma, &mat);
|
|
}
|
|
if (m_Angs.x)
|
|
{
|
|
m_ObjFlags |= FOB_TRANS_USEROTATE;
|
|
D3DXMatrixRotationX(&mat, m_Angs.x*M_PI/180.0f);
|
|
D3DXMatrixMultiply(&ma, &ma, &mat);
|
|
}
|
|
if (m_Angs.y)
|
|
{
|
|
m_ObjFlags |= FOB_TRANS_USEROTATE;
|
|
D3DXMatrixRotationY(&mat, m_Angs.y*M_PI/180.0f);
|
|
D3DXMatrixMultiply(&ma, &ma, &mat);
|
|
}
|
|
if (m_Angs.z)
|
|
{
|
|
m_ObjFlags |= FOB_TRANS_USEROTATE;
|
|
D3DXMatrixRotationZ(&mat, m_Angs.z*M_PI/180.0f);
|
|
D3DXMatrixMultiply(&ma, &ma, &mat);
|
|
}
|
|
// if (obj->m_Trans != Vec3d(0,0,0))
|
|
if ( !IsEquivalent(m_Trans,Vec3d(0,0,0)) )
|
|
{
|
|
m_ObjFlags |= FOB_TRANS_USETRANSLATE;
|
|
D3DXMatrixTranslation(&mat, m_Trans.x, m_Trans.y, m_Trans.z);
|
|
D3DXMatrixMultiply(&ma, &ma, &mat);
|
|
}
|
|
cryMemcpy(&m_Matrix(0,0), &ma, sizeof(float)*4*4);
|
|
}
|
|
|
|
void CD3D8Renderer::EF_SetObjectTransform(CCObject *obj)
|
|
{
|
|
obj->CalcMatrix();
|
|
|
|
if (obj->m_ObjFlags & FOB_TRANS_MASK)
|
|
D3DXMatrixMultiply((D3DXMATRIX *)&m_ViewMatrix(0,0), (D3DXMATRIX *)&m_RP.m_pCurObject->m_Matrix(0,0), (D3DXMATRIX *)&m_CameraMatrix(0,0));
|
|
else
|
|
m_ViewMatrix = m_CameraMatrix;
|
|
m_matView->LoadMatrix((D3DXMATRIX *)&m_ViewMatrix(0,0));
|
|
m_pd3dDevice->SetTransform(D3DTS_VIEW, m_matView->GetTop());
|
|
m_bInvertedMatrix = false;
|
|
}
|
|
|
|
bool CD3D8Renderer::EF_ObjectChange(SShader *Shader, int nObject, CRendElement *pRE)
|
|
{
|
|
CCObject *obj = m_RP.m_VisObjects[nObject];
|
|
if ((obj->m_ObjFlags & FOB_NEAREST) && ((m_RP.m_PersFlags & RBPF_DONTDRAWNEAREST) || CV_r_nodrawnear))
|
|
return false;
|
|
|
|
if (Shader)
|
|
{
|
|
// if (m_RP.m_pIgnoreObject && !(Shader->m_Flags & EF_SKY) && m_RP.m_pIgnoreObject->m_Trans == obj->m_Trans)
|
|
if (m_RP.m_pIgnoreObject && !(Shader->m_Flags & EF_SKY) && IsEquivalent(m_RP.m_pIgnoreObject->m_Trans,obj->m_Trans))
|
|
{
|
|
if (!m_RP.m_pIgnoreShader || m_RP.m_pIgnoreShader == Shader)
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (obj == m_RP.m_pPrevObject)
|
|
return true;
|
|
|
|
m_RP.m_FrameObject++;
|
|
m_RP.m_pCurObject = obj;
|
|
|
|
bool bTheSameCM = false;
|
|
if (m_RP.m_pPrevObject && (m_RP.m_pPrevObject->m_ObjFlags & FOB_CUBE_MASK))
|
|
{
|
|
bTheSameCM = (obj && (obj->m_ObjFlags & FOB_CUBE_MASK) == (m_RP.m_pPrevObject->m_ObjFlags & FOB_CUBE_MASK));
|
|
if (!bTheSameCM)
|
|
{
|
|
bool bNeedClear;
|
|
if (obj && (obj->m_ObjFlags & FOB_CUBE_MASK))
|
|
bNeedClear = false;
|
|
else
|
|
bNeedClear = true;
|
|
m_TexMan->EndCubeSide(m_RP.m_pPrevObject, bNeedClear);
|
|
}
|
|
}
|
|
|
|
int flags = 0;
|
|
if (obj->m_VisId)
|
|
{
|
|
m_RP.m_PS.m_NumRendObjects++;
|
|
if (obj->m_Color.a != 1.0f)
|
|
obj->m_ObjFlags |= FOB_HASALPHA;
|
|
if (obj->m_fBending)
|
|
obj->m_ObjFlags |= FOB_BENDED;
|
|
|
|
// Skinning
|
|
if (obj->m_pCharInstance && !CV_r_character_nodeform)
|
|
{
|
|
double time0 = 0;
|
|
ticks(time0);
|
|
m_RP.m_PS.m_NumRendSkinnedObjects++;
|
|
CREOcLeaf *pREOCL = (CREOcLeaf *)pRE;
|
|
SShader *sh = m_RP.m_pShader;
|
|
m_RP.m_pShader = Shader;
|
|
int nFlags = 0;
|
|
if (Shader->m_Flags & EF_NEEDNORMALS)
|
|
nFlags |= FHF_NORMALSUSED;
|
|
if (Shader->m_Flags & EF_NEEDTANGENTS)
|
|
nFlags |= FHF_TANGENTSUSED;
|
|
pRE->mfCheckUpdate(nFlags);
|
|
m_RP.m_pShader = sh;
|
|
CLeafBuffer *pLB = pREOCL->m_pBuffer->GetVertexContainer();
|
|
bool bForceUpdate = (pLB->m_UpdateFrame == GetFrameID());
|
|
obj->m_pCharInstance->ProcessSkinning(obj->m_Matrix, obj->m_nTemplId, obj->m_nLod, bForceUpdate);
|
|
unticks(time0);
|
|
m_RP.m_PS.m_fSkinningTime += (float)(time0*1000.0*m_RP.m_SecondsPerCycle);
|
|
}
|
|
|
|
if(obj->m_ObjFlags & FOB_NEAREST)
|
|
flags |= RBF_NEAREST;
|
|
|
|
if ((flags ^ m_RP.m_Flags) & RBF_NEAREST)
|
|
{
|
|
if (flags & RBF_NEAREST)
|
|
{
|
|
CCamera Cam = GetCamera();
|
|
m_RP.m_PrevCamera = Cam;
|
|
Cam.SetZMin(0.01f);
|
|
Cam.SetZMax(40.0f);
|
|
|
|
// set nice fov for weapons
|
|
static float weapon_fov_k = 0.6666f;//iSystem->GetIniVar("weapon_fov_k","engine.ini",0.6666f);
|
|
Cam.SetFov( Cam.GetFov() * weapon_fov_k );
|
|
SetCamera(Cam);
|
|
m_Viewport.MaxZ = 0.1f;
|
|
m_pd3dDevice->SetViewport(&m_Viewport);
|
|
}
|
|
else
|
|
{
|
|
SetCamera(m_RP.m_PrevCamera);
|
|
m_Viewport.MaxZ = 1.0f;
|
|
m_pd3dDevice->SetViewport(&m_Viewport);
|
|
}
|
|
|
|
m_RP.m_Flags &= ~RBF_NEAREST;
|
|
m_RP.m_Flags |= (flags & RBF_NEAREST);
|
|
}
|
|
if ((obj->m_ObjFlags & FOB_CUBE_MASK) && !bTheSameCM)
|
|
m_TexMan->StartCubeSide(obj);
|
|
|
|
EF_SetObjectTransform(obj);
|
|
}
|
|
else
|
|
{
|
|
if (m_RP.m_Flags & RBF_NEAREST)
|
|
{
|
|
SetCamera(m_RP.m_PrevCamera);
|
|
m_Viewport.MaxZ = 1.0f;
|
|
m_pd3dDevice->SetViewport(&m_Viewport);
|
|
m_RP.m_Flags &= ~RBF_NEAREST;
|
|
}
|
|
m_RP.m_pCurObject->m_Matrix.Identity();
|
|
m_ViewMatrix = m_CameraMatrix;
|
|
m_matView->LoadMatrix((D3DXMATRIX *)&m_CameraMatrix(0,0));
|
|
m_pd3dDevice->SetTransform(D3DTS_VIEW, m_matView->GetTop());
|
|
m_bInvertedMatrix = false;
|
|
}
|
|
m_RP.m_pPrevObject = m_RP.m_pCurObject;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void CD3D8Renderer::EF_SetClipPlane (bool bEnable, float *pPlane, bool bRefract)
|
|
{
|
|
}
|
|
|
|
//==============================================================================
|
|
// Shader Pipeline
|
|
|
|
void CD3D8Renderer::EF_CheckOverflow(int nVerts, int nInds, CRendElement *re)
|
|
{
|
|
if (m_RP.m_pRE || (m_RP.m_RendNumVerts+nVerts >= m_RP.m_MaxTris || m_RP.m_RendNumIndices+nInds >= m_RP.m_MaxTris*3))
|
|
{
|
|
m_RP.m_pRenderFunc();
|
|
if (nVerts >= m_RP.m_MaxVerts)
|
|
{
|
|
iLog->Log("CD3D8Renderer::EF_CheckOverflow: numVerts > MAX (%d > %d)\n", nVerts, m_RP.m_MaxVerts);
|
|
nVerts = m_RP.m_MaxVerts;
|
|
}
|
|
if (nInds >= m_RP.m_MaxTris*3)
|
|
{
|
|
iLog->Log("CD3D8Renderer::EF_CheckOverflow: numIndices > MAX (%d > %d)\n", nInds, m_RP.m_MaxTris*3);
|
|
nInds = m_RP.m_MaxTris*3;
|
|
}
|
|
EF_Start(m_RP.m_pShader, m_RP.m_pStateShader, m_RP.m_pShaderResources, m_RP.m_pFogVolume ? (m_RP.m_pFogVolume-&m_RP.m_FogVolumes[0]) : 0, re);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
|
|
|
|
void CD3D8Renderer::EF_Eval_DeformVerts(TArray<SDeform>* Defs)
|
|
{
|
|
int i;
|
|
|
|
if (!Defs)
|
|
return;
|
|
|
|
for (i=0; i<Defs->Num(); i++)
|
|
{
|
|
SDeform *df = &Defs->Get(i);
|
|
switch (df->m_eType)
|
|
{
|
|
case eDT_Wave:
|
|
m_RP.m_pCurFuncs->WaveDeform(df);
|
|
break;
|
|
|
|
case eDT_Flare:
|
|
m_RP.m_pCurFuncs->FlareDeform(df);
|
|
break;
|
|
|
|
case eDT_VerticalWave:
|
|
m_RP.m_pCurFuncs->VerticalWaveDeform(df);
|
|
break;
|
|
|
|
case eDT_Bulge:
|
|
m_RP.m_pCurFuncs->BulgeDeform(df);
|
|
break;
|
|
|
|
case eDT_FromCenter:
|
|
m_RP.m_pCurFuncs->FromCenterDeform(df);
|
|
break;
|
|
|
|
case eDT_Squeeze:
|
|
m_RP.m_pCurFuncs->SqueezeDeform(df);
|
|
break;
|
|
|
|
default:
|
|
iLog->Log("Unknown deform type %d in Shader '%s'\n", df->m_eType, m_RP.m_pShader->m_Name);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CD3D8Renderer::EF_Eval_TexGen(SShaderPass *sfm)
|
|
{
|
|
int j, n;
|
|
SShaderTexUnit *shl;
|
|
SShader *ef = m_RP.m_pShader;
|
|
SMRendTexVert *src;
|
|
int m;
|
|
|
|
for (j=0; j<sfm->m_TUnits.Num(); j++)
|
|
{
|
|
shl = sfm->m_TUnits[j];
|
|
|
|
if (!shl->m_TexPic || shl->m_GTC)
|
|
continue;
|
|
|
|
switch (shl->m_eGenTC)
|
|
{
|
|
case eGTC_NoFill:
|
|
break;
|
|
|
|
case eGTC_None:
|
|
break;
|
|
|
|
case eGTC_Base:
|
|
if (!m_RP.m_pRE)
|
|
{
|
|
m = m_RP.m_RendNumVerts;
|
|
src = m_RP.m_pBaseTexCoordPointer;
|
|
byte *ptr = m_RP.m_Ptr.PtrB + m_RP.m_OffsT + j*16;
|
|
for (n=0; n<m; n++, ptr+=m_RP.m_Stride)
|
|
{
|
|
*(float *)(ptr) = src[n].vert[0];
|
|
*(float *)(ptr+4) = src[n].vert[1];
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eGTC_LightMap:
|
|
if (!m_RP.m_pRE)
|
|
{
|
|
m = m_RP.m_RendNumVerts;
|
|
src = m_RP.m_pLMTexCoordPointer;
|
|
byte *ptr = m_RP.m_Ptr.PtrB + m_RP.m_OffsT + j*16;
|
|
for (n=0; n<m; n++, ptr+=m_RP.m_Stride)
|
|
{
|
|
*(float *)(ptr) = src[n].vert[0];
|
|
*(float *)(ptr+4) = src[n].vert[1];
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eGTC_Environment:
|
|
m_RP.m_pCurFuncs->ETC_Environment(j);
|
|
break;
|
|
|
|
case eGTC_Projection:
|
|
if (shl->m_TexPic->m_Matrix)
|
|
m_RP.m_pCurFuncs->ETC_Projection(j, shl->m_TexPic->m_Matrix, 1, 1);
|
|
break;
|
|
|
|
case eGTC_SphereMap:
|
|
m_RP.m_pCurFuncs->ETC_SphereMap(j);
|
|
break;
|
|
|
|
case eGTC_SphereMapEnvironment:
|
|
m_RP.m_pCurFuncs->ETC_SphereMapEnvironment(j);
|
|
break;
|
|
|
|
case eGTC_ShadowMap:
|
|
m_RP.m_pCurFuncs->ETC_ShadowMap(j);
|
|
break;
|
|
|
|
default:
|
|
iLog->Log("ERROR: invalid eGenTC '%d' specified for Shader\n", shl->m_eGenTC);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CD3D8Renderer::EF_Eval_RGBAGen(SShaderPass *sfm)
|
|
{
|
|
SShader *ef = m_RP.m_pShader;
|
|
int n;
|
|
UCol color;
|
|
bool bSetCol = false;
|
|
color.dcolor = -1;
|
|
|
|
switch(sfm->m_eEvalRGB)
|
|
{
|
|
case eERGB_NoFill:
|
|
break;
|
|
|
|
case eERGB_Identity:
|
|
{
|
|
if (m_RP.m_pRE)
|
|
{
|
|
if (!(m_RP.m_FlagsPerFlush & RBSI_RGBGEN))
|
|
{
|
|
color.dcolor = -1;
|
|
bSetCol = true;
|
|
m_RP.m_FlagsPerFlush = RBSI_RGBGEN;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
byte *ptr = m_RP.m_Ptr.PtrB+m_RP.m_OffsD;
|
|
for (n=0; n<m_RP.m_RendNumVerts; n++, ptr+=m_RP.m_Stride)
|
|
{
|
|
*(uint *)ptr = -1;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eERGB_FromClient:
|
|
if (!m_RP.m_pRE)
|
|
{
|
|
if (!gbRgb)
|
|
{
|
|
byte *ptr = m_RP.m_Ptr.PtrB+m_RP.m_OffsD;
|
|
byte *src = (byte *)(m_RP.m_pClientColors[0]);
|
|
for (n=0; n<m_RP.m_RendNumVerts; n++, ptr+=m_RP.m_Stride, src+=4)
|
|
{
|
|
*(uint *)ptr = *(uint *)(src);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
byte *ptr = m_RP.m_Ptr.PtrB+m_RP.m_OffsD;
|
|
byte *src = (byte *)(&m_RP.m_pClientColors[0]);
|
|
for (n=0; n<m_RP.m_RendNumVerts; n++, ptr+=m_RP.m_Stride, src+=4)
|
|
{
|
|
ptr[2] = src[0];
|
|
ptr[1] = src[1];
|
|
ptr[0] = src[2];
|
|
ptr[3] = src[3];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eERGB_OneMinusFromClient:
|
|
if (!m_RP.m_pRE)
|
|
{
|
|
if (!gbRgb)
|
|
{
|
|
byte *ptr = m_RP.m_Ptr.PtrB+m_RP.m_OffsD;
|
|
for (n=0; n<m_RP.m_RendNumVerts; n++, ptr+=m_RP.m_Stride)
|
|
{
|
|
ptr[0] = 255 - m_RP.m_pClientColors[n][0];
|
|
ptr[1] = 255 - m_RP.m_pClientColors[n][1];
|
|
ptr[2] = 255 - m_RP.m_pClientColors[n][2];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
byte *ptr = m_RP.m_Ptr.PtrB+m_RP.m_OffsD;
|
|
for (n=0; n<m_RP.m_RendNumVerts; n++, ptr+=m_RP.m_Stride)
|
|
{
|
|
ptr[0] = 255 - m_RP.m_pClientColors[n][2];
|
|
ptr[1] = 255 - m_RP.m_pClientColors[n][1];
|
|
ptr[2] = 255 - m_RP.m_pClientColors[n][0];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eERGB_Fixed:
|
|
color = sfm->m_FixedColor;
|
|
bSetCol = true;
|
|
m_RP.m_FlagsPerFlush = RBSI_RGBGEN;
|
|
break;
|
|
|
|
case eERGB_StyleIntens:
|
|
{
|
|
CLightStyle *ls = CLightStyle::mfGetStyle(sfm->m_Style, m_RP.m_RealTime);
|
|
color = sfm->m_FixedColor;
|
|
color.bcolor[0] = (byte)((float)color.bcolor[0] * ls->m_fIntensity);
|
|
color.bcolor[1] = (byte)((float)color.bcolor[1] * ls->m_fIntensity);
|
|
color.bcolor[2] = (byte)((float)color.bcolor[2] * ls->m_fIntensity);
|
|
bSetCol = true;
|
|
m_RP.m_FlagsPerFlush = RBSI_RGBGEN;
|
|
}
|
|
break;
|
|
|
|
case eERGB_StyleColor:
|
|
{
|
|
CLightStyle *ls = CLightStyle::mfGetStyle(sfm->m_Style, m_RP.m_RealTime);
|
|
color.dcolor = ls->m_Color.GetTrue();
|
|
bSetCol = true;
|
|
m_RP.m_FlagsPerFlush = RBSI_RGBGEN;
|
|
}
|
|
break;
|
|
|
|
case eERGB_Comps:
|
|
{
|
|
if (sfm->m_RGBComps)
|
|
{
|
|
float *vals = sfm->m_RGBComps->mfGet();
|
|
color.bcolor[0] = (byte)(vals[0] * 255.0f);
|
|
color.bcolor[1] = (byte)(vals[1] * 255.0f);
|
|
color.bcolor[2] = (byte)(vals[2] * 255.0f);
|
|
color.bcolor[3] = (byte)(vals[3] * 255.0f);
|
|
bSetCol = true;
|
|
m_RP.m_FlagsPerFlush = RBSI_RGBGEN;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eERGB_Wave:
|
|
if (sfm->m_WaveEvalRGB)
|
|
{
|
|
if (m_RP.m_pRE)
|
|
{
|
|
if (!(m_RP.m_FlagsPerFlush & RBSI_RGBGEN))
|
|
{
|
|
float val = SEvalFuncs::EvalWaveForm(sfm->m_WaveEvalRGB);
|
|
if (val < 0)
|
|
val = 0;
|
|
if (val > 1)
|
|
val = 1;
|
|
|
|
color.bcolor[0] = color.bcolor[1] = color.bcolor[2] = (int)(val * 255.0f);
|
|
COLCONV(color.dcolor);
|
|
bSetCol = true;
|
|
m_RP.m_FlagsPerFlush = RBSI_RGBGEN;
|
|
}
|
|
}
|
|
else
|
|
m_RP.m_pCurFuncs->ERGB_Wave(sfm->m_WaveEvalRGB, color);
|
|
}
|
|
break;
|
|
|
|
case eERGB_Noise:
|
|
if (sfm->m_RGBNoise)
|
|
{
|
|
if (m_RP.m_pRE)
|
|
{
|
|
if (!(m_RP.m_FlagsPerFlush & RBSI_RGBGEN))
|
|
{
|
|
float v = RandomNum();
|
|
byte r = (byte)(Clamp<float>(v * sfm->m_RGBNoise->m_RangeR + sfm->m_RGBNoise->m_ConstR, 0.0f, 1.0f) * 255.0f);
|
|
v = RandomNum();
|
|
byte g = (byte)(Clamp<float>(v * sfm->m_RGBNoise->m_RangeG + sfm->m_RGBNoise->m_ConstG, 0.0f, 1.0f) * 255.0f);
|
|
v = RandomNum();
|
|
byte b = (byte)(Clamp<float>(v * sfm->m_RGBNoise->m_RangeB + sfm->m_RGBNoise->m_ConstB, 0.0f, 1.0f) * 255.0f);
|
|
|
|
color.bcolor[0] = r;
|
|
color.bcolor[1] = g;
|
|
color.bcolor[2] = b;
|
|
COLCONV(color.dcolor);
|
|
bSetCol = true;
|
|
m_RP.m_FlagsPerFlush = RBSI_RGBGEN;
|
|
}
|
|
}
|
|
else
|
|
m_RP.m_pCurFuncs->ERGB_Noise(sfm->m_RGBNoise, color);
|
|
}
|
|
break;
|
|
|
|
case eERGB_Object:
|
|
if (m_RP.m_pRE)
|
|
{
|
|
if (m_RP.m_pCurObject && !(m_RP.m_FlagsPerFlush & RBSI_RGBGEN))
|
|
{
|
|
bSetCol = true;
|
|
color.bcolor[0] = (byte)(m_RP.m_pCurObject->m_Color[0] * 255.0f);
|
|
color.bcolor[1] = (byte)(m_RP.m_pCurObject->m_Color[1] * 255.0f);
|
|
color.bcolor[2] = (byte)(m_RP.m_pCurObject->m_Color[2] * 255.0f);
|
|
m_RP.m_FlagsPerFlush |= RBSI_RGBGEN;
|
|
}
|
|
}
|
|
else
|
|
m_RP.m_pCurFuncs->ERGB_Object();
|
|
break;
|
|
|
|
case eERGB_OneMinusObject:
|
|
if (m_RP.m_pRE)
|
|
{
|
|
if (m_RP.m_pCurObject && !(m_RP.m_FlagsPerFlush & RBSI_RGBGEN))
|
|
{
|
|
bSetCol = true;
|
|
color.bcolor[0] = (byte)((1.0f - m_RP.m_pCurObject->m_Color[0]) * 255.0f);
|
|
color.bcolor[1] = (byte)((1.0f - m_RP.m_pCurObject->m_Color[1]) * 255.0f);
|
|
color.bcolor[2] = (byte)((1.0f - m_RP.m_pCurObject->m_Color[2]) * 255.0f);
|
|
m_RP.m_FlagsPerFlush |= RBSI_RGBGEN;
|
|
}
|
|
}
|
|
else
|
|
m_RP.m_pCurFuncs->ERGB_OneMinusObject();
|
|
break;
|
|
|
|
case eERGB_RE:
|
|
if (m_RP.m_pRE && !(m_RP.m_FlagsPerFlush & RBSI_RGBGEN))
|
|
{
|
|
bSetCol = true;
|
|
color.bcolor[0] = (byte)(m_RP.m_pRE->m_Color[0] * 255.0f);
|
|
color.bcolor[1] = (byte)(m_RP.m_pRE->m_Color[1] * 255.0f);
|
|
color.bcolor[2] = (byte)(m_RP.m_pRE->m_Color[2] * 255.0f);
|
|
m_RP.m_FlagsPerFlush |= RBSI_RGBGEN;
|
|
}
|
|
break;
|
|
|
|
case eERGB_OneMinusRE:
|
|
if (m_RP.m_pRE && !(m_RP.m_FlagsPerFlush & RBSI_RGBGEN))
|
|
{
|
|
bSetCol = true;
|
|
color.bcolor[0] = (byte)((1.0f - m_RP.m_pRE->m_Color[0]) * 255.0f);
|
|
color.bcolor[1] = (byte)((1.0f - m_RP.m_pRE->m_Color[1]) * 255.0f);
|
|
color.bcolor[2] = (byte)((1.0f - m_RP.m_pRE->m_Color[2]) * 255.0f);
|
|
m_RP.m_FlagsPerFlush |= RBSI_RGBGEN;
|
|
}
|
|
break;
|
|
|
|
case eERGB_World:
|
|
if (m_RP.m_pRE && !(m_RP.m_FlagsPerFlush & RBSI_RGBGEN))
|
|
{
|
|
bSetCol = true;
|
|
color.bcolor[0] = (byte)(gRenDev->m_WorldColor[0] * 255.0f);
|
|
color.bcolor[1] = (byte)(gRenDev->m_WorldColor[1] * 255.0f);
|
|
color.bcolor[2] = (byte)(gRenDev->m_WorldColor[2] * 255.0f);
|
|
m_RP.m_FlagsPerFlush |= RBSI_RGBGEN;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
switch(sfm->m_eEvalAlpha)
|
|
{
|
|
case eEALPHA_NoFill:
|
|
break;
|
|
|
|
case eEALPHA_Identity:
|
|
if (sfm->m_eEvalRGB!=eERGB_Identity && sfm->m_eEvalRGB!=eERGB_Fixed)
|
|
{
|
|
if (m_RP.m_pRE)
|
|
{
|
|
if (!(m_RP.m_FlagsPerFlush & RBSI_RGBGEN))
|
|
{
|
|
color.bcolor[3] = 255;
|
|
bSetCol = true;
|
|
m_RP.m_FlagsPerFlush |= RBSI_RGBGEN;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
byte *ptr = m_RP.m_Ptr.PtrB+m_RP.m_OffsD;
|
|
for (n=0; n<m_RP.m_RendNumVerts; n++, ptr+=m_RP.m_Stride)
|
|
{
|
|
ptr[3] = 255;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eEALPHA_Fixed:
|
|
{
|
|
if (sfm->m_eEvalRGB == eERGB_Fixed)
|
|
break;
|
|
if (!(m_RP.m_FlagsPerFlush & RBSI_ALPHAGEN))
|
|
{
|
|
color.bcolor[3] = sfm->m_FixedColor.bcolor[3];
|
|
bSetCol = true;
|
|
m_RP.m_FlagsPerFlush |= RBSI_ALPHAGEN;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eEALPHA_Style:
|
|
{
|
|
CLightStyle *ls = CLightStyle::mfGetStyle(sfm->m_Style, m_RP.m_RealTime);
|
|
color.bcolor[3] = (byte)((float)sfm->m_FixedColor.bcolor[3] * ls->m_fIntensity);
|
|
bSetCol = true;
|
|
m_RP.m_FlagsPerFlush = RBSI_ALPHAGEN;
|
|
}
|
|
break;
|
|
|
|
case eEALPHA_Comps:
|
|
{
|
|
if (sfm->m_eEvalRGB == eERGB_Comps)
|
|
break;
|
|
if (sfm->m_RGBComps)
|
|
{
|
|
float *vals = sfm->m_RGBComps->mfGet();
|
|
if (m_RP.m_pRE)
|
|
{
|
|
if (!(m_RP.m_FlagsPerFlush & RBSI_ALPHAGEN))
|
|
{
|
|
color.bcolor[3] = (byte)(vals[0] * 255.0f);
|
|
bSetCol = true;
|
|
m_RP.m_FlagsPerFlush = RBSI_ALPHAGEN;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
byte a = (byte)(vals[0] * 255.0f);
|
|
byte *ptr = m_RP.m_Ptr.PtrB+m_RP.m_OffsD;
|
|
for (n=0; n<m_RP.m_RendNumVerts; n++, ptr+=m_RP.m_Stride)
|
|
{
|
|
ptr[3] = a;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eEALPHA_Wave:
|
|
if (sfm->m_WaveEvalAlpha)
|
|
{
|
|
if (m_RP.m_pRE)
|
|
{
|
|
if (!(m_RP.m_FlagsPerFlush & RBSI_ALPHAGEN))
|
|
{
|
|
float val = SEvalFuncs::EvalWaveForm(sfm->m_WaveEvalAlpha);
|
|
if (val < 0)
|
|
val = 0;
|
|
if (val > 1)
|
|
val = 1;
|
|
|
|
color.bcolor[3] = (int)(val * 255.0f);
|
|
bSetCol = true;
|
|
m_RP.m_FlagsPerFlush = RBSI_ALPHAGEN;
|
|
}
|
|
}
|
|
else
|
|
m_RP.m_pCurFuncs->EALPHA_Wave(sfm->m_WaveEvalAlpha, color);
|
|
}
|
|
break;
|
|
|
|
case eEALPHA_Noise:
|
|
if (sfm->m_ANoise)
|
|
{
|
|
if (m_RP.m_pRE)
|
|
{
|
|
if (!(m_RP.m_FlagsPerFlush & RBSI_ALPHAGEN))
|
|
{
|
|
float v = RandomNum();
|
|
byte a = (byte)(Clamp<float>(v * sfm->m_ANoise->m_RangeA + sfm->m_ANoise->m_ConstA, 0.0f, 1.0f) * 255.0f);
|
|
|
|
color.bcolor[3] = a;
|
|
bSetCol = true;
|
|
m_RP.m_FlagsPerFlush = RBSI_ALPHAGEN;
|
|
}
|
|
}
|
|
else
|
|
m_RP.m_pCurFuncs->EALPHA_Noise(sfm->m_ANoise, color);
|
|
}
|
|
break;
|
|
|
|
case eEALPHA_Beam:
|
|
m_RP.m_pCurFuncs->EALPHA_Beam();
|
|
break;
|
|
|
|
case eEALPHA_Object:
|
|
if (m_RP.m_pRE)
|
|
{
|
|
if (m_RP.m_pCurObject && !(m_RP.m_FlagsPerFlush & RBSI_ALPHAGEN))
|
|
{
|
|
bSetCol = true;
|
|
color.bcolor[3] = (byte)(m_RP.m_pCurObject->m_Color[3] * 255.0f);
|
|
m_RP.m_FlagsPerFlush = RBSI_ALPHAGEN;
|
|
}
|
|
}
|
|
else
|
|
m_RP.m_pCurFuncs->EALPHA_Object();
|
|
break;
|
|
|
|
case eEALPHA_OneMinusObject:
|
|
if (m_RP.m_pRE)
|
|
{
|
|
if (m_RP.m_pCurObject && !(m_RP.m_FlagsPerFlush & RBSI_ALPHAGEN))
|
|
{
|
|
bSetCol = true;
|
|
color.bcolor[3] = (byte)((1.0f - m_RP.m_pCurObject->m_Color[3]) * 255.0f);
|
|
m_RP.m_FlagsPerFlush = RBSI_ALPHAGEN;
|
|
}
|
|
}
|
|
else
|
|
m_RP.m_pCurFuncs->EALPHA_OneMinusObject();
|
|
break;
|
|
|
|
case eEALPHA_RE:
|
|
if (m_RP.m_pRE)
|
|
{
|
|
if (!(m_RP.m_FlagsPerFlush & RBSI_ALPHAGEN))
|
|
{
|
|
bSetCol = true;
|
|
color.bcolor[3] = (byte)(m_RP.m_pRE->m_Color[3] * 255.0f);
|
|
m_RP.m_FlagsPerFlush = RBSI_ALPHAGEN;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eEALPHA_OneMinusRE:
|
|
if (m_RP.m_pRE)
|
|
{
|
|
if (!(m_RP.m_FlagsPerFlush & RBSI_ALPHAGEN))
|
|
{
|
|
bSetCol = true;
|
|
color.bcolor[3] = (byte)((1.0f - m_RP.m_pCurObject->m_Color[3]) * 255.0f);
|
|
m_RP.m_FlagsPerFlush = RBSI_ALPHAGEN;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eEALPHA_World:
|
|
if (m_RP.m_pRE)
|
|
{
|
|
if (!(m_RP.m_FlagsPerFlush & RBSI_ALPHAGEN))
|
|
{
|
|
bSetCol = true;
|
|
color.bcolor[3] = (byte)(gRenDev->m_WorldColor[3] * 255.0f);
|
|
m_RP.m_FlagsPerFlush = RBSI_ALPHAGEN;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eEALPHA_FromClient:
|
|
if (!m_RP.m_pRE)
|
|
{
|
|
if (sfm->m_eEvalRGB!=eERGB_FromClient)
|
|
{
|
|
byte *ptr = m_RP.m_Ptr.PtrB+m_RP.m_OffsD;
|
|
for (n=0; n<m_RP.m_RendNumVerts; n++, ptr+=m_RP.m_Stride)
|
|
{
|
|
ptr[3] = m_RP.m_pClientColors[n][3];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
// Fog blending for non-opaque surfaces
|
|
/*if (m_RP.NumFog)
|
|
{
|
|
m_RP.bFogBlend = false;
|
|
switch(sfm->m_eFogBlendComponents)
|
|
{
|
|
case eFBLC_OnlyColor:
|
|
m_RP.bFogBlend = true;
|
|
m_RP.m_pCurFuncs->BLC_OnlyColor();
|
|
break;
|
|
|
|
case eFBLC_ColorAlpha:
|
|
m_RP.bFogBlend = true;
|
|
m_RP.m_pCurFuncs->BLC_ColorAlpha();
|
|
break;
|
|
|
|
case eFBLC_OnlyAlpha:
|
|
m_RP.bFogBlend = true;
|
|
m_RP.m_pCurFuncs->BLC_OnlyAlpha();
|
|
break;
|
|
}
|
|
}*/
|
|
if (bSetCol)
|
|
EF_SetGlobalColor(color);
|
|
}
|
|
|
|
void CD3D8Renderer::EF_EvalNormalsRB(SShader *ef)
|
|
{
|
|
if (!ef->m_NormGen)
|
|
return;
|
|
|
|
SNormalsGen *ng = ef->m_NormGen;
|
|
|
|
if (ng->m_eNormal == eNORM_Identity || !m_RP.m_OffsN)
|
|
return;
|
|
|
|
int i;
|
|
int nums = m_RP.m_RendNumVerts;
|
|
byte *ptr = m_RP.m_Ptr.PtrB+m_RP.m_OffsN;
|
|
|
|
switch(ng->m_eNormal)
|
|
{
|
|
case eNORM_Custom:
|
|
for (i=0; i<nums; i++, ptr+=m_RP.m_Stride)
|
|
{
|
|
float *tsnrm = (float *)ptr;
|
|
tsnrm[0] = ng->m_CustomNormal[0];
|
|
tsnrm[1] = ng->m_CustomNormal[1];
|
|
tsnrm[2] = ng->m_CustomNormal[2];
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CD3D8Renderer::EF_UpdateTextures(SShaderPass *Layer)
|
|
{
|
|
SShaderTexUnit *stl;
|
|
int j;
|
|
for (j=0; j<Layer->m_TUnits.Num(); j++)
|
|
{
|
|
stl = Layer->m_TUnits[j];
|
|
|
|
if (!stl->m_TexPic && !stl->m_AnimInfo)
|
|
break;
|
|
|
|
stl->mfUpdate();
|
|
}
|
|
}
|
|
|
|
void CD3D8Renderer::EF_UpdateTextures(SShaderPassHW *Layer)
|
|
{
|
|
SShaderTexUnit *stl;
|
|
int j;
|
|
for (j=0; j<Layer->m_TUnits.Num(); j++)
|
|
{
|
|
stl = Layer->m_TUnits[j];
|
|
|
|
if (!stl->m_TexPic && !stl->m_AnimInfo)
|
|
break;
|
|
|
|
stl->mfUpdate();
|
|
}
|
|
}
|
|
|
|
//=================================================================================
|
|
|
|
void CD3D8Renderer::SetState(int st)
|
|
{
|
|
int Changed;
|
|
int src, dst;
|
|
|
|
if (m_RP.m_Flags & RBF_SHOWLINES)
|
|
st |= GS_NODEPTHTEST;
|
|
|
|
if (st & (GS_DEPTHWRITE | GS_DEPTHFUNC_EQUAL))
|
|
{
|
|
if (!(m_RP.m_FlagsPerFlush & RBSI_ALPHABLEND))
|
|
m_RP.m_FlagsPerFlush |= RBSI_WASDEPTHWRITE;
|
|
}
|
|
|
|
Changed = st ^ mCurState;
|
|
if (!Changed)
|
|
return;
|
|
|
|
if (Changed & GS_DEPTHFUNC_EQUAL)
|
|
{
|
|
if (st & GS_DEPTHFUNC_EQUAL)
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
|
|
else
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
|
|
}
|
|
|
|
if (Changed & GS_POLYLINE)
|
|
{
|
|
if (st & GS_POLYLINE)
|
|
m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
|
|
else
|
|
m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
|
|
}
|
|
|
|
if (Changed & GS_NOCOLMASK)
|
|
{
|
|
if (st & GS_NOCOLMASK)
|
|
m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
|
|
else
|
|
m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0xf);
|
|
}
|
|
if (Changed & GS_COLMASKONLYALPHA)
|
|
{
|
|
if (st & GS_COLMASKONLYALPHA)
|
|
m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA);
|
|
else
|
|
m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0xf);
|
|
}
|
|
|
|
if (Changed & GS_BLEND_MASK)
|
|
{
|
|
if ((st & GS_BLEND_MASK) == GS_BLEND_MASK)
|
|
{
|
|
st &= ~GS_BLEND_MASK;
|
|
st |= (mCurState & GS_BLEND_MASK);
|
|
goto skip;
|
|
}
|
|
|
|
if (st & GS_BLEND_MASK)
|
|
{
|
|
// Source factor
|
|
switch (st & GS_BLSRC_MASK)
|
|
{
|
|
case GS_BLSRC_ZERO:
|
|
src = D3DBLEND_ZERO;
|
|
break;
|
|
|
|
case GS_BLSRC_ONE:
|
|
src = D3DBLEND_ONE;
|
|
break;
|
|
|
|
case GS_BLSRC_DSTCOL:
|
|
src = D3DBLEND_DESTCOLOR;
|
|
break;
|
|
|
|
case GS_BLSRC_ONEMINUSDSTCOL:
|
|
src = D3DBLEND_INVDESTCOLOR;
|
|
break;
|
|
|
|
case GS_BLSRC_SRCALPHA:
|
|
src = D3DBLEND_SRCALPHA;
|
|
break;
|
|
|
|
case GS_BLSRC_ONEMINUSSRCALPHA:
|
|
src = D3DBLEND_INVSRCALPHA;
|
|
break;
|
|
|
|
case GS_BLSRC_DSTALPHA:
|
|
src = D3DBLEND_DESTALPHA;
|
|
break;
|
|
|
|
case GS_BLSRC_ONEMINUSDSTALPHA:
|
|
src = D3DBLEND_INVDESTALPHA;
|
|
break;
|
|
|
|
case GS_BLSRC_ALPHASATURATE:
|
|
src = D3DBLEND_SRCALPHASAT;
|
|
break;
|
|
|
|
default:
|
|
iLog->Log("CD3D8Renderer::SetState: invalid src blend state bits '%d'", st & GS_BLSRC_MASK);
|
|
break;
|
|
}
|
|
|
|
//Destination factor
|
|
switch (st & GS_BLDST_MASK)
|
|
{
|
|
case GS_BLDST_ZERO:
|
|
dst = D3DBLEND_ZERO;
|
|
break;
|
|
|
|
case GS_BLDST_ONE:
|
|
dst = D3DBLEND_ONE;
|
|
break;
|
|
|
|
case GS_BLDST_SRCCOL:
|
|
dst = D3DBLEND_SRCCOLOR;
|
|
break;
|
|
|
|
case GS_BLDST_ONEMINUSSRCCOL:
|
|
dst = D3DBLEND_INVSRCCOLOR;
|
|
break;
|
|
|
|
case GS_BLDST_SRCALPHA:
|
|
dst = D3DBLEND_SRCALPHA;
|
|
break;
|
|
|
|
case GS_BLDST_ONEMINUSSRCALPHA:
|
|
dst = D3DBLEND_INVSRCALPHA;
|
|
break;
|
|
|
|
case GS_BLDST_DSTALPHA:
|
|
dst = D3DBLEND_DESTALPHA;
|
|
break;
|
|
|
|
case GS_BLDST_ONEMINUSDSTALPHA:
|
|
dst = D3DBLEND_INVDESTALPHA;
|
|
break;
|
|
|
|
default:
|
|
iLog->Log("CD3D8Renderer::SetState: invalid dst blend state bits '%d'", st & GS_BLDST_MASK);
|
|
break;
|
|
}
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, src);
|
|
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, dst);
|
|
}
|
|
else
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
|
}
|
|
|
|
skip:
|
|
if (Changed & GS_DEPTHWRITE)
|
|
{
|
|
if (st & GS_DEPTHWRITE)
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
|
|
else
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
|
}
|
|
|
|
if (Changed & GS_NODEPTHTEST)
|
|
{
|
|
if (st & GS_NODEPTHTEST)
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
|
|
else
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
|
|
}
|
|
|
|
if (Changed & GS_ALPHATEST_MASK)
|
|
{
|
|
if (st & GS_ALPHATEST_MASK)
|
|
{
|
|
switch (st & GS_ALPHATEST_MASK)
|
|
{
|
|
case GS_ALPHATEST_GREATER0:
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHAREF, 0);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
|
|
break;
|
|
|
|
case GS_ALPHATEST_LESS128:
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHAREF, 0x80);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESS);
|
|
break;
|
|
|
|
case GS_ALPHATEST_GEQUAL128:
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHAREF, 0x80);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
|
}
|
|
mCurState = st;
|
|
}
|
|
|
|
void CD3D8Renderer::EF_SetColorOp(byte co)
|
|
{
|
|
int stage = m_TexMan->m_CurStage;
|
|
|
|
if (co == eCurColorOp[stage])
|
|
return;
|
|
switch (co)
|
|
{
|
|
case eCO_MODULATE:
|
|
default:
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
|
break;
|
|
|
|
case eCO_ONLYCOLOR_MODULATE:
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
|
|
break;
|
|
|
|
case eCO_BLENDDIFFUSEALPHA:
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);
|
|
break;
|
|
|
|
case eCO_BLENDTEXTUREALPHA:
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA);
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_BLENDTEXTUREALPHA);
|
|
break;
|
|
|
|
case eCO_MODULATE4X:
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_MODULATE4X);
|
|
break;
|
|
|
|
case eCO_MODULATE2X:
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_MODULATE2X);
|
|
break;
|
|
|
|
case eCO_ADD:
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_ADD);
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_ADD);
|
|
break;
|
|
|
|
case eCO_ADD_MODULATE:
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_ADD);
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
|
break;
|
|
|
|
case eCO_ADDSIGNED:
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_ADDSIGNED);
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_ADDSIGNED);
|
|
break;
|
|
|
|
case eCO_REPLACE:
|
|
case eCO_DECAL:
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
|
break;
|
|
|
|
case eCO_BUMPENVMAP:
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_BUMPENVMAP);
|
|
break;
|
|
|
|
case eCO_DISABLE:
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
|
m_pd3dDevice->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
|
break;
|
|
}
|
|
eCurColorOp[stage] = co;
|
|
}
|
|
|
|
void CD3D8Renderer::D3DSetCull(ECull eCull)
|
|
{
|
|
if (eCull == m_eCull)
|
|
return;
|
|
|
|
if (eCull == eCULL_None)
|
|
m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
|
else
|
|
{
|
|
if (eCull == eCULL_Back)
|
|
m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
|
|
else
|
|
m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
|
|
}
|
|
m_eCull = eCull;
|
|
}
|
|
|
|
|
|
void CD3D8Renderer::EF_PreRender()
|
|
{
|
|
m_RP.m_RealTime = iTimer->GetCurrTime();
|
|
ResetToDefault();
|
|
|
|
m_RP.m_Flags = 0;
|
|
m_RP.m_pPrevObject = NULL;
|
|
m_RP.m_FrameObject++;
|
|
|
|
EF_SetCameraInfo();
|
|
|
|
if (!m_RP.m_bStartPipeline && !m_bWasCleared && !(m_RP.m_PersFlags & RBPF_NOCLEARBUF))
|
|
{
|
|
m_RP.m_bStartPipeline = true;
|
|
EF_ClearBuffer(false, NULL);
|
|
}
|
|
}
|
|
|
|
void CD3D8Renderer::EF_PostRender()
|
|
{
|
|
EF_ObjectChange(NULL, 0, NULL);
|
|
m_RP.m_pRE = NULL;
|
|
|
|
HRESULT h;
|
|
if (m_RP.m_PersFlags & RBPF_USESTREAM1)
|
|
{
|
|
m_RP.m_PersFlags &= ~RBPF_USESTREAM1;
|
|
h = m_pd3dDevice->SetStreamSource( 1, NULL, 0);
|
|
}
|
|
if (m_RP.m_PersFlags & RBPF_USESTREAM2)
|
|
{
|
|
m_RP.m_PersFlags &= ~RBPF_USESTREAM2;
|
|
h = m_pd3dDevice->SetStreamSource( 2, NULL, 0);
|
|
}
|
|
if (m_RP.m_PersFlags & RBPF_SETCLIPPLANE)
|
|
{
|
|
EF_SetClipPlane(false, NULL, false);
|
|
m_RP.m_PersFlags &= ~RBPF_SETCLIPPLANE;
|
|
}
|
|
m_Viewport.MaxZ = 1.0f;
|
|
m_pd3dDevice->SetViewport(&m_Viewport);
|
|
|
|
ResetToDefault();
|
|
}
|
|
|
|
//=================================================================================
|
|
|
|
bool CD3D8Renderer::EF_PreDraw()
|
|
{
|
|
bool bRet = true;
|
|
if (m_RP.m_bLocked)
|
|
{
|
|
if (!m_RP.m_pRE)
|
|
{
|
|
m_RP.m_VB.VBPtr_D_1T->Unlock();
|
|
m_RP.m_IndexBuf->Unlock();
|
|
}
|
|
m_RP.m_bLocked = false;
|
|
}
|
|
if (!m_RP.m_pRE)
|
|
{
|
|
m_pd3dDevice->SetStreamSource(0, m_RP.m_VB.VBPtr_D_1T->GetInterface(), m_RP.m_Stride);
|
|
m_pd3dDevice->SetIndices(m_RP.m_IndexBuf->GetInterface(), 0);
|
|
}
|
|
else
|
|
bRet = m_RP.m_pRE->mfPreDraw();
|
|
|
|
return bRet;
|
|
}
|
|
|
|
// Initialize of the new shader pipeline (only 2d)
|
|
void CD3D8Renderer::EF_Start(SShader *ef, SShader *efState, SRenderShaderResources *Res, CRendElement *re)
|
|
{
|
|
m_RP.m_RendPass = 0;
|
|
m_RP.m_bLocked = false;
|
|
m_RP.m_RendNumIndices = 0;
|
|
m_RP.m_RendNumVerts = 0;
|
|
m_RP.m_FirstIndex = 0;
|
|
m_RP.m_FirstVertex = 0;
|
|
m_RP.m_pShader = ef;
|
|
m_RP.mCurLightMaterial = NULL;
|
|
m_RP.m_pStateShader = efState;
|
|
m_RP.m_pShaderResources = Res;
|
|
m_RP.m_DynLMask = 0;
|
|
m_RP.m_FlagsPerFlush = 0;
|
|
m_RP.m_FlagsModificators = 0;
|
|
m_RP.m_pFogVolume = NULL;
|
|
m_RP.m_pRE = NULL;
|
|
m_RP.m_fCurOpacity = 1.0f;
|
|
|
|
int flt = ef->m_FLT;
|
|
if (flt < FLT_N && CRenderer::CV_r_shownormals)
|
|
flt |= FLT_N;
|
|
m_RP.mFT = flt;
|
|
|
|
int n = ef->m_nVB + 8;
|
|
|
|
m_RP.m_Stride = sSVB[n].Stride;
|
|
m_RP.m_OffsD = sSVB[n].OffsD;
|
|
m_RP.m_OffsT = sSVB[n].OffsT;
|
|
m_RP.m_OffsN = sSVB[n].OffsN;
|
|
m_RP.m_NextPtr = m_RP.m_Ptr;
|
|
m_RP.m_CurD3DVFormat = n;
|
|
m_RP.m_VB = sSVB[n].mVB;
|
|
|
|
m_RP.m_Frame++;
|
|
}
|
|
|
|
// Initialize of the new shader pipeline
|
|
void CD3D8Renderer::EF_Start(SShader *ef, SShader *efState, SRenderShaderResources *Res, int numFog, CRendElement *re)
|
|
{
|
|
m_RP.m_RendPass = 0;
|
|
m_RP.m_bLocked = false;
|
|
m_RP.m_FirstIndex = 0;
|
|
m_RP.m_FirstVertex = 0;
|
|
m_RP.m_RendNumIndices = 0;
|
|
m_RP.m_RendNumVerts = 0;
|
|
m_RP.m_pShader = ef;
|
|
m_RP.m_pStateShader = efState;
|
|
m_RP.m_pShaderResources = Res;
|
|
m_RP.m_DynLMask = 0;
|
|
m_RP.m_pRE = NULL;
|
|
m_RP.mCurLightMaterial = NULL;
|
|
m_RP.m_FlagsPerFlush = 0;
|
|
m_RP.m_FlagsModificators = 0;
|
|
m_RP.m_fCurOpacity = 1.0f;
|
|
if (numFog && CV_r_VolumetricFog)
|
|
m_RP.m_pFogVolume = &m_RP.m_FogVolumes[numFog];
|
|
else
|
|
m_RP.m_pFogVolume = NULL;
|
|
|
|
int n = ef->m_nVB;
|
|
int flt = ef->m_FLT;
|
|
if (flt < FLT_N && CV_r_shownormals || ef->m_LightMaterial)
|
|
flt |= FLT_N;
|
|
m_RP.mFT = flt;
|
|
if (flt & FLT_N)
|
|
n += 4;
|
|
|
|
m_RP.m_Stride = sSVB[n].Stride;
|
|
m_RP.m_OffsD = sSVB[n].OffsD;
|
|
m_RP.m_OffsT = sSVB[n].OffsT;
|
|
m_RP.m_OffsN = sSVB[n].OffsN;
|
|
m_RP.m_NextPtr = m_RP.m_Ptr;
|
|
m_RP.m_VB = sSVB[n].mVB;
|
|
m_RP.m_CurD3DVFormat = ef->m_nVB;
|
|
m_RP.m_Frame++;
|
|
}
|
|
|
|
//========================================================================================
|
|
|
|
void CD3D8Renderer::EF_SetHWLight(int Num, vec4_t Pos, CFColor& Diffuse, CFColor& Specular, float ca, float la, float qa, float fRange)
|
|
{
|
|
m_pd3dDevice->SetRenderState(D3DRS_AMBIENT, 0);
|
|
|
|
m_Lights[Num].Position.x = Pos[0];
|
|
m_Lights[Num].Position.y = Pos[1];
|
|
m_Lights[Num].Position.z = Pos[2];
|
|
m_Lights[Num].Range = fRange;
|
|
if (!Pos[3])
|
|
{
|
|
Vec3d v = Vec3d(Pos[0], Pos[1], Pos[2]);
|
|
v.Normalize();
|
|
m_Lights[Num].Direction.x = v[0];
|
|
m_Lights[Num].Direction.y = v[1];
|
|
m_Lights[Num].Direction.z = v[2];
|
|
m_Lights[Num].Type = D3DLIGHT_DIRECTIONAL;
|
|
}
|
|
else
|
|
m_Lights[Num].Type = D3DLIGHT_POINT;
|
|
|
|
m_Lights[Num].Ambient.r = 1.0f;
|
|
m_Lights[Num].Ambient.g = 1.0f;
|
|
m_Lights[Num].Ambient.b = 1.0f;
|
|
m_Lights[Num].Ambient.a = 1.0f;
|
|
|
|
m_Lights[Num].Diffuse.r = Diffuse.r;
|
|
m_Lights[Num].Diffuse.g = Diffuse.g;
|
|
m_Lights[Num].Diffuse.b = Diffuse.b;
|
|
m_Lights[Num].Diffuse.a = Diffuse.a;
|
|
|
|
m_Lights[Num].Specular.r = Specular.r;
|
|
m_Lights[Num].Specular.g = Specular.g;
|
|
m_Lights[Num].Specular.b = Specular.b;
|
|
m_Lights[Num].Specular.a = Specular.a;
|
|
|
|
m_Lights[Num].Attenuation0 = ca;
|
|
m_Lights[Num].Attenuation1 = la;
|
|
m_Lights[Num].Attenuation2 = qa;
|
|
|
|
m_pd3dDevice->SetLight(Num, &m_Lights[Num]);
|
|
m_pd3dDevice->LightEnable(Num, TRUE);
|
|
|
|
m_EnableLights |= 1<<Num;
|
|
}
|
|
|
|
static float sAttenuation(float Distance, float Radius)
|
|
{
|
|
if(Distance <= Radius)
|
|
{
|
|
float A = Distance / Radius;
|
|
float B = (2 * A * A * A - 3 * A * A + 1);
|
|
|
|
return B / A * A * 2.0f;
|
|
}
|
|
else
|
|
return 0.0f;
|
|
}
|
|
|
|
|
|
bool CD3D8Renderer::EF_SetLights(int Flags, bool Enable)
|
|
{
|
|
if (!Enable)
|
|
{
|
|
if (m_EnableLights)
|
|
{
|
|
m_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, FALSE);
|
|
for (int i=0; i<8; i++)
|
|
{
|
|
if (m_EnableLights & (1<<i))
|
|
m_pd3dDevice->LightEnable(i, FALSE);
|
|
}
|
|
}
|
|
m_EnableLights = 0;
|
|
return false;
|
|
}
|
|
float MaxD3DRange = sqrtf(FLT_MAX); // xbox libs freak out about illegal light ranges
|
|
|
|
vec4_t Pos;
|
|
Vec3d lpos;
|
|
int n = 0;
|
|
float fCA, fLA, fQA;
|
|
Vec3d vCenterRE;
|
|
float fRadRE;
|
|
bool bCalcDist = false;
|
|
CFColor cDiffuse;
|
|
for (int i=0; i<m_RP.m_DLights.Num(); i++)
|
|
{
|
|
if (i >= 32)
|
|
break;
|
|
CDLight *dl = m_RP.m_DLights[i];
|
|
if (dl->m_Flags & DLF_DETAIL)
|
|
continue;
|
|
if (!(m_RP.m_DynLMask & (1<<i)))
|
|
continue;
|
|
if ((Flags & LMF_IGNOREPROJLIGHTS) && (dl->m_Flags & DLF_PROJECT))
|
|
continue;
|
|
if (Flags & LMF_LIGHT_MASK)
|
|
{
|
|
if (((Flags & LMF_LIGHT_MASK) >> LMF_LIGHT_SHIFT) != i)
|
|
continue;
|
|
}
|
|
// some statistics
|
|
if (!(m_RP.m_StatLightMask & (1<<i)))
|
|
{
|
|
m_RP.m_StatLightMask |= (1<<i);
|
|
m_RP.m_StatNumLights++;
|
|
}
|
|
TransformPosition(lpos, dl->m_Origin, m_RP.m_pCurObject->GetInvMatrix());
|
|
float fRange = 0;
|
|
if (dl->m_Flags & DLF_DIRECTIONAL)
|
|
{
|
|
lpos.Normalize();
|
|
Pos[3] = 0.0f;
|
|
fCA = 1.0f;
|
|
fLA = 0.0f;
|
|
fQA = 0.0f;
|
|
cDiffuse = dl->m_Color;
|
|
}
|
|
else
|
|
{
|
|
fRange = dl->m_fRadius;
|
|
Pos[3] = 1.0f;
|
|
if (m_RP.m_pRE && !bCalcDist)
|
|
{
|
|
Vec3d vMins, vMaxs;
|
|
bCalcDist = true;
|
|
m_RP.m_pRE->mfGetBBox(vMins, vMaxs);
|
|
vCenterRE = (vMins + vMaxs) * 0.5f;
|
|
vCenterRE.x += m_RP.m_pCurObject->m_Matrix(3,0);
|
|
vCenterRE.y += m_RP.m_pCurObject->m_Matrix(3,1);
|
|
vCenterRE.z += m_RP.m_pCurObject->m_Matrix(3,2);
|
|
fRadRE = (vMaxs - vMins).Length() * 0.5f;
|
|
}
|
|
float fDist = Max(0.1f, (vCenterRE - dl->m_Origin).Length());
|
|
float fMaxDist = Clamp(fDist + fRadRE, dl->m_fRadius * 0.0005f, dl->m_fRadius * 0.99f);
|
|
float fMinDist = Clamp(fDist - fRadRE, dl->m_fRadius * 0.001f, dl->m_fRadius * 0.995f);
|
|
float fMinAtt = 1.0f / sAttenuation(fMinDist, dl->m_fRadius);
|
|
float fMaxAtt = 1.0f / sAttenuation(fMaxDist, dl->m_fRadius);
|
|
if(Abs(fMinAtt - fMaxAtt) < 0.00001f)
|
|
{
|
|
fCA = fMinAtt;
|
|
fLA = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
fCA = Max(0.01f, fMinAtt - (fMaxAtt - fMinAtt) / (fMaxDist - fMinDist) * fMinDist);
|
|
fLA = Max(0.0f, (fMinAtt - fCA) / fMinDist);
|
|
}
|
|
fQA = 0.0f;
|
|
fRange = (256.0f - fCA) / Max(0.01f, fLA);
|
|
cDiffuse = dl->m_Color;
|
|
}
|
|
fCA = Max(0.0f, fCA);
|
|
fLA = Max(0.0f, fLA);
|
|
fQA = Max(0.0f, fQA);
|
|
Pos[0] = lpos.x;
|
|
Pos[1] = lpos.y;
|
|
Pos[2] = lpos.z;
|
|
cDiffuse.a = 1.0f;
|
|
EF_SetHWLight(n, Pos,
|
|
cDiffuse,
|
|
dl->m_SpecColor,
|
|
fCA, fLA, fQA, fRange);
|
|
n++;
|
|
}
|
|
|
|
if (m_EnableLights)
|
|
{
|
|
m_pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void CD3D8Renderer::EF_LightMaterial(SLightMaterial *lm, bool bEnable, int Flags)
|
|
{
|
|
if (m_RP.m_pShader->m_Flags3 & EF3_NOLIGHTSOURCE)
|
|
return;
|
|
if (!(m_RP.m_pShader->m_Flags & EF_NEEDNORMALS))
|
|
return;
|
|
|
|
PROFILE_FRAME_TOTAL(State_LightStates);
|
|
|
|
if (!bEnable)
|
|
{
|
|
EF_SetLights(Flags, false);
|
|
return;
|
|
}
|
|
|
|
CFColor colAmb;
|
|
if (Flags & LMF_NOAMBIENT)
|
|
colAmb = Col_Black;
|
|
else
|
|
colAmb = m_RP.m_pCurObject->m_AmbColor;
|
|
if (!m_RP.m_pCurObject || !(m_RP.m_pCurObject->m_ObjFlags & FOB_IGNOREMATERIALAMBIENT))
|
|
{
|
|
colAmb.r *= lm->Front.m_Ambient.r;
|
|
colAmb.g *= lm->Front.m_Ambient.g;
|
|
colAmb.b *= lm->Front.m_Ambient.b;
|
|
colAmb.a *= lm->Front.m_Ambient.a;
|
|
}
|
|
if (!(Flags & LMF_IGNORELIGHTS) && EF_SetLights(Flags, true))
|
|
{
|
|
CFColor colDif = lm->Front.m_Diffuse;
|
|
if (colDif.a != 1.0f && (Flags & LMF_NOALPHA))
|
|
colDif.a = 1.0f;
|
|
else
|
|
colDif.a = m_RP.m_fCurOpacity;
|
|
switch (lm->side)
|
|
{
|
|
case SLightMaterial::FRONT:
|
|
m_Material.Ambient.r = colAmb.r;
|
|
m_Material.Ambient.g = colAmb.g;
|
|
m_Material.Ambient.b = colAmb.b;
|
|
m_Material.Ambient.a = colAmb.a;
|
|
|
|
m_Material.Diffuse.r = colDif.r;
|
|
m_Material.Diffuse.g = colDif.g;
|
|
m_Material.Diffuse.b = colDif.b;
|
|
m_Material.Diffuse.a = colDif.a;
|
|
|
|
m_Material.Specular.r = lm->Front.m_Specular.r;
|
|
m_Material.Specular.g = lm->Front.m_Specular.g;
|
|
m_Material.Specular.b = lm->Front.m_Specular.b;
|
|
m_Material.Specular.a = lm->Front.m_Specular.a;
|
|
|
|
m_Material.Power = lm->Front.m_SpecShininess;
|
|
if (lm->Front.m_Specular == CFColor(0.0f))
|
|
m_Material.Power = 0;
|
|
break;
|
|
|
|
case SLightMaterial::BACK:
|
|
m_Material.Ambient.r = lm->Back.m_Ambient.r;
|
|
m_Material.Ambient.g = lm->Back.m_Ambient.g;
|
|
m_Material.Ambient.b = lm->Back.m_Ambient.b;
|
|
m_Material.Ambient.a = lm->Back.m_Ambient.a;
|
|
|
|
m_Material.Diffuse.r = lm->Back.m_Diffuse.r;
|
|
m_Material.Diffuse.g = lm->Back.m_Diffuse.g;
|
|
m_Material.Diffuse.b = lm->Back.m_Diffuse.b;
|
|
m_Material.Diffuse.a = lm->Back.m_Diffuse.a;
|
|
|
|
m_Material.Specular.r = lm->Back.m_Specular.r;
|
|
m_Material.Specular.g = lm->Back.m_Specular.g;
|
|
m_Material.Specular.b = lm->Back.m_Specular.b;
|
|
m_Material.Specular.a = lm->Back.m_Specular.a;
|
|
|
|
m_Material.Power = lm->Back.m_SpecShininess;
|
|
if (lm->Back.m_Specular == CFColor(0.0f))
|
|
m_Material.Power = 0;
|
|
break;
|
|
|
|
case SLightMaterial::BOTH:
|
|
m_Material.Ambient.r = lm->Front.m_Ambient.r;
|
|
m_Material.Ambient.g = lm->Front.m_Ambient.g;
|
|
m_Material.Ambient.b = lm->Front.m_Ambient.b;
|
|
m_Material.Ambient.a = lm->Front.m_Ambient.a;
|
|
|
|
m_Material.Diffuse.r = lm->Front.m_Diffuse.r;
|
|
m_Material.Diffuse.g = lm->Front.m_Diffuse.g;
|
|
m_Material.Diffuse.b = lm->Front.m_Diffuse.b;
|
|
m_Material.Diffuse.a = lm->Front.m_Diffuse.a;
|
|
|
|
m_Material.Specular.r = lm->Front.m_Specular.r;
|
|
m_Material.Specular.g = lm->Front.m_Specular.g;
|
|
m_Material.Specular.b = lm->Front.m_Specular.b;
|
|
m_Material.Specular.a = lm->Front.m_Specular.a;
|
|
|
|
m_Material.Power = lm->Front.m_SpecShininess;
|
|
if (lm->Front.m_Specular == CFColor(0.0f))
|
|
m_Material.Power = 0;
|
|
break;
|
|
}
|
|
}
|
|
m_pd3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
|
|
m_pd3dDevice->SetMaterial(&m_Material);
|
|
EF_SetVertColor();
|
|
}
|
|
|
|
//=============================================================
|
|
|
|
|
|
void CD3D8Renderer::EF_ApplyMatrixOps(TArray<SMatrixTransform>* MatrixOps, bool bEnable)
|
|
{
|
|
if (!MatrixOps)
|
|
return;
|
|
|
|
LPDIRECT3DDEVICE8 dv = m_pd3dDevice;
|
|
int CurMatrix = D3DTS_VIEW;
|
|
m_CurOpMatrix = NULL;
|
|
int Stage = -1;
|
|
|
|
for (int i=0; i<MatrixOps->Num(); i++)
|
|
{
|
|
SMatrixTransform *mt = &MatrixOps->Get(i);
|
|
if (mt->m_Matrix != CurMatrix)
|
|
{
|
|
if (m_CurOpMatrix)
|
|
{
|
|
if (Stage >= 0)
|
|
dv->SetTextureStageState( Stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
|
dv->SetTransform((D3DTRANSFORMSTATETYPE)CurMatrix, m_CurOpMatrix);
|
|
m_CurOpMatrix = NULL;
|
|
}
|
|
switch (mt->m_Matrix)
|
|
{
|
|
case D3DTS_TEXTURE0:
|
|
m_CurOpMatrix = &m_TexMatrix[0];
|
|
Stage = 0;
|
|
break;
|
|
case D3DTS_TEXTURE1:
|
|
m_CurOpMatrix = &m_TexMatrix[1];
|
|
Stage = 1;
|
|
break;
|
|
case D3DTS_TEXTURE2:
|
|
m_CurOpMatrix = &m_TexMatrix[2];
|
|
Stage = 2;
|
|
break;
|
|
case D3DTS_TEXTURE3:
|
|
m_CurOpMatrix = &m_TexMatrix[3];
|
|
Stage = 3;
|
|
break;
|
|
default:
|
|
Stage = -1;
|
|
}
|
|
if (!bEnable && mt->m_Matrix != D3DTS_PROJECTION && mt->m_Matrix != D3DTS_VIEW)
|
|
{
|
|
if (m_CurOpMatrix)
|
|
{
|
|
D3DXMatrixIdentity(m_CurOpMatrix);
|
|
dv->SetTransform((D3DTRANSFORMSTATETYPE)mt->m_Matrix, m_CurOpMatrix);
|
|
if (Stage >= 0)
|
|
dv->SetTextureStageState( Stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
|
|
}
|
|
}
|
|
CurMatrix = mt->m_Matrix;
|
|
}
|
|
mt->mfSet(bEnable);
|
|
}
|
|
if (m_CurOpMatrix && bEnable)
|
|
{
|
|
if (Stage >= 0)
|
|
dv->SetTextureStageState( Stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
|
dv->SetTransform((D3DTRANSFORMSTATETYPE)CurMatrix, m_CurOpMatrix);
|
|
}
|
|
}
|
|
|
|
#include "../Common/NvTriStrip/NVTriStrip.h"
|
|
|
|
void CD3D8Renderer::EF_DrawIndexedMesh (int nPrimType)
|
|
{
|
|
D3DPRIMITIVETYPE nType;
|
|
int nFaces;
|
|
|
|
switch (nPrimType)
|
|
{
|
|
case R_PRIMV_TRIANGLES:
|
|
nType = D3DPT_TRIANGLELIST;
|
|
nFaces = m_RP.m_RendNumIndices/3;
|
|
break;
|
|
|
|
case R_PRIMV_TRIANGLE_STRIP:
|
|
nType = D3DPT_TRIANGLESTRIP;
|
|
nFaces = m_RP.m_RendNumIndices-2;
|
|
break;
|
|
|
|
case R_PRIMV_TRIANGLE_FAN:
|
|
nType = D3DPT_TRIANGLEFAN;
|
|
nFaces = m_RP.m_RendNumIndices-2;
|
|
break;
|
|
|
|
case R_PRIMV_MULTI_STRIPS:
|
|
{
|
|
list2<CMatInfo> *mats = m_RP.m_pRE->mfGetMatInfoList();
|
|
if (mats)
|
|
{
|
|
CMatInfo *m = mats->Get(0);
|
|
for (int i=0; i<mats->Count(); i++, m++)
|
|
{
|
|
if (FAILED(h=m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, m->nFirstVertId, m->nNumVerts, m->nFirstIndexId, m->nNumIndices - 2)))
|
|
{
|
|
Error("CD3D8Renderer::EF_DrawIndexedMesh: DrawIndexedPrimitive error", h);
|
|
return;
|
|
}
|
|
m_nPolygons += (m->nNumIndices - 2);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case R_PRIMV_MULTI_GROUPS:
|
|
{
|
|
CMatInfo *mi = m_RP.m_pRE->mfGetMatInfo();
|
|
if (mi)
|
|
{
|
|
int offs = mi->nFirstIndexId;
|
|
for (int i=0; i<mi->m_dwNumSections; i++)
|
|
{
|
|
SPrimitiveGroup *g = &mi->m_pPrimitiveGroups[i];
|
|
switch (g->type)
|
|
{
|
|
case PT_STRIP:
|
|
if (FAILED(h=m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, m_RP.m_FirstVertex, mi->nNumVerts, g->offsIndex+offs, g->numIndices - 2)))
|
|
{
|
|
Error("CD3D8Renderer::EF_DrawIndexedMesh: DrawIndexedPrimitive error", h);
|
|
return;
|
|
}
|
|
m_nPolygons += (g->numIndices - 2);
|
|
break;
|
|
|
|
case PT_LIST:
|
|
if (FAILED(h=m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, m_RP.m_FirstVertex, mi->nNumVerts, g->offsIndex+offs, g->numIndices / 3)))
|
|
{
|
|
Error("CD3D8Renderer::EF_DrawIndexedMesh: DrawIndexedPrimitive error", h);
|
|
return;
|
|
}
|
|
m_nPolygons += (g->numIndices / 3);
|
|
break;
|
|
|
|
case PT_FAN:
|
|
if (FAILED(h=m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, m_RP.m_FirstVertex, mi->nNumVerts, g->offsIndex+offs, g->numIndices - 2)))
|
|
{
|
|
Error("CD3D8Renderer::EF_DrawIndexedMesh: DrawIndexedPrimitive error", h);
|
|
return;
|
|
}
|
|
m_nPolygons += (g->numIndices - 2);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
if (FAILED(h=m_pd3dDevice->DrawIndexedPrimitive(nType, m_RP.m_FirstVertex, m_RP.m_RendNumVerts, m_RP.m_FirstIndex, nFaces)))
|
|
{
|
|
Error("CD3D8Renderer::EF_DrawIndexedMesh: DrawIndexedPrimitive error", h);
|
|
return;
|
|
}
|
|
m_nPolygons += nFaces;
|
|
}
|
|
|
|
void CD3D8Renderer::EF_DrawFogOverlay()
|
|
{
|
|
|
|
}
|
|
|
|
void CD3D8Renderer::EF_DrawDetailOverlay()
|
|
{
|
|
// Usually it means first pass in indoor engine (before shadow pass)
|
|
if (m_RP.m_ObjFlags & FOB_ZPASS)
|
|
return;
|
|
|
|
if (!m_RP.m_pShaderResources || !m_RP.m_pShaderResources->m_Textures[EFTT_DETAIL_OVERLAY])
|
|
return;
|
|
|
|
SEfResTexture *rt = m_RP.m_pShaderResources->m_Textures[EFTT_DETAIL_OVERLAY];
|
|
SShader *sh = m_RP.m_pShader;
|
|
int i;
|
|
|
|
float fDistToCam = 500.0f;
|
|
float fDist = CV_r_detaildistance;
|
|
if (m_RP.m_pRE)
|
|
{
|
|
fDistToCam = m_RP.m_pRE->mfMinDistanceToCamera();
|
|
if (fDistToCam > fDist+1.0f)
|
|
return;
|
|
}
|
|
CD3D8TexMan::BindNULL(2);
|
|
EF_SelectTMU(1);
|
|
CTexMan::m_Text_Fog->Set();
|
|
EnableTMU(true);
|
|
EF_SelectTMU(0);
|
|
rt->m_TU.m_TexPic->Set();
|
|
|
|
if (m_RP.m_FlagsPerFlush & RBSI_WASDEPTHWRITE)
|
|
SetState(GS_BLSRC_DSTCOL | GS_BLDST_SRCCOL | GS_DEPTHFUNC_EQUAL);
|
|
else
|
|
SetState(GS_BLSRC_DSTCOL | GS_BLDST_SRCCOL);
|
|
|
|
if (!(sh->m_Flags & EF_HASVSHADER))
|
|
{
|
|
float param[4];
|
|
int n = Clamp(CV_r_detailnumlayers, 1, 4);
|
|
float fUScale = rt->m_TexModificator.m_Tiling[0];
|
|
float fVScale = rt->m_TexModificator.m_Tiling[1];
|
|
if (!fUScale)
|
|
fUScale = CV_r_detailscale;
|
|
if (!fVScale)
|
|
fVScale = CV_r_detailscale;
|
|
|
|
for (i=0; i<n; i++)
|
|
{
|
|
/*glMatrixMode(GL_TEXTURE);
|
|
glLoadIdentity();
|
|
glScalef(fUScale, fVScale, 1.0f);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
EF_SelectTMU(1);
|
|
|
|
float intens = -0.5f / fDist;
|
|
param[0] = intens*m_ViewMatrix.m_values[0][2];
|
|
param[1] = intens*m_ViewMatrix.m_values[1][2];
|
|
param[2] = intens*m_ViewMatrix.m_values[2][2];
|
|
param[3] = intens*m_ViewMatrix.m_values[3][2] + 0.5f;
|
|
glTexGenfv(GL_S, GL_OBJECT_PLANE, param);
|
|
|
|
param[0] = param[1] = param[2] = 0;
|
|
param[3] = 0.5f;
|
|
glTexGenfv(GL_T, GL_OBJECT_PLANE, param);
|
|
|
|
glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
|
|
glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
|
|
glEnable(GL_TEXTURE_GEN_S);
|
|
glEnable(GL_TEXTURE_GEN_T);*/
|
|
|
|
EF_SelectTMU(0);
|
|
|
|
if (!m_RP.m_RCDetail)
|
|
m_RP.m_RCDetail = CPShader::mfForName("RCDetailAtten", false);
|
|
if (m_RP.m_RCDetail)
|
|
{
|
|
m_RP.m_RCDetail->mfSet(true);
|
|
param[0] = param[1] = param[2] = 0.5f; param[3] = 1.0f;
|
|
CPShader_D3D::mfSetFloat4f(0, param);
|
|
}
|
|
|
|
// Draw primitives
|
|
EF_Draw(sh, NULL);
|
|
|
|
fDist /= 2.0f;
|
|
if (fDistToCam > fDist+1.0f)
|
|
break;
|
|
fUScale *= 2.0f;
|
|
fVScale *= 2.0f;
|
|
}
|
|
|
|
/*glMatrixMode(GL_TEXTURE);
|
|
glLoadIdentity();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
EF_SelectTMU(1);
|
|
glDisable(GL_TEXTURE_GEN_S);
|
|
glDisable(GL_TEXTURE_GEN_T);*/
|
|
EF_SelectTMU(0);
|
|
}
|
|
else
|
|
{
|
|
float param[4];
|
|
if (!m_RP.m_VPDetail)
|
|
m_RP.m_VPDetail = CVProgram::mfForName("CGVProgDetail", true);
|
|
if (!m_RP.m_RCDetail)
|
|
m_RP.m_RCDetail = CPShader::mfForName("RCDetailAtten", false);
|
|
if (m_RP.m_RCDetail)
|
|
{
|
|
m_RP.m_RCDetail->mfSet(true);
|
|
param[0] = param[1] = param[2] = 0.5f; param[3] = 1.0f;
|
|
CPShader_D3D::mfSetFloat4f(0, param);
|
|
}
|
|
|
|
gRenDev->m_RP.m_FlagsModificators &= ~0x7;
|
|
m_RP.m_VPDetail->mfSet(true, NULL, 1);
|
|
|
|
EF_PreDraw();
|
|
|
|
CCGVProgram_D3D *vpD3D = (CCGVProgram_D3D *)m_RP.m_VPDetail;
|
|
SCGBind *pBindScale = vpD3D->mfGetParameterBind("DetailScaling");
|
|
SCGBind *pBindTG0 = vpD3D->mfGetParameterBind("TexGen00");
|
|
SCGBind *pBindTG1 = vpD3D->mfGetParameterBind("TexGen01");
|
|
|
|
int n = Clamp(CV_r_detailnumlayers, 1, 4);
|
|
float fUScale = rt->m_TexModificator.m_Tiling[0];
|
|
float fVScale = rt->m_TexModificator.m_Tiling[1];
|
|
if (!fUScale)
|
|
fUScale = CV_r_detailscale;
|
|
if (!fVScale)
|
|
fVScale = CV_r_detailscale;
|
|
for (i=0; i<n; i++)
|
|
{
|
|
param[0] = fUScale;
|
|
param[1] = fVScale;
|
|
param[2] = 0;
|
|
param[3] = 0;
|
|
if (pBindScale)
|
|
vpD3D->mfParameter4f(pBindScale, param);
|
|
|
|
Plane plane;
|
|
|
|
float intens = -0.25f / fDist;
|
|
Plane plane00;
|
|
plane00.n.x = intens*m_CameraMatrix(0,2);
|
|
plane00.n.y = intens*m_CameraMatrix(1,2);
|
|
plane00.n.z = intens*m_CameraMatrix(2,2);
|
|
plane00.d = intens*m_CameraMatrix(3,2);
|
|
|
|
plane = TransformPlane(m_RP.m_pCurObject->m_Matrix, plane00);
|
|
plane.d += 0.5f;
|
|
if (pBindTG0)
|
|
vpD3D->mfParameter4f(pBindTG0, &plane.n.x);
|
|
plane.n.x = plane.n.y = plane.n.z = 0;
|
|
plane.d = 0.49f;
|
|
if (pBindTG1)
|
|
vpD3D->mfParameter4f(pBindTG1, param);
|
|
|
|
// Draw primitives
|
|
EF_Draw(sh, NULL);
|
|
|
|
fDist /= 2.0f;
|
|
if (fDistToCam > fDist+1.0f)
|
|
break;
|
|
fUScale *= 2.0f;
|
|
fVScale *= 2.0f;
|
|
}
|
|
|
|
m_RP.m_VPDetail->mfSet(false, NULL, 1);
|
|
if (m_RP.m_RCDetail)
|
|
m_RP.m_RCDetail->mfSet(false);
|
|
}
|
|
CD3D8TexMan::BindNULL(1);
|
|
}
|
|
|
|
void CD3D8Renderer::EF_DrawDecalOverlay()
|
|
{
|
|
// Usually it means first pass in indoor engine (before shadow pass)
|
|
if (m_RP.m_ObjFlags & FOB_ZPASS)
|
|
return;
|
|
|
|
if (!m_RP.m_pShaderResources || !m_RP.m_pShaderResources->m_Textures[EFTT_DECAL_OVERLAY])
|
|
return;
|
|
|
|
SEfResTexture *rt = m_RP.m_pShaderResources->m_Textures[EFTT_DECAL_OVERLAY];
|
|
SShader *sh = m_RP.m_pShader;
|
|
|
|
SelectTMU(0);
|
|
rt->m_TU.m_TexPic->Set();
|
|
|
|
if (m_RP.m_FlagsPerFlush & RBSI_WASDEPTHWRITE)
|
|
SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_DEPTHFUNC_EQUAL);
|
|
else
|
|
SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA);
|
|
EF_SetColorOp(eCO_REPLACE);
|
|
|
|
bool bMatrChanged = false;
|
|
|
|
}
|
|
|
|
void CD3D8Renderer::EF_DrawLayersHW(SShaderTechnique *hs, SShader *pSH)
|
|
{
|
|
SShaderPassHW *slw;
|
|
int i;
|
|
int pass;
|
|
|
|
pass = hs->m_Passes.Num();
|
|
if (!pass)
|
|
return;
|
|
|
|
if ((m_RP.m_ObjFlags & FOB_LIGHTPASS) && (pSH->m_Flags & EF_USELIGHTS))
|
|
return;
|
|
if (m_RP.m_ObjFlags & FOB_FOGPASS)
|
|
return;
|
|
|
|
CVProgram *curVP = hs->m_VProgram;
|
|
CVProgram *newVP;
|
|
|
|
// Enable vertex shader
|
|
if (curVP)
|
|
curVP->mfSet(true, NULL);
|
|
|
|
slw = &hs->m_Passes[0];
|
|
for (i=0; i<pass; i++, slw++)
|
|
{
|
|
/*if (slw->m_Conditions)
|
|
{
|
|
SPassConditions *pc = slw->m_Conditions;
|
|
if (pc->m_Flags & SHPF_AMBIENT)
|
|
{
|
|
if (m_RP.m_pCurObject && (m_RP.m_pCurObject->m_ObjFlags & FOB_LIGHTPASS))
|
|
continue;
|
|
}
|
|
if (pc->m_Flags & SHPF_HASLM)
|
|
{
|
|
if (!m_RP.m_pShaderResources || !m_RP.m_pShaderResources->m_Textures[EFTT_LIGHTMAP].m_TU.m_TexPic)
|
|
continue;
|
|
}
|
|
}*/
|
|
if (CRenderer::CV_r_log >= 4)
|
|
Logv(SRendItem::m_RecurseLevel, "+++ Pass %d\n", m_RP.m_RendPass);
|
|
|
|
m_RP.m_StatNumPasses++;
|
|
m_RP.m_CurrPass = slw;
|
|
|
|
if (slw->m_LightMaterial)
|
|
{
|
|
if (m_RP.m_pShaderResources && m_RP.m_pShaderResources->m_LMaterial)
|
|
m_RP.m_pShaderResources->m_LMaterial->mfApply(slw->m_LMFlags);
|
|
else
|
|
slw->m_LightMaterial->mfApply(slw->m_LMFlags);
|
|
}
|
|
|
|
if (slw->m_Stencil)
|
|
slw->m_Stencil->mfSet();
|
|
|
|
EF_Eval_DeformVerts(slw->m_Deforms);
|
|
EF_Eval_TexGen(slw);
|
|
EF_Eval_RGBAGen(slw);
|
|
|
|
if (slw->m_VProgram)
|
|
newVP = slw->m_VProgram;
|
|
else
|
|
newVP = hs->m_VProgram;
|
|
|
|
// Set vertex program for the current pass if needed
|
|
if (newVP != curVP)
|
|
{
|
|
if (curVP)
|
|
{
|
|
curVP->mfSet(false, slw);
|
|
curVP = NULL;
|
|
}
|
|
if (newVP)
|
|
{
|
|
curVP = newVP;
|
|
curVP->mfSet(true, slw);
|
|
}
|
|
}
|
|
|
|
//EF_SetArrayPointers(slw->m_Pointers, 1);
|
|
EF_ApplyMatrixOps(slw->m_MatrixOps, true);
|
|
|
|
if (!curVP)
|
|
{
|
|
HRESULT hr = m_pd3dDevice->SetVertexShader(m_RP.m_D3DFixedPipeline[m_RP.m_FlagsModificators&7][m_RP.m_CurD3DVFormat].m_Handle);
|
|
if (FAILED(hr))
|
|
continue;
|
|
}
|
|
|
|
// Unlock all VB (if needed) and set current streams
|
|
EF_PreDraw();
|
|
|
|
// Set all textures and HW TexGen modes for the current pass (ShadeLayer)
|
|
if (slw->mfSetTextures(true))
|
|
{
|
|
// Set Render states for the current pass
|
|
if (m_RP.m_pCurObject->m_RenderState)
|
|
SetState(m_RP.m_pCurObject->m_RenderState);
|
|
else
|
|
{
|
|
if (m_RP.m_RendPass || (m_RP.m_ObjFlags & FOB_LIGHTPASS))
|
|
SetState(slw->m_SecondRenderState);
|
|
else
|
|
SetState(slw->m_RenderState);
|
|
}
|
|
|
|
// Set Pixel shaders and Register combiners for the current pass
|
|
if (slw->m_FShader)
|
|
slw->m_FShader->mfSet(true, slw);
|
|
|
|
EF_Draw(pSH, slw);
|
|
|
|
m_RP.m_RendPass++;
|
|
|
|
// Reset Pixel shaders and Register combiners for the current pass
|
|
if (slw->m_FShader)
|
|
slw->m_FShader->mfSet(false, slw);
|
|
}
|
|
|
|
// Reset HW TexGen modes for the current pass (ShadeLayer)
|
|
slw->mfSetTextures(false);
|
|
|
|
EF_ApplyMatrixOps(slw->m_MatrixOps, false);
|
|
|
|
if (slw->m_Stencil)
|
|
slw->m_Stencil->mfReset();
|
|
|
|
if (slw->m_LightMaterial)
|
|
slw->m_LightMaterial->mfDisable();
|
|
}
|
|
|
|
// Disable vertex shader
|
|
if (curVP)
|
|
curVP->mfSet(false, NULL);
|
|
}
|
|
|
|
void CD3D8Renderer::EF_DrawLightsHW(SShaderTechnique *hs, SShader *ef, int Stage)
|
|
{
|
|
SShaderPassHW *slw;
|
|
int i, l;
|
|
int nl = 0;
|
|
int n;
|
|
|
|
if (!hs->m_LightPasses[Stage].Num())
|
|
return;
|
|
|
|
CVProgram *curVP = hs->m_VProgram;
|
|
CVProgram *newVP;
|
|
|
|
// Set vertex shader
|
|
if (curVP)
|
|
curVP->mfSet(true, NULL);
|
|
|
|
// For each light source
|
|
for (l=0; l<m_RP.m_NumActiveDLights; l++)
|
|
{
|
|
m_RP.m_pCurLight = m_RP.m_pActiveDLights[l];
|
|
m_RP.m_nCurLight = m_RP.m_pCurLight->m_Id;
|
|
TArray<SShaderPassHW>* ll;
|
|
ll = &hs->m_LightPasses[Stage];
|
|
nl++;
|
|
|
|
// Ignore diffuse passes for specular only light sources
|
|
if ((m_RP.m_pCurLight->m_Flags & DLF_LM) && Stage==0)
|
|
{
|
|
if ((m_RP.m_pShaderResources && m_RP.m_pShaderResources->m_Textures[EFTT_LIGHTMAP_DIR]) || m_RP.m_pCurObject->m_nLMId)
|
|
continue;
|
|
}
|
|
|
|
if (m_RP.m_pStateShader && m_RP.m_pStateShader->m_State && m_RP.m_pStateShader->m_State->m_Stencil)
|
|
{
|
|
if (m_RP.m_pCurLight->m_Flags & DLF_CASTSHADOW_VOLUME)
|
|
m_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
|
|
else
|
|
m_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
|
}
|
|
|
|
n = 0;
|
|
bool bBreak = false;
|
|
// For each layer/pass
|
|
for (i=0; i<ll->Num(); i++)
|
|
{
|
|
slw = &ll[0][i];
|
|
int msk;
|
|
if (msk = (slw->m_LightFlags & DLF_LIGHTTYPE_MASK))
|
|
{
|
|
if (!(msk & (m_RP.m_pCurLight->m_Flags & DLF_LIGHTTYPE_MASK)))
|
|
continue;
|
|
if (slw->m_LightFlags & DLF_LM)
|
|
{
|
|
if (!(m_RP.m_pCurLight->m_Flags & DLF_LM))
|
|
continue;
|
|
if ((!m_RP.m_pShaderResources || !m_RP.m_pShaderResources->m_Textures[EFTT_LIGHTMAP_DIR]) && !m_RP.m_pCurObject->m_nLMId)
|
|
continue;
|
|
assert (m_RP.m_pCurLight->m_SpecColor.r!=0 || m_RP.m_pCurLight->m_SpecColor.g!=0 || m_RP.m_pCurLight->m_SpecColor.b!=0);
|
|
}
|
|
}
|
|
if (slw->m_LMFlags & LMF_NOBUMP)
|
|
{
|
|
if (!m_RP.m_pShaderResources || !m_RP.m_pShaderResources->m_Textures[EFTT_BUMP] || !m_RP.m_pShaderResources->m_Textures[EFTT_BUMP]->m_TU.m_bNoBump)
|
|
continue;
|
|
bBreak = true;
|
|
}
|
|
else
|
|
if (bBreak)
|
|
break;
|
|
|
|
if (EF_RejectLightPass(slw))
|
|
continue;
|
|
|
|
if (!n)
|
|
{
|
|
if (!(m_RP.m_StatLightMask & (1<<m_RP.m_nCurLight)))
|
|
{
|
|
m_RP.m_StatLightMask |= (1<<m_RP.m_nCurLight);
|
|
m_RP.m_StatNumLights++;
|
|
}
|
|
}
|
|
|
|
if (CRenderer::CV_r_log >= 3)
|
|
Logv(SRendItem::m_RecurseLevel, "+++ Light pass %d for light %d\n", m_RP.m_RendPass, l);
|
|
|
|
n++;
|
|
m_RP.m_StatNumLightPasses++;
|
|
|
|
m_RP.m_CurrPass = slw;
|
|
|
|
// Set stencil states for the current pass if needed
|
|
if (slw->m_Stencil)
|
|
slw->m_Stencil->mfSet();
|
|
|
|
EF_Eval_TexGen(slw);
|
|
EF_Eval_RGBAGen(slw);
|
|
|
|
//EF_SetArrayPointers(slw->m_Pointers, 1);
|
|
EF_ApplyMatrixOps(slw->m_MatrixOps, true);
|
|
|
|
if (slw->m_VProgram)
|
|
newVP = slw->m_VProgram;
|
|
else
|
|
newVP = hs->m_VProgram;
|
|
|
|
// Set vertex program for the current pass if needed
|
|
if (newVP != curVP)
|
|
{
|
|
if (curVP)
|
|
{
|
|
curVP->mfSet(false, slw);
|
|
curVP = NULL;
|
|
}
|
|
if (newVP)
|
|
{
|
|
curVP = newVP;
|
|
curVP->mfSet(true, slw);
|
|
}
|
|
}
|
|
if (!curVP)
|
|
{
|
|
HRESULT hr = m_pd3dDevice->SetVertexShader(m_RP.m_D3DFixedPipeline[m_RP.m_FlagsModificators&7][m_RP.m_CurD3DVFormat].m_Handle);
|
|
if (FAILED(hr))
|
|
continue;
|
|
}
|
|
|
|
if (slw->m_LightMaterial)
|
|
{
|
|
if (m_RP.m_pShaderResources && m_RP.m_pShaderResources->m_LMaterial)
|
|
m_RP.m_pShaderResources->m_LMaterial->mfApply(slw->m_LMFlags | (l<<LMF_LIGHT_SHIFT));
|
|
else
|
|
slw->m_LightMaterial->mfApply(slw->m_LMFlags | (l<<LMF_LIGHT_SHIFT));
|
|
}
|
|
|
|
// Unlock all VB (if needed) and set current streams
|
|
EF_PreDraw();
|
|
|
|
// Set all textures and HW TexGen modes for the current pass (ShadeLayer)
|
|
if (slw->mfSetTextures(true))
|
|
{
|
|
// Set Render states for the current pass
|
|
if (m_RP.m_pCurObject->m_RenderState)
|
|
SetState(m_RP.m_pCurObject->m_RenderState);
|
|
else
|
|
{
|
|
if (m_RP.m_RendPass || (m_RP.m_ObjFlags & FOB_LIGHTPASS))
|
|
SetState(slw->m_SecondRenderState);
|
|
else
|
|
SetState(slw->m_RenderState);
|
|
}
|
|
|
|
// Set Pixel shaders and Register combiners for the current pass
|
|
if (slw->m_FShader)
|
|
slw->m_FShader->mfSet(true, slw);
|
|
|
|
EF_Draw(ef, slw);
|
|
|
|
m_RP.m_RendPass++;
|
|
|
|
// Reset Pixel shaders and Register combiners for the current pass
|
|
if (slw->m_FShader)
|
|
slw->m_FShader->mfSet(false, slw);
|
|
}
|
|
|
|
// Reset HW TexGen modes for the current pass (ShadeLayer)
|
|
slw->mfSetTextures(false);
|
|
|
|
EF_ApplyMatrixOps(slw->m_MatrixOps, false);
|
|
|
|
if (slw->m_Stencil)
|
|
slw->m_Stencil->mfReset();
|
|
|
|
// Disable light materials for the current pass
|
|
if (slw->m_LightMaterial)
|
|
SLightMaterial::mfDisable();
|
|
}
|
|
}
|
|
|
|
// Disable vertex shader
|
|
if (curVP)
|
|
curVP->mfSet(false, NULL);
|
|
|
|
m_RP.m_nCurLight = -1;
|
|
m_RP.m_pCurLight = NULL;
|
|
}
|
|
|
|
void CD3D8Renderer::EF_FlushHW()
|
|
{
|
|
guard(CD3D8Renderer::EF_FlushHW);
|
|
|
|
SShader *ef = m_RP.m_pShader;
|
|
|
|
int nPolys = m_nPolygons;
|
|
|
|
int nHW;
|
|
int nPrevObjMask = m_RP.m_pPrevRObject ? (m_RP.m_pPrevRObject->m_ObjFlags & FOB_MASKCONDITIONS) : 0;
|
|
int nObjMask = m_RP.m_ObjFlags & FOB_MASKCONDITIONS;
|
|
|
|
if (!EF_BuildLightsList())
|
|
iLog->Log("WARNING: CGLRenderer::EF_BuildLightsList: Too many light sources per render item (> 16). Shader: '%s'\n", m_RP.m_pShader->m_Name.c_str());
|
|
|
|
//if (m_RP.m_PrevShaderID == ef->m_Id && m_RP.m_PrevDynLMask == m_RP.m_DynLMask && nPrevObjMask == nObjMask)
|
|
// nHW = m_RP.m_CurTechnique;
|
|
//else
|
|
{
|
|
m_RP.m_PrevShaderID = ef->m_Id;
|
|
m_RP.m_PrevDynLMask = m_RP.m_DynLMask;
|
|
m_RP.m_pPrevRObject = m_RP.m_pCurObject;
|
|
|
|
nHW = EF_SelectHWTechnique(ef);
|
|
m_RP.m_CurTechnique = nHW;
|
|
}
|
|
SShaderTechnique *hs = ef->m_HWTechniques[nHW];
|
|
|
|
if (hs->m_Flags & FHF_TANGENTSUSED)
|
|
m_RP.m_FlagsModificators |= RBMF_TANGENTSUSED;
|
|
if (hs->m_Flags & FHF_LMTCUSED)
|
|
m_RP.m_FlagsModificators |= RBMF_LMTCUSED;
|
|
|
|
if (m_RP.m_pRE)
|
|
m_RP.m_pRE->mfCheckUpdate(hs->m_Flags);
|
|
|
|
if (ef->m_Flags & EF_NEEDNORMALS)
|
|
EF_EvalNormalsRB(ef);
|
|
EF_Eval_DeformVerts(ef->m_Deforms);
|
|
|
|
if (ef->m_Flags & EF_POLYGONOFFSET)
|
|
{
|
|
if (m_d3dCaps.RasterCaps & D3DPRASTERCAPS_ZBIAS)
|
|
m_pd3dDevice->SetRenderState( D3DRS_ZBIAS, CV_d3d8_decaloffset );
|
|
}
|
|
|
|
if (!(m_RP.m_FlagsPerFlush & RBSI_NOCULL))
|
|
{
|
|
if (hs->m_eCull != -1)
|
|
D3DSetCull(hs->m_eCull);
|
|
else
|
|
D3DSetCull(ef->m_eCull);
|
|
}
|
|
|
|
EF_ApplyMatrixOps(hs->m_MatrixOps, true);
|
|
|
|
if (hs->m_Flags & FHF_FIRSTLIGHT)
|
|
{
|
|
EF_DrawLightsHW(hs, ef, 0); // Diffuse passes
|
|
EF_DrawLayersHW(hs, ef); // Ambient passes
|
|
EF_DrawLightsHW(hs, ef, 1); // Specular passes
|
|
}
|
|
else
|
|
{
|
|
EF_DrawLayersHW(hs, ef); // Ambient passes
|
|
EF_DrawLightsHW(hs, ef, 0); // Diffuse passes
|
|
EF_DrawLightsHW(hs, ef, 1); // Specular passes
|
|
}
|
|
|
|
EF_ApplyMatrixOps(hs->m_MatrixOps, false);
|
|
|
|
if (ef->m_Flags & EF_POLYGONOFFSET)
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZBIAS, 0);
|
|
|
|
if (m_RP.m_pShaderResources && m_RP.m_pShaderResources->m_Textures[EFTT_DECAL_OVERLAY] && CV_r_decaltextures)
|
|
EF_DrawDecalOverlay();
|
|
|
|
if (m_RP.m_pShaderResources && m_RP.m_pShaderResources->m_Textures[EFTT_DETAIL_OVERLAY] && CV_r_detailtextures)
|
|
EF_DrawDetailOverlay();
|
|
|
|
if (m_RP.m_pFogVolume && CV_r_VolumetricFog)
|
|
EF_DrawFogOverlay();
|
|
|
|
unguard;
|
|
}
|
|
|
|
bool CD3D8Renderer::EF_SetResourcesState(bool bSet)
|
|
{
|
|
bool bRes = true;
|
|
if (bSet)
|
|
{
|
|
if ((m_RP.m_ObjFlags & FOB_ZPASS) && (!(m_RP.m_pShader->m_Flags2 & EF2_OPAQUE) || m_RP.m_pShaderResources->m_Opacity != 1.0f))
|
|
return false;
|
|
|
|
if (m_RP.m_pShaderResources->m_ResFlags & MTLFLAG_2SIDED)
|
|
{
|
|
D3DSetCull(eCULL_None);
|
|
m_RP.m_FlagsPerFlush |= RBSI_NOCULL;
|
|
}
|
|
if (m_RP.m_pShaderResources->m_AlphaRef)
|
|
{
|
|
if (!(mCurState & GS_ALPHATEST_MASK))
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHAREF, (DWORD)(m_RP.m_pShaderResources->m_AlphaRef*255.0f));
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
|
m_RP.m_FlagsPerFlush |= RBSI_ALPHATEST;
|
|
}
|
|
else
|
|
if (m_RP.m_pShaderResources->m_Opacity != 1.0f)
|
|
{
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
|
mCurState &= ~GS_BLEND_MASK;
|
|
if (m_RP.m_pShaderResources->m_ResFlags & MTLFLAG_ADDITIVE)
|
|
{
|
|
mCurState |= GS_BLSRC_ONE | GS_BLDST_ONE;
|
|
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
|
|
}
|
|
else
|
|
{
|
|
mCurState |= GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA;
|
|
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
|
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
|
}
|
|
m_RP.m_FlagsPerFlush |= RBSI_ALPHABLEND;
|
|
|
|
if (mCurState & GS_DEPTHWRITE)
|
|
{
|
|
mCurState &= ~GS_DEPTHWRITE;
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
|
}
|
|
m_RP.m_FlagsPerFlush |= RBSI_DEPTHWRITE;
|
|
|
|
m_RP.m_fCurOpacity = m_RP.m_pShaderResources->m_Opacity;
|
|
SetMaterialColor(1, 1, 1, m_RP.m_fCurOpacity);
|
|
|
|
m_RP.m_FlagsPerFlush |= RBSI_ALPHAGEN;
|
|
m_RP.m_ObjFlags &= ~FOB_LIGHTPASS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_RP.m_pShaderResources->m_AlphaRef)
|
|
{
|
|
switch (mCurState & GS_ALPHATEST_MASK)
|
|
{
|
|
case GS_ALPHATEST_GREATER0:
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHAREF, 0);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
|
|
break;
|
|
|
|
case GS_ALPHATEST_LESS128:
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHAREF, 0x80);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESS);
|
|
break;
|
|
|
|
case GS_ALPHATEST_GEQUAL128:
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHAREF, 0x80);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
|
break;
|
|
|
|
default:
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CD3D8Renderer::EF_SetStateShaderState()
|
|
{
|
|
SShader *ef = m_RP.m_pStateShader;
|
|
SEfState *st = ef->m_State;
|
|
|
|
if (st->m_bClearStencil)
|
|
m_pd3dDevice->Clear(0, NULL, D3DCLEAR_STENCIL, 0, 1.0f, 0);
|
|
|
|
if (st->m_Stencil)
|
|
st->m_Stencil->mfSet();
|
|
if (st->m_Flags & ESF_STATE)
|
|
{
|
|
SetState(st->m_State);
|
|
}
|
|
bool bSetCol = false;
|
|
UCol Col;
|
|
Col.dcolor = 0;
|
|
if (st->m_Flags & ESF_RGBGEN)
|
|
{
|
|
m_RP.m_FlagsPerFlush |= RBSI_RGBGEN;
|
|
switch (st->m_eEvalRGB)
|
|
{
|
|
case eERGB_Fixed:
|
|
Col.bcolor[0] = st->m_FixedColor[0];
|
|
Col.bcolor[1] = st->m_FixedColor[1];
|
|
Col.bcolor[2] = st->m_FixedColor[2];
|
|
Col.bcolor[3] = st->m_FixedColor[3];
|
|
break;
|
|
}
|
|
bSetCol = true;
|
|
}
|
|
if (st->m_Flags & ESF_ALPHAGEN)
|
|
{
|
|
m_RP.m_FlagsPerFlush |= RBSI_ALPHAGEN;
|
|
switch (st->m_eEvalAlpha)
|
|
{
|
|
case eEALPHA_Fixed:
|
|
Col.bcolor[3] = st->m_FixedColor[3];
|
|
break;
|
|
}
|
|
bSetCol = true;
|
|
}
|
|
if (bSetCol)
|
|
EF_SetGlobalColor(Col);
|
|
if (st->m_Flags & ESF_COLORMASK)
|
|
{
|
|
m_RP.m_FlagsPerFlush |= RBSI_COLORMASK;
|
|
int mask = 0;
|
|
for (int i=0; i<4; i++)
|
|
{
|
|
if (st->m_ColorMask[i])
|
|
mask |= 1<<i;
|
|
}
|
|
m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, mask);
|
|
}
|
|
}
|
|
|
|
void CD3D8Renderer::EF_ResetStateShaderState()
|
|
{
|
|
SShader *ef = m_RP.m_pStateShader;
|
|
SEfState *st = ef->m_State;
|
|
|
|
if (st->m_Stencil)
|
|
st->m_Stencil->mfReset();
|
|
|
|
if (st->m_Flags & ESF_COLORMASK)
|
|
m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0xf);
|
|
}
|
|
|
|
void CD3D8Renderer::EF_FlushShader()
|
|
{
|
|
SShader *ef = m_RP.m_pShader;
|
|
int i;
|
|
SShaderPass *sfm;
|
|
|
|
guard(CD3D8Renderer::EF_FlushShader);
|
|
|
|
EF_SetVertColor();
|
|
|
|
if (m_RP.m_pRE) // Without buffer fill
|
|
EF_InitEvalFuncs(1); // VP
|
|
else
|
|
{ // Buffer filling
|
|
EF_InitEvalFuncs(0);
|
|
if (!m_RP.m_RendNumIndices)
|
|
return;
|
|
|
|
if ((ef->m_Flags & EF_FOGSHADER) && !m_RP.m_pFogVolume)
|
|
return;
|
|
|
|
if (m_RP.m_RendNumIndices > m_RP.m_MaxTris*3)
|
|
{
|
|
iLog->Log("CD3D8Renderer::EF_FlushShader: Shader MAX_RENDTRIS hit\n");
|
|
m_RP.m_RendNumIndices = m_RP.m_MaxTris*3;
|
|
}
|
|
if (m_RP.m_RendNumVerts > m_RP.m_MaxVerts)
|
|
{
|
|
iLog->Log("CD3D8Renderer::EF_FlushShader: Shader MAX_RENDVERTS hit\n");
|
|
m_RP.m_RendNumVerts = m_RP.m_MaxVerts;
|
|
}
|
|
}
|
|
|
|
if (m_RP.m_pShaderResources)
|
|
{
|
|
if (!EF_SetResourcesState(true))
|
|
return;
|
|
}
|
|
|
|
bool bLM = false;
|
|
if (m_RP.m_pShaderResources && m_RP.m_pShaderResources->m_LMaterial)
|
|
{
|
|
m_RP.m_pShaderResources->m_LMaterial->mfApply(ef->m_LMFlags);
|
|
bLM = true;
|
|
}
|
|
else
|
|
if (ef->m_LightMaterial)
|
|
{
|
|
ef->m_LightMaterial->mfApply(ef->m_LMFlags);
|
|
bLM = true;
|
|
}
|
|
|
|
if (m_RP.m_pStateShader && m_RP.m_pStateShader->m_State)
|
|
EF_SetStateShaderState();
|
|
|
|
bool bDraw2D = false;
|
|
if (!(m_RP.m_Flags & RBF_2D) && (m_RP.m_FlagsPerFlush & RBSI_DRAWAS2D))
|
|
{
|
|
bDraw2D = true;
|
|
Set2DMode(true,800,600);
|
|
}
|
|
|
|
// Draw using HW shader
|
|
if (ef->m_HWTechniques.Num())
|
|
{
|
|
EF_FlushHW();
|
|
if (m_RP.m_pStateShader && m_RP.m_pStateShader->m_State)
|
|
EF_ResetStateShaderState();
|
|
if (m_RP.m_pShaderResources)
|
|
EF_SetResourcesState(false);
|
|
if (bLM)
|
|
SLightMaterial::mfDisable();
|
|
if (bDraw2D)
|
|
Set2DMode(false,800,600);
|
|
return;
|
|
}
|
|
|
|
if ((ef->m_Flags & EF_FOGSHADER) && !m_RP.m_pFogVolume)
|
|
{
|
|
if (m_RP.m_pStateShader && m_RP.m_pStateShader->m_State)
|
|
EF_ResetStateShaderState();
|
|
if (m_RP.m_pShaderResources)
|
|
EF_SetResourcesState(false);
|
|
if (bLM)
|
|
SLightMaterial::mfDisable();
|
|
if (bDraw2D)
|
|
Set2DMode(false,800,600);
|
|
return;
|
|
}
|
|
|
|
CD3D8TexMan::BindNULL(1);
|
|
EF_SelectTMU(0);
|
|
|
|
if (m_RP.m_pRE)
|
|
m_RP.m_pRE->mfCheckUpdate(0);
|
|
|
|
if (ef->m_Flags & EF_NEEDNORMALS)
|
|
EF_EvalNormalsRB(ef);
|
|
EF_Eval_DeformVerts(ef->m_Deforms);
|
|
|
|
if (ef->m_Flags & EF_POLYGONOFFSET)
|
|
m_pd3dDevice->SetRenderState( D3DRS_ZBIAS, CV_d3d8_decaloffset );
|
|
|
|
if (!(m_RP.m_FlagsPerFlush & RBSI_NOCULL))
|
|
D3DSetCull(ef->m_eCull);
|
|
|
|
int nPolys = m_nPolygons;
|
|
|
|
sfm = &ef->m_Passes[0];
|
|
for (i=0; i<ef->m_Passes.Num(); i++, sfm++)
|
|
{
|
|
if (sfm->m_Stencil)
|
|
sfm->m_Stencil->mfSet();
|
|
EF_Eval_TexGen(sfm);
|
|
EF_Eval_RGBAGen(sfm);
|
|
|
|
HRESULT hr = m_pd3dDevice->SetVertexShader(m_RP.m_D3DFixedPipeline[m_RP.m_FlagsModificators&7][m_RP.m_CurD3DVFormat].m_Handle);
|
|
if (FAILED(hr))
|
|
continue;
|
|
|
|
// Unlock all VB (if needed) and set current stream
|
|
EF_PreDraw();
|
|
|
|
// Set all textures and HW TexGen modes for the current pass (ShadeLayer)
|
|
if (sfm->mfSetTextures(true))
|
|
{
|
|
// Set Render states for the current pass
|
|
SetState(m_RP.m_RendPass ? sfm->m_SecondRenderState : sfm->m_RenderState);
|
|
|
|
EF_Draw(ef, sfm);
|
|
|
|
m_RP.m_RendPass++;
|
|
}
|
|
if (sfm->m_Stencil)
|
|
sfm->m_Stencil->mfReset();
|
|
}
|
|
|
|
if (ef->m_Flags & EF_POLYGONOFFSET)
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZBIAS, 0);
|
|
|
|
if (bLM)
|
|
SLightMaterial::mfDisable();
|
|
|
|
if (m_RP.m_pStateShader && m_RP.m_pStateShader->m_State)
|
|
EF_ResetStateShaderState();
|
|
if (m_RP.m_pShaderResources)
|
|
EF_SetResourcesState(false);
|
|
|
|
if (bDraw2D)
|
|
Set2DMode(false,800,600);
|
|
|
|
unguardf(("(Shader: '%s')",ef->m_Name));
|
|
}
|
|
|
|
void CD3D8Renderer::EF_Flush()
|
|
{
|
|
CD3D8Renderer *rd = gcpRendD3D;
|
|
SShader *ef = rd->m_RP.m_pShader;
|
|
if (rd->m_RP.m_ExcludeShader)
|
|
{
|
|
if (!strcmp(rd->m_RP.m_ExcludeShader, ef->m_Name.c_str()))
|
|
return;
|
|
if(rd->m_RP.m_ExcludeShader[0] == '#')
|
|
if (strstr(ef->m_Name.c_str(), rd->m_RP.m_ExcludeShader))
|
|
return;
|
|
}
|
|
if (rd->m_RP.m_ShowOnlyShader)
|
|
{
|
|
if (strcmp(rd->m_RP.m_ShowOnlyShader, ef->m_Name.c_str()))
|
|
return;
|
|
}
|
|
if (ef->m_Flags2 & EF2_PREPR_PORTAL)
|
|
{
|
|
if (CV_r_portals && (rd->m_RP.m_PersFlags & (RBPF_DRAWPORTAL | RBPF_DRAWMIRROR)))
|
|
return;
|
|
}
|
|
|
|
if (rd->m_LogFile && CV_r_log == 3)
|
|
rd->Logv(SRendItem::m_RecurseLevel, ".. Start Flush: '%s' ..\n", ef->m_Name.c_str());
|
|
|
|
rd->m_RP.m_StatNumLightPasses = 0;
|
|
rd->m_RP.m_StatNumLights = 0;
|
|
rd->m_RP.m_StatNumPasses = 0;
|
|
rd->m_RP.m_StatLightMask = 0;
|
|
|
|
rd->m_RP.m_PS.m_NumRendShaders++;
|
|
|
|
CCObject *obj = rd->m_RP.m_pCurObject;
|
|
rd->m_RP.m_ObjFlags = obj->m_ObjFlags;
|
|
if ((rd->m_RP.m_ObjFlags & FOB_ZPASS) || !CV_r_hwlights)
|
|
rd->m_RP.m_DynLMask = 0;
|
|
else
|
|
rd->m_RP.m_DynLMask |= obj->m_DynLMMask;
|
|
|
|
if (CV_r_showlight->GetString()[0] != '0')
|
|
{
|
|
for (int i=0; i<rd->m_RP.m_DLights.Num(); i++)
|
|
{
|
|
CDLight *dl = rd->m_RP.m_DLights[i];
|
|
if (!dl)
|
|
continue;
|
|
char *str = CV_r_showlight->GetString();
|
|
if (strcmp(str, "0") != 0)
|
|
{
|
|
if (!dl->m_Name || !strstr(dl->m_Name, str))
|
|
rd->m_RP.m_DynLMask &= ~(1<<i);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((ef->m_Flags3 & EF3_CLIPPLANE) && !(rd->m_RP.m_PersFlags & RBPF_SETCLIPPLANE) && !rd->m_RP.m_ClipPlaneEnabled)
|
|
{
|
|
switch (ef->m_Flags3 & EF3_CLIPPLANE)
|
|
{
|
|
case EF3_CLIPPLANE_WATER_FRONT:
|
|
case EF3_CLIPPLANE_WATER_BACK:
|
|
{
|
|
SPlane Pl;
|
|
Pl.m_Normal = Vec3d (0, 0, 1);
|
|
Pl.m_Dist = iSystem->GetI3DEngine()->GetWaterLevel();
|
|
if (ef->m_Flags3 & EF3_CLIPPLANE_WATER_BACK)
|
|
{
|
|
Pl.m_Normal = -Pl.m_Normal;
|
|
Pl.m_Dist = -Pl.m_Dist;
|
|
}
|
|
Pl.m_Dist = -Pl.m_Dist;
|
|
rd->EF_SetClipPlane(true, &Pl.m_Normal.x, false);
|
|
rd->m_RP.m_PersFlags |= RBPF_SETCLIPPLANE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if (!(ef->m_Flags3 & EF3_CLIPPLANE) && (rd->m_RP.m_PersFlags & RBPF_SETCLIPPLANE))
|
|
{
|
|
rd->EF_SetClipPlane(false, NULL, false);
|
|
rd->m_RP.m_PersFlags &= ~RBPF_SETCLIPPLANE;
|
|
}
|
|
|
|
bool bProfile;
|
|
double time0 = 0;
|
|
int nNumPolys = rd->m_nPolygons;
|
|
if (CRenderer::CV_r_profileshaders || CRenderer::CV_r_log>=2)
|
|
{
|
|
bProfile = true;
|
|
ticks(time0);
|
|
}
|
|
else
|
|
bProfile = false;
|
|
|
|
if (rd->m_LogFile && CV_r_log >= 3)
|
|
rd->Logv(SRendItem::m_RecurseLevel, "\n");
|
|
|
|
rd->EF_FlushShader();
|
|
|
|
nNumPolys = rd->m_nPolygons - nNumPolys;
|
|
|
|
if (bProfile)
|
|
{
|
|
unticks(time0);
|
|
time0 = time0*1000.0*rd->m_RP.m_SecondsPerCycle;
|
|
}
|
|
|
|
if (CRenderer::CV_r_profileshaders)
|
|
{
|
|
SProfInfo pi;
|
|
pi.Time = time0;
|
|
pi.NumPolys = nNumPolys;
|
|
pi.ef = ef;
|
|
rd->m_RP.m_Profile.AddElem(pi);
|
|
}
|
|
|
|
if (rd->m_RP.m_DynLMask)
|
|
rd->m_RP.m_PS.m_NumLitShaders++;
|
|
|
|
if (rd->m_LogFile)
|
|
{
|
|
if (CV_r_log == 4 && rd->m_RP.m_DynLMask)
|
|
{
|
|
for (int n=0; n<rd->m_RP.m_DLights.Num(); n++)
|
|
{
|
|
CDLight *dl = rd->m_RP.m_DLights[n];
|
|
if (rd->m_RP.m_DynLMask & (1<<n))
|
|
rd->Logv(SRendItem::m_RecurseLevel, " Light %d (\"%s\")\n", n, dl->m_Name ? dl->m_Name : "<Unknown>");
|
|
}
|
|
}
|
|
|
|
char *str;
|
|
if (ef->m_HWTechniques.Num())
|
|
str = "FlushHW";
|
|
else
|
|
str = "Flush";
|
|
rd->Logv(SRendItem::m_RecurseLevel, "%s: '%s', (St: %s) Id:%d, Obj:%d(%s), Tech: %d, Cp: %d, Fog:%d, VF:%d, NL:%d, LPas:%d, Pas:%d (time: %f, %d polys)\n", str, ef->m_Name.c_str(), rd->m_RP.m_pStateShader ? rd->m_RP.m_pStateShader->m_Name.c_str() : "NULL", ef->m_Id, rd->m_RP.m_pCurObject->m_VisId, (rd->m_RP.m_pCurObject->m_ObjFlags & FOB_USEMATRIX) ? "Matr" : "NoMatr", rd->m_RP.m_CurTechnique, rd->m_RP.m_ClipPlaneEnabled, rd->m_RP.m_pFogVolume ? (rd->m_RP.m_pFogVolume-&rd->m_RP.m_FogVolumes[0]) : 0, rd->m_RP.m_pShader->m_VertexFormatId, rd->m_RP.m_StatNumLights, rd->m_RP.m_StatNumLightPasses, rd->m_RP.m_StatNumPasses, time0, nNumPolys);
|
|
if (rd->m_RP.m_FlagsPerFlush & RBSI_ALPHATEST)
|
|
rd->Logv(SRendItem::m_RecurseLevel, " %.3f, %.3f, %.3f (0x%x), LM: %d, (AT)\n", rd->m_RP.m_pCurObject->m_Matrix(3,0), rd->m_RP.m_pCurObject->m_Matrix(3,1), rd->m_RP.m_pCurObject->m_Matrix(3,2), rd->m_RP.m_pCurObject->m_ObjFlags, rd->m_RP.m_DynLMask);
|
|
else
|
|
if (rd->m_RP.m_FlagsPerFlush & RBSI_ALPHABLEND)
|
|
rd->Logv(SRendItem::m_RecurseLevel, " %.3f, %.3f, %.3f (0x%x) (AB), LM: %d (Dist: %.3f)\n", rd->m_RP.m_pCurObject->m_Matrix(3,0), rd->m_RP.m_pCurObject->m_Matrix(3,1), rd->m_RP.m_pCurObject->m_Matrix(3,2), rd->m_RP.m_pCurObject->m_ObjFlags, rd->m_RP.m_DynLMask, rd->m_RP.m_pRE ? rd->m_RP.m_pRE->mfDistanceToCameraSquared(*gRenDev->m_RP.m_pCurObject) : 0);
|
|
else
|
|
rd->Logv(SRendItem::m_RecurseLevel, " %.3f, %.3f, %.3f (0x%x), LM: %d\n", rd->m_RP.m_pCurObject->m_Matrix(3,0), rd->m_RP.m_pCurObject->m_Matrix(3,1), rd->m_RP.m_pCurObject->m_Matrix(3,2), rd->m_RP.m_pCurObject->m_ObjFlags, rd->m_RP.m_DynLMask);
|
|
}
|
|
}
|
|
|
|
void CD3D8Renderer::EF_EndEf3D(bool bSort)
|
|
{
|
|
double time0 = 0;
|
|
ticks(time0);
|
|
|
|
if (CV_r_nodrawshaders == 1)
|
|
{
|
|
SetClearColor(Vec3d(0,0,0));
|
|
EF_ClearBuffer(false, NULL);
|
|
return;
|
|
}
|
|
|
|
m_RP.m_PersFlags &= ~(RBPF_DRAWNIGHTMAP | RBPF_DRAWHEATMAP);
|
|
|
|
// tiago: commented out this. This is done in 3dengine now
|
|
//if (CV_r_glare && SRendItem::m_RecurseLevel == 1)
|
|
// EF_AddEf(0, m_RP.m_pREGlare, gcEf.m_GlareShader, NULL, NULL, -1);
|
|
|
|
if (CV_r_fullbrightness)
|
|
{
|
|
EF_SetGlobalColor(1, 1, 1, 1);
|
|
m_RP.m_FlagsPerFlush |= RBSI_RGBGEN | RBSI_ALPHAGEN;
|
|
}
|
|
|
|
m_RP.m_RealTime = iTimer->GetCurrTime();
|
|
|
|
if (CV_r_excludeshader->GetString()[0] != '0')
|
|
m_RP.m_ExcludeShader = CV_r_excludeshader->GetString();
|
|
else
|
|
m_RP.m_ExcludeShader = NULL;
|
|
|
|
if (CV_r_showonlyshader->GetString()[0] != '0')
|
|
m_RP.m_ShowOnlyShader = CV_r_showonlyshader->GetString();
|
|
else
|
|
m_RP.m_ShowOnlyShader = NULL;
|
|
|
|
EF_UpdateSplashes(m_RP.m_RealTime);
|
|
EF_AddClientPolys3D();
|
|
EF_AddClientPolys2D();
|
|
|
|
EF_RenderPipeLine(EF_Flush);
|
|
|
|
EF_DrawDebugTools();
|
|
EF_RemovePolysFromScene();
|
|
|
|
SRendItem::m_RecurseLevel--;
|
|
|
|
unticks(time0);
|
|
m_RP.m_PS.m_fFlushTime += (float)(time0*1000.0*m_RP.m_SecondsPerCycle);
|
|
}
|
|
|
|
void CD3D8Renderer::EF_RenderPipeLine(void (*RenderFunc)())
|
|
{
|
|
int numepp = SRendItem::m_RendItems[EFSLIST_PREPROCESS_ID].Num();
|
|
int numeds = SRendItem::m_RendItems[EFSLIST_DISTSORT_ID].Num();
|
|
int numeus = SRendItem::m_RendItems[EFSLIST_UNSORTED_ID].Num();
|
|
int numegn = SRendItem::m_RendItems[EFSLIST_GENERAL_ID].Num();
|
|
int numels = SRendItem::m_RendItems[EFSLIST_LAST_ID].Num();
|
|
|
|
int numspp = SRendItem::m_StartRI[EFSLIST_PREPROCESS_ID];
|
|
int numsds = SRendItem::m_StartRI[EFSLIST_DISTSORT_ID];
|
|
int numsus = SRendItem::m_StartRI[EFSLIST_UNSORTED_ID];
|
|
int numsgn = SRendItem::m_StartRI[EFSLIST_GENERAL_ID];
|
|
int numsls = SRendItem::m_StartRI[EFSLIST_LAST_ID];
|
|
|
|
EF_PipeLine(numspp, numepp, EFSLIST_PREPROCESS_ID, 1, RenderFunc); // Preprocess and probably sky
|
|
EF_PipeLine(numsus, numeus, EFSLIST_UNSORTED_ID, 0, RenderFunc); // Unsorted list for indoor
|
|
EF_PipeLine(numsgn, numegn, EFSLIST_GENERAL_ID, 1, RenderFunc); // Sorted list without preprocess
|
|
EF_PipeLine(numsds, numeds, EFSLIST_DISTSORT_ID, 2, RenderFunc); // Sorted by distance elements
|
|
EF_PipeLine(numsls, numels, EFSLIST_LAST_ID, 1, RenderFunc); // Sorted list without preprocess of all fog passes and screen shaders
|
|
}
|
|
|
|
void CD3D8Renderer::EF_PipeLine(int nums, int nume, int nList, int nSortType, void (*RenderFunc)())
|
|
{
|
|
int i;
|
|
CCObject *savedObj;
|
|
SShader *Shader, *CurShader, *ShaderState, *CurShaderState;
|
|
SRenderShaderResources *Res, *CurRes;
|
|
int nObject, nCurObject;
|
|
int nFog, nCurFog;
|
|
|
|
if (nume > 16384)
|
|
{
|
|
nume = 16384;
|
|
iLog->Log("CD3D8Renderer::EF_PipeLine: too many items for %d list ( > 16384 )\n", nList);
|
|
}
|
|
|
|
if (nume-nums < 1)
|
|
return;
|
|
|
|
m_RP.m_Flags |= RBF_3D;
|
|
|
|
m_RP.m_pRenderFunc = RenderFunc;
|
|
|
|
m_RP.m_nCurLightParam = -1;
|
|
savedObj = m_RP.m_pCurObject;
|
|
m_RP.m_pCurObject = m_RP.m_VisObjects[0];
|
|
m_RP.m_pPrevObject = m_RP.m_pCurObject;
|
|
|
|
if (m_LogFile)
|
|
Logv(SRendItem::m_RecurseLevel, "*** Start frame for list %d ***\n", nList);
|
|
|
|
if (nSortType == 1)
|
|
{
|
|
SRendItem::mfSort(&SRendItem::m_RendItems[nList][nums], nume-nums);
|
|
|
|
// If sort number of the first shader is 1 (eS_Preprocess)
|
|
// run preprocess operations for the current frame
|
|
if ((SRendItem::m_RendItems[nList][nums].SortVal.i.High >> 26) == eS_PreProcess)
|
|
nums += EF_Preprocess(&SRendItem::m_RendItems[nList][0], nums, nume);
|
|
}
|
|
else
|
|
if (nSortType == 2)
|
|
{
|
|
SRendItem::mfSortByDist(&SRendItem::m_RendItems[nList][nums], nume-nums);
|
|
}
|
|
|
|
m_RP.m_Flags |= RBF_3D;
|
|
|
|
EF_PreRender();
|
|
EF_PushMatrix();
|
|
|
|
UnINT64 oldVal;
|
|
oldVal.SortVal = -1;
|
|
nCurObject = -2;
|
|
nCurFog = 0;
|
|
CurShader = NULL;
|
|
CurShaderState = NULL;
|
|
CurRes = NULL;
|
|
|
|
for (i=nums; i<nume; i++)
|
|
{
|
|
SRendItemPre *ri = &SRendItem::m_RendItems[nList][i];
|
|
CRendElement *re = ri->Item;
|
|
if (ri->SortVal.SortVal == oldVal.SortVal)
|
|
{
|
|
// Optimizations: not necessary to check of changing shaders and objects
|
|
// if sort value is the same (contains the same info about shaders, objects, fog volumes, ...)
|
|
re->mfPrepare();
|
|
continue;
|
|
}
|
|
oldVal.SortVal = ri->SortVal.SortVal;
|
|
|
|
SRendItem::mfGet(ri->SortVal, &nObject, &Shader, &ShaderState, &nFog, &Res);
|
|
|
|
if (nObject != nCurObject)
|
|
{
|
|
if (CurShader)
|
|
{
|
|
m_RP.m_pRenderFunc();
|
|
CurShader = NULL;
|
|
}
|
|
if (!EF_ObjectChange(Shader, nObject, re))
|
|
continue;
|
|
nCurObject = nObject;
|
|
}
|
|
|
|
if (Shader != CurShader || CurRes != Res || ShaderState != CurShaderState || nFog != nCurFog)
|
|
{
|
|
if (CurShader)
|
|
m_RP.m_pRenderFunc();
|
|
|
|
EF_Start(Shader, ShaderState, Res, nFog, re);
|
|
|
|
nCurFog = nFog;
|
|
CurShader = Shader;
|
|
CurShaderState = ShaderState;
|
|
CurRes = Res;
|
|
}
|
|
|
|
re->mfPrepare();
|
|
}
|
|
if (CurShader)
|
|
m_RP.m_pRenderFunc();
|
|
|
|
EF_PostRender();
|
|
|
|
EF_PopMatrix();
|
|
|
|
if (m_LogFile)
|
|
Logv(SRendItem::m_RecurseLevel, "*** End frame ***\n\n");
|
|
|
|
m_RP.m_pCurObject = savedObj;
|
|
}
|
|
|
|
void CD3D8Renderer::EF_DrawWire()
|
|
{
|
|
if (CV_r_showlines == 1)
|
|
gcpRendD3D->SetState(GS_POLYLINE | GS_NODEPTHTEST);
|
|
else
|
|
if (CV_r_showlines == 2)
|
|
gcpRendD3D->SetState(GS_POLYLINE);
|
|
gcpRendD3D->SetMaterialColor(1,1,1,1);
|
|
CTexMan::m_Text_White->Set();
|
|
gcpRendD3D->EF_SetColorOp(eCO_MODULATE);
|
|
if (gcpRendD3D->m_RP.m_pRE)
|
|
gcpRendD3D->m_RP.m_pRE->mfCheckUpdate(0);
|
|
int StrVrt;
|
|
void *verts = (void *)gcpRendD3D->EF_GetPointer(eSrcPointer_Vert, &StrVrt, GL_FLOAT, eSrcPointer_Vert, 0);
|
|
gcpRendD3D->EF_Draw(gcpRendD3D->m_RP.m_pShader, NULL);
|
|
}
|
|
|
|
void CD3D8Renderer::EF_DrawNormals()
|
|
{
|
|
float len = CRenderer::CV_r_normalslength;
|
|
if (gcpRendD3D->m_bEditor)
|
|
len *= 100.0f;
|
|
int StrVrt, StrNrm;
|
|
byte *verts = (byte *)gcpRendD3D->EF_GetPointer(eSrcPointer_Vert, &StrVrt, GL_FLOAT, eSrcPointer_Vert, FGP_SRC | FGP_REAL);
|
|
byte *norms = (byte *)gcpRendD3D->EF_GetPointer(eSrcPointer_TNormal, &StrNrm, GL_FLOAT, eSrcPointer_TNormal, FGP_SRC | FGP_REAL);
|
|
if ((int)norms > 256)
|
|
{
|
|
int numVerts = gcpRendD3D->m_RP.m_RendNumVerts;
|
|
|
|
CTexMan::m_Text_White->Set();
|
|
gcpRendD3D->EF_SetColorOp(eCO_MODULATE);
|
|
gcpRendD3D->SetState(GS_POLYLINE);
|
|
SPipeVertex_D_1T *Verts = new SPipeVertex_D_1T[numVerts*2];
|
|
|
|
uint col0 = 0x000000ff;
|
|
uint col1 = 0x00ffffff;
|
|
|
|
for (int v=0; v<numVerts*2; v+=2,verts+=StrVrt,norms+=StrNrm)
|
|
{
|
|
float *fverts = (float *)verts;
|
|
float *fnorms = (float *)norms;
|
|
Verts[v].xyz[0] = fverts[0];
|
|
Verts[v].xyz[1] = fverts[1];
|
|
Verts[v].xyz[2] = fverts[2];
|
|
Verts[v].color.dcolor = col0;
|
|
|
|
Verts[v+1].xyz[0] = fverts[0] + fnorms[0]*len;
|
|
Verts[v+1].xyz[1] = fverts[1] + fnorms[1]*len;
|
|
Verts[v+1].xyz[2] = fverts[2] + fnorms[2]*len;
|
|
Verts[v+1].color.dcolor = col1;
|
|
}
|
|
gcpRendD3D->m_pd3dDevice->SetVertexShader( D3DFVF_VERTEX_D_1T );
|
|
h = gcpRendD3D->m_pd3dDevice->DrawPrimitiveUP(D3DPT_LINELIST, numVerts, Verts, STRIDE_D_1T);
|
|
delete [] Verts;
|
|
}
|
|
}
|
|
|
|
void CD3D8Renderer::EF_DrawTangents()
|
|
{
|
|
float len = CRenderer::CV_r_normalslength;
|
|
if (gcpRendD3D->m_bEditor)
|
|
len *= 100.0f;
|
|
if (gcpRendD3D->m_RP.m_pRE)
|
|
gcpRendD3D->m_RP.m_pRE->mfCheckUpdate(FHF_TANGENTSUSED);
|
|
int StrVrt, StrTang, StrBinorm, StrTNorm;
|
|
byte *verts = NULL;
|
|
byte *tangs = NULL;
|
|
byte *binorm = NULL;
|
|
byte *tnorm = NULL;
|
|
int flags = 0;
|
|
if (CRenderer::CV_r_showtangents == 1)
|
|
flags = FGP_SRC | FGP_REAL;
|
|
else
|
|
flags = FGP_REAL;
|
|
verts = (byte *)gcpRendD3D->EF_GetPointer(eSrcPointer_Vert, &StrVrt, GL_FLOAT, eSrcPointer_Vert, flags);
|
|
tangs = (byte *)gcpRendD3D->EF_GetPointer(eSrcPointer_Tangent, &StrTang, GL_FLOAT, eSrcPointer_Tangent, flags);
|
|
binorm = (byte *)gcpRendD3D->EF_GetPointer(eSrcPointer_Binormal, &StrBinorm, GL_FLOAT, eSrcPointer_Binormal, flags);
|
|
tnorm = (byte *)gcpRendD3D->EF_GetPointer(eSrcPointer_TNormal, &StrTNorm, GL_FLOAT, eSrcPointer_TNormal, flags);
|
|
if ((int)tangs>256 && (int)binorm>256 && (int)tnorm>256)
|
|
{
|
|
int numVerts = gcpRendD3D->m_RP.m_RendNumVerts;
|
|
|
|
CTexMan::m_Text_White->Set();
|
|
gcpRendD3D->EF_SetColorOp(eCO_MODULATE);
|
|
if (gcpRendD3D->m_polygon_mode == R_SOLID_MODE)
|
|
gcpRendD3D->SetState(GS_POLYLINE);
|
|
else
|
|
gcpRendD3D->SetState(0);
|
|
SPipeVertex_D_1T *Verts = new SPipeVertex_D_1T[numVerts*6];
|
|
|
|
for (int v=0; v<numVerts*6; v+=6,verts+=StrVrt,tangs+=StrTang, binorm+=StrBinorm, tnorm+=StrTNorm)
|
|
{
|
|
uint col0 = 0x00ff0000;
|
|
uint col1 = 0x00ffffff;
|
|
float *fverts = (float *)verts;
|
|
float *fv = (float *)tangs;
|
|
Verts[v].xyz[0] = fverts[0];
|
|
Verts[v].xyz[1] = fverts[1];
|
|
Verts[v].xyz[2] = fverts[2];
|
|
Verts[v].color.dcolor = col0;
|
|
|
|
Verts[v+1].xyz[0] = fverts[0] + fv[0]*len;
|
|
Verts[v+1].xyz[1] = fverts[1] + fv[1]*len;
|
|
Verts[v+1].xyz[2] = fverts[2] + fv[2]*len;
|
|
Verts[v+1].color.dcolor = col1;
|
|
|
|
col0 = 0x0000ff00;
|
|
col1 = 0x00ffffff;
|
|
fverts = (float *)verts;
|
|
fv = (float *)binorm;
|
|
Verts[v+2].xyz[0] = fverts[0];
|
|
Verts[v+2].xyz[1] = fverts[1];
|
|
Verts[v+2].xyz[2] = fverts[2];
|
|
Verts[v+2].color.dcolor = col0;
|
|
|
|
Verts[v+3].xyz[0] = fverts[0] + fv[0]*len;
|
|
Verts[v+3].xyz[1] = fverts[1] + fv[1]*len;
|
|
Verts[v+3].xyz[2] = fverts[2] + fv[2]*len;
|
|
Verts[v+3].color.dcolor = col1;
|
|
|
|
col0 = 0x000000ff;
|
|
col1 = 0x00ffffff;
|
|
fverts = (float *)verts;
|
|
fv = (float *)tnorm;
|
|
Verts[v+4].xyz[0] = fverts[0];
|
|
Verts[v+4].xyz[1] = fverts[1];
|
|
Verts[v+4].xyz[2] = fverts[2];
|
|
Verts[v+4].color.dcolor = col0;
|
|
|
|
Verts[v+5].xyz[0] = fverts[0] + fv[0]*len;
|
|
Verts[v+5].xyz[1] = fverts[1] + fv[1]*len;
|
|
Verts[v+5].xyz[2] = fverts[2] + fv[2]*len;
|
|
Verts[v+5].color.dcolor = col1;
|
|
}
|
|
gcpRendD3D->m_pd3dDevice->SetVertexShader( D3DFVF_VERTEX_D_1T );
|
|
h = gcpRendD3D->m_pd3dDevice->DrawPrimitiveUP(D3DPT_LINELIST, numVerts*3, Verts, STRIDE_D_1T);
|
|
delete [] Verts;
|
|
}
|
|
}
|
|
|
|
void CD3D8Renderer::EF_DrawDebugLights()
|
|
{
|
|
static int sFrame = 0;
|
|
if (m_nFrameID != sFrame)
|
|
{
|
|
int i;
|
|
sFrame = m_nFrameID;
|
|
|
|
HRESULT hr = m_pd3dDevice->SetVertexShader( D3DFVF_VERTEX_D );
|
|
|
|
for (i=0; i<m_RP.m_DLights.Num(); i++)
|
|
{
|
|
CDLight *dl = m_RP.m_DLights[i];
|
|
if (!dl)
|
|
continue;
|
|
char *str = CV_r_showlight->GetString();
|
|
if (strcmp(str, "0") != 0)
|
|
{
|
|
if (!dl->m_Name || strcmp(str, dl->m_Name))
|
|
continue;
|
|
}
|
|
SetMaterialColor(dl->m_Color[0], dl->m_Color[1], dl->m_Color[2], dl->m_Color[3]);
|
|
if (dl->m_Flags & DLF_DIRECTIONAL)
|
|
DrawPoint(dl->m_Origin[0], dl->m_Origin[1], dl->m_Origin[2], 10);
|
|
else
|
|
if (dl->m_Flags & DLF_POINT)
|
|
DrawBall(dl->m_Origin[0], dl->m_Origin[1], dl->m_Origin[2], 0.05f);
|
|
if (dl->m_Flags & DLF_PROJECT)
|
|
{
|
|
Vec3d dir, rgt, org;
|
|
|
|
dir = dl->m_Orientation.m_vForward;
|
|
rgt = dl->m_Orientation.m_vRight;
|
|
float ang = dl->m_fLightFrustumAngle;
|
|
if (ang == 0)
|
|
ang = 45.0f;
|
|
org = dl->m_Origin;
|
|
|
|
dir *= 0.3f;
|
|
|
|
CFColor Col = dl->m_Color;
|
|
|
|
Matrix m;
|
|
Vec3d vertex = dir;
|
|
|
|
// vertex = m.GetRotation(rgt, ang)*vertex;
|
|
vertex = Matrix33::GetRotationAA33(ang*gf_DEGTORAD,GetNormalized(rgt)) * vertex; //NOTE: angle need to be in radians
|
|
// Matrix mat = m.GetRotation(dir, 60);
|
|
Matrix mat = Matrix33::GetRotationAA33(60*gf_DEGTORAD,GetNormalized(dir)); //NOTE: angle need to be in radians
|
|
Vec3d tmpvertex;
|
|
int ctr;
|
|
|
|
//fill the inside of the light
|
|
EnableTMU(false);
|
|
SPipeVertex_D Verts[32];
|
|
memset(Verts, 0, sizeof(Verts));
|
|
CFColor cl = Col*0.3f;
|
|
int n = 0;
|
|
Verts[n].xyz = org;
|
|
Verts[n].color.dcolor = D3DRGBA(cl[0], cl[1], cl[2], 1.0f);
|
|
n++;
|
|
tmpvertex = org + vertex;
|
|
Verts[n].xyz = tmpvertex;
|
|
Verts[n].color.dcolor = D3DRGBA(Col[0], Col[1], Col[2], 1.0f);
|
|
n++;
|
|
for (ctr=0; ctr<6; ctr++)
|
|
{
|
|
vertex = mat * vertex;
|
|
Vec3d tmpvertex = org + vertex;
|
|
Verts[n].xyz = tmpvertex;
|
|
Verts[n].color.dcolor = D3DRGBA(Col[0], Col[1], Col[2], 1.0f);
|
|
n++;
|
|
}
|
|
m_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, n-2, Verts, STRIDE_D);
|
|
|
|
//draw the inside of the light with lines and the outside filled
|
|
m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
|
|
SetCullMode(R_CULL_NONE);
|
|
n = 0;
|
|
Verts[n].xyz = org;
|
|
Verts[n].color.dcolor = D3DRGBA(0.3f, 0.3f, 0.3f, 1.0f);
|
|
n++;
|
|
tmpvertex = org + vertex;
|
|
Verts[n].xyz = tmpvertex;
|
|
Verts[n].color.dcolor = D3DRGBA(1.0f, 1.0f, 1.0f, 1.0f);
|
|
n++;
|
|
for (ctr=0; ctr<6; ctr++)
|
|
{
|
|
vertex = mat * vertex;
|
|
Vec3d tmpvertex = org + vertex;
|
|
Verts[n].xyz = tmpvertex;
|
|
Verts[n].color.dcolor = D3DRGBA(1.0f, 1.0f, 1.0f, 1.0f);
|
|
n++;
|
|
}
|
|
m_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, n-2, Verts, STRIDE_D);
|
|
SetCullMode(R_CULL_BACK);
|
|
m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
|
|
|
|
//set the color to the color of the light
|
|
Verts[0].xyz = org;
|
|
Verts[0].color.dcolor = D3DRGBA(Col[0], Col[1], Col[2], 1.0f);
|
|
|
|
//draw a point at the origin of the light
|
|
m_pd3dDevice->DrawPrimitiveUP(D3DPT_POINTLIST, 1, Verts, STRIDE_D);
|
|
|
|
//draw a line in the center of the light
|
|
Verts[0].xyz = org;
|
|
Verts[0].color.dcolor = D3DRGBA(Col[0], Col[1], Col[2], 1.0f);
|
|
Verts[1].xyz = org + dir;
|
|
Verts[1].color.dcolor = D3DRGBA(Col[0], Col[1], Col[2], 1.0f);
|
|
m_pd3dDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1, Verts, STRIDE_D);
|
|
|
|
EnableTMU(true);
|
|
}
|
|
if (CV_r_debuglights == 2 && !(dl->m_Flags & DLF_DIRECTIONAL))
|
|
{
|
|
SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA);
|
|
SetCullMode(R_CULL_NONE);
|
|
SetMaterialColor(dl->m_Color[0], dl->m_Color[1], dl->m_Color[2], 0.25f);
|
|
EF_SetColorOp(eCO_MODULATE);
|
|
DrawBall(dl->m_Origin[0], dl->m_Origin[1], dl->m_Origin[2], dl->m_fRadius);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CD3D8Renderer::EF_DrawDebugTools()
|
|
{
|
|
if (CV_r_showlines)
|
|
EF_RenderPipeLine(EF_DrawWire);
|
|
|
|
if (CV_r_shownormals)
|
|
EF_RenderPipeLine(EF_DrawNormals);
|
|
|
|
if (CV_r_showtangents)
|
|
EF_RenderPipeLine(EF_DrawTangents);
|
|
|
|
if (SRendItem::m_RecurseLevel==1 && CV_r_debuglights)
|
|
EF_DrawDebugLights();
|
|
}
|
|
|
|
|
|
int TimeProfCallback( const VOID* arg1, const VOID* arg2 )
|
|
{
|
|
SProfInfo *pi1 = (SProfInfo *)arg1;
|
|
SProfInfo *pi2 = (SProfInfo *)arg2;
|
|
if (pi1->ef->m_fProfileTime > pi2->ef->m_fProfileTime)
|
|
return -1;
|
|
if (pi1->ef->m_fProfileTime < pi2->ef->m_fProfileTime)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int NameCallback( const VOID* arg1, const VOID* arg2 )
|
|
{
|
|
SProfInfo *pi1 = (SProfInfo *)arg1;
|
|
SProfInfo *pi2 = (SProfInfo *)arg2;
|
|
if (pi1->ef > pi2->ef)
|
|
return -1;
|
|
if (pi1->ef < pi2->ef)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
void CD3D8Renderer::EF_PrintProfileInfo()
|
|
{
|
|
double fTime = 0;
|
|
{ // group by name
|
|
qsort(&m_RP.m_Profile[0], m_RP.m_Profile.Num(), sizeof(SProfInfo), NameCallback );
|
|
|
|
for(int i=0; i<m_RP.m_Profile.Num(); i++)
|
|
{
|
|
// if next is the same
|
|
if( i<(m_RP.m_Profile.Num()-1) && m_RP.m_Profile[i].ef == m_RP.m_Profile[i+1].ef )
|
|
{
|
|
m_RP.m_Profile[i].Time += m_RP.m_Profile[i+1].Time;
|
|
m_RP.m_Profile[i].NumPolys += m_RP.m_Profile[i+1].NumPolys;
|
|
m_RP.m_Profile.DelElem(i+1);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
|
|
TextToScreenColor(8,14, 0,2,0,1, "Shad.: %d, VShad: %d, PShad: %d, RComb: %d, Text: %d, Lit Shaders: %d", m_RP.m_PS.m_NumRendShaders, m_RP.m_PS.m_NumVShaders, m_RP.m_PS.m_NumPShaders, m_RP.m_PS.m_NumRCombiners, m_RP.m_PS.m_NumTextures, m_RP.m_PS.m_NumLitShaders);
|
|
TextToScreenColor(8,17, 0,2,0,1, "Preprocess: %8.02f ms", m_RP.m_PS.m_fPreprocessTime);
|
|
TextToScreenColor(8,20, 0,2,0,1, "Skinning: %8.02f ms", m_RP.m_PS.m_fSkinningTime);
|
|
|
|
int nLine;
|
|
|
|
|
|
{ // sort by interpolated time and print
|
|
qsort(&m_RP.m_Profile[0], m_RP.m_Profile.Num(), sizeof(SProfInfo), TimeProfCallback );
|
|
|
|
for(nLine=0; nLine<m_RP.m_Profile.Num(); nLine++)
|
|
{
|
|
fTime += m_RP.m_Profile[nLine].Time;
|
|
if (nLine >= 18)
|
|
continue;
|
|
m_RP.m_Profile[nLine].ef->m_fProfileTime = (m_RP.m_Profile[nLine].ef->m_fProfileTime + (float)m_RP.m_Profile[nLine].Time);
|
|
TextToScreenColor(4,(24+(nLine*3)), 1,0,0,1, "%8.02f ms, %5d polys, '%s'", m_RP.m_Profile[nLine].Time, m_RP.m_Profile[nLine].NumPolys, m_RP.m_Profile[nLine].ef->m_Name.c_str());
|
|
}
|
|
}
|
|
if (nLine > 18)
|
|
nLine = 18;
|
|
TextToScreenColor(8,(26+(nLine*3)), 0,2,0,1, "Total draw time: %8.02f ms", fTime);
|
|
TextToScreenColor(8,(29+(nLine*3)), 0,2,0,1, "Total shaders processing time (flush): %8.02f ms", m_RP.m_PS.m_fFlushTime);
|
|
}
|
|
|
|
void CD3D8Renderer::EF_DrawREPreprocess(SRendItemPreprocess *ris, int Nums)
|
|
{
|
|
int i;
|
|
CCObject *savedObj;
|
|
SShader *Shader, *CurShader, *ShaderState, *CurShaderState;
|
|
SRenderShaderResources *Res, *CurRes;
|
|
int nObject, nCurObject;
|
|
int nFog, nCurFog;
|
|
|
|
if (Nums < 1)
|
|
return;
|
|
|
|
savedObj = m_RP.m_pCurObject;
|
|
m_RP.m_pCurObject = m_RP.m_VisObjects[0];
|
|
m_RP.m_pPrevObject = m_RP.m_pCurObject;
|
|
|
|
EF_PreRender();
|
|
|
|
EF_PushMatrix();
|
|
|
|
UnINT64 oldVal;
|
|
oldVal.SortVal = -1;
|
|
nCurObject = -2;
|
|
nCurFog = 0;
|
|
CurShader = NULL;
|
|
CurShaderState = NULL;
|
|
CurRes = NULL;
|
|
|
|
for (i=0; i<Nums; i++)
|
|
{
|
|
SRendItemPreprocess *ri = &ris[i];
|
|
CRendElement *re = ri->Item;
|
|
if (ri->SortVal.SortVal == oldVal.SortVal)
|
|
{
|
|
// Optimizations: not necessary to check of changing shaders and objects
|
|
// if sort value is the same (consist the same info about shaders, objects, fog volumes, ...)
|
|
re->mfPrepare();
|
|
continue;
|
|
}
|
|
oldVal.SortVal = ri->SortVal.SortVal;
|
|
|
|
SRendItem::mfGet(ri->SortVal, &nObject, &Shader, &ShaderState, &nFog, &Res);
|
|
|
|
if (nObject != nCurObject)
|
|
{
|
|
if (CurShader)
|
|
EF_Flush();
|
|
if (!EF_ObjectChange(Shader, nObject, re))
|
|
continue;
|
|
nCurObject = nObject;
|
|
}
|
|
|
|
if (Shader != CurShader || Res != CurRes || ShaderState != CurShaderState || nFog != nCurFog)
|
|
{
|
|
if (CurShader)
|
|
m_RP.m_pRenderFunc();
|
|
|
|
EF_Start(Shader, ShaderState, Res, nFog, re);
|
|
|
|
nCurFog = nFog;
|
|
CurShader = Shader;
|
|
CurShaderState = ShaderState;
|
|
CurRes = Res;
|
|
}
|
|
|
|
re->mfPrepare();
|
|
}
|
|
if (CurShader)
|
|
m_RP.m_pRenderFunc();
|
|
|
|
EF_PostRender();
|
|
|
|
EF_PopMatrix();
|
|
|
|
m_RP.m_pCurObject = savedObj;
|
|
}
|
|
|
|
struct SPreprocess
|
|
{
|
|
int m_Num;
|
|
int m_nObject;
|
|
SShader *m_Shader;
|
|
SRenderShaderResources *m_pRes;
|
|
CRendElement *m_RE;
|
|
};
|
|
|
|
STWarpZone *CD3D8Renderer::EF_SetWarpZone(SWarpSurf *sf, int *NumWarps, STWarpZone Warps[])
|
|
{
|
|
int i;
|
|
STWarpZone *wp;
|
|
Plane p, pl;
|
|
|
|
sf->srf->mfGetPlane(pl);
|
|
if (sf->nobj > 0)
|
|
{
|
|
p = pl;
|
|
CCObject *obj = m_RP.m_VisObjects[sf->nobj];
|
|
obj->CalcMatrix();
|
|
pl = TransformPlane(obj->m_Matrix, p);
|
|
}
|
|
for (i=0; i<NumWarps[0]; i++)
|
|
{
|
|
// if (pl.d == Warps[i].plane.d && pl.n == Warps[i].plane.n)
|
|
if (pl.d == Warps[i].plane.d && IsEquivalent(pl.n,Warps[i].plane.n))
|
|
break;
|
|
}
|
|
if (i == NumWarps[0])
|
|
{
|
|
NumWarps[0]++;
|
|
wp = &Warps[i];
|
|
wp->numSrf = 0;
|
|
wp->plane.d = pl.d;
|
|
wp->plane.n = pl.n;
|
|
}
|
|
EF_UpdateWarpZone(&Warps[i], sf);
|
|
|
|
return &Warps[i];
|
|
}
|
|
|
|
void CD3D8Renderer::EF_UpdateWarpZone(STWarpZone *wp, SWarpSurf *srf)
|
|
{
|
|
if (wp->numSrf == MAX_WARPSURFS)
|
|
return;
|
|
wp->Surfs[wp->numSrf].nobj = srf->nobj;
|
|
wp->Surfs[wp->numSrf].Shader = srf->Shader;
|
|
wp->Surfs[wp->numSrf].srf = srf->srf;
|
|
wp->numSrf++;
|
|
}
|
|
|
|
bool CD3D8Renderer::EF_CalcWarpCamera(STWarpZone *wp, int nObject, CCamera& prevCam, CCamera& newCam)
|
|
{
|
|
Vec3d vPrevPos = prevCam.GetPos();
|
|
Vec3d vPrevAngs = prevCam.GetAngles();
|
|
Vec3d vNewPos, vNewOccPos, vNewAngs;
|
|
bool bMirror = true;
|
|
if (nObject > 0)
|
|
{
|
|
CCObject *pObj = m_RP.m_VisObjects[nObject];
|
|
if (pObj->m_ObjFlags & FOB_PORTAL)
|
|
{
|
|
bMirror = false;
|
|
m_RP.m_PersFlags &= ~RBPF_DRAWMIRROR;
|
|
m_RP.m_PersFlags |= RBPF_DRAWPORTAL;
|
|
vNewPos = pObj->m_Trans2;
|
|
vNewOccPos = vNewPos;
|
|
vNewAngs = pObj->m_Angs2;
|
|
}
|
|
}
|
|
if (bMirror)
|
|
{
|
|
float fDot = vPrevPos.Dot(wp->plane.n) - wp->plane.d;
|
|
vNewPos = vPrevPos + wp->plane.n * -2.0f*fDot;
|
|
vNewOccPos = vPrevPos + wp->plane.n * -0.99f*fDot;
|
|
|
|
if (fDot < 0)
|
|
m_RP.m_MirrorClipSide = 1;
|
|
else
|
|
m_RP.m_MirrorClipSide = 2;
|
|
|
|
fDot = m_RP.m_CamVecs[0].Dot(wp->plane.n);
|
|
Vec3d vNewDir = m_RP.m_CamVecs[0] + wp->plane.n * -2.0f*fDot;
|
|
|
|
vNewAngs[0] = asinf (vNewDir[2])/M_PI*180.0f;
|
|
vNewAngs[1] = vPrevAngs[1] + 180.0f;
|
|
vNewAngs[2] = -atan2f (vNewDir[0], -vNewDir[1])/M_PI*180.0f;
|
|
|
|
m_RP.m_PersFlags &= ~RBPF_DRAWPORTAL;
|
|
m_RP.m_PersFlags |= RBPF_DRAWMIRROR;
|
|
}
|
|
|
|
newCam.SetPos(vNewPos);
|
|
newCam.SetOccPos(vNewOccPos);
|
|
newCam.SetAngle(vNewAngs);
|
|
if (bMirror)
|
|
newCam.SetScale(Vec3d(-1.0f, 1.0f, 1.0f));
|
|
newCam.Update();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CD3D8Renderer::EF_RenderWarpZone(STWarpZone *wp)
|
|
{
|
|
guard(CD3D8Renderer::EF_RenderWarpZone);
|
|
|
|
if (!wp->numSrf)
|
|
return false;
|
|
|
|
CCamera prevCam = GetCamera();
|
|
CCamera newCam = prevCam;
|
|
|
|
int prevFlags = m_RP.m_PersFlags;
|
|
|
|
if (!EF_CalcWarpCamera(wp, wp->Surfs[0].nobj, prevCam, newCam))
|
|
return false;
|
|
|
|
if (m_LogFile)
|
|
Logv(SRendItem::m_RecurseLevel, "\n ********** Start Render Portal **********\n");
|
|
|
|
STWarpZone *prevWarp = m_RP.m_CurWarp;
|
|
m_RP.m_CurWarp = wp;
|
|
|
|
m_matProj->Push();
|
|
EF_PushMatrix();
|
|
|
|
iSystem->SetViewCamera(newCam);
|
|
SetCamera(newCam);
|
|
|
|
float plane[4];
|
|
plane[0] = wp->plane.n[0];
|
|
plane[1] = wp->plane.n[1];
|
|
plane[2] = wp->plane.n[2];
|
|
plane[3] = -wp->plane.d;
|
|
|
|
EF_PushFog();
|
|
EF_SetClipPlane(true, plane, false);
|
|
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
eng->DrawLowDetail(DLD_TERRAIN_WATER | DLD_DETAIL_TEXTURES | DLD_DETAIL_OBJECTS | DLD_STATIC_OBJECTS | DLD_FAR_SPRITES | DLD_ENTITIES);
|
|
|
|
/*unsigned char *pic=new unsigned char [m_width*m_height*4];
|
|
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, pic);
|
|
WriteTGA(pic, m_width, m_height,"Warp.tga");
|
|
delete [] pic;*/
|
|
|
|
if (m_LogFile)
|
|
Logv(SRendItem::m_RecurseLevel, "\n ********** End Render Portal **********\n");
|
|
|
|
m_RP.m_PersFlags &= ~(RBPF_DRAWMIRROR | RBPF_DRAWPORTAL);
|
|
m_RP.m_PersFlags |= prevFlags & (RBPF_DRAWMIRROR | RBPF_DRAWPORTAL);
|
|
|
|
EF_SetClipPlane(false, plane, false);
|
|
EF_PopFog();
|
|
|
|
m_RP.m_CurWarp = prevWarp;
|
|
|
|
iSystem->SetViewCamera(prevCam);
|
|
SetCamera(prevCam);
|
|
|
|
EF_PopMatrix();
|
|
m_matProj->Pop();
|
|
|
|
unguard
|
|
|
|
return true;
|
|
}
|
|
|
|
void sTransformPlane( float *u, const float *v, const float *m )
|
|
{
|
|
float v0=v[0], v1=v[1], v2=v[2], v3=v[3];
|
|
#define M(row,col) m[col*4+row]
|
|
u[0] = v0 * M(0,0) + v1 * M(1,0) + v2 * M(2,0) + v3 * M(3,0);
|
|
u[1] = v0 * M(0,1) + v1 * M(1,1) + v2 * M(2,1) + v3 * M(3,1);
|
|
u[2] = v0 * M(0,2) + v1 * M(1,2) + v2 * M(2,2) + v3 * M(3,2);
|
|
u[3] = v0 * M(0,3) + v1 * M(1,3) + v2 * M(2,3) + v3 * M(3,3);
|
|
#undef M
|
|
}
|
|
|
|
static _inline int Compare(SPreprocess &a, SPreprocess &b)
|
|
{
|
|
SShader *sh1 = a.m_Shader;
|
|
SShader *sh2 = b.m_Shader;
|
|
|
|
if ((sh1->m_Flags2 & EF2_PREPR_CORONA) < (sh2->m_Flags2 & EF2_PREPR_CORONA))
|
|
return 1;
|
|
if ((sh1->m_Flags2 & EF2_PREPR_CORONA) > (sh2->m_Flags2 & EF2_PREPR_CORONA))
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
int CD3D8Renderer::EF_Preprocess(SRendItemPre *ri, int nums, int nume)
|
|
{
|
|
int i, m;
|
|
SShader *Shader;
|
|
SShader *ShaderState;
|
|
SRenderShaderResources *Res;
|
|
int nObject;
|
|
int nFog;
|
|
|
|
TArray<SPreprocess> Procs;
|
|
SPreprocess Proc;
|
|
TArray<SRendItemPreprocess> RIs;
|
|
SWarpSurf srfs[1024];
|
|
int nPortals = 0;
|
|
|
|
int NumWarps = 0;
|
|
STWarpZone Warps[MAX_WARPS];
|
|
STWarpZone *wp;
|
|
|
|
if (m_LogFile)
|
|
Logv(SRendItem::m_RecurseLevel, "*** Start preprocess frame ***\n");
|
|
|
|
for (i=nums; i<nume; i++)
|
|
{
|
|
SRendItem::mfGet(ri[i].SortVal, &nObject, &Shader, &ShaderState, &nFog, &Res);
|
|
if ((ri[i].SortVal.i.High >> 26) != eS_PreProcess)
|
|
break;
|
|
Proc.m_Num = i;
|
|
Proc.m_Shader = Shader;
|
|
Proc.m_pRes = Res;
|
|
Proc.m_RE = ri[i].Item;
|
|
Proc.m_nObject = nObject;
|
|
Procs.AddElem(Proc);
|
|
}
|
|
if (!Procs.Num())
|
|
return 0;
|
|
m = Procs.Num();
|
|
|
|
for (i=0; i<m; i++)
|
|
{
|
|
SPreprocess *pr = &Procs[i];
|
|
if (!pr->m_Shader)
|
|
continue;
|
|
// Draw environment to cube texture
|
|
if ((pr->m_Shader->m_Flags2 & EF2_PREPR_SCANCM) && !m_RP.m_bDrawToTexture)
|
|
{
|
|
CCObject *objIgn = m_RP.m_pIgnoreObject;
|
|
SShader *shadIgn = m_RP.m_pIgnoreShader;
|
|
Vec3d Pos;
|
|
m_RP.m_pRE = pr->m_RE;
|
|
if (pr->m_nObject < 0)
|
|
Pos.Set(0, 0, 0);
|
|
else
|
|
{
|
|
CCObject *obj = m_RP.m_VisObjects[pr->m_nObject];
|
|
m_RP.m_pIgnoreObject = obj;
|
|
m_RP.m_pIgnoreShader = pr->m_Shader;
|
|
if (obj->m_ObjFlags & FOB_USEMATRIX)
|
|
Pos = Vec3d(obj->m_Matrix(3,0), obj->m_Matrix(3,1), obj->m_Matrix(3,2));
|
|
else
|
|
Pos = obj->m_Trans;
|
|
}
|
|
if (m_LogFile)
|
|
Logv(SRendItem::m_RecurseLevel, "*** Draw environment to cube-map ***\n");
|
|
// if (Pos != Vec3d(0, 0, 0))
|
|
if (!IsEquivalent(Pos,Vec3d(0,0,0)))
|
|
SEnvTexture *cm = gcEf.mfFindSuitableEnvCMap(Pos, false, pr->m_Shader->m_DLDFlags);
|
|
m_RP.m_pIgnoreObject = objIgn;
|
|
m_RP.m_pIgnoreShader = shadIgn;
|
|
}
|
|
else
|
|
if ((pr->m_Shader->m_Flags2 & EF2_PREPR_SCANSCR) && !m_RP.m_bDrawToTexture)
|
|
{ // Draw screen to texture
|
|
}
|
|
else
|
|
if ((pr->m_Shader->m_Flags2 & EF2_PREPR_SCANTEX) && !m_RP.m_bDrawToTexture)
|
|
{ // Draw environment to texture
|
|
bool bWater = (pr->m_Shader->m_Flags2 & EF2_PREPR_SCANTEXWATER) ? 1 : 0;
|
|
bool bDraw = true;
|
|
if (!bWater || CV_r_waterrefractions)
|
|
{
|
|
if (pr->m_Shader->m_fUpdateFactor > 0)
|
|
{
|
|
m_RP.m_VisObjects[pr->m_nObject]->CalcMatrix();
|
|
float fDist = pr->m_RE->mfMinDistanceToCamera();
|
|
if (fDist > 0)
|
|
{
|
|
fDist *= pr->m_Shader->m_fUpdateFactor;
|
|
if (fDist > 0.5f)
|
|
fDist = 0.5f;
|
|
if (m_RP.m_RealTime-m_RP.m_pCurObject->m_fLastUpdate < fDist)
|
|
bDraw = false;
|
|
else
|
|
m_RP.m_pCurObject->m_fLastUpdate = m_RP.m_RealTime;
|
|
}
|
|
}
|
|
if (bDraw)
|
|
{
|
|
CCObject *objIgn = m_RP.m_pIgnoreObject;
|
|
SShader *shadIgn = m_RP.m_pIgnoreShader;
|
|
if (!CV_r_selfrefract)
|
|
{
|
|
m_RP.m_pIgnoreObject = m_RP.m_VisObjects[pr->m_nObject];
|
|
m_RP.m_pIgnoreShader = pr->m_Shader;
|
|
}
|
|
Vec3d Angs = GetCamera().GetAngles();
|
|
Vec3d Pos = GetCamera().GetPos();
|
|
m_RP.m_pRE = pr->m_RE;
|
|
if (m_LogFile)
|
|
Logv(SRendItem::m_RecurseLevel, "*** Draw environment to texture ***\n");
|
|
|
|
int DLDFlags = 0;
|
|
if (bWater)
|
|
{
|
|
m_RP.m_PersFlags |= RBPF_DONTDRAWSUN;
|
|
DLDFlags |= DLD_TERRAIN_WATER | DLD_DETAIL_TEXTURES;
|
|
}
|
|
m_RP.m_pShader = pr->m_Shader;
|
|
m_RP.m_pCurObject = m_RP.m_pIgnoreObject;
|
|
DLDFlags |= pr->m_Shader->m_DLDFlags;
|
|
SEnvTexture *cm = gcEf.mfFindSuitableEnvTex(Pos, Angs, false, DLDFlags);
|
|
m_RP.m_pIgnoreObject = objIgn;
|
|
m_RP.m_pIgnoreShader = shadIgn;
|
|
}
|
|
}
|
|
}
|
|
if ((pr->m_Shader->m_Flags2 & EF2_PREPR_SCANTEXWATER) && !m_RP.m_bDrawToTexture)
|
|
{
|
|
if (CV_r_waterreflections)
|
|
{
|
|
if (!(CTexMan::m_Text_WaterMap->m_Flags & FT_BUILD))
|
|
{
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
float fDist = eng->GetDistanceToSectorWithWater();
|
|
fDist *= CV_r_waterupdateFactor;
|
|
if (fDist > 0.3f)
|
|
fDist = 0.3f;
|
|
Vec3d Angs = GetCamera().GetAngles();
|
|
if (m_RP.m_RealTime-m_RP.m_fLastWaterUpdate > fDist || fabs(Angs[2]-m_RP.m_fLastWaterAngleUpdate)>CV_r_waterupdateDeltaAngle)
|
|
{
|
|
m_RP.m_fLastWaterUpdate = m_RP.m_RealTime;
|
|
m_RP.m_fLastWaterAngleUpdate = Angs[2];
|
|
|
|
CCamera tmp_cam = GetCamera();
|
|
Plane Pl;
|
|
Pl.n = Vec3d(0,0,1);
|
|
Pl.d = eng->GetWaterLevel();
|
|
CCObject *savedObj = m_RP.m_pCurObject;
|
|
CCObject *objIgn = m_RP.m_pIgnoreObject;
|
|
CCObject *obj = NULL;
|
|
SShader *shIgn = m_RP.m_pIgnoreShader;
|
|
if (pr->m_nObject > 0)
|
|
{
|
|
obj = m_RP.m_VisObjects[pr->m_nObject];
|
|
m_RP.m_VisObjects[pr->m_nObject]->CalcMatrix();
|
|
}
|
|
m_RP.m_PersFlags |= RBPF_DONTDRAWSUN;
|
|
m_RP.m_pCurObject = obj;
|
|
m_RP.m_pIgnoreObject = obj;
|
|
m_RP.m_pIgnoreShader = pr->m_Shader;
|
|
if (m_LogFile)
|
|
Logv(SRendItem::m_RecurseLevel, "*** Draw environment to texture for water reflections ***\n");
|
|
m_TexMan->DrawToTexture(Pl, CTexMan::m_Text_WaterMap, pr->m_Shader->m_DLDFlags);
|
|
m_RP.m_pCurObject = savedObj;
|
|
m_RP.m_pIgnoreObject = objIgn;
|
|
m_RP.m_pIgnoreShader = shIgn;
|
|
m_RP.m_PersFlags &= ~RBPF_DONTDRAWSUN;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if ((pr->m_Shader->m_Flags2 & EF2_PREPR_SHADOWMAPGEN))
|
|
{
|
|
CCObject *obj = m_RP.m_VisObjects[pr->m_nObject];
|
|
m_RP.m_pCurObject = obj;
|
|
/* if (pr->m_RE->mfGetType() == eDATA_ShadowMap)
|
|
{
|
|
CREShadowMap * pRE = (CREShadowMap*)pr->m_RE;
|
|
|
|
// Please never comment this lines !!!
|
|
if (m_LogFile)
|
|
Logv(SRendItem::m_RecurseLevel, "*** Prepare shadow maps for REShadowMap***\n");
|
|
if(obj && pRE->m_pShadowFrustum && ((ShadowMapLightSource*)pRE->m_pShadowFrustum)->m_LightFrustums.Count() && !m_RP.m_bDrawToTexture)
|
|
PrepareDepthMap(&((ShadowMapLightSource*)pRE->m_pShadowFrustum)->m_LightFrustums[0], false);
|
|
}
|
|
else*/
|
|
if (pr->m_RE->mfGetType() == eDATA_OcLeaf)
|
|
{
|
|
CREOcLeaf * pRE = (CREOcLeaf*)pr->m_RE;
|
|
ShadowMapFrustum * pFr = obj->m_pShadowFrustum;
|
|
|
|
// Please never comment this lines !!!
|
|
if (m_LogFile)
|
|
Logv(SRendItem::m_RecurseLevel, "*** Prepare shadow maps for REOcLeaf***\n");
|
|
if(obj && pFr && !m_RP.m_bDrawToTexture)
|
|
PrepareDepthMap(pFr, false);
|
|
}
|
|
}
|
|
else
|
|
if ((pr->m_Shader->m_Flags2 & EF2_PREPR_CORONA) && pr->m_nObject>0)
|
|
{
|
|
if (pr->m_RE->mfGetType() == eDATA_Flare)
|
|
{
|
|
CREFlare *fl = (CREFlare *)pr->m_RE;
|
|
CCObject *obj = m_RP.m_VisObjects[pr->m_nObject];
|
|
if (m_LogFile)
|
|
Logv(SRendItem::m_RecurseLevel, "*** Check corona visibility ***\n");
|
|
bool bVis = fl->mfCheckVis(obj);
|
|
}
|
|
}
|
|
else
|
|
if (pr->m_Shader->m_Flags2 & EF2_PREPR_OUTSPACE)
|
|
{
|
|
CCObject *obj = m_RP.m_VisObjects[pr->m_nObject];
|
|
m_RP.m_pCurObject = obj;
|
|
CREOutSpace * pRE = (CREOutSpace*)pr->m_RE;
|
|
|
|
if(obj && pRE && !m_RP.m_bDrawToTexture)
|
|
PrepareOutSpaceTextures(pRE);
|
|
}
|
|
else
|
|
if (pr->m_Shader->m_Flags2 & EF2_PREPR_PORTAL)
|
|
{
|
|
if (!CV_r_portals)
|
|
continue;
|
|
|
|
if (m_RP.m_RecurseLevel+1 >= MAX_PORTAL_RECURSES)
|
|
continue;
|
|
|
|
if (!CV_r_portalsrecursive && m_RP.m_CurWarp)
|
|
continue;
|
|
|
|
if (!m_RP.m_CurWarp)
|
|
{
|
|
srfs[nPortals].nobj = pr->m_nObject;
|
|
srfs[nPortals].srf = pr->m_RE;
|
|
srfs[nPortals].Shader = pr->m_Shader;
|
|
nPortals++;
|
|
}
|
|
else
|
|
{
|
|
Plane pl;
|
|
pr->m_RE->mfGetPlane(pl);
|
|
|
|
// if (m_RP.m_CurWarp->plane.d != pl.d || m_RP.m_CurWarp->plane.n != pl.n)
|
|
if (m_RP.m_CurWarp->plane.d != pl.d || !IsEquivalent(m_RP.m_CurWarp->plane.n,pl.n))
|
|
{
|
|
srfs[nPortals].nobj = pr->m_nObject;
|
|
srfs[nPortals].srf = pr->m_RE;
|
|
srfs[nPortals].Shader = pr->m_Shader;
|
|
nPortals++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pr->m_nObject < 0)
|
|
continue;
|
|
SRendItemPreprocess rip;
|
|
SRendItemPre *r = &ri[pr->m_Num];
|
|
rip.Item = r->Item;
|
|
rip.m_Object = m_RP.m_VisObjects[pr->m_nObject];
|
|
if (rip.m_Object->m_ObjFlags & FOB_CUBE_MASK)
|
|
RIs.AddElem(rip);
|
|
}
|
|
}
|
|
if (RIs.Num())
|
|
{
|
|
if (m_LogFile)
|
|
Logv(SRendItem::m_RecurseLevel, "*** Preprocess pipeline ***\n");
|
|
SRendItemPreprocess::mfSort(&RIs[0], RIs.Num());
|
|
EF_DrawREPreprocess(&RIs[0], RIs.Num());
|
|
}
|
|
|
|
if (nPortals)
|
|
{
|
|
for (i=0; i<nPortals; i++)
|
|
{
|
|
EF_SetWarpZone(&srfs[i], &NumWarps, Warps);
|
|
}
|
|
|
|
m_RP.m_RecurseLevel++;
|
|
m_RP.m_WasPortals += NumWarps;
|
|
m_RP.m_CurPortal += NumWarps;
|
|
|
|
for (i=0; i<NumWarps; i++)
|
|
{
|
|
wp = &Warps[i];
|
|
|
|
if (m_LogFile)
|
|
Logv(SRendItem::m_RecurseLevel, "*** Start rendering of warp zone %d ***\n", i);
|
|
EF_RenderWarpZone(wp);
|
|
m_RP.m_CurPortal--;
|
|
|
|
EF_PreRender();
|
|
|
|
// Render translucent mirror surface(s)
|
|
int nObj = -1;
|
|
SShader *sh = NULL;
|
|
SRenderShaderResources *Res = NULL;
|
|
for (int j=0; j<wp->numSrf; j++)
|
|
{
|
|
SWarpSurf *ws = &wp->Surfs[j];
|
|
if (nObj != ws->nobj)
|
|
{
|
|
if (sh)
|
|
EF_Flush();
|
|
|
|
if (!EF_ObjectChange(sh, ws->nobj, ws->srf))
|
|
continue;
|
|
nObj = ws->nobj;
|
|
}
|
|
if (ws->Shader != sh || ws->ShaderRes != Res)
|
|
{
|
|
if (sh)
|
|
m_RP.m_pRenderFunc();
|
|
EF_Start(ws->Shader, NULL, ws->ShaderRes, 0, ws->srf);
|
|
sh = ws->Shader;
|
|
}
|
|
|
|
ws->srf->mfPrepare();
|
|
}
|
|
if (sh)
|
|
m_RP.m_pRenderFunc();
|
|
}
|
|
m_RP.m_RecurseLevel--;
|
|
}
|
|
|
|
if (m_LogFile)
|
|
Logv(SRendItem::m_RecurseLevel, "*** End preprocess frame ***\n");
|
|
|
|
return m;
|
|
}
|
|
|
|
void CD3D8Renderer::EF_EndEf2D(bool bSort)
|
|
{
|
|
int i;
|
|
SShader *Shader, *CurShader, *ShaderState, *CurShaderState;
|
|
SRenderShaderResources *Res, *CurRes;
|
|
|
|
EF_AddClientPolys2D();
|
|
|
|
int nums = SRendItem::m_StartRI[0];
|
|
int nume = SRendItem::m_RendItems[0].Num();
|
|
|
|
if (bSort)
|
|
{
|
|
SRendItem::mfSort(&SRendItem::m_RendItems[0][0], nume);
|
|
// If sort number of the first shader is 1 (eS_Preprocess)
|
|
// run preprocess operations for the current frame
|
|
if ((SRendItem::m_RendItems[0][nums].SortVal.i.High >> 26) == eS_PreProcess)
|
|
nums += EF_Preprocess(&SRendItem::m_RendItems[nums][0], nums, nume);
|
|
}
|
|
|
|
EF_PreRender();
|
|
ResetToDefault();
|
|
|
|
CurShader = NULL;
|
|
CurRes = NULL;
|
|
CurShaderState = NULL;
|
|
UnINT64 oldVal;
|
|
oldVal.SortVal = -1;
|
|
m_RP.m_Flags = RBF_2D;
|
|
|
|
for (i=nums; i<nume; i++)
|
|
{
|
|
SRendItemPre *ri = &SRendItem::m_RendItems[0][i];
|
|
CRendElement *re = ri->Item;
|
|
if (ri->SortVal.SortVal == oldVal.SortVal)
|
|
{
|
|
re->mfPrepare();
|
|
continue;
|
|
}
|
|
oldVal.SortVal = ri->SortVal.SortVal;
|
|
|
|
SRendItem::mfGet(ri->SortVal, &Shader, &ShaderState, &Res);
|
|
if (Shader != CurShader || Res != CurRes || ShaderState != CurShaderState)
|
|
{
|
|
if (CurShader)
|
|
m_RP.m_pRenderFunc();
|
|
|
|
EF_Start(Shader, ShaderState, Res, re);
|
|
|
|
CurShader = Shader;
|
|
CurShaderState = ShaderState;
|
|
CurRes = Res;
|
|
}
|
|
|
|
re->mfPrepare();
|
|
}
|
|
if (CurShader)
|
|
m_RP.m_pRenderFunc();
|
|
|
|
EF_PostRender();
|
|
}
|