You are on page 1of 34

const const const const const const const const const const const const const const const

const const

int float bool float bool int int int int int int int int float float float float

shadowMapResolution shadowDistance generateShadowMipmap shadowIntervalSize shadowHardwareFiltering R8 RG8 RGB8 RGB16 gcolorFormat gdepthFormat gnormalFormat compositeFormat eyeBrightnessHalflife centerDepthHalflife wetnessHalflife drynessHalflife = 10.0f; = 2.0f;

= = = = =

2048; 120.0f; false; 4.0f; true; = 0; = 0; = 1; = 2; = = = = RGB16; RGB8; RGB16; RGB8;

= 200.0f; = 10.0f; = 0; = -40.0f;

const int const float const float const int

superSamplingLevel sunPathRotation ambientOcclusionLevel = 0.019f; noiseTextureResolution = 64;

//END OF INTERNAL VARIABLES//

#define BANDING_FIX_FACTOR 1.0f uniform sampler2D gcolor; uniform sampler2D gdepth; uniform sampler2D gdepthtex; uniform sampler2D gnormal; uniform sampler2D composite; uniform sampler2DShadow shadow; uniform sampler2D noisetex; uniform sampler2D shadowcolor; //uniform sampler2D gaux1; //uniform sampler2D gaux2; //uniform sampler2D gaux3; //uniform sampler2D gaux4; varying vec4 texcoord; varying vec3 lightVector; varying vec3 upVector; uniform int worldTime; uniform uniform uniform uniform uniform mat4 mat4 mat4 mat4 mat4 gbufferProjection; gbufferProjectionInverse; gbufferModelViewInverse; gbufferModelView; shadowProjectionInverse;

uniform uniform uniform uniform uniform uniform uniform uniform uniform uniform uniform uniform uniform uniform uniform uniform uniform uniform uniform varying varying varying varying varying varying varying varying varying varying varying varying varying

mat4 mat4 mat4 vec3 vec3 vec3 float float float float float float float float int float ivec2 ivec2 int float float float float float vec3 vec3 vec3 vec3 vec3 vec3 vec3 vec3

shadowProjection; shadowModelView; shadowModelViewInverse; sunPosition; cameraPosition; upPosition; near; far; viewWidth; viewHeight; rainStrength; wetness; aspectRatio; frameTimeCounter; isEyeInWater; eyeAltitude; eyeBrightness; eyeBrightnessSmooth; fogMode; timeSunrise; timeNoon; timeSunset; timeMidnight; timeSkyDark; colorSunlight; colorSkylight; colorSunglow; colorBouncedSunlight; colorScatteredSunlight; colorTorchlight; colorWaterMurk; colorWaterBlue;

/////////////////////////FUNCTIONS////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// /////////////////////////FUNCTIONS////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// //Get gbuffer textures vec3 GetAlbedoLinear(in vec2 coord) { //Function that retrieves the diffuse texture and convert it into linear space. return pow(texture2D(gcolor, coord).rgb, vec3(2.2f)); } vec3 GetAlbedoGamma(in vec2 coord) { s the diffuse texture and leaves it in gamma space. return texture2D(gcolor, coord).rgb; } //Function that retrieve

