Skip to content

Commit

Permalink
Gloom: Improved transparent surface shader
Browse files Browse the repository at this point in the history
  • Loading branch information
skyjake committed Sep 1, 2019
1 parent 9535514 commit 177db34
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 45 deletions.
4 changes: 2 additions & 2 deletions doomsday/tests/test_gloom/net.dengine.gloom.pack/images.dei
Expand Up @@ -13,9 +13,9 @@ group world {
}
image test2.diffuse { path = "images/mat-test2.png" }
group water {
image diffuse { path = "images/softnoise.png/Color.solid:32,32,32" }
image diffuse { path = "images/softnoise.png/Color.solid:0,210,0,32" }
image normaldisp { path = "images/softnoise.png/HeightMap.toNormals" }
image specgloss { path = "images/softnoise.png/Color.solid:255,255,255,255"}
image specgloss { path = "images/softnoise.png/Color.solid:128,128,128,128"}
}
}

Expand Down
Expand Up @@ -3,6 +3,7 @@

#include "defs.glsl"
#include "miplevel.glsl"
#include "time.glsl"

uniform sampler2D uTextureAtlas[4];
uniform samplerBuffer uTextureMetrics;
Expand Down Expand Up @@ -48,17 +49,19 @@ struct MaterialSampler {
uint matIndex;
int texture;
Metrics metrics;
int animation;
};

MaterialSampler Gloom_Sampler(uint matIndex, int texture) {
return MaterialSampler(
matIndex,
texture,
Gloom_TextureMetrics(matIndex, texture)
Gloom_TextureMetrics(matIndex, texture),
0
);
}

