Created
January 13, 2017 15:44
-
-
Save jcm2606/1139d64d88b1bb98348c7b6c91655b21 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 COMPOSITE | |
#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_GAUX2 | |
#include "/lib/utility/Samplers.glsl" | |
uniform sampler2D depthtex0; | |
uniform sampler2D depthtex1; | |
uniform sampler2DShadow shadow; | |
uniform sampler2DShadow watershadow; | |
uniform sampler2DShadow shadowcolor; | |
// UNIFORM FIELDS | |
uniform mat4 gbufferProjectionInverse; | |
uniform mat4 gbufferProjection; | |
uniform mat4 gbufferModelViewInverse; | |
uniform mat4 gbufferModelView; | |
uniform mat4 shadowModelView; | |
uniform mat4 shadowProjection; | |
uniform int isEyeInWater; | |
uniform float rainStrength; | |
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 lightVector; | |
varying vec3 sunVector; | |
varying vec3 moonVector; | |
varying vec3 upVector; | |
// STRUCTS | |
#include "/lib/struct/StructFragment.glsl" | |
#include "/lib/struct/StructShading.glsl" | |
#include "/lib/struct/StructPosition.glsl" | |
#include "/lib/struct/StructMaterial.glsl" | |
Fragment fragment; | |
SurfaceShading directShading; | |
Position position; | |
Material material; | |
// ARBITRARY FIELDS | |
RAIN_SCALAR; | |
vec3 directLight; | |
vec3 ambientLight; | |
vec3 dlSunlight; | |
vec3 dlMoonlight; | |
// FUNCTIONS | |
#include "/lib/feature/Shadow.glsl" | |
#include "/lib/utility/Colour.glsl" | |
#include "/lib/utility/Tonemap.glsl" | |
#include "/lib/utility/Worldtime.glsl" | |
#include "/lib/utility/Noise.glsl" | |
#include "/lib/feature/Lighting.glsl" | |
#include "/lib/feature/Sky.glsl" | |
#include "/lib/utility/LightingFunctions.glsl" | |
#include "/lib/feature/Textures.glsl" | |
#include "/lib/feature/Fog.glsl" | |
#include "/lib/feature/VolumetricLight.glsl" | |
#include "/lib/utility/Depth.glsl" | |
#include "/lib/feature/Reflection.glsl" | |
float getShadowBiasDistort(in vec4 worldpos) { | |
vec2 pos = abs(worldpos.xy * 1.165); | |
return (1.0 - SHADOW_BIAS) + (pow(pow(pos.x, 8.0) + pow(pos.y, 8.0), 1.0 / 8.0)) * SHADOW_BIAS; | |
} | |
vec4 biasShadowPosition(in vec4 worldpos) { | |
worldpos.xy /= getShadowBiasDistort(worldpos) * 0.97; | |
worldpos = worldpos * vec4(0.5, 0.5, 0.2, 0.5) + vec4(0.5); | |
return worldpos; | |
} | |
void distortShadowSpace(inout vec2 worldSpacePosition) { | |
worldSpacePosition = worldSpacePosition * 2.0 - 1.0; | |
worldSpacePosition /= (1.0 - SHADOW_BIAS) + fLength(worldSpacePosition) * SHADOW_BIAS; | |
worldSpacePosition = worldSpacePosition * 0.5 + 0.5; | |
} | |
vec4 getShadowWorldPos(in float shadowdepth, in vec2 texcoord){ | |
vec4 sworldposition = gbufferModelViewInverse * getFragPosition(texcoord.st, shadowdepth, true); | |
sworldposition = shadowModelView * sworldposition; | |
sworldposition = shadowProjection * sworldposition; | |
sworldposition /= sworldposition.w; | |
return sworldposition * 0.5 + 0.5; | |
} | |
void calculateShading(in float translucent) { | |
mat2x4 shadowPositionMatrix; | |
#define shadowPosition shadowPositionMatrix[0] | |
#define shadowPositionSolid shadowPositionMatrix[1] | |
shadowPosition = getShadowWorldPos(position.depthTransparent, texcoord.st); | |
shadowPositionSolid = getShadowWorldPos(position.depthSolid, texcoord.st); | |
distortShadowSpace(shadowPosition.st); | |
distortShadowSpace(shadowPositionSolid.st); | |
mat3x4 shadingMatrix; | |
#define NdotL shadingMatrix[2].y | |
#define diffthresh 0.0005 | |
#define shadowStep shadingMatrix[2].x | |
#define sampleColour shadingMatrix[1] | |
#define sampleSolid shadingMatrix[0].x | |
#define sampleTransparent shadingMatrix[0].y | |
#define sampleSurface shadingMatrix[0].z | |
#define sampleDifference shadingMatrix[0].w | |
#define shadingFinal shadingMatrix[1].a | |
NdotL = clamp(dot(fragment.normal.xyz * 2.0 - 1.0, lightVector), 0.0, 1.0); | |
const vec2 shadowFilter[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) | |
); | |
int weight; | |
shadowPosition.z -= diffthresh; | |
shadowPositionSolid.z -= diffthresh; | |
if(max(abs(shadowPosition.x), abs(shadowPosition.y)) < 0.99) { | |
shadowStep = SHADOW_FILTER_STEP / shadowMapResolution; | |
#ifdef SHADOW_FILTER | |
#ifdef SHADOW_LQ_FILTER | |
for(int i = 0; i < 4; i++) { | |
#else | |
#ifdef SHADOW_HQ_FILTER | |
for(int i = 0; i < 16; i++) { | |
#else | |
for(int i = 0; i < 8; i++) { | |
#endif | |
#endif | |
sampleColour += shadow2D(shadowcolor, vec3(shadowPosition.st + shadowFilter[i] * shadowStep, shadowPosition.z)); | |
sampleSolid += shadow2D(shadow, vec3(shadowPosition.st + shadowFilter[i] * shadowStep, shadowPosition.z)).r; | |
sampleTransparent += shadow2D(watershadow, vec3(shadowPosition.st + shadowFilter[i] * shadowStep, shadowPosition.z)).x; | |
sampleSurface += shadow2D(shadow, vec3(shadowPositionSolid.st + shadowFilter[i] * shadowStep, shadowPositionSolid.z)).x; | |
weight++; | |
} | |
sampleColour /= weight; | |
sampleSolid /= weight; | |
sampleTransparent /= weight; | |
sampleSurface /= weight; | |
#else | |
sampleColour = shadow2D(shadowcolor, vec3(shadowPosition.st, shadowPosition.z)); | |
sampleSolid = shadow2D(shadow, vec3(shadowPosition.st, shadowPosition.z)).x; | |
sampleTransparent = shadow2D(watershadow, vec3(shadowPosition.st, shadowPosition.z)).x; | |
sampleSurface = shadow2D(shadow, vec3(shadowPositionSolid.st, shadowPositionSolid.z)).x; | |
#endif | |
} | |
sampleDifference = (sampleSolid - sampleTransparent); | |
shadingFinal = mix(sampleSolid, 1.0, sampleTransparent) * mix(clamp(NdotL, 0.0, 1.0), 1.0, min(1.0, translucent + material.foliage)); | |
#ifdef LOCAL_SUBSURFACE_SCATTERING | |
if(material.foliage > 0.5) shadingFinal *= 1.0 + mix(0.0, 2.0, max(0.0, pow(dot(normalize(position.fragPositionSolid.xyz), lightVector), 16.0))); | |
#endif | |
directShading.final = sampleColour; | |
directShading.shading = vec4(sampleDifference, sampleSurface, 0.0, 0.0); | |
fragment.colour.a = directShading.shading.g; | |
#undef shadowPosition | |
#undef shadowPositionSolid | |
#undef NdotL | |
#undef diffthresh | |
#undef shadowStep | |
#undef sampleColour | |
#undef sampleSolid | |
#undef sampleTransparent | |
#undef sampleSurface | |
#undef sampleDifference | |
#undef shadingFinal | |
} | |
vec3 calculateLitShading(in vec3 colour) { | |
mat2x3 lightMatrix; | |
#define direct lightMatrix[0] | |
#define ambient lightMatrix[1] | |
direct = colour.rgb * (directLight * mix(vec3(1.0), directShading.finalShading_colour * SHADOW_TRANSLUCENCY_COLOUR_STRENGTH, directShading.finalShading_differenceMask)); | |
ambient = colour.rgb * ambientLight * pow(fragment.skyLight, AL_SPREAD) * (isEyeInWater == 1 ? pow(fragment.skyLight, 3.0) : (material.water > 0.5 ? 0.5 : 1.0)); | |
return mix(ambient, direct * (isEyeInWater == 1 ? max(DL_WATER_MINIMUM, pow(fragment.skyLight, DL_WATER_FALLOFF)) : 1.0), directShading.finalShading_shading) + colour.rgb * colourSaturate(BL_COLOUR, BL_SATURATION) * getBlockLight(fragment.blockLight); | |
#undef direct | |
#undef ambient | |
} | |
vec3 calculateBaseShading(in vec3 colour) { | |
vec3 ambient = colour.rgb * ambientLight * pow(fragment.skyLight, AL_SPREAD) * (isEyeInWater == 1 ? pow(fragment.skyLight, 3.0) : (material.water > 0.5 ? 0.5 : 1.0)); | |
return ambient + colour.rgb * colourSaturate(BL_COLOUR, BL_SATURATION) * pow(fragment.blockLight * BL_STRENGTH, BL_ATTENUATION); | |
} | |
vec3 drawDepthFog(in vec3 colour, in float brightness, in float height) { | |
vec4 upos = gbufferProjectionInverse * vec4(vec3(texcoord.st, position.depthTransparent) * 2.0 - 1.0, 1.0); | |
upos /= upos.w; | |
vec3 uvec = position.fragPositionSolid.xyz - upos.xyz; | |
upos.w = sqrt(dot(uvec, uvec)) * abs(dot(normalize(uvec), fragment.normal.xyz * 2.0 - 1.0)); | |
upos.w = 1-clamp(exp(-upos.w / height), 0.0, 1.0); | |
return mix(fragment.colour.rgb, colour * brightness * fragment.skyLight, upos.w); | |
} | |
float puddle(vec2 position, vec2 wind) { | |
vec2 dcVector = vec2(0.0); // density, cl | |
#define density dcVector.x | |
#define cl dcVector.y | |
density = generate2DNoise(position - wind * 0.25); | |
density += generate2DNoise(position * 3.5 - wind * 0.25) / 3.5; | |
density += generate2DNoise(position * 6.125 - wind * 0.25) / 6.125; | |
density += generate2DNoise(position * 12.25 - wind * 0.25) / 12.25; | |
density += generate2DNoise(position * 24.50 - wind * 0.25) / 24.50; | |
density += generate2DNoise(position * 49.0 - wind * 0.25) / 49.0; | |
density /= 0.13; | |
cl = max(density - 0.9, 0.0); | |
cl = max(cl, 0.0) * 0.05; | |
density = pow(max(1.0 - cl * 2.5, 0.0), 2.0) / 11.0 / 3.0; | |
density *= 20.0; | |
//density -= 0.1; | |
density = max(0.0, density); | |
density = mix(density, 0.0, pow(1.0 - density, 100.0)); | |
return density * 3.0; | |
#undef density | |
#undef cl | |
} | |
float generatePuddles() { | |
vec3 worldpos = getWorldPosition(position.fragPositionSolid, true) + cameraPosition; | |
float puddle = puddle(worldpos.xz / REFLECTION_PUDDLE_SIZE, vec2(0.0)); | |
return puddle; | |
} | |
#ifdef VOLUMETRIC_LIGHT | |
float distx(in float dist){ | |
return (far * (dist - near)) / (dist * (far - near)); | |
} | |
// dirived from: http://devlog-martinsh.blogspot.nl/2011/03/glsl-8x8-bayer-matrix-dithering.html | |
float find_closest(vec2 pos) { | |
const int ditherPattern[64] = int[64]( | |
0, 32, 8, 40, 2, 34, 10, 42, /* 8x8 Bayer ordered dithering */ | |
48, 16, 56, 24, 50, 18, 58, 26, /* pattern. Each input pixel */ | |
12, 44, 4, 36, 14, 46, 6, 38, /* is scaled to the 0..63 range */ | |
60, 28, 52, 20, 62, 30, 54, 22, /* before looking in this table */ | |
3, 35, 11, 43, 1, 33, 9, 41, /* to determine the action. */ | |
51, 19, 59, 27, 49, 17, 57, 25, | |
15, 47, 7, 39, 13, 45, 5, 37, | |
63, 31, 55, 23, 61, 29, 53, 21); | |
vec2 positon = vec2(0.0f); | |
positon.x = floor(mod(texcoord.s * viewWidth, 8.0f)); | |
positon.y = floor(mod(texcoord.t * viewHeight, 8.0f)); | |
int dither = ditherPattern[int(positon.x) + int(positon.y) * 8]; | |
return float(dither) / 64.0f; | |
} | |
float dynamicExposure() | |
{ | |
return mix(1.0,0.0,(pow(eyeBrightnessSmooth.y / 240.0f, 3.0f))); | |
} | |
float getVolumetricRays(out vec4 sampledColour) { | |
///////////////////////Setting up functions/////////////////////// | |
mat3x4 matrix0; | |
#define rSD matrix0[0] | |
#define worldposition matrix0[1] | |
#define colour matrix0[2] | |
rSD.x; | |
rSD.y = 6.0 / VL_QUALITY; | |
rSD.z = find_closest(texcoord.st); | |
rSD.z *= rSD.y; | |
mat2 matrix1; | |
#define minDist matrix1[0].x | |
#define weight matrix1[0].y | |
const float maxDist = (VL_DISTANCE); | |
minDist = (0.001); | |
minDist += rSD.z; | |
weight = (maxDist / rSD.y); | |
colour = vec4(vec3(0.25), 0.0); | |
bool colsample = false; | |
#define solidShadow matrix1[1].x | |
#define transparentShadow matrix1[1].y | |
for (minDist; minDist < maxDist;) { | |
if (linearDepth(position.depthTransparent) < minDist) break; // VL wall fix | |
worldposition = getShadowWorldPos(distx(minDist),texcoord.st); | |
distortShadowSpace(worldposition.st); | |
solidShadow = shadow2D(watershadow, worldposition.rgb).x; | |
#ifdef VL_TRANSPARENCY | |
transparentShadow = shadow2D(shadow, worldposition.rgb).x - solidShadow; | |
#ifdef VL_ADVANCED | |
if(transparentShadow > 0.0 && !colsample) colour = shadow2D(shadowcolor, worldposition.rgb); | |
if(transparentShadow > 0.0 && !colsample && isEyeInWater == 1) transparentShadow *= colour.a; | |
if(transparentShadow > 0.0 && !colsample) colsample = true; | |
#endif | |
solidShadow += transparentShadow; | |
#endif | |
rSD.x += solidShadow; | |
minDist = minDist + rSD.y; | |
} | |
#undef solidShadow | |
#undef transparentShadow | |
rSD.x /= weight; | |
rSD.x *= 0.15 * maxDist / 32; | |
#undef minDist | |
#undef weight | |
rSD.x = mix(rSD.x, clamp(rSD.x, 0.0, 0.1), dynamicExposure()); | |
sampledColour = colour; | |
return rSD.x; | |
#undef rSD | |
#undef worldposition | |
#undef colour | |
} | |
#else | |
float getVolumetricRays(out vec4 sampledColour){ | |
return 0.0; | |
} | |
#endif | |
float exponentialFog(float dist, float density) { | |
const float LOG2 = -1.442695; | |
float d = density * dist; | |
return 1.0 - clamp(exp2(d * d * LOG2), 0.0, 1.0); | |
} | |
void doUnderwaterFog(inout vec3 colour) { | |
float fog = exponentialFog(linearDepth(position.depthSolid) / UNDERWATER_FOG_DISTANCE, UNDERWATER_FOG_DENSITY); | |
colour = mix(colour, waterColour * UNDERWATER_FOG_BRIGHTNESS, fog); | |
} | |
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); | |
if(material.water > 0.5) fragment.composite = vec4(0.08, 0.0, 0.0, 1.0); | |
if(material.translucent > 0.5) fragment.composite = vec4(0.2, 0.0, 0.0, 1.0); | |
// PERFORM GAMMA CORRECTION | |
fragment.aux1.rgb = gamma2linear(fragment.aux1.rgb); | |
fragment.aux2.rgb = gamma2linear(fragment.aux2.rgb); | |
// VARIABLES | |
float skyMask = SKY_MASK; | |
fragment.colour.a = fragment.aux1.a; | |
mat2x3 colour; // [0] bufferSolid, [1] bufferTransparent | |
colour[0] /* bufferSolid */ = fragment.aux1.rgb; | |
colour[1] /* bufferTransparent */ = fragment.aux2.rgb; | |
// CALCULATE SHADING | |
if(material.sky < 0.5) calculateShading(0.0); | |
// CALCULATE COLOUR OF DIRECT LIGHT | |
calculateDirectLightColour(); | |
// DRAW THE SKY | |
if(1.0 - skyMask > 0.5 && material.hand < 0.5) colour[0] = drawSky(position.fragPositionTransparent, false); | |
// CALCULATE THE COLOUR OF AMBIENT LIGHT | |
if(material.sky < 0.5) calculateAmbientLightColour(); | |
// PERFORM SHADING ON THE SOLID BUFFER | |
if(skyMask > 0.5) colour[0] /* bufferSolid */ = calculateLitShading(colour[0] /* bufferSolid */); | |
//if(material.weather > 0.5) colour[0] /* bufferSolid */ = calculateBaseShading(colour[0] /* bufferSolid */); | |
// TINT THE SOLID BUFFER BEFORE SHADING THE TRANSPARENT BUFFER | |
if(material.weather < 0.5 && any(greaterThan(colour[1] /* bufferTransparent */, vec3(0.0)))) colour[0] /* bufferSolid */ *= colour[1] /* bufferTransparent */ * TRANSPARENCY_TINT_STRENGTH; | |
// PERFORM SHADING ON THE TRANSPARENT BUFFER | |
colour[1] /* bufferTransparent */ = calculateBaseShading(colour[1] /* bufferTransparent */); | |
// COMBINE BUFFERS | |
fragment.colour.rgb = mix(colour[0], colour[1], fragment.aux2.a); | |
// DRAW DEPTH FOG | |
#ifdef DEPTH_FOG | |
if(isEyeInWater == 0 && material.water > 0.5) fragment.colour.rgb = drawDepthFog(waterColour, 0.05 * (DEPTH_FOG_WATER_BRIGHTNESS_HORIZON * HorizonAmb + DEPTH_FOG_WATER_BRIGHTNESS_NOON * Noon + DEPTH_FOG_WATER_BRIGHTNESS_MIDNIGHT * MidnightAmb), DEPTH_FOG_WATER_HEIGHT); | |
if(isEyeInWater == 0 && material.ice > 0.5) fragment.colour.rgb = drawDepthFog(iceColour, 0.03 * (DEPTH_FOG_ICE_BRIGHTNESS_HORIZON * HorizonAmb + DEPTH_FOG_ICE_BRIGHTNESS_NOON * Noon + DEPTH_FOG_ICE_BRIGHTNESS_MIDNIGHT * MidnightAmb), DEPTH_FOG_ICE_HEIGHT); | |
#endif | |
// CALCULATE VOLUMETRIC LIGHT SAMPLES | |
#ifdef VOLUMETRIC_LIGHT | |
vec4 vlColour = vec4(0.0); | |
fragment.aux3.a = getVolumetricRays(vlColour); | |
fragment.aux3.rgb = vlColour.rgb; | |
#endif | |
#ifdef UNDERWATER_FOG | |
if(isEyeInWater == 1) doUnderwaterFog(fragment.colour.rgb); | |
#endif | |
if(material.solid > 0.5) fragment.aux1.a = generatePuddles(); | |
// POPULATE OUTGOING BUFFERS | |
/* DRAWBUFFERS:0 */ | |
gl_FragData[0] = fragment.colour; | |
gl_FragData[1] = fragment.normal; | |
gl_FragData[2] = fragment.depth; | |
gl_FragData[3] = fragment.composite; | |
gl_FragData[4] = fragment.aux1; | |
gl_FragData[6] = fragment.aux3; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ddh