0% found this document useful (0 votes)
30 views6 pages

Block Reflection V3

This document contains GLSL shader code for rendering a dynamic scene with atmospheric effects, clouds, and reflections. It includes functions for tone mapping, atmospheric scattering, and BRDF calculations, as well as a main function that computes the final color output based on the viewer's perspective. The shader is designed for use in a real-time rendering context, utilizing various techniques to simulate realistic lighting and materials.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
30 views6 pages

Block Reflection V3

This document contains GLSL shader code for rendering a dynamic scene with atmospheric effects, clouds, and reflections. It includes functions for tone mapping, atmospheric scattering, and BRDF calculations, as well as a main function that computes the final color output based on the viewer's perspective. The shader is designed for use in a real-time rendering context, utilizing various techniques to simulate realistic lighting and materials.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

#version 310 es

#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif

uniform vec2 resolution;


uniform float time;
//uniform sampler2D ironblock;
uniform vec2 touch;
uniform sampler2D ironblock;///min:n;mag:n;s:r;t:r;
float rainy = 0.0;

#define u_resolution resolution


#define u_mouse touch
#define u_time time
#define CAM_FOV 2.5
#define MOUSE_SENSITIVITY 6.3
#define SPHERE_SIZE 0.04
#define saturate(x) clamp(x,0.0,1.0)
out vec4 outCol;

/* CONFIG */
// PLAY AROUND WITH THE CODE
// Search learnopengl to learn about this
#define ROUGHNESS 0.2
#define METALLIC 0.0 // I set it zero it darkens texture
#define SUNCOLOR vec3(1.0, 0.5, 0.1)
#define RESOLUTION 102 // in Rd you will set it to [128,256,512,1024]
const float PI = 3.141592653589793;

// --- Tone mapping ---


vec3 ACESFilm(vec3 x) {
return clamp((x * (2.51 * x + 0.03)) /
(x * (2.43 * x + 0.59) + 0.14), 0.0, 1.0);
}

// --- Atmospheric scattering ---


float rayleighPhase(float cosTheta) {
return (3.0 / (16.0 * PI)) * (1.0 + cosTheta * cosTheta);
}

float miePhase(float cosTheta, float g) {


float g2 = g * g;
return (1.0 - g2) /
(4.0 * PI * pow(1.0 + g2 - 2.0 * g * cosTheta, 1.5));
}

float opticaldepth(float k, float Vy) {


return 1.0 - exp(-k * max(Vy, 0.0));
}

vec3 scattering(vec3 viewDir, vec3 sunDir) {


float cosTheta = dot(viewDir, sunDir);
float depth = opticaldepth(2.0, viewDir.y);

float r = rayleighPhase(cosTheta);
float m = miePhase(cosTheta, 0.8);

vec3 rayleighColor = vec3(0.8, 0.8, 1.0) * r * depth;


vec3 mieColor = vec3(1.0, 0.5, 0.1) * m * depth;

return rayleighColor + mieColor;


}

// --- Sky color ---


vec3 skyColor(vec3 viewDir, vec3 sunDir,bool sky) {
float y = smoothstep(0.0, 1.0, viewDir.y);
vec3 dayhorizon = vec3(0.7, 0.85, 1.0);
vec3 dayzenith = vec3(0.2, 0.5, 0.9);
vec3 duskzenith = vec3(0.1, 0.15, 0.3);
vec3 duskhorizon = vec3(1.0, 0.35, 0.1);
vec3 nightzenith = vec3(0.03, 0.05, 0.15);
vec3 nighthorizon = vec3(0.07, 0.1, 0.25);

vec3 up = vec3(0.0, 1.0, 0.0);


float sunHeight = dot(normalize(sunDir), up);

float dayThreshold = 0.8;


float duskThreshold = 0.7;

vec3 skyCol;

if (sunHeight > dayThreshold) {


skyCol = mix(dayhorizon, dayzenith, y);
} else if (sunHeight > duskThreshold) {
float t = smoothstep(duskThreshold, dayThreshold, sunHeight);
vec3 dayColor = mix(dayhorizon, dayzenith, y);
vec3 duskColor = mix(duskhorizon, duskzenith, y);
skyCol = mix(duskColor, dayColor, t);
} else if (sunHeight > -duskThreshold) {
float t = smoothstep(-duskThreshold, duskThreshold, sunHeight);
vec3 duskColor = mix(duskhorizon, duskzenith, y);
vec3 nightColor = mix(nighthorizon, nightzenith, y);
skyCol = mix(nightColor, duskColor, t);
} else {
skyCol = mix(nighthorizon, nightzenith, y);
}
if(sky){
skyCol += scattering(viewDir, sunDir);
}else{
}
return skyCol;
}
// === ACES Tonemapping ===
vec3 RRTAndODTFit(vec3 v) {
vec3 a = v * (v + 0.0245786) - 0.000090537;
vec3 b = v * (0.983729 * v + 0.4329510) + 0.238081;
return a / b;
}

