#version 120 const float pi = 3.14159265358; const float tau = 6.28318530717; uniform sampler2D surfaceData, biomes, lookup; varying vec2 uv[5], uvB; uniform vec2 cracksColorIntensity; uniform vec4[3] biomesPicks; uniform vec2 texSize; uniform vec2 fullSize; varying vec2 blur; // calculates palette for cracks vec3 paletteCracks(float c) { return 0.5 + 0.5 * cos(tau * (1.0 * c + vec3(0.0, 0.33, 0.67)) ); } // pow alternatives vec3 square(vec3 x) { return x*x; } // pow alternatives float dotter(vec3 x) { return dot(x,x); } vec2 square(vec2 x) { return x*x; } float square(float x) { return x*x; } vec3 pow3(vec3 x) { return x*x*x; } void main() { // clamp so we don't get south poles blending into north poles an vice versa vec2 uvL; vec2 uvS = uv[0]; vec2 surfUV = texSize / fullSize; vec2 surfMin = vec2(0.0, blur.y); vec2 surfMax = vec2(1.0, 1.0 - blur.y); if(uvS.x < surfUV.x) { surfMin.x = blur.x; surfMax.x = surfUV.x - blur.x * 0.5; } if(uvS.y < surfUV.y) { surfMin.y = blur.y; surfMax.y = surfUV.y - blur.y * 0.5; } vec4 splatMap = texture2D(surfaceData, clamp(uvS, surfMin, surfMax)); if(splatMap.a < 0.5 && splatMap.r < 0.5 && splatMap.g < 0.5) discard; vec3 albedo = vec3(0.0); float cracks = 0.0; vec2 cracksWaterMask = vec2(0.0); // make barren moon if(splatMap.a < 0.5 && splatMap.r > 0.5) { vec2 moonBiome = texture2D(biomes, uvB + vec2(0.25, 0.5)).ba; moonBiome.g = clamp((1.0 - moonBiome.g), 0.00390625, 0.984375); albedo += texture2D(lookup, vec2(0.4072265625, moonBiome.g)).rgb * (0.5 + moonBiome.r); } // else make terran continent 0.6103515625 else if(splatMap.a < 0.5 && splatMap.g > 0.5) { vec2 continentBiome = texture2D(biomes, uvB + vec2(0.5, 0.5)).ba; continentBiome.g = clamp((1.0 - continentBiome.g), 0.00390625, 0.984375); albedo += texture2D(lookup, vec2(0.4072265625, continentBiome.g)).rgb * (0.5 + continentBiome.r); } // make regular biome else { splatMap.rgb *= 2.0; for (int i = 0; i < 4; i++) { uvL = uv[i+1]; vec2 blurUV = clamp(uvL, surfMin, surfMax); splatMap.rgb += texture2D(surfaceData, blurUV).rgb; } splatMap.rgb *= 0.166666666; cracksWaterMask = vec2((splatMap.b - 0.5) * 2.0); cracksWaterMask = max(vec2(0.0),vec2(-1.0 * cracksWaterMask.x, cracksWaterMask.y)); // need to sample xy normal channels vec2 firstBiome = texture2D(biomes, uvB + biomesPicks[0].xy).ba; vec2 secondBiome = texture2D(biomes, uvB + biomesPicks[1].xy).ba; vec2 thirdBiome = texture2D(biomes, uvB + biomesPicks[2].xy).ba; vec3 heightSamps = vec3(firstBiome.g, secondBiome.g, thirdBiome.g); vec2 splatMaskMixed = vec2(firstBiome.g + secondBiome.g, secondBiome.g + thirdBiome.g); splatMaskMixed = min(vec2(1.0), (splatMaskMixed + splatMap.rg) * splatMap.rg); heightSamps = clamp((1.0 - heightSamps), vec3(0.00390625), vec3(0.984375)); // sample albedo, no need to sample roughness data vec3 firstBiomesAlbedoR = texture2D(lookup, vec2(biomesPicks[0].z, heightSamps.r)).rgb; //, 0.0 vec3 secondBiomesAlbedoR = texture2D(lookup, vec2(biomesPicks[1].z, heightSamps.g)).rgb; //, 0.0 vec3 thirdBiomesAlbedoR = texture2D(lookup, vec2(biomesPicks[2].z, heightSamps.b)).rgb; //, 0.0 vec2 dataSamp = mix(mix(firstBiome, secondBiome, splatMaskMixed.r), thirdBiome, splatMaskMixed.g); float ao = min(1.0,(dataSamp.r * 2.0)); cracks = min(1.0, (1.0 - ao) * cracksWaterMask.r); vec3 glow = pow3(paletteCracks(fract(cracks * 0.025 + cracksColorIntensity.x)) * cracks * cracksColorIntensity.y); albedo += mix(mix(firstBiomesAlbedoR, secondBiomesAlbedoR, splatMaskMixed.r), thirdBiomesAlbedoR, splatMaskMixed.g); albedo.rgb *= 0.25 + dataSamp.r; float waterDepth = max(0.0, 1.0 - (dataSamp.g + square(cracksWaterMask.y))); vec3 oceanColor = texture2D(lookup, vec2(biomesPicks[0].z, max(0.995,waterDepth * 0.0025))).rgb * (waterDepth * 0.66 + 0.33); // from 0.0065 to 0.0025 cracksWaterMask.y = max(0.0, ceil(dataSamp.g - cracksWaterMask.y)); albedo = mix(oceanColor, albedo, cracksWaterMask.y) * (1.0 - cracks) + glow * 8.0; } gl_FragColor.rgb = albedo; gl_FragColor.a = 1.0; }