vec3 GetNormals(in vec2 coord) { //Function that retrieves the screen space surface normals. Used for lighting calculations return texture2D(gnormal, texcoord.st).rgb * 2.0f - 1.0f; } float GetDepth(in vec2 coord) { //Functi on that retrieves the scene depth. 0 - 1, higher values meaning farther away return texture2D(gdepthtex, coord).r; } float GetDepthLinear(in vec2 coord) { //Functi on that retrieves the scene depth. 0 - 1, higher values meaning farther away return 2.0f * near * far / (far + near - (2.0f * texture2D(gdepthtex, co ord).x - 1.0f) * (far - near)); } float { near)); } //Lightmaps float GetLightmapTorch(in vec2 coord) { //Function that retrieves the lightmap of light emitted by emissive blocks like torches and lava float lightmap = texture2D(gdepth, coord).g; //Apply inverse square law and normalize for natural light falloff lightmap = clamp(lightmap * 1.22f, 0.0f, 1.0f); lightmap = 1.0f - lightmap; lightmap *= 5.6f; lightmap = 1.0f / pow((lightmap + 0.2f), 2.0f); lightmap -= 0.02975f; // if (lightmap <= 0.0f) // lightmap = 1.0f; lightmap lightmap lightmap lightmap return lightmap; } float GetLightmapSky(in vec2 coord) { //Function that retrieve s the lightmap of light emitted by the sky. This is a raw value from 0 (fully da rk) to 1 (fully lit) regardless of time of day return pow(texture2D(gdepth, coord).b, 4.3f); } float } //Specularity float GetSpecularity(in vec2 coord) { GetUnderwaterLightmapSky(in vec2 coord) { return texture2D(composite, coord).r; = max(0.0f, lightmap); *= 0.008f; = clamp(lightmap, 0.0f, 1.0f); = pow(lightmap, 0.9f); ExpToLinearDepth(in float depth) return 2.0f * near * far / (far + near - (2.0f * depth - 1.0f) * (far -

//Function that retrieve

s how reflective any surface/pixel is in the scene. Used for reflections and spe cularity return texture2D(composite, texcoord.st).r; } float GetGlossiness(in vec2 coord) { //Function that retrieve s how reflective any surface/pixel is in the scene. Used for reflections and spe cularity return texture2D(composite, texcoord.st).g; }

//Material IDs float GetMaterialIDs(in vec2 coord) { s the texture that has all material IDs stored in it return texture2D(gdepth, coord).r; }

//Function that retrieve

bool GetSky(in vec2 coord) { //Function that returns true for any pixel that is part of the sky, and false for any pixel that isn't part of the sky float matID = GetMaterialIDs(coord); //Gets texture that has all material IDs stored in it matID = floor(matID * 255.0f); //Scale texture from 0-1 float to 0-255 integer format if (matID == 0.0f) { //Checks to see if the current pixel's material ID is 0 = the sky return true; //If the current pixel has the material ID of 0 (sky material ID), Return "this pixel is part of the sky" } else { return false; //Return "this pixel is not part of the sky" } } bool GetMaterialMask(in vec2 coord, in int ID, in float matID) { matID = floor(matID * 255.0f); //Catch last part of sky if (matID > 254.0f) { matID = 0.0f; } if (matID == ID) { return true; } else { return false; } }

//Water float GetWaterTex(in vec2 coord) { //Function that returns the texture used for water. 0 means "this pixel is not water". 0.5 and g reater means "this pixel is water".

return texture2D(composite, coord).b; //values from 0.5 to 1.0 represent the amount of sky light hitting the surface of the water. It is used to simulate fake sky reflections in composite1.fsh } bool GetWaterMask(in vec2 coord, in float matID) { //Function that returns "true" if a pixel is water, and "false" if a pixel is no t water. matID = floor(matID * 255.0f); if (matID >= 35.0f && matID <= 51) { return true; } else { return false; } }

//Surface calculations vec4 GetScreenSpacePosition(in vec2 coord) { //Function that calculates the s creen-space position of the objects in the scene using the depth texture and the texture coordinates of the full-screen quad float depth = GetDepth(coord); depth += float(GetMaterialMask(coord, 5, GetMaterialIDs(coord) )) * 0.38f; //float handMask = float(GetMaterialMask(coord, 5, GetMaterial IDs(coord))); vec4 fragposition = gbufferProjectionInverse * vec4(coord.s * 2.0f - 1.0 f, coord.t * 2.0f - 1.0f, 2.0f * depth - 1.0f, 1.0f); fragposition /= fragposition.w; //fragposition.xyz *= mix(1.0f, 15.0f, handMask); return fragposition; } vec4 GetScreenSpacePosition(in vec2 coord, in float depth) { //Function that calculates the screen-space position of the objects in the scene using the depth texture and the texture coordinates of the full-screen quad //depth += float(GetMaterialMask(coord, 5)) * 0.38f; vec4 fragposition = gbufferProjectionInverse * vec4(coord.s * 2.0f - 1.0 f, coord.t * 2.0f - 1.0f, 2.0f * depth - 1.0f, 1.0f); fragposition /= fragposition.w; return fragposition; } vec4 { GetWorldSpacePosition(in vec2 coord, in float depth) vec4 pos = GetScreenSpacePosition(coord, depth); pos = gbufferModelViewInverse * pos; pos.xyz += cameraPosition.xyz; return pos; } vec4 { ScreenSpaceFromWorldSpace(in vec4 worldPosition)

worldPosition.xyz -= cameraPosition; worldPosition = gbufferModelView * worldPosition; return worldPosition; }

void DoNightEye(inout vec3 color) { input at night, simulating the rods in the human eye

//Desaturates any color

float amount = 0.8f; //How mu ch will the new desaturated and tinted image be mixed with the original image vec3 rodColor = vec3(0.2f, 0.5f, 1.0f); //Cyan color that humans percieve when viewing extremely low light levels via rod cells in the eye float colorDesat = dot(color, vec3(1.0f)); //Desaturated color color = mix(color, vec3(colorDesat) * rodColor, timeSkyDark * amount); //color.rgb = color.rgb; } float { ExponentialToLinearDepth(in float depth) vec4 worldposition = vec4(depth); worldposition = gbufferProjection * worldposition; return worldposition.z; } void DoLowlightEye(inout vec3 color) { y color input at night, simulating the rods in the human eye //Desaturates an

// float amount = 0.8f; //How much will the new desaturated and tinted image be mixed with the original image // vec3 rodColor = vec3(0.2f, 0.5f, 1.0f); //Cyan color that humans percieve when viewing extremely low light levels via rod cells in the eye // float colorDesat = dot(color, vec3(1.0f)); //Desaturated color // color = mix(color, vec3(colorDesat) * rodColor, amount); color.rgb = color.rgb; } void FixLightFalloff(inout float lightmap) { //Fixes the ugly lightmap fallof f and creates a nice linear one float additive = 5.35f; float exponent = 40.0f; lightmap += additive; //Prevent ugly fast falloff lightmap = pow(lightmap, exponent); //Curve light fa lloff lightmap = max(0.0f, lightmap); //Make sure light properly falls off to zero lightmap /= pow(1.0f + additive, exponent); } float } CalculateLuminance(in vec3 color) { return (color.r * 0.2126f + color.g * 0.7152f + color.b * 0.0722f);

vec3 Glowmap(in vec3 albedo, in bool mask, in float curve, in vec3 emissiveCo lor) { vec3 color = albedo * float(mask); color = pow(color, vec3(curve)); color = vec3(CalculateLuminance(color)); color *= emissiveColor; return color; } float ChebyshevUpperBound(in vec2 moments, in float distance) { if (distance <= moments.x) return 1.0f; float variance = moments.y - (moments.x * moments.x); variance = max(variance, 0.000002f); float d = distance - moments.x; float pMax = variance / (variance + d*d); return pMax; } float CalculateDitherPattern1() { const int[16] ditherPattern = int[16] (0 , 9 , 3 , 11,

13, 5 , 15, 7 , 4 , 12, 2, 10, 16, 8 , 14, 6 ); vec2 count = vec2(0.0f); count.x = floor(mod(texcoord.s * viewWidth, 4.0f)); count.y = floor(mod(texcoord.t * viewHeight, 4.0f)); int dither = ditherPattern[int(count.x) + int(count.y) * 4]; return float(dither) / 17.0f; } float CalculateDitherPattern2() { const int[64] ditherPattern = int[64] ( 1, 49, 13, 61, 4, 52, 16, 64,

33, 17, 45, 29, 36, 20, 48, 32, 9, 57, 5, 53, 12, 60, 8, 56, 41, 25, 37, 21, 44, 28, 40, 24, 3, 51, 15, 63, 2, 50, 14, 62, 35, 19, 47, 31, 34, 18, 46, 30, 11, 59, 7, 55, 10, 58, 6, 54, 43, 27, 39, 23, 42, 26, 38, 22);

vec2 count = vec2(0.0f); count.x = floor(mod(texcoord.s * viewWidth, 8.0f)); count.y = floor(mod(texcoord.t * viewHeight, 8.0f)); int dither = ditherPattern[int(count.x) + int(count.y) * 8]; return float(dither) / 65.0f; } vec3 CalculateNoisePattern1(vec2 offset, float size) { vec2 coord = texcoord.st; coord *= vec2(viewWidth, viewHeight); coord = mod(coord + offset, vec2(size)); coord /= noiseTextureResolution; return texture2D(noisetex, coord).xyz; } void DrawDebugSquare(inout vec3 color) { vec2 pix = vec2(1.0f / viewWidth, 1.0f / viewHeight); vec2 offset = vec2(0.5f); vec2 size = vec2(0.0f); size.x = 1.0f / 2.0f; size.y = 1.0f / 2.0f; vec2 padding = pix * 0.0f; size += padding; if ( texcoord.s + offset.s / 2.0f + padding.x / 2.0f > offset.s && texcoord.s + offset.s / 2.0f + padding.x / 2.0f < offset.s + si ze.x && texcoord.t + offset.t / 2.0f + padding.y / 2.0f > offset.t && texcoord.t + offset.t / 2.0f + padding.y / 2.0f < offset.t + si ze.y ) { int[16] ditherPattern = int[16] (0, 3, 0, 3, 2, 1, 2, 1, 0, 3, 0, 3, 2, 1, 2, 1); vec2 count = vec2(0.0f); count.x = floor(mod(texcoord.s * viewWidth, 4.0f)); count.y = floor(mod(texcoord.t * viewHeight, 4.0f)); int dither = ditherPattern[int(count.x) + int(count.y) * 4]; color.rgb = vec3(float(dither) / 3.0f); }

} /////////////////////////STRUCTS//////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// /////////////////////////STRUCTS//////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// struct MCLightmapStruct { float torch; other emissive blocks float sky; sky float lightning; //Lightmaps directly from MC engine //Light emitted from torches and //Light coming from the //Light coming from lightning

vec3 torchVector; //Vector in screen space that re presents the direction of average light transfered vec3 skyVector; } mcLightmap;

struct DiffuseAttributesStruct { //Diffuse surface shadin g attributes float roughness; //Roughness of surface. More rou ghness will use Oren Nayar reflectance. float translucency; //How translucent the surface is. Transl ucency represents how much energy will be transfered through the surface vec3 translucencyColor; //Color that will be multiplied with sun light for backsides of translucent materials. }; struct SpecularAttributesStruct { //Specular surface shadi ng attributes float specularity; //How reflective a surface is float extraSpecularity; //Additional reflectance for specular re flections from sun only float glossiness; //How smooth or rough a specular surface is float metallic; //from 0 - 1. 0 representing non -metallic, 1 representing fully metallic. float gain; //Adjust specularity fur ther float base; //Reflectance when the c amera is facing directly at the surface normal. 0 allows only the fresnel effect to add specularity float fresnelPower; //Curve of fresnel effect. Higher values mean the surface has to be viewed at more extreme angles to see reflectance }; struct SkyStruct { //All sky shading attributes vec3 albedo; //Diffuse texture aka "color tex ture" of the sky vec3 tintColor; //Color that will be multiplied with the sky to tint it vec3 sunglow; //Color that will be added to th e sky simulating scattered light arond the sun/moon vec3 sunSpot; //Actual sun surface };

struct WaterStruct { vec3 albedo; }; struct MaskStruct { float matIDs; bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool bool sky; land; grass; leaves; ice; hand; translucent; glow; sunspot; goldBlock; ironBlock; diamondBlock; emeraldBlock; sand; sandstone; stone; cobblestone; wool; clouds; torch; lava; glowstone; fire;

bool water; bool volumeCloud; }; struct CloudsStruct { vec3 albedo; }; struct AOStruct { float skylight; float scatteredUpLight; float bouncedSunlight; float scatteredSunlight; float constant; }; struct SurfaceStruct { , and functions //Surface shading properties, attributes

//Attributes that change how shading is applied to each pixel DiffuseAttributesStruct diffuse; ns all diffuse surface attributes SpecularAttributesStruct specular; ns all specular surface attributes

//Contai //Contai

SkyStruct and properties WaterStruct roperties MaskStruct CloudsStruct AOStruct ion

sky; water; mask; clouds; ao;

//Sky shading attributes //Water shading attributes and p //Material ID Masks //ambient occlus

//Properties that are required for lighting calculation vec3 albedo; //Diffuse textur e aka "color texture" vec3 normal; //Screen-space s urface normals float depth; //Scene depth float linearDepth; //Linear depth vec4 screenSpacePosition; //Vector representing the screen -space position of the surface vec3 viewVector; //Vector representing th e viewing direction vec3 lightVector; //Vector representing su nlight direction vec3 upVector; //Vector represe nting "up" direction float NdotL; //dot(normal, li ghtVector). used for direct lighting calculation vec3 debug; float } surface; struct LightmapStruct { //Lighting information to light the scen e. These are untextured colored lightmaps to be multiplied with albedo to get th e final lit and textured image. vec3 sunlight; //Direct light from the sun vec3 skylight; //Ambient light from the sky vec3 bouncedSunlight; //Fake bounced light, coming from opposi te of sun direction and adding to ambient light vec3 scatteredSunlight; //Fake scattered sunlight, coming from s ame direction as sun and adding to ambient light vec3 scatteredUpLight; //Fake GI from ground vec3 torchlight; //Light emitted from torches and other emissive blocks vec3 lightning; //Light caused by lightning vec3 nolight; //Base ambient light added to ev erything. For lighting caves so that the player can barely see even when no ligh ts are present vec3 specular; //Reflected direct light from su n vec3 translucent; //Light on the backside of objec ts representing thin translucent materials vec3 sky; //Color and brightness o f the sky itself vec3 underwater; //underwater lightmap } lightmap; struct ShadingStruct { float direct; //Shading calculation variables shadow;

float waterDirect; float bounced; //Fake bounced sunlight float skylight; //Light coming from sky float scattered; //Fake scattered sunlight float scatteredUp; //Fake GI from ground float specular; //Reflected direct light float translucent; //Backside of objects lit up from the su n via thin translucent materials float sunlightVisibility; //Shadows } shading; struct GlowStruct { vec3 torch; vec3 lava; vec3 glowstone; vec3 fire; }; struct FinalStruct { y what is illuminating them. GlowStruct erial final images glow; //Final textured and lit images sorted b //Struct containing emissive mat

vec3 sunlight; //Direct light from the sun vec3 skylight; //Ambient light from the sky vec3 bouncedSunlight; //Fake bounced light, coming from opposi te of sun direction and adding to ambient light vec3 scatteredSunlight; //Fake scattered sunlight, coming from s ame direction as sun and adding to ambient light vec3 scatteredUpLight; //Fake GI from ground vec3 torchlight; //Light emitted from torches and other emissive blocks vec3 lightning; //Light caused by lightning vec3 nolight; //Base ambient light added to ev erything. For lighting caves so that the player can barely see even when no ligh ts are present vec3 translucent; //Light on the backside of objec ts representing thin translucent materials vec3 sky; //Color and brightness o f the sky itself vec3 underwater; //underwater colors } final;

/////////////////////////STRUCT FUNCTIONS/////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// /////////////////////////STRUCT FUNCTIONS/////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// //Mask void CalculateMasks(inout MaskStruct mask) { mask.sky = GetMaterialMask(texcoord.st, 0 , mask.matIDs); mask.land = GetMaterialMask(texcoord.st, 1

, mask.matIDs); mask.grass atIDs); mask.leaves , mask.matIDs); mask.ice , mask.matIDs); mask.hand , mask.matIDs); mask.translucent atIDs); mask.glow 0, mask.matIDs); mask.sunspot matIDs); mask.goldBlock matIDs); mask.ironBlock matIDs); mask.diamondBlock matIDs); mask.emeraldBlock matIDs); mask.sand 4, mask.matIDs); mask.sandstone matIDs); mask.stone 6, mask.matIDs); mask.cobblestone matIDs); mask.wool 8, mask.matIDs); mask.clouds matIDs); mask.torch 0, mask.matIDs); mask.lava 1, mask.matIDs); mask.glowstone matIDs); mask.fire 3, mask.matIDs); mask.water .matIDs); mask.volumeCloud } //Surface void CalculateNdotL(inout SurfaceStruct surface) { //Calculates dir ect sunlight without visibility check float direct = dot(surface.normal.rgb, surface.lightVector); direct = direct * 1.0f + 0.0f; //direct = clamp(direct, 0.0f, 1.0f); = false; = GetMaterialMask(texcoord.st, 2 = GetMaterialMask(texcoord.st, 25, mask. = GetMaterialMask(texcoord.st, 2 = GetMaterialMask(texcoord.st, 27, mask. = GetMaterialMask(texcoord.st, 2 = GetMaterialMask(texcoord.st, 29, mask. = GetMaterialMask(texcoord.st, 3 = GetMaterialMask(texcoord.st, 3 = GetMaterialMask(texcoord.st, 32, mask. = GetMaterialMask(texcoord.st, 3 = GetWaterMask(texcoord.st, mask = GetMaterialMask(texcoord.st, 23, mask. = GetMaterialMask(texcoord.st, 22, mask. = GetMaterialMask(texcoord.st, 21, mask. = GetMaterialMask(texcoord.st, 1 = GetMaterialMask(texcoord.st, 11, mask. = GetMaterialMask(texcoord.st, 20, mask. = GetMaterialMask(texcoord.st, 6, mask.m = GetMaterialMask(texcoord.st, 5 = GetMaterialMask(texcoord.st, 4 = GetMaterialMask(texcoord.st, 3 = GetMaterialMask(texcoord.st, 2, mask.m

