/*============================================================================= 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; jLog("\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 (m_pd3dDevice, m_RP.m_MaxTris*3); sSVB[0].mVB.VBPtr_D_1T = new StaticVB (m_pd3dDevice, D3DFVF_VERTEX_D_1T, m_RP.m_MaxVerts); sSVB[1].mVB.VBPtr_D_2T = new StaticVB (m_pd3dDevice, D3DFVF_VERTEX_D_2T, m_RP.m_MaxVerts); sSVB[2].mVB.VBPtr_D_3T = new StaticVB (m_pd3dDevice, D3DFVF_VERTEX_D_3T, m_RP.m_MaxVerts); sSVB[3].mVB.VBPtr_D_4T = new StaticVB (m_pd3dDevice, D3DFVF_VERTEX_D_4T, m_RP.m_MaxVerts); sSVB[4].mVB.VBPtr_N_D_1T = new StaticVB (m_pd3dDevice, D3DFVF_VERTEX_N_D_1T, m_RP.m_MaxVerts); sSVB[5].mVB.VBPtr_N_D_2T = new StaticVB (m_pd3dDevice, D3DFVF_VERTEX_N_D_2T, m_RP.m_MaxVerts); sSVB[6].mVB.VBPtr_N_D_3T = new StaticVB (m_pd3dDevice, D3DFVF_VERTEX_N_D_3T, m_RP.m_MaxVerts); sSVB[7].mVB.VBPtr_N_D_4T = new StaticVB (m_pd3dDevice, D3DFVF_VERTEX_N_D_4T, m_RP.m_MaxVerts); sSVB[8].mVB.VBPtr_TR_D_1T = new StaticVB (m_pd3dDevice, D3DFVF_TRVERTEX_D_1T, m_RP.m_MaxVerts); sSVB[9].mVB.VBPtr_TR_D_2T = new StaticVB (m_pd3dDevice, D3DFVF_TRVERTEX_D_2T, m_RP.m_MaxVerts); sSVB[10].mVB.VBPtr_TR_D_3T = new StaticVB (m_pd3dDevice, D3DFVF_TRVERTEX_D_3T, m_RP.m_MaxVerts); sSVB[11].mVB.VBPtr_TR_D_4T = new StaticVB (m_pd3dDevice, D3DFVF_TRVERTEX_D_4T, m_RP.m_MaxVerts); // Used for sprites m_RP.m_VBSprites.VBPtr_D_T2F = new StaticVB (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; iInit(); 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; imfReset(); } } if (nFlags & EFRF_PSHADERS) { for (i=0; imfReset(); } } } 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* Defs) { int i; if (!Defs) return; for (i=0; iNum(); 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; jm_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; nETC_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; nm_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(v * sfm->m_RGBNoise->m_RangeR + sfm->m_RGBNoise->m_ConstR, 0.0f, 1.0f) * 255.0f); v = RandomNum(); byte g = (byte)(Clamp(v * sfm->m_RGBNoise->m_RangeG + sfm->m_RGBNoise->m_ConstG, 0.0f, 1.0f) * 255.0f); v = RandomNum(); byte b = (byte)(Clamp(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; nm_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; nm_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(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; nm_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; im_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; jm_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; jm_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<SetRenderState(D3DRS_LIGHTING, FALSE); m_pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, FALSE); for (int i=0; i<8; i++) { if (m_EnableLights & (1<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= 32) break; CDLight *dl = m_RP.m_DLights[i]; if (dl->m_Flags & DLF_DETAIL) continue; if (!(m_RP.m_DynLMask & (1<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<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* MatrixOps, bool bEnable) { if (!MatrixOps) return; LPDIRECT3DDEVICE8 dv = m_pd3dDevice; int CurMatrix = D3DTS_VIEW; m_CurOpMatrix = NULL; int Stage = -1; for (int i=0; iNum(); 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 *mats = m_RP.m_pRE->mfGetMatInfoList(); if (mats) { CMatInfo *m = mats->Get(0); for (int i=0; iCount(); 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; im_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; imfSet(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; imfParameter4f(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; im_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; lm_Id; TArray* 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; iNum(); 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<= 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<m_LightMaterial->mfApply(slw->m_LMFlags | (l<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<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; im_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; im_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<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; nm_RP.m_DLights.Num(); n++) { CDLight *dl = rd->m_RP.m_DLights[n]; if (rd->m_RP.m_DynLMask & (1<Logv(SRendItem::m_RecurseLevel, " Light %d (\"%s\")\n", n, dl->m_Name ? dl->m_Name : ""); } } 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; iItem; 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; vm_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; vm_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; iGetString(); 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= 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; iItem; 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; inumSrf = 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 Procs; SPreprocess Proc; TArray 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> 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; im_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; inumSrf; 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; iItem; 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(); }