From 10c0232b83305b89779cf3cc0aac7d3ce2993358 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 19 Apr 2018 09:52:30 +0200 Subject: [PATCH] fixed neo reflections; implemented leeds reflections --- premake5.lua | 8 +- resources/Resource.rc | Bin 1738 -> 1836 bytes resources/VersionInfo.rc | Bin 2968 -> 2968 bytes resources/resource.h | Bin 1050 -> 1112 bytes shaders/vs/leedsCarFxVS.hlsl | 32 +++++ shaders/vs/neoVehiclePass1VS.hlsl | 3 +- shaders/vs/neoVehiclePass2VS.hlsl | 3 +- src/main.cpp | 42 ++++-- src/neo.h | 3 +- src/neoCarpipe.cpp | 60 ++++---- src/neoWaterdrops.cpp | 2 +- src/pipelinecommon.cpp | 9 ++ src/skygfx.h | 22 ++- src/vehiclePipe.cpp | 221 ++++++++++++++++++++++++++++++ 14 files changed, 353 insertions(+), 52 deletions(-) create mode 100644 shaders/vs/leedsCarFxVS.hlsl diff --git a/premake5.lua b/premake5.lua index 7cdcd19..bfcbd12 100644 --- a/premake5.lua +++ b/premake5.lua @@ -4,7 +4,7 @@ workspace "skygfx" defines { "rsc_CompanyName=\"aap\"" } defines { "rsc_LegalCopyright=\"\""} - defines { "rsc_FileVersion=\"3.6.0.0\"", "rsc_ProductVersion=\"3.6.0.0\"" } + defines { "rsc_FileVersion=\"3.7.0.0\"", "rsc_ProductVersion=\"3.7.0.0\"" } defines { "rsc_InternalName=\"%{prj.name}\"", "rsc_ProductName=\"%{prj.name}\"", "rsc_OriginalFilename=\"%{prj.name}.dll\"" } defines { "rsc_FileDescription=\"https://github.com/aap\"" } defines { "rsc_UpdateUrl=\"https://github.com/aap/skygfx\"" } @@ -33,13 +33,15 @@ project "skygfx" targetextension ".dll" characterset ("MBCS") + buildoptions { "/Zc:threadSafeInit-" } + filter "configurations:Debug" defines { "DEBUG" } symbols "On" flags { "StaticRuntime" } debugdir "C:/Users/aap/games/gtasa" debugcommand "C:/Users/aap/games/gtasa/gta_sa.exe" - postbuildcommands "copy /y \"$(TargetPath)\" \"C:\\Users\\aap\\games\\gtasa\\dlls\\skygfx.dll\"" + postbuildcommands "copy /y \"$(TargetPath)\" \"C:\\Users\\aap\\games\\gtasa\\plugins\\skygfx.dll\"" filter "configurations:Release" defines { "NDEBUG" } @@ -47,4 +49,4 @@ project "skygfx" flags { "StaticRuntime" } debugdir "C:/Users/aap/games/gtasa" debugcommand "C:/Users/aap/games/gtasa/gta_sa.exe" - postbuildcommands "copy /y \"$(TargetPath)\" \"C:\\Users\\aap\\games\\gtasa\\dlls\\skygfx.dll\"" + postbuildcommands "copy /y \"$(TargetPath)\" \"C:\\Users\\aap\\games\\gtasa\\plugins\\skygfx.dll\"" diff --git a/resources/Resource.rc b/resources/Resource.rc index 7158658bdc94028fb4f4204ed6c972bf1f45dd73..927639a80ee97304bc054fa03a901dbc159ca87b 100644 GIT binary patch delta 58 zcmX@byM}MWDYl6lID~x|T!GMqA(+9L!I2?|!HpqevLc(Ja1KK%5T-B`1H}^=ih$x3 IlN(uu0j{qNN&o-= delta 7 OcmZ3(cZzqzDK-EM-vbf= diff --git a/resources/VersionInfo.rc b/resources/VersionInfo.rc index fedcdc14d67ea74d2c540237169b283310d5b14e..4d527c9717307a898fc9ce112305d94ec64284bb 100644 GIT binary patch delta 20 bcmbOsK0|zi6bqyIWN8*dM)S?SEZ*z@IQInB delta 20 bcmbOsK0|zi6bqx-WN8*dMzhVnEZ*z@IOPP? diff --git a/resources/resource.h b/resources/resource.h index 8d59b9ca0259da5991beb064b9c68711b6655041..7927bc169b013bda0a18b20f1f8215899ad949c4 100644 GIT binary patch delta 50 zcmbQmaf4%n6w72WW(hSP23H_-VF+e$W^iN(VsK-KU9IDycR!HB_>ftP`c0RZ^| B2ZjIu delta 7 Ocmcb?F^gk^6bk?gi2_jo diff --git a/shaders/vs/leedsCarFxVS.hlsl b/shaders/vs/leedsCarFxVS.hlsl new file mode 100644 index 0000000..bc17b5a --- /dev/null +++ b/shaders/vs/leedsCarFxVS.hlsl @@ -0,0 +1,32 @@ +float4x4 combined : register(c0); +float4 fxParams : register(c30); +float3x3 envmat : register(c32); +float4x4 texmat : register(c36); + +#define shininess (fxParams.y) +#define lightmult (fxParams.w) + +struct VS_INPUT { + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 Texcoord1: TEXCOORD1; +}; + +struct VS_OUTPUT { + float4 Position : POSITION; + float2 Texcoord : TEXCOORD0; + float4 Color : COLOR0; +}; + +VS_OUTPUT +main(VS_INPUT IN) +{ + VS_OUTPUT OUT; + OUT.Position = mul(IN.Position, combined); + + float3 envNormal = mul(envmat, IN.Normal); + OUT.Texcoord = mul(texmat, float4(envNormal.xy, 0.0, 1.0)).xy; + OUT.Color = float4(128.0, 128.0, 128.0, 255.0)/255.0*shininess*lightmult; + OUT.Color.a = 1.0; + return OUT; +} diff --git a/shaders/vs/neoVehiclePass1VS.hlsl b/shaders/vs/neoVehiclePass1VS.hlsl index 9619009..41127ec 100644 --- a/shaders/vs/neoVehiclePass1VS.hlsl +++ b/shaders/vs/neoVehiclePass1VS.hlsl @@ -32,7 +32,6 @@ float3 surfProps : register(c32); #define shininess (reflProps.x) #define fresnel (reflProps.y) -#define lightmult (reflProps.z) #define power (reflProps.w) #define surfAmb (surfProps.x) #define surfDiff (surfProps.z) @@ -58,7 +57,7 @@ main(in VS_INPUT In) uv2 = mul((float3x3)tex, uv2); Out.texcoord1.xy = uv2.xy*0.5 + 0.5; float b = 1.0 - saturate(dot(V, N)); - Out.reflcolor = lerp(b*b*b*b*b, 1.0f, fresnel)*shininess;//*lightmult; + Out.reflcolor = lerp(b*b*b*b*b, 1.0f, fresnel)*shininess; return Out; } diff --git a/shaders/vs/neoVehiclePass2VS.hlsl b/shaders/vs/neoVehiclePass2VS.hlsl index 2f549c4..c878a9a 100644 --- a/shaders/vs/neoVehiclePass2VS.hlsl +++ b/shaders/vs/neoVehiclePass2VS.hlsl @@ -29,7 +29,6 @@ float3 surfProps : register(c32); #define shininess (reflProps.x) #define fresnel (reflProps.y) -#define lightmult (reflProps.z) #define power (reflProps.w) #define surfSpec (surfProps.y) @@ -51,7 +50,7 @@ main(in VS_INPUT In) Out.color = float4(directSpec*specTerm(N, -directDir, V, power), 1.0); for(int i = 0; i < 6; i++) Out.color.rgb += lightCol[i]*specTerm(N, -lightDir[i], V, power*2); - Out.color = saturate(Out.color*surfSpec*lightmult); + Out.color = saturate(Out.color*surfSpec); return Out; } diff --git a/src/main.cpp b/src/main.cpp index 1625c52..4b73823 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,6 +33,8 @@ void *gpCurrentShaderForDefaultCallbacks; float *gfLaRiotsLightMult = (float*)0x8CD060; float *ambientColors = (float*)0xB7C4A0; +GlobalScene &Scene = *(GlobalScene*)0xC17038; + static int defaultColourLeftUOffset; static int defaultColourRightUOffset; static int defaultColourTopVOffset; @@ -590,11 +592,29 @@ void CSkidmarks__Render(void) RwRenderStateSet(rwRENDERSTATEALPHATESTFUNCTION, (void*)alphafunc); } +static uint32_t RenderScene_A; +WRAPPER void RenderScene(void) { VARJMP(RenderScene_A); } + +void RenderReflectionMap_leeds(void); +void RenderReflectionScene(void); + +void +RenderScene_hook(void) +{ + RenderScene(); +// RenderReflectionScene(); + if(config->vehiclePipe == 4) + CarPipe::RenderEnvTex(); + else if(config->vehiclePipe == 5) + RenderReflectionMap_leeds(); +} + void (*InitialiseGame)(void); void InitialiseGame_hook(void) { ONCE; + InterceptCall(&RenderScene_A, RenderScene_hook, 0x53EABF); neoInit(); InitialiseGame(); } @@ -647,7 +667,7 @@ int StrAssoc::get(StrAssoc *desc, const char *key) { for(; desc->key[0] != '\0'; desc++) - if(strcmp(desc->key, key) == 0) + if(strcmpi(desc->key, key) == 0) return desc->val; return desc->val; } @@ -757,6 +777,7 @@ readIni(int n) {"Xbox", 2}, {"Spec", 3}, {"Neo", 4}, + {"Leeds", 5}, {"", -1}, }; c->vehiclePipe = StrAssoc::get(vehPipeMap, cfg.get("SkyGfx", "vehiclePipe", "").c_str()); @@ -766,8 +787,9 @@ readIni(int n) } c->dualPassVehicle = readint(cfg.get("SkyGfx", "dualPassVehicle", ""), config->dualPassGlobal); - c->neoShininess = readfloat(cfg.get("SkyGfx", "neoShininess", ""), 0.75); - c->neoSpecularity = readfloat(cfg.get("SkyGfx", "neoSpecularity", ""), 0.75); + c->leedsShininessMult = readfloat(cfg.get("SkyGfx", "leedsShininessMult", ""), 1.0); + c->neoShininessMult = readfloat(cfg.get("SkyGfx", "neoShininessMult", ""), 1.0); + c->neoSpecularityMult = readfloat(cfg.get("SkyGfx", "neoSpecularityMult", ""), 1.0); envMapSize = readint(cfg.get("SkyGfx", "neoEnvMapSize", ""), 128); int i = 1; while(i < envMapSize) i *= 2; @@ -921,8 +943,9 @@ afterStreamIni(void) X(dualPassGrass) \ X(buildingPipe) \ X(vehiclePipe) \ - X(neoShininess) \ - X(neoSpecularity) \ + X(leedsShininessMult) \ + X(neoShininessMult) \ + X(neoSpecularityMult) \ X(doglare) \ X(fixGrassPlacement) \ X(grassAddAmbient) \ @@ -998,7 +1021,7 @@ installMenu(void) if(DebugMenuLoad()){ static const char *ps2pcStr[] = { "PS2", "PC" }; static const char *buildPipeStr[] = { "PS2", "PC" }; - static const char *vehPipeStr[] = { "PS2", "PC", "Xbox", "Spec", "Neo" }; + static const char *vehPipeStr[] = { "PS2", "PC", "Xbox", "Spec", "Neo", "Leeds" }; static const char *colFilterStr[] = { "None", "PS2", "PC", "Mobile", "III", "VC", "VCS" }; static const char *lightningStr[] = { "Sky only", "Sky and objects" }; static const char *shadStr[] = { "Default", "PS2", "PC" }; @@ -1013,7 +1036,7 @@ installMenu(void) DebugMenuEntrySetWrap(menu.buildingPipe, true); } if(iCanHasvehiclePipe){ - menu.vehiclePipe = DebugMenuAddVar("SkyGFX", "Vehicle Pipeline", &config->vehiclePipe, nil, 1, 0, 4, vehPipeStr); + menu.vehiclePipe = DebugMenuAddVar("SkyGFX", "Vehicle Pipeline", &config->vehiclePipe, nil, 1, 0, 5, vehPipeStr); DebugMenuEntrySetWrap(menu.vehiclePipe, true); } menu.grassAddAmbient = DebugMenuAddVarBool32("SkyGFX", "Add Ambient to Grass", &config->grassAddAmbient, nil); @@ -1038,8 +1061,9 @@ installMenu(void) DebugMenuAddVarBool8("SkyGFX|Misc", "Blur PS2 Colour Filter", (int8_t*)&CPostEffects::m_bBlurColourFilter, nil); if(iCanHasSunGlare) menu.doglare = DebugMenuAddVarBool32("SkyGFX|Misc", "Sun Glare", &config->doglare, nil); - menu.neoShininess = DebugMenuAddVar("SkyGFX|Misc", "Neo Car Shininess", &config->neoShininess, nil, 0.1f, 0.0f, 10.0f); - menu.neoSpecularity = DebugMenuAddVar("SkyGFX|Misc", "Neo Car Specularity", &config->neoSpecularity, nil, 0.1f, 0.0f, 10.0f); + menu.leedsShininessMult = DebugMenuAddVar("SkyGFX|Misc", "Leeds Car Shininess", &config->leedsShininessMult, nil, 0.1f, 0.0f, 10.0f); + menu.neoShininessMult = DebugMenuAddVar("SkyGFX|Misc", "Neo Car Shininess", &config->neoShininessMult, nil, 0.1f, 0.0f, 10.0f); + menu.neoSpecularityMult = DebugMenuAddVar("SkyGFX|Misc", "Neo Car Specularity", &config->neoSpecularityMult, nil, 0.1f, 0.0f, 10.0f); menu.fixGrassPlacement = DebugMenuAddVarBool32("SkyGFX|Misc", "Fix Grass Placement", &config->fixGrassPlacement, nil); menu.lightningIlluminatesWorld = DebugMenuAddVar("SkyGFX|Misc", "Lightning illuminates", &config->lightningIlluminatesWorld, nil, 1, 0, 1, lightningStr); DebugMenuEntrySetWrap(menu.lightningIlluminatesWorld, true); diff --git a/src/neo.h b/src/neo.h index 7ef0c1d..786d802 100644 --- a/src/neo.h +++ b/src/neo.h @@ -69,13 +69,14 @@ void neoInit(void); class CarPipe : public CustomPipe { +public: void CreateShaders(void); static void LoadTweakingTable(void); static void MakeScreenQuad(void); static void MakeQuadTexCoords(bool textureSpace); static void RenderReflectionScene(void); -public: + static InterpolatedFloat fresnel; static InterpolatedFloat power; static InterpolatedLight diffColor; diff --git a/src/neoCarpipe.cpp b/src/neoCarpipe.cpp index fccd2fc..be81509 100644 --- a/src/neoCarpipe.cpp +++ b/src/neoCarpipe.cpp @@ -22,8 +22,10 @@ enum { //#define DEBUGTEX +WRAPPER void CRenderer__RenderRoads(void) { EAXJMP(0x553A10); } WRAPPER void CRenderer__RenderEverythingBarRoads(void) { EAXJMP(0x553AA0); } -WRAPPER void CRenderer__RenderFadingInEntities(void) { EAXJMP(0x553220); } +WRAPPER void CRenderer__RenderFadingInEntities(void) { EAXJMP(0x5531E0); } +WRAPPER void CRenderer__RenderFadingInUnderwaterEntities(void) { EAXJMP(0x553220); } short &skyBotRed = *(short*)0xB7C4CA; short &skyBotGreen = *(short*)0xB7C4CC; @@ -45,24 +47,12 @@ RwImVertexIndex CarPipe::screenindices[6] = { 0, 1, 2, 0, 2, 3 }; CarPipe carpipe; -static uint32_t RenderScene_A; -WRAPPER void RenderScene(void) { VARJMP(RenderScene_A); } - -void -RenderScene_hook(void) -{ - RenderScene(); - if(config->vehiclePipe == 4) - CarPipe::RenderEnvTex(); -} - void neoCarPipeInit(void) { ONCE; carpipe.Init(); CarPipe::SetupEnvMap(); - InterceptCall(&RenderScene_A, RenderScene_hook, 0x53EABF); } // @@ -70,7 +60,6 @@ neoCarPipeInit(void) // int envMapSize; -RpWorld *&scene = *(RpWorld**)0xC17038; void CarPipe::SetupEnvMap(void) @@ -88,7 +77,7 @@ CarPipe::SetupEnvMap(void) RwV2d vw; vw.x = vw.y = 0.4f; RwCameraSetViewWindow(reflectionCam, &vw); - RpWorldAddCamera(scene, reflectionCam); + RpWorldAddCamera(Scene.world, reflectionCam); reflectionTex = RwTextureCreate(envFB); RwTextureSetFilterMode(reflectionTex, rwFILTERLINEAR); @@ -148,16 +137,15 @@ void CarPipe::RenderReflectionScene(void) { RwRenderStateSet(rwRENDERSTATEFOGENABLE, 0); + CRenderer__RenderRoads(); CRenderer__RenderEverythingBarRoads(); CRenderer__RenderFadingInEntities(); } -RwCamera *>acam = *(RwCamera**)0xC1703C; - void CarPipe::RenderEnvTex(void) { - RwCameraEndUpdate(gtacam); + RwCameraEndUpdate(Scene.camera); RwV2d oldvw, vw = { 2.0f, 2.0f }; oldvw = reflectionCam->viewWindow; @@ -176,18 +164,22 @@ CarPipe::RenderEnvTex(void) reflectionMatrix->at.y = 0.0f; reflectionMatrix->at.z = 1.0f; } - RwMatrix *cammatrix = RwFrameGetMatrix(RwCameraGetFrame(gtacam)); + RwMatrix *cammatrix = RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)); reflectionMatrix->pos = cammatrix->pos; RwMatrixUpdate(reflectionMatrix); RwFrameTransform(RwCameraGetFrame(reflectionCam), reflectionMatrix, rwCOMBINEREPLACE); RwRGBA color = { skyBotRed, skyBotGreen, skyBotBlue, 255 }; + // blend a bit of white into the sky color, otherwise it tends to be very blue + color.red = color.red*0.6f + 255*0.4f; + color.green = color.green*0.6f + 255*0.4f; + color.blue = color.blue*0.6f + 255*0.4f; RwCameraClear(reflectionCam, &color, rwCAMERACLEARIMAGE | rwCAMERACLEARZ); RwCameraBeginUpdate(reflectionCam); - RwCamera *savedcam = gtacam; - gtacam = reflectionCam; // they do some begin/end updates with this in the called functions :/ + RwCamera *savedcam = Scene.camera; + Scene.camera = reflectionCam; // they do some begin/end updates with this in the called functions :/ RenderReflectionScene(); - gtacam = savedcam; + Scene.camera = savedcam; RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)1); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDZERO); @@ -201,7 +193,7 @@ CarPipe::RenderEnvTex(void) RwCameraEndUpdate(reflectionCam); RwCameraSetViewWindow(reflectionCam, &oldvw); - RwCameraBeginUpdate(gtacam); + RwCameraBeginUpdate(Scene.camera); #ifdef DEBUGTEX RwRenderStateSet(rwRENDERSTATETEXTURERASTER, reflectionTex->raster); RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, screenQuad, 4, screenindices, 6); @@ -363,13 +355,10 @@ CarPipe::DiffusePass(RxD3D9ResEntryHeader *header, RpAtomic *atomic) envData = *RWPLUGINOFFSET(CustomEnvMapPipeMaterialData*, material, CCustomCarEnvMapPipeline__ms_envMapPluginOffset); RwUInt32 materialFlags = *(RwUInt32*)&material->surfaceProps.specular; - bool hasRefl = !((materialFlags & 1) == 0); - bool hasEnv = !((materialFlags & 2) == 0); + bool hasEnv = !!(materialFlags & 3); int matfx = RpMatFXMaterialGetEffects(material); - if(matfx != rpMATFXEFFECTENVMAP){ + if(matfx != rpMATFXEFFECTENVMAP) hasEnv = false; - hasRefl = false; - } Color c = diffColor.Get(); Color diff(c.r*c.a, c.g*c.a, c.b*c.a, 1.0f-c.a); @@ -381,13 +370,14 @@ CarPipe::DiffusePass(RxD3D9ResEntryHeader *header, RpAtomic *atomic) RwD3D9SetVertexShaderConstant(LOC_matCol, (void*)&mat, 1); RwSurfaceProperties surfprops = material->surfaceProps; - surfprops.specular = config->neoSpecularity; + // if ambient light is too dark reflections don't look too good, so bump it + if(surfprops.ambient > 0.1f && surfprops.ambient < 0.8f) + surfprops.ambient = max(surfprops.ambient, 0.8f); RwD3D9SetVertexShaderConstant(LOC_surfProps, &surfprops, 1); float reflProps[4]; - reflProps[0] = (hasEnv||hasRefl) && !noRefl ? config->neoShininess : 0.0f; + reflProps[0] = hasEnv && !noRefl ? envData->shininess/255.0f * 8.0f * config->neoShininessMult : 0.0f; reflProps[1] = fresnel.Get(); - reflProps[2] = CCustomCarEnvMapPipeline__m_EnvMapLightingMult; reflProps[3] = power.Get(); RwD3D9SetVertexShaderConstant(LOC_reflProps, (void*)reflProps, 1); @@ -426,6 +416,7 @@ CarPipe::SpecularPass(RxD3D9ResEntryHeader *header, RpAtomic *atomic) RwD3D9GetRenderState(D3DRS_LIGHTING, &lighting); noRefl = CVisibilityPlugins__GetAtomicId(atomic) & 0x6000; + float lightmult = 1.85f * CCustomCarEnvMapPipeline__m_EnvMapLightingMult; for(uint i = 0; i < header->numMeshes; i++){ RwUInt32 materialFlags = *(RwUInt32*)&inst->material->surfaceProps.specular; bool hasSpec = !((materialFlags & 4) == 0 || !lighting); @@ -434,8 +425,13 @@ CarPipe::SpecularPass(RxD3D9ResEntryHeader *header, RpAtomic *atomic) hasSpec = false; specData = *RWPLUGINOFFSET(CustomSpecMapPipeMaterialData*, inst->material, CCustomCarEnvMapPipeline__ms_specularMapPluginOffset); - if(hasSpec && !noRefl) + if(hasSpec && !noRefl){ + RwSurfaceProperties surfprops; + surfprops.specular = specData->specularity*5.0f*config->neoSpecularityMult*lightmult; + if(surfprops.specular > 1.0f) surfprops.specular = 1.0f; + RwD3D9SetVertexShaderConstant(LOC_surfProps, &surfprops, 1); D3D9Render(header, inst); + } inst++; } RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)zwrite); diff --git a/src/neoWaterdrops.cpp b/src/neoWaterdrops.cpp index 5935ce6..1f1276c 100644 --- a/src/neoWaterdrops.cpp +++ b/src/neoWaterdrops.cpp @@ -106,7 +106,7 @@ int WaterDrops::ms_numDropsMoving; bool WaterDrops::ms_enabled; bool WaterDrops::ms_movingEnabled; -int WaterDrops::ms_splashDuration; +int WaterDrops::ms_splashDuration = -1; float WaterDrops::ms_distMoved, WaterDrops::ms_vecLen, WaterDrops::ms_rainStrength; RwV3d WaterDrops::ms_vec; diff --git a/src/pipelinecommon.cpp b/src/pipelinecommon.cpp index 793dcf4..7966c53 100644 --- a/src/pipelinecommon.cpp +++ b/src/pipelinecommon.cpp @@ -94,6 +94,14 @@ pipeGetComposedTransformMatrix(RpAtomic *atomic, float *out) memcpy(out, &combined, 64); } +// Have to call the above before! +void +pipeGetCameraTransformMatrix(float *out) +{ + DirectX::XMMATRIX combined = DirectX::XMMatrixMultiply(pipeViewMat, pipeWorldMat); + memcpy(out, &combined, 64); +} + void pipeUploadMatCol(int flags, RpMaterial *m, int loc) { @@ -205,6 +213,7 @@ CreateShaders(void) makeVS(IDR_SPECCARFXVS, &specCarFxVS); makePS(IDR_SPECCARFXPS, &specCarFxPS); makeVS(IDR_XBOXCARVS, &xboxCarVS); + makeVS(IDR_LEEDSCARFXVS, &leedsCarFxVS); // building makeVS(IDR_PS2BUILDINGVS, &ps2BuildingVS); diff --git a/src/skygfx.h b/src/skygfx.h index 2e9c68a..940eb3e 100644 --- a/src/skygfx.h +++ b/src/skygfx.h @@ -28,7 +28,7 @@ typedef int32_t int32; extern HMODULE dllModule; #define nil NULL -#define VERSION 0x360 +#define VERSION 0x370 struct Config { // these are at fixed offsets @@ -46,7 +46,7 @@ struct Config { RwBool backfaceCull; RwBool dualPassDefault, dualPassGrass, dualPassVehicle, dualPassPed; int vehiclePipe; - float neoShininess, neoSpecularity; + float neoShininessMult, neoSpecularityMult; int colorFilter; int infraredVision, nightVision, grainFilter; RwBool doRadiosity; @@ -69,6 +69,8 @@ struct Config { float cbScale, cbOffset; float crScale, crOffset; int zwriteThreshold; + + float leedsShininessMult; }; extern int numConfigs; extern int currentConfig; @@ -148,6 +150,12 @@ enum { #endif }; +struct GlobalScene +{ + RpWorld *world; + RwCamera *camera; +}; +extern GlobalScene &Scene; struct Imf { @@ -315,6 +323,14 @@ extern RwReal &CCustomCarEnvMapPipeline__m_EnvMapLightingMult; extern RwInt32 &CCustomBuildingDNPipeline__ms_extraVertColourPluginOffset; extern RwReal &CCustomBuildingDNPipeline__m_fDNBalanceParam; +void CRenderer__RenderRoads(void); +void CRenderer__RenderEverythingBarRoads(void); +void CRenderer__RenderFadingInEntities(void); +void CRenderer__RenderFadingInUnderwaterEntities(void); +extern short &skyBotRed; +extern short &skyBotGreen; +extern short &skyBotBlue; + //////// Pipelines ///// Shaders @@ -325,6 +341,7 @@ extern void *vehiclePipeVS, *ps2CarFxVS; extern void *ps2EnvSpecFxPS; // also used by the building pipeline extern void *specCarFxVS, *specCarFxPS; extern void *xboxCarVS; +extern void *leedsCarFxVS; // postfx extern void *iiiTrailsPS, *vcTrailsPS; extern void *gradingPS; @@ -335,6 +352,7 @@ void CreateShaders(void); void RwToD3DMatrix(void *d3d, RwMatrix *rw); void MakeProjectionMatrix(void *d3d, RwCamera *cam, float nbias = 0.0f, float fbias = 0.0f); void pipeGetComposedTransformMatrix(RpAtomic *atomic, float *out); +void pipeGetCameraTransformMatrix(float *out); void pipeUploadMatCol(int flags, RpMaterial *m, int loc); void pipeUploadZero(int loc); void pipeUploadLightColor(RpLight *light, int loc); diff --git a/src/vehiclePipe.cpp b/src/vehiclePipe.cpp index 290f092..bc1cdd0 100644 --- a/src/vehiclePipe.cpp +++ b/src/vehiclePipe.cpp @@ -27,6 +27,7 @@ void *vehiclePipeVS, *ps2CarFxVS; void *ps2EnvSpecFxPS; // also used by the building pipeline void *specCarFxVS, *specCarFxPS; void *xboxCarVS; +void *leedsCarFxVS; float black4f[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; float white4f[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; @@ -43,6 +44,11 @@ static RwMatrix carfx_view, carfx_env1Inv, carfx_env2Inv; static RwV3d carfx_lightdir; // view space static RwFrame *carfx_env1Frame, *carfx_env2Frame; +// Leeds reflections +static RwCamera *reflectionCam; +static RwTexture *reflectionTex; +static D3DMATRIX envtexmat; + CustomEnvMapPipeAtomicData* CCustomCarEnvMapPipeline__AllocEnvMapPipeAtomicData(RpAtomic *atomic) { @@ -81,6 +87,43 @@ CCustomCarEnvMapPipeline__Init(void) RwFrameSetIdentity(carfx_env2Frame); RwFrameUpdateObjects(carfx_env2Frame); } + + // leeds reflections + RwRaster *envFB = RwRasterCreate(envMapSize, envMapSize, 0, rwRASTERTYPECAMERATEXTURE); + RwRaster *envZB = RwRasterCreate(envMapSize, envMapSize, 0, rwRASTERTYPEZBUFFER); + reflectionCam = RwCameraCreate(); + RwCameraSetRaster(reflectionCam, envFB); + RwCameraSetZRaster(reflectionCam, envZB); + RwCameraSetFrame(reflectionCam, RwFrameCreate()); + RwCameraSetNearClipPlane(reflectionCam, 0.1f); + RwCameraSetFarClipPlane(reflectionCam, 250.0f); + RwV2d vw; + vw.x = vw.y = 0.4f; + RwCameraSetViewWindow(reflectionCam, &vw); + RpWorldAddCamera(Scene.world, reflectionCam); + + reflectionTex = RwTextureCreate(envFB); + RwTextureSetFilterMode(reflectionTex, rwFILTERLINEAR); + + envtexmat.m[0][0] = 0.5f; + envtexmat.m[0][1] = 0.0f; + envtexmat.m[0][2] = 0.0f; + envtexmat.m[0][3] = 0.0f; + + envtexmat.m[1][0] = 0.0f; + envtexmat.m[1][1] = -0.5f; + envtexmat.m[1][2] = 0.0f; + envtexmat.m[1][3] = 0.0f; + + envtexmat.m[2][0] = 0.0f; + envtexmat.m[2][1] = 0.0f; + envtexmat.m[2][2] = 0.0f; + envtexmat.m[2][3] = 0.0f; + + envtexmat.m[3][0] = 0.5f; + envtexmat.m[3][1] = 0.5f; + envtexmat.m[3][2] = 0.0f; + envtexmat.m[3][3] = 1.0f; } void (*CCustomCarEnvMapPipeline__PreRenderUpdate_orig)(void); @@ -860,6 +903,181 @@ CCustomCarEnvMapPipeline__CustomPipeRenderCB_Xbox(RwResEntry *repEntry, void *ob RwD3D9SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); } + + +void +CCustomCarEnvMapPipeline__CustomPipeRenderCB_leeds(RwResEntry *repEntry, void *object, RwUInt8 type, RwUInt32 flags) +{ + RxD3D9ResEntryHeader *resEntryHeader; + RxD3D9InstanceData *instancedData; + RpAtomic *atomic; + RwInt32 numMeshes; + RwBool noFx; + CustomEnvMapPipeMaterialData *envData; + RpMaterial *material; + RwUInt32 materialFlags; + RwBool hasEnv, hasAlpha; + struct { + float fxSwitch; + float shininess; + float specularity; + float lightmult; + } fxParams; + float envmat[16]; + RwV3d eye; + RwMatrix lightmat; + float transform[16]; + + atomic = (RpAtomic*)object; + + _rwD3D9EnableClippingIfNeeded(object, type); + + float colorscale = 1.0f; + RwD3D9SetPixelShaderConstant(0, &colorscale, 1); + + pipeGetComposedTransformMatrix(atomic, transform); + RwD3D9SetVertexShaderConstant(0, transform, 4); + RwMatrixInvert(&lightmat, RwFrameGetLTM(RpAtomicGetFrame(atomic))); + if(flags & rpGEOMETRYLIGHT) + uploadLights(&lightmat); + else + uploadNoLights(); + + resEntryHeader = (RxD3D9ResEntryHeader *)(repEntry + 1); + instancedData = (RxD3D9InstanceData *)(resEntryHeader + 1); + if(resEntryHeader->indexBuffer != NULL) + RwD3D9SetIndices(resEntryHeader->indexBuffer); + _rwD3D9SetStreams(resEntryHeader->vertexStream,resEntryHeader->useOffsets); + RwD3D9SetVertexDeclaration(resEntryHeader->vertexDeclaration); + numMeshes = resEntryHeader->numMeshes; + + int alphafunc, alpharef; + int src, dst; + int fog; + RwRenderStateGet(rwRENDERSTATEALPHATESTFUNCTIONREF, &alpharef); + RwRenderStateGet(rwRENDERSTATEALPHATESTFUNCTION, &alphafunc); + RwRenderStateGet(rwRENDERSTATESRCBLEND, &src); + RwRenderStateGet(rwRENDERSTATEDESTBLEND, &dst); + RwRenderStateGet(rwRENDERSTATEFOGENABLE, &fog); + + noFx = CVisibilityPlugins__GetAtomicId(atomic) & 0x6000; + fxParams.lightmult = CCustomCarEnvMapPipeline__m_EnvMapLightingMult; + RwMatrix *camfrm = RwFrameGetLTM(RwCameraGetFrame(Camera)); + RwV3dTransformPoint(&eye, RwMatrixGetPos(camfrm), &lightmat); + RwD3D9SetVertexShaderConstant(REG_eye, &eye, 1); + + pipeGetCameraTransformMatrix(envmat); + RwD3D9SetVertexShaderConstant(REG_envmat, &envmat, 3); + RwD3D9SetVertexShaderConstant(36, &envtexmat, 4); + + for(; numMeshes--; instancedData++){ + material = instancedData->material; + pipeSetTexture(material->texture, 0); + + hasAlpha = instancedData->vertexAlpha || instancedData->material->color.alpha != 255; + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)hasAlpha); + + pipeUploadMatCol(flags, material, REG_matCol); + float surfProps[4]; + surfProps[0] = material->surfaceProps.ambient; + if(surfProps[0] > 0.1f && surfProps[0] < 1.0f) + surfProps[0] = 1.0f; + surfProps[2] = material->surfaceProps.diffuse; + surfProps[3] = !!(flags & rpGEOMETRYPRELIT); + RwD3D9SetVertexShaderConstant(REG_surfProps, surfProps, 1); + + RwD3D9SetVertexShader(vehiclePipeVS); + RwD3D9SetPixelShader(simplePS); + + D3D9RenderDual(config->dualPassVehicle, resEntryHeader, instancedData); + + // + // FX pass + // + materialFlags = *(RwUInt32*)&material->surfaceProps.specular; + hasEnv = !!(materialFlags & 3); + if(RpMatFXMaterialGetEffects(material) != rpMATFXEFFECTENVMAP) + hasEnv = false; + if(noFx || !hasEnv) + continue; + + RwD3D9SetVertexShader(leedsCarFxVS); + + envData = *RWPLUGINOFFSET(CustomEnvMapPipeMaterialData*, material, CCustomCarEnvMapPipeline__ms_envMapPluginOffset); + + fxParams.lightmult = 1.0f; + fxParams.shininess = envData->shininess/255.0f * 3.0f * config->leedsShininessMult; + if(fxParams.shininess > 1.0f) + fxParams.shininess = 1.0f; + + RwD3D9SetVertexShaderConstant(REG_envmat, &envmat, 3); + RwD3D9SetVertexShaderConstant(REG_fxParams, &fxParams, 1); + + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwD3D9SetTexture(reflectionTex, 0); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)1); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + + D3D9Render(resEntryHeader, instancedData); + + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)fog); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + + } + RwD3D9SetVertexShader(NULL); + RwD3D9SetPixelShader(NULL); + RwD3D9SetTexture(NULL, 1); + RwD3D9SetTexture(NULL, 2); + RwD3D9SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + RwD3D9SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + RwD3D9SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1); + RwD3D9SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); +} + +void +RenderReflectionScene(void) +{ + RwRenderStateSet(rwRENDERSTATEFOGENABLE, 0); + CRenderer__RenderRoads(); + CRenderer__RenderEverythingBarRoads(); + // this renders vehicles and peds in vehicles, probably don't want it here + // let's hope it doesn't render some other objects we'd like to see +// CRenderer__RenderFadingInEntities(); +} + +void +RenderReflectionMap_leeds(void) +{ + RwCamera *cam = Scene.camera; + RwCameraEndUpdate(cam); + + RwCameraSetViewWindow(reflectionCam, &cam->viewWindow); + + RwFrameTransform(RwCameraGetFrame(reflectionCam), &RwCameraGetFrame(cam)->ltm, rwCOMBINEREPLACE); +// RwRGBA color = { skyTopRed, skyTopGreen, skyTopBlue, 255 }; + + RwRGBA color = { skyBotRed, skyBotGreen, skyBotBlue, 255 }; + // blend a bit of white into the sky color, otherwise it tends to be very blue + color.red = color.red*0.6f + 255*0.4f; + color.green = color.green*0.6f + 255*0.4f; + color.blue = color.blue*0.6f + 255*0.4f; + RwCameraClear(reflectionCam, &color, rwCAMERACLEARIMAGE | rwCAMERACLEARZ); + + RwCameraBeginUpdate(reflectionCam); + RwCamera *savedcam = Scene.camera; + Scene.camera = reflectionCam; // they do some begin/end updates with this in the called functions :/ + RenderReflectionScene(); + Scene.camera = savedcam; + RwCameraEndUpdate(reflectionCam); + + RwCameraBeginUpdate(cam); +} + void CCustomCarEnvMapPipeline__CustomPipeRenderCB_Switch(RwResEntry *repEntry, void *object, RwUInt8 type, RwUInt32 flags) { @@ -880,6 +1098,9 @@ CCustomCarEnvMapPipeline__CustomPipeRenderCB_Switch(RwResEntry *repEntry, void * if(iCanHasNeoCar) CarPipe::RenderCallback(repEntry, object, type, flags); break; + case 5: + CCustomCarEnvMapPipeline__CustomPipeRenderCB_leeds(repEntry, object, type, flags); + break; } fixSAMP(); }