From 9d7470e14cb2e57c6300ce9e633ed7db635e0b7c Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 19 Jul 2012 20:18:34 +0200 Subject: [PATCH] temp commit --- extern/shiny | 2 +- files/materials/objects.shader | 46 ++++++++++--- files/materials/terrain.shader | 10 +-- files/materials/underwater.h | 116 +++++++++++++++++++++++++++++++++ 4 files changed, 159 insertions(+), 15 deletions(-) create mode 100644 files/materials/underwater.h diff --git a/extern/shiny b/extern/shiny index bf003238a..4853ea735 160000 --- a/extern/shiny +++ b/extern/shiny @@ -1 +1 @@ -Subproject commit bf003238a27d94be43724e6774d25c38b4d578c8 +Subproject commit 4853ea7351edced75a48662da5f3e857961e0b47 diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 0c1867d66..fdf2b3676 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -42,7 +42,7 @@ #if HAS_VERTEXCOLOR shColourInput(float4) - shOutput(float4, colorPassthrough) + shOutput(float4, colourPassthrough) #endif #if SHADOWS @@ -75,7 +75,7 @@ #endif #if HAS_VERTEXCOLOR - colorPassthrough = colour; + colourPassthrough = colour; #endif #if SHADOWS @@ -128,12 +128,12 @@ #endif #if FOG - shUniform(float3, fogColor) @shAutoConstant(fogColor, fog_colour) + shUniform(float3, fogColour) @shAutoConstant(fogColour, fog_colour) shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params) #endif #ifdef HAS_VERTEXCOLOR - shInput(float4, colorPassthrough) + shInput(float4, colourPassthrough) #endif #if SHADOWS @@ -201,11 +201,13 @@ float3 caustics = float3(1,1,1); #if UNDERWATER - float4 worldPos = shMatrixMult(worldMatrix, float4(objSpacePositionPassthrough,1)); + float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePositionPassthrough,1)).xyz; + float3 waterEyePos = float3(1,1,1); if (worldPos.y < waterLevel) { float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0)); - caustics = getCaustics(causticMap, worldPos.xyz, cameraPos.xyz, worldNormal.xyz, lightDirectionWS0.xyz, waterLevel, waterTimer, windDir_windSpeed); + waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,1,0), waterLevel); + caustics = getCaustics(causticMap, worldPos, waterEyePos.xyz, worldNormal.xyz, lightDirectionWS0.xyz, waterLevel, waterTimer, windDir_windSpeed); } #endif @@ -235,7 +237,7 @@ @shEndForeach #if HAS_VERTEXCOLOR - ambient *= colorPassthrough.xyz; + ambient *= colourPassthrough.xyz; #endif shOutputColour(0).xyz *= (ambient + diffuse + materialEmissive.xyz); @@ -243,16 +245,40 @@ #if HAS_VERTEXCOLOR && !LIGHTING - shOutputColour(0).xyz *= colorPassthrough.xyz; + shOutputColour(0).xyz *= colourPassthrough.xyz; #endif #if FOG float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w); - shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue); + + #if UNDERWATER + // regular fog only if fragment is above water + if (worldPos.y > waterLevel) + #endif + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); #endif - // prevent negative color output (for example with negative lights) + // prevent negative colour output (for example with negative lights) shOutputColour(0).xyz = max(shOutputColour(0).xyz, float3(0,0,0)); + +#if UNDERWATER + float fogAmount = (worldPos.y > waterLevel) + ? shSaturate(length(waterEyePos-worldPos) / VISIBILITY) + : shSaturate(length(cameraPos.xyz-worldPos)/ VISIBILITY); + + float3 eyeVec = normalize(cameraPos.xyz-worldPos); + float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz)); + waterSunGradient = clamp(pow(waterSunGradient*0.7+0.3,2.0),0.0,1.0); + + float waterGradient = dot(eyeVec, vec3(0.0,-1.0,0.0)); + waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); + + float3 waterSunColour = vec3(0.0,1.0,0.85)*waterSunGradient; + waterSunColour = (cameraPos.z < waterLevel) ? waterSunColour*0.5:waterSunColour*0.25;//below or above water? + + float3 waterColour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; + shOutputColour(0).xyz = waterColour; +#endif #if MRT shOutputColour(1) = float4(depthPassthrough / far,1,1,1); diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index 722108a58..77ba01494 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -147,7 +147,7 @@ @shEndForeach #if FOG - shUniform(float3, fogColor) @shAutoConstant(fogColor, fog_colour) + shUniform(float3, fogColour) @shAutoConstant(fogColour, fog_colour) shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params) #endif @@ -221,11 +221,13 @@ float3 caustics = float3(1,1,1); #if UNDERWATER - float4 worldPos = shMatrixMult(worldMatrix, float4(objSpacePosition,1)); + float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePosition,1)).xyz; + float3 waterEyePos = float3(1,1,1); if (worldPos.y < waterLevel) { float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0)); - caustics = getCaustics(causticMap, worldPos.xyz, cameraPos.xyz, worldNormal.xyz, lightDirectionWS0.xyz, waterLevel, waterTimer, windDir_windSpeed); + waterEyePos = intercept(worldPos, eyePosWS - worldPos, float3(0,1,0), waterLevel); + caustics = getCaustics(causticMap, worldPos, waterEyePos.xyz, worldNormal.xyz, lightDirectionWS0.xyz, waterLevel, waterTimer, windDir_windSpeed); } #endif @@ -329,7 +331,7 @@ #if FOG float fogValue = shSaturate((depth - fogParams.y) * fogParams.w); - shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue); + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); #endif diff --git a/files/materials/underwater.h b/files/materials/underwater.h new file mode 100644 index 000000000..fa744ac39 --- /dev/null +++ b/files/materials/underwater.h @@ -0,0 +1,116 @@ +#define VISIBILITY 1500.0 // how far you can look through water + +#define BIG_WAVES_X 0.3 // strength of big waves +#define BIG_WAVES_Y 0.3 + +#define MID_WAVES_X 0.3 // strength of middle sized waves +#define MID_WAVES_Y 0.15 + +#define SMALL_WAVES_X 0.15 // strength of small waves +#define SMALL_WAVES_Y 0.1 + +#define WAVE_CHOPPYNESS 0.15 // wave choppyness +#define WAVE_SCALE 0.01 // overall wave scale + +#define ABBERATION 0.001 // chromatic abberation amount + +float3 intercept(float3 lineP, + float3 lineN, + float3 planeN, + float planeD) +{ + + float distance = (planeD - dot(planeN, lineP)) / dot(lineN, planeN); + return lineP + lineN * distance; +} + +float3 perturb1(shTexture2D tex, float2 coords, float bend, float2 windDir, float windSpeed, float timer) +{ + float2 nCoord = float2(0.0); + bend *= WAVE_CHOPPYNESS; + nCoord = coords * (WAVE_SCALE * 0.05) + windDir * timer * (windSpeed*0.04); + float3 normal0 = 2.0 * shSample(tex, nCoord + float2(-timer*0.015,-timer*0.05)).rgb - 1.0; + nCoord = coords * (WAVE_SCALE * 0.1) + windDir * timer * (windSpeed*0.08)-normal0.xy*bend; + float3 normal1 = 2.0 * shSample(tex, nCoord + float2(+timer*0.020,+timer*0.015)).rgb - 1.0; + + nCoord = coords * (WAVE_SCALE * 0.25) + windDir * timer * (windSpeed*0.07)-normal1.xy*bend; + float3 normal2 = 2.0 * shSample(tex, nCoord + float2(-timer*0.04,-timer*0.03)).rgb - 1.0; + nCoord = coords * (WAVE_SCALE * 0.5) + windDir * timer * (windSpeed*0.09)-normal2.xy*bend; + float3 normal3 = 2.0 * shSample(tex, nCoord + float2(+timer*0.03,+timer*0.04)).rgb - 1.0; + + nCoord = coords * (WAVE_SCALE* 1.0) + windDir * timer * (windSpeed*0.4)-normal3.xy*bend; + float3 normal4 = 2.0 * shSample(tex, nCoord + float2(-timer*0.2,+timer*0.1)).rgb - 1.0; + nCoord = coords * (WAVE_SCALE * 2.0) + windDir * timer * (windSpeed*0.7)-normal4.xy*bend; + float3 normal5 = 2.0 * shSample(tex, nCoord + float2(+timer*0.1,-timer*0.06)).rgb - 1.0; + + + float3 normal = normalize(normal0 * BIG_WAVES_X + normal1 * BIG_WAVES_Y + + normal2 * MID_WAVES_X + normal3 * MID_WAVES_Y + + normal4 * SMALL_WAVES_X + normal5 * SMALL_WAVES_Y); + return normal; +} + +float3 perturb(shTexture2D tex, float2 coords, float bend, float2 windDir, float windSpeed, float timer) +{ + bend *= WAVE_CHOPPYNESS; + float3 col = float3(0.0); + float2 nCoord = float2(0.0); //normal coords + + nCoord = coords * (WAVE_SCALE * 0.025) + windDir * timer * (windSpeed*0.03); + col += shSample(tex,nCoord + float2(-timer*0.005,-timer*0.01)).rgb*0.20; + nCoord = coords * (WAVE_SCALE * 0.1) + windDir * timer * (windSpeed*0.05)-(col.xy/col.zz)*bend; + col += shSample(tex,nCoord + float2(+timer*0.01,+timer*0.005)).rgb*0.20; + + nCoord = coords * (WAVE_SCALE * 0.2) + windDir * timer * (windSpeed*0.1)-(col.xy/col.zz)*bend; + col += shSample(tex,nCoord + float2(-timer*0.02,-timer*0.03)).rgb*0.20; + nCoord = coords * (WAVE_SCALE * 0.5) + windDir * timer * (windSpeed*0.2)-(col.xy/col.zz)*bend; + col += shSample(tex,nCoord + float2(+timer*0.03,+timer*0.02)).rgb*0.15; + + nCoord = coords * (WAVE_SCALE* 0.8) + windDir * timer * (windSpeed*1.0)-(col.xy/col.zz)*bend; + col += shSample(tex, nCoord + float2(-timer*0.06,+timer*0.08)).rgb*0.15; + nCoord = coords * (WAVE_SCALE * 1.0) + windDir * timer * (windSpeed*1.3)-(col.xy/col.zz)*bend; + col += shSample(tex,nCoord + float2(+timer*0.08,-timer*0.06)).rgb*0.10; + + return col; +} + + +float3 getCaustics (shTexture2D causticMap, float3 worldPos, float3 waterEyePos, float3 worldNormal, float3 lightDirectionWS0, float waterLevel, float waterTimer, float3 windDir_windSpeed) +{ + float waterDepth = shSaturate((waterEyePos.y - worldPos.y) / 50.0); + + float3 causticPos = intercept(worldPos.xyz, lightDirectionWS0.xyz, float3(0,1,0), waterLevel); + + ///\ todo clean this up + float causticdepth = length(causticPos-worldPos.xyz); + causticdepth = 1.0-shSaturate(causticdepth / VISIBILITY); + causticdepth = shSaturate(causticdepth); + + // NOTE: the original shader calculated a tangent space basis here, + // but using only the world normal is cheaper and i couldn't see a visual difference + // also, if this effect gets moved to screen-space some day, it's unlikely to have tangent information + float3 causticNorm = worldNormal.xyz * perturb(causticMap, causticPos.xz, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).xzy * 2 - 1; + + //float fresnel = pow(clamp(dot(LV,causticnorm),0.0,1.0),2.0); + + float NdotL = max(dot(worldNormal.xyz, lightDirectionWS0.xyz),0.0); + + float causticR = 1.0-perturb(causticMap, causticPos.xz, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).z; + + /// \todo sunFade + + // float3 caustics = clamp(pow(float3(causticR)*5.5,float3(5.5*causticdepth)),0.0,1.0)*NdotL*sunFade*causticdepth; + float3 caustics = clamp(pow(float3(causticR)*5.5,float3(5.5*causticdepth)),0.0,1.0)*NdotL*causticdepth; + float causticG = 1.0-perturb(causticMap,causticPos.xz+(1.0-causticdepth)*ABBERATION, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).z; + float causticB = 1.0-perturb(causticMap,causticPos.xz+(1.0-causticdepth)*ABBERATION*2.0, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).z; + //caustics = shSaturate(pow(float3(causticR,causticG,causticB)*5.5,float3(5.5*causticdepth)))*NdotL*sunFade*causticdepth; + caustics = shSaturate(pow(float3(causticR,causticG,causticB)*5.5,float3(5.5*causticdepth)))*NdotL*causticdepth; + + caustics *= 3; + + // shore transition + caustics = shLerp (float3(1,1,1), caustics, waterDepth); + + return caustics; +} +