surface.NdotL = direct; } float CalculateDirectLighting(in SurfaceStruct surface) { //Tall grass translucent shading if (surface.mask.grass) { return 1.0f; //Leaves } else if (surface.mask.leaves) { // if (surface.NdotL > -0.01f) { // return surface.NdotL * 0.99f + 0.01f; // } else { // return abs(surface.NdotL) * 0.25f; // } return 1.0f; //clouds } else if (surface.mask.clouds) { return 0.5f; //Default lambert shading } else { return max(0.0f, surface.NdotL * 0.99f + 0.01f); } } float CalculateSunlightVisibility(inout SurfaceStruct surface, in ShadingStruc t shadingStruct) { //Calculates shadows if (rainStrength >= 0.99f) return 1.0f; if (shadingStruct.direct > 0.0f) { float distance = sqrt( surface.screenSpacePosition.x * surface. screenSpacePosition.x //Get surface distance in meters + surface.screenSpaceP osition.y * surface.screenSpacePosition.y + surface.screenSpaceP osition.z * surface.screenSpacePosition.z); vec4 worldposition = vec4(0.0f); worldposition = gbufferModelViewInverse * surface.scree nSpacePosition; //Transform from screen space to world space float yDistanceSquared = worldposition.y * worldposition.y; worldposition = shadowModelView * worldposition; orm from world space to shadow space float comparedepth = -worldposition.z; //Surface distance from sun to be compared to the shadow map worldposition = shadowProjection * worldposition; //Transf

worldposition /= worldposition.w; float dist = sqrt(worldposition.x * worldposition.x + worldposit ion.y * worldposition.y); float distortFactor = (1.0f - SHADOW_MAP_BIAS) + dist * SHADOW_M AP_BIAS; worldposition.xy *= 1.0f / distortFactor; worldposition = worldposition * 0.5f + 0.5f; //Transf orm from shadow space to shadow map coordinates float shadowMult = 0.0f; //Multiplier used to fade out shadows at distance float shading = 0.0f; if (distance < shadowDistance && comparedepth > 0.0f && //Avoid computing shadows past the shadow map projection worldposition.s < 1.0f && worldposition.s > 0.0f && wor ldposition.t < 1.0f && worldposition.t > 0.0f) { float fademult = 0.15f; shadowMult = clamp((shadowDistance * 0.85f * fad emult) - (distance * fademult), 0.0f, 1.0f); //Calculate shadowMult to fade s hadows out float diffthresh = dist * 1.0f + 0.10f; diffthresh *= 3.0f / (shadowMapResolution / 20 48.0f); //diffthresh /= shadingStruct.direct + 0.1f; #if defined ENABLE_SOFT_SHADOWS int count = 0; float spread = 1.0f / shadowMapResolution; for (float i = -1.0f; i <= 1.0f; i += 1.0f) { for (float j = -1.0f; j <= 1.0f; j += 1. 0f) { shading += shadow2D(shadow, vec 3(worldposition.st + vec2(i, j) * spread, worldposition.z - 0.0018f * diffthresh )).x; count += 1; } } shading /= count; #else diffthresh *= 3.0f; shading = shadow2D(shadow, vec3(worldposition.st , worldposition.z - 0.0008f * diffthresh)).x; #endif } shading = mix(1.0f, shading, shadowMult); surface.shadow = shading; return shading; } else {

return 0.0f; } } float CalculateBouncedSunlight(in SurfaceStruct surface) { float NdotL = surface.NdotL; float bounced = clamp(-NdotL + 0.95f, 0.0f, 1.95f) / 1.95f; bounced = bounced * bounced * bounced; return bounced; } float CalculateScatteredSunlight(in SurfaceStruct surface) { float NdotL = surface.NdotL; float scattered = clamp(NdotL * 0.75f + 0.25f, 0.0f, 1.0f); //scattered *= scattered * scattered; return scattered; } float CalculateSkylight(in SurfaceStruct surface) { if (surface.mask.clouds) { return 1.0f; } else if (surface.mask.leaves) { return 1.0f; } else if (surface.mask.grass) { return 1.0f; } else { float skylight = dot(surface.normal, surface.upVector); skylight = skylight * 0.5f + 0.5f; return skylight; } } float CalculateScatteredUpLight(in SurfaceStruct surface) { float scattered = dot(surface.normal, surface.upVector); scattered = scattered * 0.5f + 0.5f; scattered = 1.0f - scattered; return scattered; } float CalculateSunglow(in SurfaceStruct surface) { float curve = 4.0f; vec3 npos = normalize(surface.screenSpacePosition.xyz); vec3 halfVector2 = normalize(-surface.lightVector + npos); float factor = 1.0f - dot(halfVector2, npos);

return factor * factor * factor * factor; } float CalculateAntiSunglow(in SurfaceStruct surface) { float curve = 4.0f; vec3 npos = normalize(surface.screenSpacePosition.xyz); vec3 halfVector2 = normalize(surface.lightVector + npos); float factor = 1.0f - dot(halfVector2, npos); return factor * factor * factor * factor; } bool CalculateSunspot(in SurfaceStruct surface) { //circular sun float curve = 1.0f; vec3 npos = normalize(surface.screenSpacePosition.xyz); vec3 halfVector2 = normalize(-surface.lightVector + npos); float sunProximity = 1.0f - dot(halfVector2, npos); if (sunProximity > 0.96f) { return true; } else { return false; } //Sun based on matID // if (surface.mask.sunspot) // return true; // else // return false; } void GetLightVectors(inout MCLightmapStruct mcLightmap, in SurfaceStruct surf ace) { vec2 torchDiff = vec2(0.0f); torchDiff.x = GetLightmapTorch(texcoord.st) - GetLightmapTorch( texcoord.st + vec2(1.0f / viewWidth, 0.0f)); torchDiff.y = GetLightmapTorch(texcoord.st) - GetLightmapTorch( texcoord.st + vec2(0.0f, 1.0f / viewWidth)); //torchDiff /= GetDepthLinear(texcoord.st); mcLightmap.torchVector.x = torchDiff.x * 200.0f; //mcLightmap.torchVector.x *= 1.0f - surface.viewVector.x; mcLightmap.torchVector.y = torchDiff.y * 200.0f; mcLightmap.torchVector.x = 1.0f; mcLightmap.torchVector.y = 0.0f; mcLightmap.torchVector.z = sqrt(1.0f - mcLightmap.torchVector.x * mcLigh tmap.torchVector.x + mcLightmap.torchVector.y + mcLightmap.torchVector.y);

float torchNormal = dot(surface.normal.rgb, mcLightmap.torchVector.rgb); mcLightmap.torchVector.x = torchNormal; //mcLightmap.torchVector = mcLightmap.torchVector * 0.5f + 0.5f; } void AddSkyGradient(inout SurfaceStruct surface) { float curve = 4.0f; vec3 npos = normalize(surface.screenSpacePosition.xyz); vec3 halfVector2 = normalize(-surface.upVector + npos); float skyGradientFactor = dot(halfVector2, npos); float skyDirectionGradient = skyGradientFactor;

skyGradientFactor = pow(skyGradientFactor, curve); surface.sky.albedo *= mix(skyGradientFactor, 1.0f, clamp((0.12f - (timeN oon * 0.1f)) + rainStrength, 0.0f, 1.0f)); vec3 skyBlueColor = vec3(0.15f, 0.35f, 1.0f) * 1.75f; skyBlueColor.g *= skyGradientFactor * 2.0f + 0.75f; skyBlueColor = mix(skyBlueColor, vec3(1.0f, 1.2f, 1.0f), vec3(timeSkyDar k)); skyBlueColor *= mix(vec3(1.0f), vec3(1.0f, 1.0f, 0.5f), vec3(timeSunrise + timeSunset)); float fade1 = clamp(skyGradientFactor - 0.12f, 0.0f, 0.2f) / 0.2f; vec3 color1 = vec3(1.0f, 1.5, 1.0f) * 0.5f; color1 = mix(color1, vec3(1.0f, 0.25f, 0.0f), vec3(timeSunrise + timeSunset)); surface.sky.albedo *= mix(skyBlueColor, color1, vec3(fade1)); float fade2 = clamp(skyGradientFactor - 0.18f, 0.0f, 0.2f) / 0.2f; vec3 color2 = vec3(1.7f, 1.0f, 0.8f); color2 = mix(color2, vec3(1.0f, 0.15f, 0.0f), vec3(timeSunrise + timeSunset)); surface.sky.albedo *= mix(vec3(1.0f), color2, vec3(fade2 * 0.5f));

float horizonGradient = 1.0f - distance(skyDirectionGradient, 0.72f) / 0 .72f; horizonGradient = pow(horizonGradient, 10.0f); horizonGradient = max(0.0f, horizonGradient); float sunglow = CalculateSunglow(surface); horizonGradient *= sunglow * 2.0f + (0.65f - timeSunrise * 0.5 5f - timeSunset * 0.55f); vec3 horizonColor1 = vec3(1.5f, 1.5f, 1.5f); horizonColor1 = mix(horizonColor1, vec3(1.5f, 1.95f, 0.5f) * 2. 0f, vec3(timeSunrise + timeSunset)); vec3 horizonColor2 = vec3(1.5f, 1.2f, 0.8f) * 1.0f; horizonColor2 = mix(horizonColor2, vec3(1.9f, 0.6f, 0.4f) * 2.0 f, vec3(timeSunrise + timeSunset));

surface.sky.albedo *= mix(vec3(1.0f), horizonColor1, vec3(horizonGradien t) * (1.0f - timeMidnight)); surface.sky.albedo *= mix(vec3(1.0f), horizonColor2, vec3(pow(horizonGra dient, 2.0f)) * (1.0f - timeMidnight)); float grayscale = surface.sky.albedo.r + surface.sky.albedo.g + surface. sky.albedo.b; grayscale /= 3.0f; surface.sky.albedo = mix(surface.sky.albedo, vec3(grayscale) * 1.4f, vec 3(rainStrength)); } void AddSunglow(inout SurfaceStruct surface) { float sunglowFactor = CalculateSunglow(surface); float antiSunglowFactor = CalculateAntiSunglow(surface);

surface.sky.albedo *= 1.0f + sunglowFactor * (15.0f + timeNoon * 5.0f) * (1.0f - rainStrength); surface.sky.albedo *= mix(vec3(1.0f), colorSunlight, pow(clamp(vec3(sung lowFactor) * (1.0f - timeMidnight) * (1.0f - rainStrength), vec3(0.0f), vec3(1.0 f)), vec3(2.0f))); surface.sky.albedo *= 1.0f + antiSunglowFactor * 2.0f * (1.0f - rainStre ngth); //surface.sky.albedo *= mix(vec3(1.0f), colorSunlight, antiSunglowFactor ); } void AddCloudGlow(inout vec3 color, in SurfaceStruct surface) { float glow = CalculateSunglow(surface); glow = pow(glow, 1.0f); float mult = mix(50.0f, 800.0f, timeSkyDark); color.rgb *= 1.0f + glow * mult * float(surface.mask.clouds); } void te) { CalculateUnderwaterFog(in SurfaceStruct surface, inout vec3 finalComposi vec3 fogColor = colorWaterMurk * vec3(colorSkylight.b); // float fogDensity = 0.045f; // float fogFactor = exp(GetDepthLinear(texcoord.st) * fogDensity) - 1.0 f; // fogFactor = min(fogFactor, 1.0f); float fogFactor = GetDepthLinear(texcoord.st) / 100.0f; fogFactor = min(fogFactor, 0.7f); fogFactor = sin(fogFactor * 3.1415 / 2.0f); fogFactor = pow(fogFactor, 0.5f); finalComposite.rgb = mix(finalComposite.rgb, fogColor * 0.002f, vec3(fog Factor)); finalComposite.rgb *= mix(vec3(1.0f), colorWaterBlue * colorWaterBlue * colorWaterBlue * colorWaterBlue, vec3(fogFactor)); //finalComposite.rgb = vec3(0.1f); }

void {

TestRaymarch(inout vec3 color, in SurfaceStruct surface) //visualize march steps float rayDepth = 0.0f; float rayIncrement = 0.05f; float fogFactor = 0.0f;

while (rayDepth < 1.0f) { vec4 rayPosition = GetScreenSpacePosition(texcoord.st, pow(rayDe pth, 0.002f));

if (abs(rayPosition.z - surface.screenSpacePosition.z) < 0.025f) { color.rgb = vec3(0.01f, 0.0f, 0.0f); } // if (SphereTestDistance(vec3(surface.screenSpacePosition.x, su rface.screenSpacePosition.y, surface.screenSpacePosition.z)) <= 0.001f) // fogFactor += 0.001f; rayDepth += rayIncrement; } // color.rgb = mix(color.rgb, vec3(1.0f) * 0.01f, fogFactor); // vec4 newPosition = surface.screenSpacePosition; // color.rgb = vec3(distance(newPosition.rgb, vec3(0.0f, 0.0f, 0.0f)) * 0.00001f); } void InitializeAO(inout SurfaceStruct surface) { surface.ao.skylight = 1.0f; surface.ao.bouncedSunlight = 1.0f; surface.ao.scatteredUpLight = 1.0f; surface.ao.constant = 1.0f; } void CalculateAO(inout SurfaceStruct surface) { const int numSamples = 20; vec3[numSamples] kernel; vec3 stochastic = texture2D(noisetex, texcoord.st * vec2(viewWidth, view Height) / noiseTextureResolution).rgb; //Generate positions for sample points in hemisphere for (int i = 0; i < numSamples; i++) { //Random direction kernel[i] = vec3(texture2D(noisetex, vec2(0.0f + (i * 1.0f) / no iseTextureResolution)).r * 2.0f - 1.0f, texture2D(noisetex, vec2(0.0f + (i

* 1.0f) / noiseTextureResolution)).g * 2.0f - 1.0f, texture2D(noisetex, vec2(0.0f + (i * 1.0f) / noiseTextureResolution)).b * 2.0f - 1.0f); //kernel[i] += (stochastic * vec3(2.0f, 2.0f, 1.0f) - vec3(1.0f, 1.0f, 0.0f)) * 0.0f; kernel[i] = normalize(kernel[i]); //scale randomly to distribute within hemisphere; kernel[i] *= pow(texture2D(noisetex, vec2(0.3f + (i * 1.0f) / no iseTextureResolution)).r * CalculateNoisePattern1(vec2(43.0f), 64.0f).x * 1.0f, 1.2f); } //Determine origin position and normal vec3 origin = surface.screenSpacePosition.xyz; vec3 normal = surface.normal.xyz; //normal = lightVector; //Create matrix to orient hemisphere according to surface normal //vec3 randomRotation = texture2D(noisetex, texcoord.st * vec2(viewWidth / noiseTextureResolution, viewHeight / noiseTextureResolution)).rgb * 2.0f - 1. 0f; //float dither1 = CalculateDitherPattern1() * 2.0f - 1.0f; //randomRotation = vec3(dither1, mod(dither1 + 0.5f, 2.0f), mod( dither1 + 1.0f, 2.0f)); vec3 randomRotation = CalculateNoisePattern1(vec2(0.0f), 64.0f).xyz * 2.0f - 1.0f; //vec3 randomRotation = vec3(1.0f, 0.0f, 0.0f); vec3 tangent = normalize(randomRotation - upVector * dot(randomRotation, upVector)); vec3 bitangent = cross(upVector, tangent); mat3 tbn = mat3(tangent, bitangent, upVector); float float float float float ao = 0.0f; aoSkylight aoUp aoBounced aoScattered = = = = 0.0f; 0.0f; 0.0f; 0.0f;