vec4 Gloom_SampleMaterial(const MaterialSampler sampler, vec2 uv) {
vec4 Gloom_MaterialTexel(const MaterialSampler sampler, vec2 uv) {
vec2 normUV = uv * sampler.metrics.scale;
vec2 atlasUV = sampler.metrics.uvRect.xy + fract(normUV) * sampler.metrics.uvRect.zw;
float mip = mipLevel(normUV, sampler.metrics.sizeInTexels.xy) - 0.5;
Expand All @@ -76,6 +79,21 @@ vec4 Gloom_SampleMaterial(const MaterialSampler sampler, vec2 uv) {
return vec4(0.0);
}

vec4 Gloom_SampleMaterial(const MaterialSampler sampler, vec2 uv) {
if (sampler.animation == 0) {
return Gloom_MaterialTexel(sampler, uv);
}
else if (sampler.animation == 1) {
// Water offsets.
vec2 waterOff1 = vec2( 0.182, -0.3195) * uCurrentTime;
vec2 waterOff2 = vec2(-0.203, 0.01423) * uCurrentTime;
vec4 texel1 = Gloom_MaterialTexel(sampler, uv + waterOff1);
vec4 texel2 = Gloom_MaterialTexel(sampler, uv + waterOff2);
return (texel1 + texel2) * 0.5;
}
return vec4(0.0);
}

vec4 Gloom_TryFetchTexture(uint matIndex, int texture, vec2 uv, vec4 fallback) {
MaterialSampler ms = Gloom_Sampler(matIndex, texture);
if (!ms.metrics.isValid) {
Expand All @@ -89,9 +107,8 @@ vec4 Gloom_FetchTexture(uint matIndex, int texture, vec2 uv) {
Material_DefaultTextureValue[texture]);
}

vec2 Gloom_Parallax(uint matIndex, vec2 texCoords, vec3 tsViewDir,
out float displacementDepth) {
MaterialSampler matSamp = Gloom_Sampler(matIndex, Texture_NormalDisplacement);
vec2 Gloom_SamplerParallax(MaterialSampler matSamp, vec2 texCoords, vec3 tsViewDir,
out float displacementDepth) {
if (!matSamp.metrics.isValid) {
// Parallax does not have effect.
displacementDepth = 0.0;
Expand Down Expand Up @@ -142,7 +159,14 @@ vec2 Gloom_Parallax(uint matIndex, vec2 texCoords, vec3 tsViewDir,

displacementDepth = mix(d1, d2, weight) * heightScale;

return mix(curTexCoords, prevTexCoords, weight);
return mix(curTexCoords, prevTexCoords, weight);
}

vec2 Gloom_Parallax(uint matIndex, vec2 texCoords, vec3 tsViewDir,
out float displacementDepth) {
return Gloom_SamplerParallax(
Gloom_Sampler(matIndex, Texture_NormalDisplacement),
texCoords, tsViewDir, displacementDepth);
}

#endif // GLOOM_MATERIAL_H
Expand Up @@ -3,10 +3,10 @@

#include "defs.glsl"
#include "tangentspace.glsl"
#include "time.glsl"

uniform samplerBuffer uPlanes;
uniform samplerBuffer uTexOffsets;
uniform float uCurrentTime;
uniform vec4 uCameraPos; // world space

in vec4 aVertex;
Expand Down
@@ -0,0 +1,6 @@
#ifndef GLOOM_TIME_H
#define GLOOM_TIME_H

uniform float uCurrentTime;

#endif // GLOOM_TIME_H
Expand Up @@ -6,9 +6,9 @@
#include "common/ambient.glsl"
#include "common/dir_lights.glsl"
#include "common/omni_lights.glsl"
#include "common/time.glsl"

uniform mat4 uProjMatrix;
uniform float uCurrentTime;
uniform sampler2D uRefractedFrame;
uniform mat3 uWorldToViewRotate;

Expand All @@ -31,46 +31,27 @@ void main(void) {
normalize(vWSBitangent),
normalize(vWSNormal));

// Water offsets.
vec2 waterOff[2] = vec2[2](
vec2( 0.182, -0.3195) * uCurrentTime,
vec2(-0.203, 0.01423) * uCurrentTime
);
// Depth at fragment.
vec3 backPos;

MaterialSampler matSamp = Gloom_Sampler(matIndex, Texture_NormalDisplacement);
matSamp.animation = 1;

// Parallax mapping.
// TODO: Better to sample from two textures at the lower level, not here...
float displacementDepths[2];
float displacementDepth;
vec3 viewDir = normalize(vTSViewDir);
vec2 texCoord = Gloom_Parallax(matIndex, vUV + waterOff[0], viewDir, displacementDepths[0]);
vec2 texCoord2 = Gloom_Parallax(matIndex, vUV + waterOff[1], viewDir, displacementDepths[1]);

vec3 normal = GBuffer_UnpackNormal(
Gloom_FetchTexture(matIndex, Texture_NormalDisplacement, texCoord));
vec3 normal2 = GBuffer_UnpackNormal(
Gloom_FetchTexture(matIndex, Texture_NormalDisplacement, texCoord2));

float displacementDepth = (displacementDepths[0] + displacementDepths[1]) / 2.0;
vec2 texCoord = Gloom_SamplerParallax(matSamp, vUV, viewDir, displacementDepth);
vec3 normal = normalize(GBuffer_UnpackNormal(Gloom_SampleMaterial(matSamp, texCoord)));

normal = normalize(normal + normal2);
vec3 vsNormal = uWorldToViewRotate * (Gloom_TangentMatrix(ts) * normal);
mat3 tsToViewRotate = uWorldToViewRotate * Gloom_TangentMatrix(ts);
vec3 vsNormal = tsToViewRotate * normal;

vec4 diffuse = Gloom_FetchTexture(matIndex, Texture_Diffuse, texCoord);
float density = diffuse.a;
vec3 emissive = Gloom_FetchTexture(matIndex, Texture_Emissive, texCoord).rgb;
vec4 specGloss = Gloom_FetchTexture(matIndex, Texture_SpecularGloss, texCoord);

// Refraction.
float reflectRatio;
vec3 refracted = refract(viewDir, normal, 1.1);
if (refracted != vec3(0.0)) {
// TODO: Offset must be determined from viewDir.
vec2 fragPos = (gl_FragCoord.xy + refracted.xy * uViewportSize.y * 0.05) / uViewportSize;
reflectRatio = max(0.0, dot(refracted, viewDir));
out_FragColor = (1.0 - reflectRatio) * texture(uRefractedFrame, fragPos);
}
else {
out_FragColor = vec4(vec3(0.0), 1.0);
reflectRatio = 1.0;
}

vec3 vsViewDir = -normalize(vVSPos.xyz);

vec3 vsPos = vVSPos.xyz / vVSPos.w;

// Write a displaced depth. // TODO: Add a routine for doing this.
Expand All @@ -83,10 +64,36 @@ void main(void) {
else {
gl_FragDepth = gl_FragCoord.z;
}

// Refraction. This is calculated in view space so the offset will be view-dependent.
vec4 refractedColor;
float reflectRatio;
vec3 refracted = refract(vsViewDir, vsNormal, 1.05);
if (refracted != vec3(0.0)) {
vec2 fragPos = (gl_FragCoord.xy + refracted.xy * uViewportSize.y * 0.05) / uViewportSize;
reflectRatio = max(0.0, dot(refracted, vsViewDir));
refractedColor = texture(uRefractedFrame, fragPos) * (1.0 - reflectRatio);
backPos = GBuffer_ViewSpacePos(fragPos).xyz;

// How far does light travel through the volume?
float volumetric = distance(backPos, vsPos);

if (density > 0.0) {
refractedColor = mix(refractedColor, diffuse,
min(volumetric * density + pow(density, 2.0), 1.0));
}
}
else {
refractedColor = vec4(0.0);
reflectRatio = 1.0;
}

// Now we can apply lighting to the surface.
SurfacePoint sp = SurfacePoint(vsPos, vsNormal, diffuse.rgb, specGloss);
SurfacePoint sp = SurfacePoint(vsPos, vsNormal, diffuse.rgb * diffuse.a, specGloss);

out_FragColor.rgb += Gloom_DirectionalLighting(sp) + Gloom_OmniLighting(sp) +
out_FragColor = vec4(emissive, 0.0) + refractedColor;
out_FragColor.rgb +=
Gloom_DirectionalLighting(sp) +
Gloom_OmniLighting(sp) +
reflectRatio * Gloom_CubeReflection(uEnvMap, sp);
}

0 comments on commit 177db34

Please sign in to comment.