Last active
October 27, 2022 17:10
-
-
Save dzil123/27b1a7a3fa6ab1f38b1b8bfd4b412b11 to your computer and use it in GitHub Desktop.
Planet ocean effect depth fix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/shader.glsl b/shader.glsl | |
index ec7854a..3825944 100644 | |
--- a/shader.glsl | |
+++ b/shader.glsl | |
@@ -140,31 +140,34 @@ void fragment() { | |
depth = exp(-depth);*/ | |
// Normalized Device Coordinates needs to be -1 to 1 in Godot | |
- vec3 ndc = vec3(SCREEN_UV, depth) * 2.0 - 1.0; | |
+ vec3 ndc = vec3(SCREEN_UV * 2.0 - 1.0, depth); | |
// Convert between NDC and view space to get distance to camera | |
vec4 view = INV_PROJECTION_MATRIX * vec4(ndc, 1.0); | |
view.xyz /= view.w; | |
- float linear_depth = view.z; | |
+ float linear_depth = -view.z; | |
float scaled_depth = (ZFar * ZNear) / (ZFar + (linear_depth * (ZNear - ZFar))); | |
// Distance from fragment point to camera? | |
float viewLength = length(viewVector); | |
- | |
+ linear_depth *= viewLength; | |
vec3 rayPos = CAMERA_POSITION_WORLD; | |
vec3 rayDir = viewVector / viewLength; | |
//vec2 hit = raySphere(rayPos, rayDir, OceanCentre, OceanRadius); | |
vec2 hit = raySphere(rayPos, rayDir, OceanRadius); | |
float dstToOcean = hit.x; | |
- float dstThroughOcean = dstToOcean + OceanRadius/2.0; | |
+ float dstThroughOcean = hit.y - hit.x; | |
+ if (hit.y <= 0.0) { | |
+ dstThroughOcean = -1.0; | |
+ } | |
//float dstToOcean = sphereIntersect(rayPos, rayDir, OceanCentre, OceanRadius); | |
vec3 rayOceanIntersectPos = rayPos + rayDir * dstToOcean - OceanCentre; | |
// dst that view ray travels through ocean (before hitting terrain / exiting ocean) | |
//float oceanViewDepth = sceneDepth + dstToOcean; | |
- float oceanViewDepth = min(dstThroughOcean, scaled_depth + dstToOcean); | |
+ float oceanViewDepth = min(dstThroughOcean, linear_depth - dstToOcean); | |
vec4 finalCol = originalCol; | |
float alpha = 1.0; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
shader_type spatial; | |
render_mode unshaded, depth_draw_never, depth_prepass_alpha; | |
uniform float ZNear = 0.05; | |
uniform float ZFar = 4000.0; | |
uniform vec4 ColA : source_color; | |
uniform vec4 ColB : source_color; | |
uniform vec4 SpecularCol : source_color; | |
uniform float DepthMultiplier = 0.5; | |
uniform float AlphaMultiplier = 3; | |
uniform float Smoothness = 0.92; | |
uniform sampler2D WaveNormalA; | |
uniform sampler2D WaveNormalB; | |
uniform float WaveStrength = 0.15; | |
uniform float WaveNormalScale = 15.0; | |
uniform float WaveSpeed = 0.5; | |
uniform float PlanetScale = 200.0; | |
uniform vec3 OceanCentre = vec3(0.0); | |
uniform float OceanRadius = 190.0; | |
uniform vec3 DirToSun = vec3(0.0, 1.0, 0.0); | |
varying vec2 uv; | |
varying vec3 viewVector; | |
vec2 raySphere(vec3 o, vec3 d, float r) { | |
float a = dot(d,d); | |
float b = 2.0 * dot(o,d); | |
float c = dot(o,o) - r * r; | |
float q = b * b - 4.0 * a * c; | |
if (q < 0.0){ | |
return vec2(-1.0, -1.0); | |
} | |
float sq = sqrt(q); | |
float t1 = (-b - sq) / (2.0*a); | |
float t2 = (-b + sq) / (2.0*a); | |
if (t1 > t2){ | |
float a = t2; | |
t2 = t1; | |
t1 = a; | |
} | |
return vec2(t1,t2); | |
} | |
float saturate(float value) { | |
return min(max(value, 0.0), 1.0); | |
} | |
vec3 saturate3(vec3 value) { | |
return min(max(value, 0.0), 1.0); | |
} | |
vec3 unpackNormal(vec4 packednormal) | |
{ | |
vec3 normal; | |
normal.xy = packednormal.wy * 2.0 - 1.0; | |
normal.z = sqrt(1.0 - normal.x * normal.x - normal.y * normal.y); | |
return normal; | |
} | |
// Reoriented Normal Mapping | |
// http://blog.selfshadow.com/publications/blending-in-detail/ | |
// Altered to take normals (-1 to 1 ranges) rather than unsigned normal maps (0 to 1 ranges) | |
vec3 blend_rnm(vec3 n1, vec3 n2) | |
{ | |
n1.z += 1.0; | |
n2.xy = -n2.xy; | |
return n1 * dot(n1, n2) / n1.z - n2; | |
} | |
// Sample normal map with triplanar coordinates | |
// Returned normal will be in obj/world space (depending whether pos/normal are given in obj or world space) | |
// Based on: medium.com/@bgolus/normal-mapping-for-a-triplanar-shader-10bf39dca05a | |
vec3 triplanarNormal(vec3 vertPos, vec3 normal, float scale, vec2 offset, sampler2D normalMap) { | |
vec3 absNormal = abs(normal); | |
// Calculate triplanar blend | |
vec3 blendWeight = saturate3(pow(normal, 4.0 * vec3(1.0, 1.0, 1.0))); | |
// Divide blend weight by the sum of its components. This will make x + y + z = 1 | |
blendWeight /= dot(blendWeight, vec3(1.0, 1.0, 1.0)); | |
// Calculate triplanar coordinates | |
vec2 uvX = vertPos.zy * scale + offset; | |
vec2 uvY = vertPos.xz * scale + offset; | |
vec2 uvZ = vertPos.xy * scale + offset; | |
// Sample tangent space normal maps | |
// unpackNormal puts values in range [-1, 1] (and accounts for DXT5nm compression) | |
vec3 tangentNormalX = unpackNormal(texture(normalMap, uvX)); | |
vec3 tangentNormalY = unpackNormal(texture(normalMap, uvY)); | |
vec3 tangentNormalZ = unpackNormal(texture(normalMap, uvZ)); | |
// Swizzle normals to match tangent space and apply reoriented normal mapping blend | |
tangentNormalX = blend_rnm(vec3(normal.zy, absNormal.x), tangentNormalX); | |
tangentNormalY = blend_rnm(vec3(normal.xz, absNormal.y), tangentNormalY); | |
tangentNormalZ = blend_rnm(vec3(normal.xy, absNormal.z), tangentNormalZ); | |
// Apply input normal sign to tangent space Z | |
vec3 axisSign = sign(normal); | |
tangentNormalX.z *= axisSign.x; | |
tangentNormalY.z *= axisSign.y; | |
tangentNormalZ.z *= axisSign.z; | |
// Swizzle tangent normals to match input normal and blend together | |
vec3 outputNormal = normalize( | |
tangentNormalX.zyx * blendWeight.x + | |
tangentNormalY.xzy * blendWeight.y + | |
tangentNormalZ.xyz * blendWeight.z | |
); | |
return outputNormal; | |
} | |
const vec2 vertices[3] = {vec2(-1,-1), vec2(3,-1), vec2(-1, 3)}; | |
void vertex() { | |
// Generate triangle in clip space | |
POSITION = vec4(vertices[VERTEX_ID],0.0,1.0); | |
uv = 0.5 * POSITION.xy + vec2(0.5, 0.5); | |
UV = uv; | |
// View vector in world space | |
viewVector = (INV_PROJECTION_MATRIX * vec4(uv * 2.0 - 1.0, 0.0, 1.0)).xyz; | |
viewVector = (INV_VIEW_MATRIX * vec4(viewVector, 0.0)).xyz; | |
} | |
void fragment() { | |
vec4 originalCol = texture(SCREEN_TEXTURE, SCREEN_UV); | |
// Get depth value from DEPTH_TEXTURE | |
float depth = texture(DEPTH_TEXTURE, SCREEN_UV).r; | |
/*depth = depth * 2.0 - 1.0; | |
depth = PROJECTION_MATRIX[3][2] / (depth + PROJECTION_MATRIX[2][2]); | |
depth = depth + VERTEX.z; | |
depth = exp(-depth);*/ | |
// Normalized Device Coordinates needs to be -1 to 1 in Godot | |
vec3 ndc = vec3(SCREEN_UV * 2.0 - 1.0, depth); | |
// Convert between NDC and view space to get distance to camera | |
vec4 view = INV_PROJECTION_MATRIX * vec4(ndc, 1.0); | |
view.xyz /= view.w; | |
float linear_depth = -view.z; | |
float scaled_depth = (ZFar * ZNear) / (ZFar + (linear_depth * (ZNear - ZFar))); | |
// Distance from fragment point to camera? | |
float viewLength = length(viewVector); | |
linear_depth *= viewLength; | |
vec3 rayPos = CAMERA_POSITION_WORLD; | |
vec3 rayDir = viewVector / viewLength; | |
//vec2 hit = raySphere(rayPos, rayDir, OceanCentre, OceanRadius); | |
vec2 hit = raySphere(rayPos, rayDir, OceanRadius); | |
float dstToOcean = hit.x; | |
float dstThroughOcean = hit.y - hit.x; | |
if (hit.y <= 0.0) { | |
dstThroughOcean = -1.0; | |
} | |
//float dstToOcean = sphereIntersect(rayPos, rayDir, OceanCentre, OceanRadius); | |
vec3 rayOceanIntersectPos = rayPos + rayDir * dstToOcean - OceanCentre; | |
// dst that view ray travels through ocean (before hitting terrain / exiting ocean) | |
//float oceanViewDepth = sceneDepth + dstToOcean; | |
float oceanViewDepth = min(dstThroughOcean, linear_depth - dstToOcean); | |
vec4 finalCol = originalCol; | |
float alpha = 1.0; | |
if (oceanViewDepth > 0.0) { | |
vec3 clipPlanePos = rayPos + viewVector * ZNear; | |
float dstAboveWater = length(clipPlanePos - OceanCentre) - OceanRadius; | |
float t = 1.0 - exp(-oceanViewDepth / PlanetScale * DepthMultiplier); | |
alpha = 1.0 - exp(-oceanViewDepth / PlanetScale * AlphaMultiplier); | |
vec4 oceanCol = mix(ColA, ColB, t); | |
vec3 oceanSphereNormal = normalize(rayOceanIntersectPos); | |
finalCol = oceanCol; | |
} | |
//ALBEDO = vec3(normalize(hit), 0.0); | |
//ALBEDO = normalize(rayOceanIntersectPos) * 0.5 + 0.5; | |
//ALBEDO = vec3(dstThroughOcean, dstToOcean, 0.0); | |
ALBEDO = finalCol.rgb; | |
ALPHA = alpha; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment