Skip to content

Instantly share code, notes, and snippets.

@jcm2606
Created January 13, 2017 15:50
Show Gist options
  • Save jcm2606/91c7769e2cfcd65f6869de6be50e1b44 to your computer and use it in GitHub Desktop.
Save jcm2606/91c7769e2cfcd65f6869de6be50e1b44 to your computer and use it in GitHub Desktop.
/*
Clarity Shader Pack for Minecraft. Written by jcm2606, credit to Chocapic13, Robobo1221 and the author of "bump-shadow-waving-0.9.9-140906".
Please read "license.txt" at the root of the shader pack before editing this file. Any edits done to this file fall under the terms outlined in "license.txt".
*/
// INITIALISATION
#version 120
#include "/lib/arch/Pipeline.glsl"
#define STAGE COMPOSITE1
#include "/lib/utility/Syntax.glsl"
#include "/lib/segment/Constant.glsl"
#include "/lib/segment/BufferFormat.glsl"
#include "/lib/Global.glsl"
#include "/lib/utility/Materials.glsl"
// SAMPLERS
#define USE_GCOLOUR
#define USE_GNORMAL
#define USE_GDEPTH
#define USE_GCOMPOSITE
#define USE_GAUX1
#define USE_GAUX3
#include "/lib/utility/Samplers.glsl"
const bool gaux3MipmapEnabled = true;
const bool gnormalMipmapEnabled = true;
const bool depthtex1MipmapEnabled = true;
uniform sampler2D depthtex0;
uniform sampler2D depthtex1;
// UNIFORM FIELDS
uniform mat4 gbufferProjectionInverse;
uniform mat4 gbufferProjection;
uniform mat4 gbufferModelViewInverse;
uniform mat4 gbufferModelView;
uniform int isEyeInWater;
uniform float rainStrength;
uniform float wetness;
uniform float sunAngle;
uniform float near;
uniform float far;
uniform float viewWidth;
uniform float viewHeight;
uniform float frameTimeCounter;;
uniform ivec2 eyeBrightnessSmooth;
uniform vec3 cameraPosition;
// VARYING FIELDS
varying vec2 texcoord;
varying vec3 sunVector;
varying vec3 upVector;
varying vec3 lightVector;
// STRUCTS
#include "/lib/struct/StructFragment.glsl"
#include "/lib/struct/StructPosition.glsl"
#include "/lib/struct/StructMaterial.glsl"
Fragment fragment;
Position position;
Material material;
// ARBITRARY FIELDS
RAIN_SCALAR;
vec3 dlSunlight;
vec3 dlMoonlight;
vec3 directLight;
vec3 ambientLight;
vec3 refractionVector;
// FUNCTIONS
#include "/lib/utility/Tonemap.glsl"
#include "/lib/utility/Colour.glsl"
#include "/lib/utility/Worldtime.glsl"
#include "/lib/feature/Waves.glsl"
#include "/lib/feature/Lighting.glsl"
#include "/lib/feature/Sky.glsl"
#include "/lib/utility/LightingFunctions.glsl"
#include "/lib/feature/Reflection.glsl"
#include "/lib/feature/VolumetricLight.glsl"
#include "/lib/utility/Depth.glsl"
#include "/lib/feature/Refraction.glsl"
#include "/lib/utility/BRDF.glsl"
#include "/lib/feature/Fog.glsl"
#include "/lib/feature/Textures.glsl"
const int maxf = 6; //number of refinements
const float stp = 1.0; //size of one step for raytracing algorithm
const float ref = 0.1; //refinement multiplier
const float inc = 2.2; //increasement factor at each step
vec3 nvec3(vec4 pos) {
return pos.xyz/pos.w;
}
vec4 nvec4(vec3 pos) {
return vec4(pos.xyz, 1.0);
}
float cdist(vec2 coord) {
return max(abs(coord.s-0.5),abs(coord.t-0.5))*2.0;
}
vec3 blurColour(in vec2 texcoord, in float roughness) {
const vec2 offsets[16] = vec2[16] (
vec2(1,0),
vec2(-1,0),
vec2(0,1),
vec2(0,-1),
vec2(0.7, 0.7),
vec2(-0.7, 0.7),
vec2(0.7, -0.7),
vec2(-0.7, -0.7),
vec2(0.35, 0.9),
vec2(-0.35, 0.9),
vec2(0.35, -0.9),
vec2(-0.35, -0.9),
vec2(0.9, 0.35),
vec2(-0.9, 0.35),
vec2(0.9, -0.35),
vec2(-0.9, -0.35)
);
vec3 sample = vec3(0.0);
for(int i = 0; i < REFLECTION_ROUGHNESS_BLUR_QUALITY; i++) {
sample += texture2D(GCOLOUR, texcoord + offsets[i] * mix(0.0001, 0.02, roughness)).rgb;
}
return sample / REFLECTION_ROUGHNESS_BLUR_QUALITY;
}
vec3 blurDepth(in vec2 texcoord, in float roughness) {
const vec2 offsets[16] = vec2[16] (
vec2(1,0),
vec2(-1,0),
vec2(0,1),
vec2(0,-1),
vec2(0.7, 0.7),
vec2(-0.7, 0.7),
vec2(0.7, -0.7),
vec2(-0.7, -0.7),
vec2(0.35, 0.9),
vec2(-0.35, 0.9),
vec2(0.35, -0.9),
vec2(-0.35, -0.9),
vec2(0.9, 0.35),
vec2(-0.9, 0.35),
vec2(0.9, -0.35),
vec2(-0.9, -0.35)
);
vec3 sample = vec3(0.0);
for(int i = 0; i < 16; i++) {
sample += texture2D(depthtex0, texcoord + offsets[i] * mix(0.0001, 0.02, roughness)).rgb;
}
return sample / 16;
}
vec4 raytrace(out vec2 bounds, in vec3 fragpos, in vec3 normal, in vec3 fogclr, in vec3 rvector, in float fresnel) {
vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
vec3 start = fragpos;
vec3 vector = stp * rvector;
vec3 tvector = vector;
vec3 pos = vec3(0.0);
vec3 spos = vec3(0.0);
vec2 deVector = vec2(0.0); // depth, error
#define fragDepth deVector.x
#define errorCheck deVector.y
fragpos += vector;
int sr = 0;
for(int i = 0; i < 16; i++) {
pos = nvec3(gbufferProjection * nvec4(fragpos)) * 0.5 + 0.5;
if(pos.x < 0.0 || pos.x > 1 || pos.y < 0 || pos.y > 1 || pos.z < 0 || pos.z > 1.0) break;
fragDepth = texture2D(depthtex0, pos.xy).x;
spos = vec3(pos.xy, fragDepth);
spos = nvec3(gbufferProjectionInverse * nvec4(spos * 2.0 - 1.0));
errorCheck = distance(fragpos.xyz, spos.xyz);
if(errorCheck < pow(sqrt(dot(vector, vector)) * pow(sqrt(dot(vector, vector)), 0.11), 1.1) * 1.1) {
sr++;
if(sr >= maxf) break;
tvector -= vector;
vector *= ref;
}
vector *= inc;
tvector += vector;
fragpos = start + tvector;
}
bounds.x = float(fragDepth < (1.0 - near / far / far)) /* land mask */;
bounds.y = clamp(pow(cdist(pos.xy), 10.0), 0.0, 1.0) /* border */;
color.a *= bounds.x * (1.0 - bounds.y);
if((fragDepth - position.depthSolid) < 0.0075) color.a *= fresnel;
if(bounds.x > 0.5 && (fragDepth - position.depthSolid) < 0.0075) bounds.y = mix(bounds.y, 1.0 - bounds.y, 1.0 - bounds.y);
#ifdef REFLECTION_ROUGHNESS_BLUR
if(color.a > 0.5) color.rgb = blurColour(pos.xy, fragment.composite.r) * 8.0;
#else
if(color.a > 0.5) color.rgb = texture2D(GCOLOUR, pos.xy).rgb * 8.0;
#endif
return color;
#undef fragDepth
#undef errorCheck
}
vec3 drawUnderwaterReflection(in vec3 colour) {
vec3 fragpos = position.fragPositionSolid.xyz;
vec3 rnormal = fragment.normal.xyz * 2.0 - 1.0;
float fresnel = pow(1.0 + dot(normalize(fragpos.xyz), rnormal), 1.0 / 16.0);
fresnel = pow(fresnel, 8.0);
fresnel *= 0.65;
return mix(colour, waterColour * UNDERWATER_FOG_BRIGHTNESS, fresnel);
}
vec3 drawReflection(in vec3 colour) {
#define roughness fragment.composite.r
#define metallic fragment.composite.g
mat3x4 colourMatrix;
#define reflection colourMatrix[0]
#define skyc colourMatrix[1].rgb
#define metallicAlbedo colourMatrix[2].rgb
mat3x4 positionMatrix;
#define fragpos positionMatrix[0]
#define rnormal positionMatrix[1].xyz
#define reflectedVector positionMatrix[2].xyz
#define fresnel positionMatrix[2].w
fragpos = position.fragPositionSolid;
rnormal = fragment.normal.xyz * 2.0 - 1.0;
metallicAlbedo = mix(vec3(1.0), colourSaturate(fragment.aux1.rgb * REFLECTION_METALLIC_STRENGTH, REFLECTION_METALLIC_SATURATION), metallic);
fresnel = pow(1.0 + dot(normalize(fragpos.xyz), rnormal), 3.5);
fresnel = clamp(fresnel, 0.0, 1.0);
reflectedVector = normalize(reflect(fragpos.xyz, rnormal));
skyc = drawSky(vec4(reflectedVector.xyz, 0.0), true);
vec2 bounds = vec2(0.0); // land, off-screen
reflection = raytrace(bounds, fragpos.xyz, rnormal, skyc, reflectedVector, min(1.0, pow(fresnel, 0.3) * 2.0));
fresnel = clamp(fresnel, metallic * 0.9, 1.0);
reflection.rgb *= 0.2;
if(bounds.y > 0.5) skyc *= pow(fragment.depth.g, mix(1.0, 4.0, metallic));
reflection.rgb = mix(skyc, reflection.rgb, reflection.a);
reflection.rgb *= metallicAlbedo;
reflection.rgb = mix(colour * (1.0 - metallic), reflection.rgb, clamp(fresnel * pow(1.0 - roughness, mix(4.0, 1.0, metallic)), 0.0, 1.0));
reflection.rgb += ggx(mix(normalize(rnormal), rnormal, 0.02 * material.water), normalize(fragpos.xyz), lightVector, roughness, metallic, mix(mix(0.02, 0.3, material.water), 0.8, metallic)) * fragment.colour.a * directLight * metallicAlbedo;
return reflection.rgb;
#undef roughness
#undef metallic
#undef reflection
#undef skyc
#undef metallicAlbedo
#undef fragpos
#undef rnormal
#undef reflectedVector
#undef fresnel
}
#ifdef VOLUMETRIC_LIGHT
vec3 getVLColour(in vec3 background, in vec2 texcoord, in vec4 fragpos) {
vec4 vl = vec4(vec3(1.0), 0.0); // We're going to borrow the alpha component of this 4-component vector to store the intensity in.
vec4 vlSample = vec4(0.0);
// Sample the VL buffer, storing both the colour and the strength of VL.
#ifdef VL_BLUR
float weight = 0.0;
vec2 vlVector = vec2(0.0); // vlWeight, vlDepth
for(float i = -1.0; i < 1.0; i++) {
for(float j = -1.0; j < 1.0; j++) {
vec2 offset = vec2(i,j) / vec2(viewWidth, viewHeight);
weight = pow(1.0 - abs(position.depthSolid - position.depthTransparent) * 10.0, 32.0);
weight = max(0.1e-8, weight);
if(texture2DLod(depthtex1, texcoord.xy + refractionVector.xy + offset * 8.0, 2.0).x > position.depthTransparent) continue;
vlSample += texture2DLod(GAUX3, texcoord.xy + refractionVector.xy + offset * 4.0, 2.0);
vlVector.x += 1.0;
}
}
vlSample /= vlVector.x;
vl.a = vlSample.a;
#else
vlSample = texture2DLod(GAUX3, texcoord.xy + refractionVector.xy, VL_MIPMAP_LEVEL);
vl.a = vlSample.a;
#endif
mat2 efsMatrix; // [0] eBS & FdotL, [1] vlStrength
#define eBS efsMatrix[0].x
#define FdotL efsMatrix[0].y
eBS = mix(1.0, 0.0, max(0.1, eyeBrightnessSmooth.y / 240.0));
FdotL = max(0.0, mix(0.0, pow(dot(normalize(fragpos.xyz), normalize(lightVector)), VL_LIGHT_DISTANCE2), pow(dot(normalize(fragpos.xyz), normalize(lightVector)), VL_LIGHT_DISTANCE1)));
// Generate strength scalars for VL.
#define strengthOutdoors efsMatrix[1].x
#define strengthIndoors efsMatrix[1].y
// Outside
strengthOutdoors = VL_STRENGTH_HORIZON * HorizonAmb + VL_STRENGTH_NOON * Noon + VL_STRENGTH_MIDNIGHT * MidnightAmb;
// Outside near the sun/moon
strengthOutdoors = mix(strengthOutdoors, (VL_STRENGTH_NEAR_HORIZON * HorizonAmb + VL_STRENGTH_NEAR_NOON * Noon + VL_STRENGTH_NEAR_MIDNIGHT * MidnightAmb) * vlNearIntensity * mix(VL_NEAR_STRENGTH_OUTSIDE, VL_NEAR_STRENGTH_INSIDE, eBS) * mix(1.0, VL_RAIN_NEAR_MULTIPLIER, rain), FdotL);
// Inside
strengthIndoors = (VL_INSIDE_STRENGTH_HORIZON * HorizonAmb + VL_INSIDE_STRENGTH_NOON * Noon + VL_INSIDE_STRENGTH_MIDNIGHT * MidnightAmb) * eBS;
// Colourise VL
vl.rgb = directLight;
#ifdef VL_ADVANCED
if(any(greaterThan(vlSample.rgb, vec3(0.0)))) vl.rgb *= vlSample.rgb;
#else
vl.rgb *= 0.25;
#endif
// Handle strength of VL. The actual VL alpha is what is modified, rather than the colour itself.
vl.a *= vlIntensity; // Base VL intensity.
vl.a *= strengthOutdoors; // Outside intensity.
vl.a *= 1.0 + strengthIndoors * mix(1.0, VL_INSIDE_RAIN_MULTIPLIER, rain); // Inside intensity;
vl.a *= mix(1.0, VL_RAIN_STRENGTH, rain);
if(isEyeInWater == 1) vl.a *= VL_STRENGTH_UNDERWATER;
return background + vl.rgb * max(0.0, vl.a);
#undef eBS
#undef FdotL
#undef strengthOutdoors
#undef strengthIndoors
}
#endif
vec3 calculateSurfaceRefraction() {
vec3 refracted = vec3(0.0);
// Surface refraction
// TODO: Decide whether I need to call the wave function again, or just send normals down gaux4.
mat3 wpwvrsMatrix; // [0] worldPos, [1] waveVector, [2] refractStrength
#define worldPos wpwvrsMatrix[0]
#define waveVector wpwvrsMatrix[1]
#define refractStrength wpwvrsMatrix[2]
worldPos = getWorldPosition(position.fragPositionSolid, true);
waveVector = getWaveHeight((worldPos + cameraPosition).xz, material.water, 0.0);
refractStrength = vec3(clamp(position.depthTransparent - position.depthSolid, 0.025, 0.025));
refractStrength /= position.depthSolid;
if(material.water > 0.5) refractStrength *= REFRACTION_SURFACE_WATER_STRENGTH * vec3(1.0 + REFRACTION_SURFACE_WATER_DISPERSION, 1.0, 1.0 - REFRACTION_SURFACE_WATER_DISPERSION);
if(material.ice > 0.5) refractStrength *= REFRACTION_SURFACE_ICE_STRENGTH * vec3(1.0 + REFRACTION_SURFACE_ICE_DISPERSION, 1.0, 1.0 - REFRACTION_SURFACE_ICE_DISPERSION);
if(material.water > 0.5 || material.ice > 0.5) refractionVector += waveVector * refractStrength.y;
// TODO: Fix refraction refracting adjacent blocks without breaking things.
// Underwater refraction
float time = frameTimeCounter * REFRACTION_UNDERWATER_SPEED;
vec2 uwRefraction = vec2(0.0);
if(isEyeInWater == 1) uwRefraction.xy = vec2(sin(sin(pi * 2 * (time * 0.25)) * 1.3 + texcoord.s * 21.0 + texcoord.t * 19.0), cos(-time * 1.7 + texcoord.s * 18.0 + texcoord.s * 23.0)) * REFRACTION_UNDERWATER_STRENGTH;
if(isEyeInWater == 1) refractionVector.xy += uwRefraction.xy;
#ifdef REFRACTION_SURFACE_DISPERSION
mat3x2 refractCoordinates;
#define red refractCoordinates[0]
#define green refractCoordinates[1]
#define blue refractCoordinates[2]
if(material.water > 0.5 || material.ice > 0.5) red = waveVector.xy * refractStrength.x;
if(material.water > 0.5 || material.ice > 0.5) green = waveVector.xy * refractStrength.y;
if(material.water > 0.5 || material.ice > 0.5) blue = waveVector.xy * refractStrength.z;
refracted.r = texture2D(colortex0, texcoord.xy + red.xy + uwRefraction.xy).r;
refracted.g = texture2D(colortex0, texcoord.xy + green.xy + uwRefraction.xy).g;
refracted.b = texture2D(colortex0, texcoord.xy + blue.xy + uwRefraction.xy).b;
#undef red
#undef green
#undef blue
#else
refracted = texture2D(colortex0, texcoord.xy + waveVector * refractStrength.y + uwRefraction.xy).rgb;
#endif
return refracted;
#undef worldPos
#undef waveVector
#undef refractStrength
}
void getPuddle() {
float sky = min(1.0, pow(fragment.depth.g, 24.0));
float puddle = fragment.aux1.a;
puddle = mix(mix(fragment.composite.r, REFLECTION_PUDDLE_ROUGHNESS, 0.5), REFLECTION_PUDDLE_ROUGHNESS, clamp(puddle, 0.0, 1.0));
fragment.composite.r = mix(fragment.composite.r, puddle, (wetness * 1.5) * sky);
//fragment.colour.rgb = vec3(puddle);
}
void main() {
#if defined DEBUG_COMPARISON
#if DEBUG_COMPARISON_SHADER == -2 || DEBUG_COMPARISON_SHADER == STAGE
if(texcoord.x <= 0.5) gl_FragData[0] = texture2D(GCOLOUR, texcoord.xy);
if(texcoord.x <= 0.5) return;
#endif
#endif
// POPULATE STRUCTS
createFragment(fragment, texcoord.xy);
createPosition(position, texcoord.xy);
createMaterial(material, fragment);
createFragmentPosition(position, texcoord.xy, true, true);
calculateDirectLightColour();
calculateAmbientLightColour();
#ifdef DEBUG_VISUAL_REFLECTION_ROUGHNESS
if(texcoord.y < 4.0 / 4.0) fragment.composite.r = 0.0;
if(texcoord.y < 3.0 / 4.0) fragment.composite.r = 0.6;
if(texcoord.y < 2.0 / 4.0) fragment.composite.r = 0.5;
if(texcoord.y < 1.0 / 4.0) fragment.composite.r = 0.4;
#endif
if(material.water > 0.5 || material.ice > 0.5 || isEyeInWater == 1) fragment.colour.rgb = calculateSurfaceRefraction();
if(isEyeInWater == 0 && (material.solid > 0.5 || material.transparent > 0.5)) getPuddle();
if(isEyeInWater == 0 && (material.solid > 0.5 || material.transparent > 0.5) && fragment.composite.r < 0.97) fragment.colour.rgb = drawReflection(fragment.colour.rgb);
if(isEyeInWater == 1 && material.water > 0.5) fragment.colour.rgb = drawUnderwaterReflection(fragment.colour.rgb);
#ifdef VOLUMETRIC_LIGHT
fragment.colour.rgb = getVLColour(fragment.colour.rgb, texcoord.xy, position.fragPositionSolid);
#endif
#ifdef DEBUG_MODE
#ifdef DEBUG_VISUAL_MATERIALS
fragment.colour.rgb = vec3(0.0);
// Roughness
if(texcoord.x < 0.5 && texcoord.y < 1.0 && texcoord.y > 0.5) fragment.colour.r = texture2D(GCOMPOSITE, vec2(texcoord.x * 2.0, texcoord.y * 2.0 - 1.0)).r;
// Metallic
if(texcoord.x < 0.5 && texcoord.y < 0.5) fragment.colour.g = texture2D(GCOMPOSITE, texcoord.xy * 2.0).g;
#endif
#endif
// POPULATE OUTGOING BUFFERS
/* DRAWBUFFERS:02 */
gl_FragData[0] = fragment.colour;
gl_FragData[2] = fragment.depth;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment