forked from teamnwah/openmw-tes3coop
temp commit
This commit is contained in:
parent
739455e6f8
commit
9d7470e14c
4 changed files with 159 additions and 15 deletions
2
extern/shiny
vendored
2
extern/shiny
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit bf003238a27d94be43724e6774d25c38b4d578c8
|
Subproject commit 4853ea7351edced75a48662da5f3e857961e0b47
|
|
@ -42,7 +42,7 @@
|
||||||
|
|
||||||
#if HAS_VERTEXCOLOR
|
#if HAS_VERTEXCOLOR
|
||||||
shColourInput(float4)
|
shColourInput(float4)
|
||||||
shOutput(float4, colorPassthrough)
|
shOutput(float4, colourPassthrough)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SHADOWS
|
#if SHADOWS
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_VERTEXCOLOR
|
#if HAS_VERTEXCOLOR
|
||||||
colorPassthrough = colour;
|
colourPassthrough = colour;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SHADOWS
|
#if SHADOWS
|
||||||
|
@ -128,12 +128,12 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FOG
|
#if FOG
|
||||||
shUniform(float3, fogColor) @shAutoConstant(fogColor, fog_colour)
|
shUniform(float3, fogColour) @shAutoConstant(fogColour, fog_colour)
|
||||||
shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params)
|
shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAS_VERTEXCOLOR
|
#ifdef HAS_VERTEXCOLOR
|
||||||
shInput(float4, colorPassthrough)
|
shInput(float4, colourPassthrough)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SHADOWS
|
#if SHADOWS
|
||||||
|
@ -201,11 +201,13 @@
|
||||||
|
|
||||||
float3 caustics = float3(1,1,1);
|
float3 caustics = float3(1,1,1);
|
||||||
#if UNDERWATER
|
#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)
|
if (worldPos.y < waterLevel)
|
||||||
{
|
{
|
||||||
float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0));
|
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
|
#endif
|
||||||
|
|
||||||
|
@ -235,7 +237,7 @@
|
||||||
@shEndForeach
|
@shEndForeach
|
||||||
|
|
||||||
#if HAS_VERTEXCOLOR
|
#if HAS_VERTEXCOLOR
|
||||||
ambient *= colorPassthrough.xyz;
|
ambient *= colourPassthrough.xyz;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
shOutputColour(0).xyz *= (ambient + diffuse + materialEmissive.xyz);
|
shOutputColour(0).xyz *= (ambient + diffuse + materialEmissive.xyz);
|
||||||
|
@ -243,16 +245,40 @@
|
||||||
|
|
||||||
|
|
||||||
#if HAS_VERTEXCOLOR && !LIGHTING
|
#if HAS_VERTEXCOLOR && !LIGHTING
|
||||||
shOutputColour(0).xyz *= colorPassthrough.xyz;
|
shOutputColour(0).xyz *= colourPassthrough.xyz;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FOG
|
#if FOG
|
||||||
float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w);
|
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
|
#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));
|
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
|
#if MRT
|
||||||
shOutputColour(1) = float4(depthPassthrough / far,1,1,1);
|
shOutputColour(1) = float4(depthPassthrough / far,1,1,1);
|
||||||
|
|
|
@ -147,7 +147,7 @@
|
||||||
@shEndForeach
|
@shEndForeach
|
||||||
|
|
||||||
#if FOG
|
#if FOG
|
||||||
shUniform(float3, fogColor) @shAutoConstant(fogColor, fog_colour)
|
shUniform(float3, fogColour) @shAutoConstant(fogColour, fog_colour)
|
||||||
shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params)
|
shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -221,11 +221,13 @@
|
||||||
float3 caustics = float3(1,1,1);
|
float3 caustics = float3(1,1,1);
|
||||||
#if UNDERWATER
|
#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)
|
if (worldPos.y < waterLevel)
|
||||||
{
|
{
|
||||||
float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0));
|
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
|
#endif
|
||||||
|
@ -329,7 +331,7 @@
|
||||||
|
|
||||||
#if FOG
|
#if FOG
|
||||||
float fogValue = shSaturate((depth - fogParams.y) * fogParams.w);
|
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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
116
files/materials/underwater.h
Normal file
116
files/materials/underwater.h
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue