Skip to content

Commit

Permalink
馃寠 Significantly improve water shader
Browse files Browse the repository at this point in the history
  • Loading branch information
paulcscharf committed Nov 5, 2019
1 parent 6c8f274 commit 8476c61
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 8 deletions.
13 changes: 12 additions & 1 deletion src/Bearded.TD/Rendering/Deferred/FluidGeometry.cs
Expand Up @@ -39,8 +39,19 @@ public FluidGeometry(GameInstance game, Fluid fluid, RenderContext context, Mate
.WithShader(material.Shader.SurfaceShader)
.AndSettings(
context.Surfaces.ViewMatrix,
context.Surfaces.ProjectionMatrix
context.Surfaces.ProjectionMatrix,
context.Surfaces.Time,
context.Surfaces.FarPlaneBaseCorner,
context.Surfaces.FarPlaneUnitX,
context.Surfaces.FarPlaneUnitY,
context.Surfaces.CameraPosition,
context.Surfaces.DepthBuffer
);

foreach (var texture in material.ArrayTextures)
{
surface.AddSetting(new ArrayTextureUniform(texture.UniformName, texture.Texture));
}
}

public void Render()
Expand Down
1 change: 1 addition & 0 deletions src/Bearded.TD/Rendering/FrameCompositor.cs
Expand Up @@ -121,6 +121,7 @@ private void setUniformsFrom(IRenderLayer layer)
private void setUniformsFrom(IDeferredRenderLayer deferredRenderLayer)
{
surfaces.FarPlaneDistance.Float = deferredRenderLayer.FarPlaneDistance;
surfaces.Time.Float = deferredRenderLayer.Time;

setFarPlaneParameters(deferredRenderLayer);
}
Expand Down
8 changes: 6 additions & 2 deletions src/Bearded.TD/Rendering/SurfaceManager.cs
Expand Up @@ -18,6 +18,10 @@ class SurfaceManager
public Vector3Uniform FarPlaneUnitX { get; } = new Vector3Uniform("farPlaneUnitX");
public Vector3Uniform FarPlaneUnitY { get; } = new Vector3Uniform("farPlaneUnitY");
public Vector3Uniform CameraPosition { get; } = new Vector3Uniform("cameraPosition");

public FloatUniform Time { get; } = new FloatUniform("time");

public TextureUniform DepthBuffer { get; set; }

public IndexedSurface<PrimitiveVertexData> Primitives { get; }
public IndexedSurface<PrimitiveVertexData> ConsoleBackground { get; }
Expand Down Expand Up @@ -75,9 +79,9 @@ public SurfaceManager()
public void InjectDeferredBuffer(Texture normalBuffer, Texture depthBuffer)
{
var normalUniform = new TextureUniform("normalBuffer", normalBuffer, TextureUnit.Texture0);
var depthUniform = new TextureUniform("depthBuffer", depthBuffer, TextureUnit.Texture1);
DepthBuffer = new TextureUniform("depthBuffer", depthBuffer, TextureUnit.Texture1);

PointLights.AddSettings(normalUniform, depthUniform);
PointLights.AddSettings(normalUniform, DepthBuffer);
}

private static string asset(string path) => "assets/" + path;
Expand Down
2 changes: 2 additions & 0 deletions src/Bearded.TD/UI/Controls/game/GameWorldControl.cs
Expand Up @@ -38,6 +38,8 @@ public override Matrix4 ProjectionMatrix
}

public float FarPlaneDistance => game.Camera.Distance - lowestZToRender;

public float Time => (float)game.State.Time.NumericValue;
public ContentSurfaceManager DeferredSurfaces => renderer.DeferredSurfaces;