vec3 ACESFittedTonemap(vec3 color) {


return saturate(RRTAndODTFit(color));
}

// === Saturation ===


vec3 AdjustSaturation(vec3 color, float saturation) {
float avg = (color.r + color.g + color.b) / 3.0;
return mix(vec3(avg), color, saturation);
}

vec3 colorPost(vec3 col){


col = ACESFittedTonemap(col);
col = saturate(col);
col = AdjustSaturation(col,1.15);
return col;
}
float hash13(vec3 p) {
p = fract(p * 0.1031);
p += dot(p, p.yzx + 33.33);
return fract((p.x + p.y) * p.z);
}

vec4 sampleClouds(vec3 rayOrigin, vec3 viewDir, float cloudBase, float cloudTop,


float cellSize, float time,vec2 sp) {
int steps = 4;
float stepSize = (cloudTop - cloudBase) / float(steps);

vec3 cloudAccum = vec3(0.0);


float alphaAccum = 0.0;

float viewLift = smoothstep(0.01, 0.1, viewDir.y);

for (int i = 0; i < steps; i++) {


float height = cloudBase + stepSize * float(i);
float t = height / max(viewDir.y, 0.001);

float jitterX = fract(sin(dot(sp.xy + vec2(float(i), height),


vec2(12.9898,78.233))) * 43758.5453) - 0.5;
float jitterZ = fract(sin(dot(sp.xy + vec2(height, float(i)),
vec2(93.9898,67.345))) * 43758.5453) - 0.5;

vec3 pos = rayOrigin + viewDir * t;

float base = hash13(floor(pos/0.9));


float density = step(0.55, base);

float heightNorm = (height - cloudBase) / (cloudTop - cloudBase);


float heightFactor =
step(0.2, heightNorm) *
(1.0 - step(0.6, heightNorm));
density = pow(density,2.2) * heightFactor;
float alpha = density * (1.0 - alphaAccum) * viewLift;
float scattering = smoothstep(0.0, 0.5, heightNorm);
cloudAccum += vec3(1.0) * (scattering)*alpha;
alphaAccum += alpha;

if (alphaAccum > 0.98 && viewDir.y < 0.9) break;


}

return vec4(cloudAccum, alphaAccum);


}
float fresnelSchlickRoughness(vec3 N, vec3 V, float F0, float roughness)
{
float cosTheta = clamp(dot(normalize(N), normalize(V)), 0.0, 1.0);
return F0 + (max(1.0 - roughness, F0) - F0) * pow(1.0 - cosTheta, 5.0);
}
float luminance601(vec3 color) {
return color.r * 0.299 + color.g * 0.587 + color.b * 0.114;
}

vec3 getNormal(sampler2D TEXTURE_0, vec2 coord) {


float offsets = 1.0 / float(RESOLUTION);
//float offsets = 0.00125;

float lumR = luminance601(texture(TEXTURE_0, coord + vec2(offsets, 0.0)).rgb);


float lumL = luminance601(texture(TEXTURE_0, coord - vec2(offsets, 0.0)).rgb);
float lumD = luminance601(texture(TEXTURE_0, coord + vec2(0.0, offsets)).rgb);
float lumU = luminance601(texture(TEXTURE_0, coord - vec2(0.0, offsets)).rgb);

vec2 gradient = vec2(lumR - lumL, lumD - lumU);


float lenSq = dot(gradient, gradient);
vec3 normal = normalize(vec3(gradient, sqrt(max(0.0,1.0-lenSq))));

return normalize(normal);
}

mat3 getTBN(vec3 normal) {


vec3 T = vec3(abs(normal.y) + normal.z, 0.0, normal.x);
vec3 B = vec3(0.0, -abs(normal).x - abs(normal).z, abs(normal).y);
vec3 N = normal;
return transpose(mat3(T, B, N));
}
vec3 brdf(vec3 lightDir, vec3 viewDir, float roughness, vec3 normal, vec3 albedo,
float metallic, vec3 reflectance, vec3 sunCol) {

float alpha = pow(roughness,2.0);

vec3 H = normalize(lightDir + viewDir);

//dot products
float NdotV = clamp(dot(normal, viewDir), 0.5,1.0);
float NdotL = clamp(dot(normal, lightDir), 0.5,1.0);
float NdotH = clamp(dot(normal,H), 0.5,1.0);
float VdotH = clamp(dot(viewDir, H), 0.5,1.0);

// Fresnel
vec3 F0 = reflectance;
vec3 fresnelReflectance = F0 + (1.0 - F0) * pow(1.0 - VdotH, 5.0); //Schlick's
Approximation

//phong diffuse
vec3 rhoD = albedo;
rhoD *= (vec3(1.0)- fresnelReflectance); //energy conservation - light that
doesn't reflect adds to diffuse

rhoD *= (1.0-metallic); //diffuse is 0 for metals

// Geometric attenuation
float k = alpha/2.0;
float geometry = (NdotL / (NdotL*(1.0-k)+k)) * (NdotV / ((NdotV*(1.0-k)+k)));
// Distribution of Microfacets
float lowerTerm = pow(NdotH,2.0) * (pow(alpha,2.0) - 1.0) + 1.0;
float normalDistributionFunctionGGX = pow(alpha,2.0) / (3.14159 *
pow(lowerTerm,2.0));

vec3 phongDiffuse = rhoD; //


vec3 cookTorrance =
(fresnelReflectance*normalDistributionFunctionGGX*geometry)/(4.0*NdotL*NdotV);

vec3 BRDF = (phongDiffuse+cookTorrance*sunCol)*NdotL;

vec3 diffFunction = BRDF;

return BRDF;
}

