Created
January 13, 2017 15:50
-
-
Save jcm2606/91c7769e2cfcd65f6869de6be50e1b44 to your computer and use it in GitHub Desktop.
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
/* | |
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