From dfb03065b3064ebd1b12fa2c18dcafaa5f28f6a6 Mon Sep 17 00:00:00 2001 From: XProger Date: Sun, 20 Jan 2019 16:43:26 +0300 Subject: [PATCH] #15 optimize water_compose shader --- src/cache.h | 36 +++++++----- src/shaders/common.hlsl | 14 ++++- src/shaders/compile_gxm.bat | 4 +- src/shaders/water.glsl | 6 +- src/shaders/water_caustics.hlsl | 2 +- src/shaders/water_compose.hlsl | 101 +++++++++++++++----------------- 6 files changed, 89 insertions(+), 74 deletions(-) diff --git a/src/cache.h b/src/cache.h index 8b6dc2b..61a2ece 100644 --- a/src/cache.h +++ b/src/cache.h @@ -837,7 +837,11 @@ struct WaterCache { if (screen) { Core::setTarget(refract, NULL, RT_LOAD_DEPTH | RT_STORE_COLOR | RT_STORE_DEPTH); - blitTexture(screen); + bool flip = false; + #if defined(_GAPI_D3D9) || defined(_GAPI_GXM) + flip = true; + #endif + blitTexture(screen, flip); Core::setTarget(screen, NULL, RT_LOAD_COLOR | RT_LOAD_DEPTH | RT_STORE_COLOR); } else { Core::copyTarget(refract, 0, 0, x, y, Core::viewportDef.width, Core::viewportDef.height); // copy framebuffer into refraction texture @@ -947,7 +951,7 @@ struct WaterCache { game->setShader(Core::passWater, Shader::WATER_COMPOSE); Core::updateLights(); - Core::active.shader->setParam(uParam, vec4(float(refract->origWidth) / refract->width, float(refract->origHeight) / refract->height, 0.05f, 0.03f)); + Core::active.shader->setParam(uParam, vec4(float(refract->origWidth) / refract->width, float(refract->origHeight) / refract->height, 0.05f, 0.0f)); float sx = item.size.x * DETAIL / (item.data[0]->width / 2); float sz = item.size.z * DETAIL / (item.data[0]->height / 2); @@ -976,7 +980,7 @@ struct WaterCache { dropCount = 0; } - void blitTexture(Texture *tex) { + void blitTexture(Texture *tex, bool flip = false) { ASSERT(tex); game->setShader(Core::passGUI, Shader::DEFAULT); @@ -1001,17 +1005,21 @@ struct WaterCache { vertices[2].light = vertices[3].light = ubyte4(255, 255, 255, 255); -#if defined(_GAPI_D3D9) || defined(_GAPI_GXM) - vertices[0].texCoord = short4( 0, 0, 0, 0); - vertices[1].texCoord = short4(32767, 0, 0, 0); - vertices[2].texCoord = short4(32767, 32767, 0, 0); - vertices[3].texCoord = short4( 0, 32767, 0, 0); -#else - vertices[0].texCoord = short4( 0, 32767, 0, 0); - vertices[1].texCoord = short4(32767, 32767, 0, 0); - vertices[2].texCoord = short4(32767, 0, 0, 0); - vertices[3].texCoord = short4( 0, 0, 0, 0); -#endif + #if defined(_GAPI_D3D9) || defined(_GAPI_GXM) + flip = !flip; + #endif + + if (flip) { + vertices[0].texCoord = short4( 0, 0, 0, 0); + vertices[1].texCoord = short4(32767, 0, 0, 0); + vertices[2].texCoord = short4(32767, 32767, 0, 0); + vertices[3].texCoord = short4( 0, 32767, 0, 0); + } else { + vertices[0].texCoord = short4( 0, 32767, 0, 0); + vertices[1].texCoord = short4(32767, 32767, 0, 0); + vertices[2].texCoord = short4(32767, 0, 0, 0); + vertices[3].texCoord = short4( 0, 0, 0, 0); + } Core::setDepthTest(false); Core::setBlendMode(bmNone); diff --git a/src/shaders/common.hlsl b/src/shaders/common.hlsl index 990be65..0124f45 100644 --- a/src/shaders/common.hlsl +++ b/src/shaders/common.hlsl @@ -9,6 +9,7 @@ #define WATER_FOG_DIST (1.0 / (6.0 * 1024.0)) #define WATER_COLOR_DIST (1.0 / (2.0 * 1024.0)) #define UNDERWATER_COLOR float3(0.6, 0.9, 0.9) +#define UNDERWATER_COLOR_H half3(0.6, 0.9, 0.9) #define SHADOW_NORMAL_BIAS 16.0 #define SHADOW_CONST_BIAS 0.05 #define SHADOW_SIZE 1024 @@ -103,12 +104,23 @@ float calcCaustics(float3 coord, float3 n) { return tex2Dlod(sReflect, float4(cc.x, 1.0 - cc.y, 0, 0)).x * max(0.0, -n.y); } -half3 calcNormal(float2 tc, half base) { +half3 calcNormalV(float2 tc, half base) { half dx = (half)tex2Dlod(sNormal, float4(tc.x + uTexParam.x, tc.y, 0, 0)).x - base; half dz = (half)tex2Dlod(sNormal, float4(tc.x, tc.y + uTexParam.y, 0, 0)).x - base; return normalize( half3(dx, 64.0 / (1024.0 * 8.0), dz) ); } +float3 calcNormalF(float2 tcR, float2 tcB, float base) { + float dx = tex2D(sNormal, tcR).x - base; + float dz = tex2D(sNormal, tcB).x - base; + return normalize( float3(dx, 64.0 / (1024.0 * 8.0), dz) ); +} + +half calcFresnel(half VoH, half f0) { + half f = pow(1.0 - VoH, 5.0); + return f + f0 * (1.0f - f); +} + void applyFogUW(inout float3 color, float3 coord, float waterFogDist) { float dist; if (uViewPos.y < uParam.y) diff --git a/src/shaders/compile_gxm.bat b/src/shaders/compile_gxm.bat index 28a9436..31a5a5c 100644 --- a/src/shaders/compile_gxm.bat +++ b/src/shaders/compile_gxm.bat @@ -45,8 +45,8 @@ EXIT /B %ERRORLEVEL% echo compile gxm/%~1%~2 %~3 echo #include "%~1%~2_v.h" >> gxm/shaders.h echo #include "%~1%~2_f.h" >> gxm/shaders.h - psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic %~1.hlsl -o gxm/%~1%~2_v.gxp %~3 -DVERTEX - psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic %~1.hlsl -o gxm/%~1%~2_f.gxp %~3 -DPIXEL + psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic %~1.hlsl -cache -o gxm/%~1%~2_v.gxp %~3 -DVERTEX + psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic %~1.hlsl -cache -o gxm/%~1%~2_f.gxp %~3 -DPIXEL ENDLOCAL EXIT /B 0 diff --git a/src/shaders/water.glsl b/src/shaders/water.glsl index 96fefec..a217b0c 100644 --- a/src/shaders/water.glsl +++ b/src/shaders/water.glsl @@ -94,6 +94,11 @@ vec3 calcNormal(vec2 tc, float base) { #endif vViewVec = uViewPos.xyz - vCoord.xyz; vLightVec = uLightPos[0].xyz - vCoord.xyz; + + #ifdef WATER_COMPOSE + vViewVec.y = abs(vViewVec.y); + vLightVec.y = abs(vLightVec.y); + #endif } #else uniform sampler2D sDiffuse; @@ -212,7 +217,6 @@ vec3 calcNormal(vec2 tc, float base) { vec2 value = texture2D(sNormal, vTexCoord).xy; vec3 normal = calcNormal(vTexCoord, value.x); - normal.y *= sign(viewVec.y); vec2 dudv = (uViewProj * vec4(normal.x, 0.0, normal.z, 0.0)).xy; diff --git a/src/shaders/water_caustics.hlsl b/src/shaders/water_caustics.hlsl index be934dd..bd15158 100644 --- a/src/shaders/water_caustics.hlsl +++ b/src/shaders/water_caustics.hlsl @@ -31,7 +31,7 @@ VS_OUTPUT main(VS_INPUT In) { float2 uv = getInvUV(rCoord.xy, uTexParam).xy; float2 info = tex2Dlod(sNormal, float4(uv, 0, 0)).xy; - float3 normal = calcNormal(uv, info.x).xzy; + float3 normal = calcNormalV(uv, info.x).xzy; float3 light = float3(0.0, 0.0, 1.0); float3 refOld = refract(-light, float3(0.0, 0.0, 1.0), 0.75); diff --git a/src/shaders/water_compose.hlsl b/src/shaders/water_compose.hlsl index 7cfee0e..2fb4bfb 100644 --- a/src/shaders/water_compose.hlsl +++ b/src/shaders/water_compose.hlsl @@ -2,86 +2,77 @@ struct VS_OUTPUT { float4 pos : POSITION; - float3 coord : TEXCOORD0; - float2 texCoord : TEXCOORD1; - float2 maskCoord : TEXCOORD2; - float3 viewVec : TEXCOORD3; + half2 texCoord : TEXCOORD1; + half2 maskCoord : TEXCOORD2; + half2 texCoordR : TEXCOORD6; + half2 texCoordB : TEXCOORD7; + float4 viewVec : TEXCOORD3; float3 lightVec : TEXCOORD4; float3 hpos : TEXCOORD5; }; -float2 invUV(float2 uv) { - return float2(uv.x, 1.0 - uv.y); -} - -float2 getInvUV(float2 uv, float4 param) { - float2 p = (float2(uv.x, -uv.y) * 0.5 + 0.5) * param.zw; -#ifndef _GAPI_GXM - p.xy += 0.5 * param.xy; -#endif - return p; -} - -float2 getUV(float2 uv, float4 param) { - return (uv.xy * 0.5 + 0.5) * param.zw; -} - #ifdef VERTEX VS_OUTPUT main(VS_INPUT In) { VS_OUTPUT Out; float3 coord = In.aCoord.xyz * (1.0 / 32767.0); - Out.coord = float3(coord.x, 0.0, coord.y) * uPosScale[1].xyz + uPosScale[0].xyz; - Out.pos = mul(uViewProj, float4(Out.coord, 1.0)); - Out.viewVec = uViewPos.xyz - Out.coord.xyz; - Out.lightVec = uLightPos[0].xyz - Out.coord.xyz; - Out.texCoord = getInvUV(coord.xy, uTexParam); - Out.maskCoord = getUV(coord.xy, uRoomSize); - Out.hpos = Out.pos.xyw; + float4 uv = float4(coord.x, coord.y, coord.x, -coord.y) * 0.5 + 0.5; + Out.maskCoord = uv.xy * uRoomSize.zw; + Out.texCoord = uv.zw * uTexParam.zw; + #ifndef _GAPI_GXM + Out.texCoord += 0.5 * uTexParam.xy; + #endif + coord = float3(coord.x, 0.0, coord.y) * uPosScale[1].xyz + uPosScale[0].xyz; + + Out.pos = mul(uViewProj, float4(coord, 1.0)); + Out.hpos = Out.pos.xyw; + Out.viewVec.xyz = uViewPos.xyz - coord; + Out.viewVec.y = abs(Out.viewVec.y); + Out.lightVec.y = abs(Out.lightVec.y); + Out.lightVec = uLightPos[0].xyz - coord; + + Out.viewVec.w = step(uPosScale[0].y, uViewPos.y) * WATER_COLOR_DIST; + + Out.texCoordR = Out.texCoord + float2(uTexParam.x, 0.0); + Out.texCoordB = Out.texCoord + float2(0.0, uTexParam.y); + return Out; } #else // PIXEL -float calcFresnel(float VoH, float f0) { - float f = pow(1.0 - VoH, 5.0); - return f + f0 * (1.0f - f); -} - -float4 main(VS_OUTPUT In) : COLOR0 { - float3 viewVec = normalize(In.viewVec); +half4 main(VS_OUTPUT In) : COLOR0 { + float3 viewVec = normalize(In.viewVec.xyz); - float2 value = tex2D(sNormal, In.texCoord).xy; - - float3 normal = calcNormal(In.texCoord, value.x); - normal.y *= sign(viewVec.y); - - float2 dudv = mul(uViewProj, float4(normal.x, 0.0, normal.z, 0.0)).xy; - + float base = tex2D(sNormal, In.texCoord).x; + float3 normal = calcNormalF(In.texCoordR, In.texCoordB, base); + + float2 dudv = mul(uViewProj, float4(normal.x, 0.0, normal.z, 0.0)).xy * uParam.z; float3 rv = reflect(-viewVec, normal); float3 lv = normalize(In.lightVec); - float spec = pow(max(0.0, dot(rv, lv)), 64.0) * 0.5; + half specular = pow(max(0.0, dot(rv, lv)), 64.0) * 0.75; float2 tc = In.hpos.xy / In.hpos.z * 0.5 + 0.5; - float4 refrA = tex2D(sDiffuse, uParam.xy * invUV(clamp(tc + dudv * uParam.z, 0.0, 0.999))); - float4 refrB = tex2D(sDiffuse, uParam.xy * invUV(tc)); - float4 refr = float4(lerp(refrA.xyz, refrB.xyz, refrA.w), 1.0); - float4 refl = tex2D(sReflect, tc.xy + dudv * uParam.w); + half4 refrA = tex2D(sDiffuse, tc - dudv); + half4 refrB = tex2D(sDiffuse, tc); + half3 refr = lerp(refrA.xyz, refrB.xyz, refrA.w); + half3 refl = tex2D(sReflect, tc + dudv).xyz; - float fresnel = calcFresnel(max(0.0, dot(normal, viewVec)), 0.12); + half fresnel = calcFresnel(max(0.0, dot(normal, viewVec)), 0.12); + + half4 color = half4(lerp(refr, refl, fresnel), tex2D(sMask, In.maskCoord).a); + color.xyz += specular; + + float dist = (In.viewVec.y / viewVec.y) * In.viewVec.w; + color.xyz *= lerp((half3)1.0, UNDERWATER_COLOR_H, (half)clamp(dist, 0.0, 2.0)); + + half fog = saturate(1.0h / exp(dist)); + color.xyz = lerp(UNDERWATER_COLOR_H * 0.2, color.xyz, fog); - float4 color = lerp(refr, refl, fresnel) + spec * 1.5; - color.w *= tex2D(sMask, In.maskCoord).a; - - float dist = In.viewVec.y / viewVec.y; - dist *= step(In.coord.y, uViewPos.y); - color.xyz *= lerp(float3(1.0, 1.0, 1.0), UNDERWATER_COLOR, clamp(dist * WATER_COLOR_DIST, 0.0, 2.0)); - float fog = saturate(1.0 / exp(dist * WATER_FOG_DIST)); - color.xyz = lerp(UNDERWATER_COLOR * 0.2, color.xyz, fog); return color; }