public GameWorldControl(GameInstance game, RenderContext renderContext)
Expand Down
1 change: 1 addition & 0 deletions src/Bearded.TD/UI/Layers/IRenderLayer.cs
Expand Up @@ -14,6 +14,7 @@ interface IRenderLayer
interface IDeferredRenderLayer : IRenderLayer
{
float FarPlaneDistance { get; }
float Time { get; }
ContentSurfaceManager DeferredSurfaces { get; }
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -1,4 +1,12 @@
{
"id" : "water",
"shader" : "water"
"shader" : "water",
"textureArrays" : [
{
"name" : "noiseTexture",
"files" : [
"noise.png"
]
},
]
}
83 changes: 82 additions & 1 deletion src/Bearded.TD/assets/mods/default/gfx/shaders/water.fs
@@ -1,12 +1,93 @@
#version 150

uniform sampler2D depthBuffer;

uniform sampler2DArray noiseTexture;

uniform vec3 cameraPosition;
uniform float time;

in vec2 fragmentUV;
in vec3 fragmentPosition;
in vec3 fragmentNormal;
in vec2 fragmentFlow;
in vec3 pointOnFarPlane;

out vec4 fragColor;

float getCaustics(vec3 geometryPosition, float contrast)
{
vec2 uv = geometryPosition.xy * 0.6;

vec2 offset = vec2(time * 0.05, 0);

vec4 noise = texture(noiseTexture, vec3((uv + offset) * 0.25, 0));
vec4 noise2 = texture(noiseTexture, vec3((uv.yx + offset * 1.5) * 0.235, 0));
vec4 noise3 = texture(noiseTexture, vec3((uv - vec2(offset.x * 1.2, offset.x * 1.2)) * -0.23, 0));

float n1 = max(0, 1 - abs(noise.x - 0.5) * contrast);
float n2 = max(0, 1 - abs(noise2.x - 0.5) * contrast);
float n3 = max(0, 1 - abs(noise3.x - 0.5) * contrast);

float n = n2 * n1 * n3;

return n * n;
}

void main()
{
fragColor = vec4(0.2, 0.2, 0.5, 0.5);
float depth = texture(depthBuffer, fragmentUV).x;

vec3 geometryPositionRelativeToCamera = pointOnFarPlane * depth;
vec3 geometryPosition = geometryPositionRelativeToCamera - cameraPosition;

// caustics
float c = getCaustics(geometryPosition, 6);
vec4 causticHighlight = vec4(c, c, c, 0);

// surface
float surfaceHeight = getCaustics(fragmentPosition, 1)
* 5 / -cameraPosition.z;

float surfaceDx = dFdx(surfaceHeight);
float surfaceDy = dFdy(surfaceHeight);

vec3 surfaceNormal = -vec3(surfaceDx, surfaceDy,
sqrt(1 - surfaceDx * surfaceDx - surfaceDy * surfaceDy)
);

vec3 lightDir = normalize(vec3(1, -1, 3));

float lightSurfaceDot = -dot(lightDir, surfaceNormal);

float diffuseSurfaceLight = lightSurfaceDot;
vec3 surfaceColor = vec3(0.2, 0.25, 0.5) * diffuseSurfaceLight;

// why is this normalize needed?
vec3 reflectedLightDir = normalize(lightDir + 2 * lightSurfaceDot * surfaceNormal);

// why is this needed?
vec3 c2 = vec3(-cameraPosition.xy, cameraPosition.z);

vec3 fragmentToCamera = normalize(c2 - fragmentPosition);

float specularSurfaceLight = dot(reflectedLightDir, fragmentToCamera);

float specularHighlight = max(0, pow(specularSurfaceLight, 10));

// compose
float distanceToGeometry = length(geometryPosition - fragmentPosition);

float transparency = clamp(distanceToGeometry * 0.5, 0.4, 0.8);
float opacity = 1 - transparency;

float causticVisibility = min(1, distanceToGeometry * 2) * 0.5 * opacity;

fragColor =
causticHighlight * causticVisibility
+ vec4(surfaceColor, 1) * transparency
+ vec4(specularHighlight, specularHighlight, specularHighlight, 0) * 0.5;

//float argb = specularHighlight;
//fragColor = vec4(argb, argb, argb, 1);
}
20 changes: 17 additions & 3 deletions src/Bearded.TD/assets/mods/default/gfx/shaders/water.vs
Expand Up @@ -3,19 +3,33 @@
uniform mat4 projection;
uniform mat4 view;

uniform vec3 farPlaneBaseCorner;
uniform vec3 farPlaneUnitX;
uniform vec3 farPlaneUnitY;

in vec3 vertexPosition;
in vec3 vertexNormal;
in vec2 vertexFlow;

out vec2 fragmentUV;
out vec3 fragmentPosition;
out vec3 fragmentNormal;
out vec2 fragmentFlow;
out vec3 pointOnFarPlane;

void main()
{
vec4 viewPosition = view * vec4(vertexPosition, 1.0);
vec4 position = projection * viewPosition;
gl_Position = position;
vec4 p = projection * view * vec4(vertexPosition, 1.0);
gl_Position = p;

fragmentUV = (p.xy / p.w + 1) * 0.5;


// interpolation along the diagonal might be broken?
// probably only for weird geometry
pointOnFarPlane = farPlaneBaseCorner
+ farPlaneUnitX * fragmentUV.x
+ farPlaneUnitY * fragmentUV.y;

fragmentPosition = vertexPosition;
fragmentNormal = vertexNormal;
Expand Down

0 comments on commit 8476c61

Please sign in to comment.