// --- World rendering ---


vec3 renderWorld(vec3 vdir, vec3 wpos, float t) {
vec3 sunDir = normalize(vec3(cos(t * 0.05), sin(t * 0.05), 0.2));
vec3 s = skyColor(vdir, sunDir,true);

if (wpos.y > 0.0) {


vec3 rayOrigin = vec3(0.0);
float cloudBase = 1.5;
float cloudTop = 2.0;
float cellSize = 0.9;
vec2 screenpos = gl_FragCoord.xy;

vec4 clouds = sampleClouds(rayOrigin, vdir, cloudBase, cloudTop, cellSize,


time, screenpos);
s = mix(s, clouds.rgb, clouds.a*0.3);
// Sky
} else {
// Reflection
vec2 waterUV = vdir.xz/vdir.y ;
vec2 blockuv = wpos.xz/wpos.y;

vec3 blockNormal = getNormal(ironblock, waterUV)*2.0;


vec3 worldPos = wpos.xyz; // in Rd use v_position = a_position in vertex
vec3 dpx = dFdx(worldPos);
vec3 dpy = dFdy(worldPos);
vec3 Ngeo = normalize(cross(dpx, dpy));
mat3 TBN = getTBN(Ngeo);

// in Rd you will use mul(Tex/position,mat3)


// example : vec3 worldNormal = normalize(mul(blockNormal,TBN)).xyz;

vec3 worldNormal = normalize(TBN*blockNormal).xyz;

vec3 V = normalize(-wpos);//viewDir used by normals


vdir = reflect(vdir, worldNormal);//distortion using worldNormal

vec3 rayOrigin = vec3(0.0);


float cloudBase = 1.5;
float cloudTop = 2.0;
float cellSize = 0.9;
vec2 screenpos = gl_FragCoord.xy;

vec4 clouds = sampleClouds(rayOrigin, vdir, cloudBase, cloudTop, cellSize,


time, screenpos);

//won't explain this since it doesn't work as expected but good enough
float fresnel = fresnelSchlickRoughness(worldNormal,V, 0.6, 0.2);

s = skyColor(vdir, sunDir,false);
s = mix(s, clouds.rgb, clouds.a*0.2);
vec3 base = texture(ironblock,blockuv).rgb;
//albedo = base.rgb = texture without shading

// s is skyColor
base.rgb = base.rgb * (1.0 - fresnel) + s * fresnel;

vec3 F0_Iron = vec3(0.56, 0.57, 0.58);//reflectance

vec3 specular = brdf(sunDir,V,ROUGHNESS, worldNormal, base.rgb,


METALLIC,F0_Iron,SUNCOLOR);
s = 1.9 * specular;
}

return s;
}

// --- Main ---


void main() {
vec2 uv = (gl_FragCoord.xy - 0.5 * u_resolution.xy) / u_resolution.x;
vec2 an = MOUSE_SENSITIVITY * ((u_mouse.yx / u_resolution.yx) - 0.5);
an.x = clamp(-an.x, -1.57, 1.57);
vec2 s = sin(an), c = cos(an);
mat3 r = mat3(
c.y, s.x * s.y, c.x * s.y,
0.0, c.x, -s.x,
-s.y, s.x * c.y, c.x * c.y
);

vec3 vdir = normalize(vec3(uv, 1.0 / tan(0.5 * CAM_FOV))) * r;

vec2 st = gl_FragCoord.xy / (u_resolution.x * SPHERE_SIZE) - 1.4;


bool f = st.x > 1.0; if (f) st.x -= 2.3;
float d = dot(st, st);
if (d < 1.0) {
vdir = vec3(st, sqrt(1.0 - d));
if (f) vdir = vdir.xzy;
}

vec3 wpos = vdir / abs(vdir.y);


vec3 color = renderWorld(vdir, wpos, u_time);
outCol = vec4(colorPost(color), 1.0);
}

You might also like