float aoRadius = 0.35f * -surface.screenSpacePosition.z; //aoRadius = 3.0f; float zThickness = 0.35f * -surface.screenSpacePosition.z; zThickness = 6.0f; vec3 float vec4 float float float samplePosition intersect sampleScreenSpace sampleDepth distanceWeight finalRadius = vec3(0.0f); = 0.0f; = vec4(0.0f); = 0.0f; = 0.0f; = 0.0f;

float skylightWeight = 0.0f; float bouncedWeight = 0.0f; float scatteredUpWeight = 0.0f; float scatteredSunWeight = 0.0f; vec3 bentNormal = vec3(0.0f);

for (int i = 0; i < numSamples; i++) { samplePosition = tbn * kernel[i]; samplePosition = samplePosition * aoRadius + origin; intersect = dot(normalize(samplePosition - origin), surface.norm al); if (intersect > 0.2f) { //Convert camera space to screen space sampleScreenSpace = gbufferProjection * vec4(samplePosit ion, 1.0f); sampleScreenSpace.xyz /= sampleScreenSpace.w; sampleScreenSpace.xyz = sampleScreenSpace.xyz * 0.5f + 0 .5f; //Check depth at sample point sampleDepth = GetScreenSpacePosition(sampleScreenSpace.x y).z; //If point is behind geometry, buildup AO if (sampleDepth >= samplePosition.z && !surface.mask.sky ) { //Reduce halo float sampleLength = length(samplePosition - ori gin) * 4.0f; //distanceWeight = 1.0f - clamp(distance(sampleD epth, origin.z) - (sampleLength * 0.5f), 0.0f, sampleLength * 0.5f) / (sampleLen gth * 0.5f); distanceWeight = 1.0f - step(sampleLength, dista nce(sampleDepth, origin.z)); //Weigh samples based on light direction skylightWeight = clamp(dot(norm alize(samplePosition - origin), upVector) * 1.0f - 0.0f , 0.0f, 0. 01f) / 0.01f; //skylightWeight += clamp(dot( normalize(samplePosition - origin), upVector), 0.0f, 1.0f); bouncedWeight = clamp(dot(norm alize(samplePosition - origin), -lightVector) * 1.0f - 0.0f , 0.0f, 0.51f) / 0 .51f; scatteredUpWeight = clamp(dot(norm alize(samplePosition - origin), -upVector) * 1.0f - 0.0f , 0.0f, 0. 51f) / 0.51f; scatteredSunWeight = clamp(dot(norm alize(samplePosition - origin), lightVector) * 1.0f - 0.25f, 0.0f, 0.51f) / 0 .51f; //buildup occlusion more for further f acing surfaces /= clamp(dot(normal, upVector) /= clamp(dot(normal, -lightVector) (dot(normal, -upVector) (dot(normal, lightVector) skylightWeight * 0.5f + 0.501f, 0.01f, bouncedWeight * 0.5f + 0.501f, 0.01f, scatteredUpWeight * 0.5f + 0.501f, 0.01f, 1.0f); scatteredSunWeight * 0.75f + 0.25f, 0.01f, 1.0f); 1.0f); 1.0f); /= clamp /= clamp

//Accumulate ao ao ; eight eredUpWeight edWeight SunWeight gin); } } } bentNormal.rgb /= numSamples; ao /= numSamples; aoSkylight /= numSamples; aoUp /= numSamples; aoBounced /= numSamples; aoScattered /= numSamples; ao = 1.0f - ao; aoSkylight = 1.0f - aoSkylight; aoUp = 1.0f - aoUp; aoBounced = 1.0f - aoBounced; aoScattered = 1.0f - aoScattered; ao = clamp(ao, aoSkylight = clamp(aoSkylight, aoUp = clamp(aoUp, aoBounced = clamp(aoBounced, aoScattered = clamp(aoScattered, surface.ao.constant 1.0f); surface.ao.skylight 3.0f); surface.ao.bouncedSunlight 6.0f); surface.ao.scatteredUpLight surface.ao.scatteredSunlight ; } else { ; aoUp ; aoBounced ;

+= 2.0f * distanceWeight

aoSkylight += 2.0f * distanceWeight * skylightW += 2.0f * distanceWeight * scatt += 2.0f * distanceWeight * bounc

aoScattered += 2.0f * distanceWeight * scattered bentNormal.rgb += normalize(samplePosition - ori

0.0f, 1.0f); 0.0f, 1.0f); 0.0f, 1.0f); 0.0f, 1.0f); 0.0f, 1.0f); = pow(ao, = pow(aoSkylight, = pow(aoBounced, = pow(aoUp, 6.0f); = pow(aoScattered, 1.0f);

surface.debug = vec3(pow(aoSkylight, 2.0f) * clamp((dot(surface.normal, upVector) * 0.75f + 0.25f), 0.0f, 1.0f)); //surface.debug = vec3(dot(normalize(bentNormal), upVector)); } void { CalculateRainFog(inout vec3 color, in SurfaceStruct surface) vec3 fogColor = colorSkylight * 0.055f; float fogDensity = 0.0018f * rainStrength;

fogDensity *= mix(0.0f, 1.0f, pow(eyeBrightnessSmooth.y / 240. 0f, 6.0f)); float visibility = 1.0f / (pow(exp(distance(surface.screenSpacePosition. xyz, vec3(0.0f)) * fogDensity), 1.0f)); float fogFactor = 1.0f - visibility; fogFactor = clamp(fogFactor, 0.0f, 1.0f); fogFactor = mix(fogFactor, 1.0f, float(surface.mask.sky) * 0.8 f * rainStrength); fogFactor = mix(fogFactor, 1.0f, float(surface.mask.clouds) * 0.8f * rainStrength); color = mix(color, fogColor, vec3(fogFactor)); } void e) { CalculateAtmosphericScattering(inout vec3 color, in SurfaceStruct surfac vec3 fogColor = mix(colorSkylight, colorSunlight, vec3(0.05f)) * 0.11f; float sat = 0.5f; fogColor.r = fogColor.r * (1.0f + sat) - (fogColor.g + fogColor .b) * 0.5f * sat; fogColor.g = fogColor.g * (1.0f + sat) - (fogColor.r + fogColor .b) * 0.5f * sat; fogColor.b = fogColor.b * (1.0f + sat) - (fogColor.r + fogColor .g) * 0.5f * sat; float sunglow = pow(CalculateSunglow(surface), 2.0f); vec3 sunColor = colorSunlight; fogColor += mix(vec3(0.0f), sunColor, sunglow * 0.8f); float fogDensity = 0.004f; fogDensity *= mix(0.0f, 1.0f, pow(eyeBrightnessSmooth.y / 240. 0f, 6.0f)); float visibility = 1.0f / (pow(exp(distance(surface.screenSpacePosition. xyz, vec3(0.0f)) * fogDensity), 1.0f)); float fogFactor = 1.0f - visibility; fogFactor = clamp(fogFactor, 0.0f, 1.0f); fogFactor = pow(fogFactor, 2.7f); //fogFactor = mix(fogFactor, 1.0f, float(surface.mask.sky) * 0 .8f * rainStrength); //fogFactor = mix(fogFactor, 1.0f, float(surface.mask.clouds) * 0.8f * rainStrength); fogFactor = mix(fogFactor, 0.0f, min(1.0f, surface.sky.sunSpot.r)); fogFactor *= mix(1.0f, 0.25f, float(surface.mask.sky)); fogFactor *= mix(1.0f, 0.75f, float(surface.mask.clouds)); float redshift = 1.5f * (1.0f - rainStrength); redshift *= float(surface.mask.land); //scatter away high frequency light color.b *= 1.0f - clamp(fogFactor * 1.65 * redshift, 0.0f, 0.75f); color.g *= 1.0f - fogFactor * 0.4* redshift; color.g *= 1.0f - clamp(fogFactor - 0.26f, 0.0f, 1.0f) * 0.5* redshift; //add scattered low frequency light color += fogColor * fogFactor * 1.0f;

} float Get3DNoise(in vec3 pos) { pos.z += 0.0f; vec3 p = floor(pos); vec3 f = fract(pos); vec2 uv = (p.xy + p.z * vec2(17.0f)) + f.xy; vec2 uv2 = (p.xy + (p.z + 1.0f) * vec2(17.0f)) + f.xy; vec2 coord = (uv + 0.5f) / noiseTextureResolution; vec2 coord2 = (uv2 + 0.5f) / noiseTextureResolution; float xy1 = texture2D(noisetex, coord).x; float xy2 = texture2D(noisetex, coord2).x; return mix(xy1, xy2, f.z); } vec4 CloudColor(in vec3 worldPosition, in float sunglow) { float float float float ight) return vec4(0.0f); else { vec3 p = worldPosition.xyz / 40.0f; float t = frameTimeCounter; //t *= 0.0; p.x += t * 0.005f; float noise = Get3DNoise(p) * 1.0f; p *= 4.0f; p.x += t * 0.07f; noise += (1.0f - abs(Get3DNoise(p) * 3.0f - 1.0f)) * 0 .30f; p *= 3.0f; p.xz += t * 0.15f; noise += (1.0f - abs(Get3DNoise(p) * 3.0f - 1.0f)) * 0 .085f; p *= 2.0f; p.xz += t * 0.15f; noise += (1.0f - abs(Get3DNoise(p) * 3.0f - 1.0f)) * 0 .06f; noise /= 1.2f; float cloudAltitudeWeight = 1.0f - clamp(distance(worldPosition. y, cloudHeight) / (cloudDepth / 2.0f), 0.0f, 1.0f); cloudAltitudeWeight = pow(cloudAltitudeWeight, 0.15f); noise *= cloudAltitudeWeight; //cloud edge float coverage = 0.4f; coverage = mix(coverage, 0.77f, rainStrength); float density = 0.05f; noise = clamp(noise - (1.0f - coverage), 0.0f, 1.0f - density) / cloudHeight = 140.0f; cloudDepth = 25.0f; cloudUpperHeight = cloudHeight + (cloudDepth / 2.0f); cloudLowerHeight = cloudHeight - (cloudDepth / 2.0f);

if (worldPosition.y < cloudLowerHeight || worldPosition.y > cloudUpperHe

(1.0f - density); float sunProximity = pow(sunglow, 1.0f); float propigation = mix(3.0f, 18.0f, sunProximity); float heightGradient = clamp(( - (cloudLowerHeight - worldPositi on.y) / cloudDepth), 0.0f, 1.0f); float directLightFalloff = pow(heightGradient, propigation); * 2.5f, 0.0f, 1.0f), low, 1.2f)); directLightFalloff *= mix( clamp(pow(noise, 0.85f) clamp(pow(1.0f - noise, 10.3f), 0.0f, 0.5f), pow(sung

vec3 colorDirect = colorSunlight * 1.0f; colorDirect *= 1.0f + pow(sunglow, 10.0f) * 100.0f; colorDirect *= 1.0f + pow(sunglow, 2.0f) * 100.0f; vec3 colorAmbient = mix(colorSkylight, colorSunlight, 0.15f) * 0 .075f; colorAmbient *= 1.0f + clamp(pow(noise, 1.0f) * 1.0f, 0 .0f, 1.0f); colorAmbient *= heightGradient + 0.75f; vec3 colorBounced = colorBouncedSunlight * 0.05f; colorBounced *= pow((1.0f - heightGradient), 5.0f); vec3 color = mix(colorAmbient, colorDirect, vec3(min(1.0f, direc tLightFalloff * 4.0))); color += colorBounced; //vec3 color = colorAmbient; color *= clamp(pow(noise, 0.1f), 0.0f, 1.0f); color *= mix(1.0f, 0.1f, timeMidnight); vec4 result = vec4(color.rgb, noise); return result; } } void { CalculateClouds (inout vec3 color, inout SurfaceStruct surface) //if (texcoord.s < 0.5f && texcoord.t < 0.5f) //{ vec2 coord = texcoord.st * 2.0f; vec4 worldPosition = gbufferModelViewInverse * surface.screenSpa cePosition; worldPosition.xyz += cameraPosition.xyz; float cloudHeight = 140.0f; float cloudDepth = 25.0f; float cloudDensity = 1.0f; float rayDepth = 1.0f; rayDepth += CalculateDitherPattern1() * 0.11f; //rayDepth += texture2D(noisetex, texcoord.st * (viewW

idth / noiseTextureResolution, viewHeight / noiseTextureResolution)).x * 0.1f; //rayDepth += CalculateDitherPattern2() * 0.1f; float rayIncrement = 0.025f; float previousRayDistance = 0.0f; int i = 0; vec3 cloudColor = colorSunlight; vec4 cloudSum = vec4(0.0f); cloudSum.rgb = colorSkylight * 0.2f; cloudSum.rgb = color.rgb; float sunglow = CalculateSunglow(surface); while (rayDepth > 0.0f) { //determine worldspace ray position vec4 rayPosition = GetWorldSpacePosition(texcoord.st, po w(rayDepth, 0.0005f * (1.0f - rayDepth))); if (rayPosition.y > cloudHeight - (cloudHeight / 2.0f) & & rayPosition.y < cloudHeight + (cloudHeight / 2.0f)) { //determine screen space ray position float rayDistance = length(rayPosition.xyz - cam eraPosition.xyz); float surfaceDistance = length(worldPosition.xyz - cameraPosition.xyz); //if ray is past surface, don't accumulate if (rayDistance < surfaceDistance) { //add cloud density. Multiply by ray dis tance traveled if (i > 0) { float stepDistance = abs(rayDist ance - previousRayDistance); vec4 proximity = CloudColor(ray Position.xyz, sunglow); proximity.a *= min(step Distance * cloudDensity, cloudDensity); cloudSum.rgb = mix(cloudSum.rgb, proximity.rgb, vec3(pow(min(1.0f, proximity.a * 1.2f), 0.1f))); cloudSum.a += proximity.a * 1.0f ; } else //add cloud density for first step { float stepDistance = 0.0f; vec4 proximity = CloudColor(ray Position.xyz, sunglow); proximity.a *= min(step Distance * 0.9f, 1.0f); cloudSum.rgb = mix(cloudSum.rgb, proximity.rgb, vec3(min(1.0f, proximity.a * 2.0f)));

cloudSum.a += proximity.a; } //record previous ray position previousRayDistance = rayDistance; } } //Increment ray rayDepth -= rayIncrement; i++; } color.rgb = mix(color.rgb, cloudSum.rgb, vec3(min(1.0f, cloudSum .a * 20.0f))); //if (cloudSum.a > 0.0f) //color.rgb = mix(color.rgb, colorSunlight * 4.0f, 1.0f - pow(cl oudSum.a, 0.02f)); if (cloudSum.a > 0.00f) { surface.mask.volumeCloud = true; } //} //color.rgb = vec3(noise) * 0.2f; } void { SnowShader(inout SurfaceStruct surface) float snowFactor = dot(surface.normal, upVector); snowFactor = clamp(snowFactor - 0.1f, 0.0f, 0.05f) / 0.05f; surface.albedo = mix(surface.albedo.rgb, vec3(1.0f), vec3(snowFactor)); } //////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////MAIN/////////////// /////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// void main() { //Initialize surface properties required for lighting calculation for an y surface that is not part of the sky surface.albedo = GetAlbedoLinear(texcoord.st); //Gets the albedo texture surface.albedo = pow(surface.albedo, vec3(1.4f) ); surface.albedo = mix(surface.albedo, vec3(dot(surface.albedo, vec3(0.333 3f))), vec3(0.075f));

//surface.albedo = vec3(0.8f); surface.normal = GetNormals(texcoord.st); //Gets the screen-space normals surface.depth = GetDepth(texcoord.st); //Gets the scene depth surface.linearDepth = ExpToLinearDepth(surface.depth); //Get linear scene depth surface.screenSpacePosition = GetScreenSpacePosition(texcoord.st); //Gets the screen-space position surface.viewVector = normalize(surface.screenSpaceP osition.rgb); //Gets the view vector surface.lightVector = lightVector; //Gets the sunlight vector surface.upVector = upVector; //Store the up vector

surface.mask.matIDs //Gets material ids CalculateMasks(surface.mask);

= GetMaterialIDs(texcoord.st);

surface.albedo *= 1.0f - float(surface.mask.sky); //Remove the sky from surface albedo, because sky will be handled separately //surface.water.albedo = surface.albedo * float(surface.mask.water); //Store underwater albedo //surface.albedo *= 1.0f - float(surface.mask.water); //Remove water from surface albedo to handle water separately

//Initialize sky surface properties surface.sky.albedo = GetAlbedoLinear(texcoord.st) * (min(1. 0f, float(surface.mask.sky) + float(surface.mask.sunspot))); //Gets the albedo texture for the sky surface.sky.tintColor = mix(colorSunlight, vec3(colorSunlight.r), vec3 (0.8f)); //Initializes the defualt tint color for the sky surface.sky.tintColor *= mix(1.0f, 500.0f, timeSkyDark); //Boost sky color at night //Scale sunglow back to be less intense surface.sky.sunSpot = vec3(float(CalculateSunspot(surface))) * vec3( (min(1.0f, float(surface.mask.sky) + float(surface.mask.sunspot)))) * colorSunli ght; surface.sky.sunSpot *= 1.0f - timeMidnight; surface.sky.sunSpot *= 1500.0f; surface.sky.sunSpot *= 1.0f - rainStrength; //surface.sky.sunSpot *= 1.0f - timeMidnight; AddSkyGradient(surface); AddSunglow(surface);

//Initialize MCLightmap values mcLightmap.torch = GetLightmapTorch(texcoord.st); //Gets the lightmap for light coming from emissive blocks mcLightmap.sky = GetLightmapSky(texcoord.st); //Gets the lightmap for light coming from the sky // mcLightmap.sky = 1.0f / pow((1.0f - mcLightmap.sky + 0. 00001f), 2.0f); // mcLightmap.sky -= 1.0f; // mcLightmap.sky = max(0.0f, mcLightmap.sky); mcLightmap.lightning = 0.0f; //gets the lightmap for light coming from lightning //Initialize default surface shading attributes surface.diffuse.roughness = 0.0f; //Default surface roughness surface.diffuse.translucency = 0.0f; //Default surface translucency surface.diffuse.translucencyColor = vec3(1.0f); //Default translucency color surface.specular.specularity = //Gets the reflectance/specularity of the surface surface.specular.extraSpecularity = //Default value for extra specularity surface.specular.glossiness = surface.specular.metallic //Default value of how metallic the surface is surface.specular.gain //Default surface specular gain surface.specular.base //Default reflectance when the surface normal and surface.specular.fresnelPower = //Default surface fresnel power GetSpecularity(texcoord.st); 0.0f; GetGlossiness(texcoord.st); = 0.0f; = 1.0f; = 0.0f; viewing normal are aligned 5.0f;

//Calculate surface shading CalculateNdotL(surface); shading.direct = CalculateDirectLighting(surfac e); //Calculate direct sunlight without visibility c heck (shadows) shading.direct = mix(shading.direct, 1.0f, floa t(surface.mask.water)); //Remove shading from water shading.sunlightVisibility = CalculateSunlightVisibility(surface, s hading); //Calculate shadows and apply th em to direct lighting shading.direct *= shading.sunlightVisibility; shading.direct *= mix(1.0f, 0.0f, rainStrength) ; shading.waterDirect = shading.direct; shading.direct *= pow(mcLightmap.sky, 0.1f); shading.bounced = CalculateBouncedSunlight(surface); //Calculate fake bounced sunlight shading.scattered = CalculateScatteredSunlight(surface); //Calculate fake scattered sunlight

shading.skylight = CalculateSkylight(surface); //Calculate scattered light from sky shading.scatteredUp = CalculateScatteredUpLight(surface); InitializeAO(surface); //if (texcoord.s < 0.5f && texcoord.t < 0.5f) //CalculateAO(surface); //Colorize surface shading and store in lightmaps lightmap.sunlight = vec3(shading.direct) * colorSu nlight; AddCloudGlow(lightmap.sunlight, surface); //lightmap.sunlight *= 2.0f - AO; lightmap.skylight = vec3(mcLightmap.sky); lightmap.skylight *= mix(pow(colorSkylight, vec3(1 .3f)), colorBouncedSunlight, max(vec3(0.0f), (vec3(1.0f - pow(mcLightmap.sky + 0 .23f, 0.45f)) * 1.0f) + (1.0f - shading.skylight) * 0.25f)); lightmap.skylight *= shading.skylight; lightmap.skylight *= mix(1.0f, 5.0f, float(surface .mask.clouds)); lightmap.skylight *= mix(1.0f, 50.0f, float(surfac e.mask.clouds) * timeSkyDark); lightmap.skylight *= surface.ao.skylight; //lightmap.skylight *= surface.ao.constant * 0.5f + 0.5f; lightmap.skylight += mix(colorSkylight, colorSunli ght, vec3(0.2f)) * vec3(mcLightmap.sky) * surface.ao.constant * 0.15f; lightmap.bouncedSunlight nlight; lightmap.bouncedSunlight ); lightmap.bouncedSunlight nset); lightmap.bouncedSunlight lightmap.bouncedSunlight //lightmap.bouncedSunlight *= mix(1.0f, 0.0f, rainStrength); *= surface.ao.bouncedSunlight; *= surface.ao.constant * 0.5f + 0.5f; *= mix(1.0f, 0.25f, timeSunrise + timeSu *= pow(vec3(mcLightmap.sky), vec3(1.75f) = vec3(shading.bounced) * colorBouncedSu

lightmap.scatteredSunlight = vec3(shading.scattered) * colorScatteredSu nlight; lightmap.scatteredSunlight ; lightmap.scatteredSunlight *= surface.ao.scatteredSunlight; //lightmap.scatteredSunlight *= surface.ao.constant * 0.5f + 0.5f; lightmap.underwater lightmap.torchlight lightmap.torchlight tant; lightmap.nolight lightmap.nolight lightmap.scatteredUpLight unlight, colorSkylight, vec3(0.3f)); = vec3(0.05f); *= surface.ao.constant; = vec3(shading.scatteredUp) * mix(colorS = vec3(mcLightmap.sky) * colorSkylight; = mcLightmap.torch * colorTorchlight; *= surface.ao.constant * surface.ao.cons *= pow(vec3(mcLightmap.sky), vec3(1.0f))

lightmap.scatteredUpLight *= pow(mcLightmap.sky, 0.5f); lightmap.scatteredUpLight *= surface.ao.scatteredUpLight; lightmap.scatteredUpLight *= mix(1.0f, 0.1f, rainStrength); //lightmap.scatteredUpLight *= surface.ao.constant * 0.5f + 0.5f;

//If eye is in water if (isEyeInWater > 0) { vec3 halfColor = mix(colorWaterMurk, vec3(1.0f), vec3(0.5f)); lightmap.sunlight *= mcLightmap.sky * halfColor; lightmap.skylight *= halfColor; lightmap.bouncedSunlight *= 0.0f; lightmap.scatteredSunlight *= halfColor; lightmap.nolight *= halfColor; lightmap.scatteredUpLight *= halfColor; } //Apply lightmaps to albedo and generate final shaded surface final.nolight = surface.albedo * lightmap.nolight; final.sunlight = surface.albedo * lightmap.sunlight; final.skylight = surface.albedo * lightmap.skylight; final.bouncedSunlight = surface.albedo * lightmap.bouncedSunlight; final.scatteredSunlight = surface.albedo * lightmap.scatteredSunlight; final.scatteredUpLight = surface.albedo * lightmap.scatteredUpLight; final.torchlight = surface.albedo * lightmap.torchlight; final.underwater = surface.water.albedo * colorWaterBlue; // final.underwater *= GetUnderwaterLightmapSky(texcoord.st) ; // final.underwater += vec3(0.9f, 1.00f, 0.35f) * float(surf ace.mask.water) * 0.065f; final.underwater *= (lightmap.sunlight * 0.3f) + (lightma p.skylight * 0.06f) + (lightmap.torchlight * 0.0165) + (lightmap.nolight * 0.002 f); //final.glow.torch = pow(surface.albedo, ve c3(4.0f)) * float(surface.mask.torch); final.glow.lava = Glowmap(surface.albedo , surface.mask.lava, 6.0f, vec3(1.0f, 0.05f, 0.001f)); final.glow.glowstone e.mask.glowstone, 3.2f, colorTorchlight); final.torchlight glowstone); final.glow.fire (surface.mask.fire); final.glow.fire ec3(1.0f)); = Glowmap(surface.albedo, surfac *= 1.0f - float(surface.mask. = surface.albedo * float = pow(final.glow.fire, v

//Remove glow items from torchlight to keep control final.torchlight *= 1.0f - float(surface.mask.lava); //Do night eye effect on outdoor lighting and sky DoNightEye(final.sunlight);

DoNightEye(final.skylight); DoNightEye(final.bouncedSunlight); DoNightEye(final.scatteredSunlight); DoNightEye(surface.sky.albedo); DoNightEye(final.underwater); DoLowlightEye(final.nolight); float sunlightMult = 0.8f; //Apply lightmaps to albedo and generate final shaded surface vec3 finalComposite = final.sunlight * 0.35f //* sunlightMult //Add direct sunlight + final.skylight * 0.04f //Add ambient skylight + final.nolight * 0.0001f //Add base ambient light + final.bouncedSunlight * 0.015f * sunlightMult //Add fake bounced sunli ght + final.scatteredSunlight * 0.00f * sunlightMult //Add fake scattered sunlight + final.scatteredUpLight * 0.0025f * sunlightMult + final.torchlight * 2.0f //Add light coming from emissive blocks + final.glow.lava * 7.6f + final.glow.glowstone * 5.1f + final.glow.fire * 0.05f ; //Apply sky to final composite surface.sky.albedo *= 0.95f; surface.sky.albedo = surface.sky.albedo * surface.sky.tintColor + surface.sky.sunglow + surface.sky.sunSpot; surface.sky.albedo *= mix(1.0f, 0.125f, timeMidnight); //DoNightEye(surface.sky.albedo); finalComposite += surface.sky.albedo; //Add sk y to final image //if eye is in water, do underwater fog if (isEyeInWater > 0) { CalculateUnderwaterFog(surface, finalComposite); } CalculateRainFog(finalComposite.rgb, surface); CalculateAtmosphericScattering(finalComposite.rgb, surface); CalculateClouds(finalComposite.rgb, surface); //finalComposite.rgb = texture2D(shadowcolor, texcoord.st).rgb * 0.05f; //finalComposite.rgb = vec3(AO) * 0.2f;

finalComposite *= 0.0005f; //Scale image down for HDR finalComposite.b *= 1.0f;

//TestRaymarch(finalComposite.rgb, surface); //finalComposite.rgb = surface.debug * 0.00004f; finalComposite = pow(finalComposite, vec3(1.0f / 2.2f)); //Convert final image into gamma 0.45 space to compensate for gamma 2.2 on displ ays finalComposite = pow(finalComposite, vec3(1.0f / BANDING_FIX_FACTOR)); //Convert final image into banding fix space to help reduce color banding // if (finalComposite.r > 1.0f) { // finalComposite.r = 0.0f; // } // if (finalComposite.g > 1.0f) { // finalComposite.g = 0.0f; // } // if (finalComposite.b > 1.0f) { // finalComposite.b = 0.0f; // }

gl_FragData[0] = vec4(finalComposite, 1.0f); gl_FragData[1] = vec4(surface.mask.matIDs, mcLightmap.torch, mcLightmap. sky, 1.0f); gl_FragData[2] = vec4(surface.normal.rgb * 0.5f + 0.5f, 1.0f); gl_FragData[3] = vec4(surface.specular.specularity, surface.shadow, surf ace.specular.glossiness, 1.0f); // gl_FragData[4] = vec4(surface.albedo, 1.0f); // gl_FragData[5] = vec4(lightmap.) }

You might also like