mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	This is the language used for writing OpenGL shaders, which are becoming much more mainstream lately.
		
			
				
	
	
		
			630 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			GLSL
		
	
	
	
	
	
			
		
		
	
	
			630 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			GLSL
		
	
	
	
	
	
| //// High quality (Some browsers may freeze or crash)
 | ||
| //#define HIGHQUALITY
 | ||
| 
 | ||
| //// Medium quality (Should be fine on all systems, works on Intel HD2000 on Win7 but quite slow)
 | ||
| //#define MEDIUMQUALITY
 | ||
| 
 | ||
| //// Defaults
 | ||
| //#define REFLECTIONS
 | ||
| #define SHADOWS
 | ||
| //#define GRASS
 | ||
| //#define SMALL_WAVES
 | ||
| #define RAGGED_LEAVES
 | ||
| //#define DETAILED_NOISE
 | ||
| //#define LIGHT_AA // 2 sample SSAA
 | ||
| //#define HEAVY_AA // 2x2 RG SSAA
 | ||
| //#define TONEMAP
 | ||
| 
 | ||
| //// Configurations
 | ||
| #ifdef MEDIUMQUALITY
 | ||
| 	#define SHADOWS
 | ||
| 	#define SMALL_WAVES
 | ||
| 	#define RAGGED_LEAVES
 | ||
| 	#define TONEMAP
 | ||
| #endif
 | ||
| 
 | ||
| #ifdef HIGHQUALITY
 | ||
| 	#define REFLECTIONS
 | ||
| 	#define SHADOWS
 | ||
| 	//#define GRASS
 | ||
| 	#define SMALL_WAVES
 | ||
| 	#define RAGGED_LEAVES
 | ||
| 	#define DETAILED_NOISE
 | ||
| 	#define LIGHT_AA
 | ||
| 	#define TONEMAP
 | ||
| #endif
 | ||
| 
 | ||
| // Constants
 | ||
| const float eps = 1e-5;
 | ||
| const float PI = 3.14159265359;
 | ||
| 
 | ||
| const vec3 sunDir = vec3(0.79057,-0.47434, 0.0);
 | ||
| const vec3 skyCol = vec3(0.3, 0.5, 0.8);
 | ||
| const vec3 sandCol = vec3(0.9, 0.8, 0.5);
 | ||
| const vec3 treeCol = vec3(0.8, 0.65, 0.3);
 | ||
| const vec3 grassCol = vec3(0.4, 0.5, 0.18);
 | ||
| const vec3 leavesCol = vec3(0.3, 0.6, 0.2);
 | ||
| const vec3 leavesPos = vec3(-5.1,13.4, 0.0);
 | ||
| 
 | ||
| #ifdef TONEMAP
 | ||
| const vec3 sunCol = vec3(1.8, 1.7, 1.6);
 | ||
| #else
 | ||
| const vec3 sunCol = vec3(0.9, 0.85, 0.8);
 | ||
| #endif
 | ||
| 
 | ||
| const float exposure = 1.1; // Only used when tonemapping
 | ||
| 
 | ||
| // Description : Array and textureless GLSL 2D/3D/4D simplex
 | ||
| // noise functions.
 | ||
| // Author : Ian McEwan, Ashima Arts.
 | ||
| // License : Copyright (C) 2011 Ashima Arts. All rights reserved.
 | ||
| // Distributed under the MIT License. See LICENSE file.
 | ||
| // https://github.com/ashima/webgl-noise
 | ||
| vec3 mod289(vec3 x) {
 | ||
|   return x - floor(x * (1.0 / 289.0)) * 289.0;
 | ||
| }
 | ||
| 
 | ||
| vec4 mod289(vec4 x) {
 | ||
|   return x - floor(x * (1.0 / 289.0)) * 289.0;
 | ||
| }
 | ||
| 
 | ||
| vec4 permute(vec4 x) {
 | ||
|      return mod289(((x*34.0)+1.0)*x);
 | ||
| }
 | ||
| 
 | ||
| vec4 taylorInvSqrt(vec4 r) {
 | ||
|   return 1.79284291400159 - 0.85373472095314 * r;
 | ||
| }
 | ||
| 
 | ||
| float snoise(vec3 v) {
 | ||
|   const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;
 | ||
|   const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
 | ||
| 
 | ||
| // First corner
 | ||
|   vec3 i = floor(v + dot(v, C.yyy) );
 | ||
|   vec3 x0 = v - i + dot(i, C.xxx) ;
 | ||
| 
 | ||
| // Other corners
 | ||
|   vec3 g = step(x0.yzx, x0.xyz);
 | ||
|   vec3 l = 1.0 - g;
 | ||
|   vec3 i1 = min( g.xyz, l.zxy );
 | ||
|   vec3 i2 = max( g.xyz, l.zxy );
 | ||
| 
 | ||
|   // x0 = x0 - 0.0 + 0.0 * C.xxx;
 | ||
|   // x1 = x0 - i1 + 1.0 * C.xxx;
 | ||
|   // x2 = x0 - i2 + 2.0 * C.xxx;
 | ||
|   // x3 = x0 - 1.0 + 3.0 * C.xxx;
 | ||
|   vec3 x1 = x0 - i1 + C.xxx;
 | ||
|   vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
 | ||
|   vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
 | ||
| 
 | ||
| // Permutations
 | ||
|   i = mod289(i);
 | ||
|   vec4 p = permute( permute( permute(
 | ||
|              i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
 | ||
|            + i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
 | ||
|            + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
 | ||
| 
 | ||
| // Gradients: 7x7 points over a square, mapped onto an octahedron.
 | ||
| // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
 | ||
|   float n_ = 0.142857142857; // 1.0/7.0
 | ||
|   vec3 ns = n_ * D.wyz - D.xzx;
 | ||
| 
 | ||
|   vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
 | ||
| 
 | ||
|   vec4 x_ = floor(j * ns.z);
 | ||
|   vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)
 | ||
| 
 | ||
|   vec4 x = x_ *ns.x + ns.yyyy;
 | ||
|   vec4 y = y_ *ns.x + ns.yyyy;
 | ||
|   vec4 h = 1.0 - abs(x) - abs(y);
 | ||
| 
 | ||
|   vec4 b0 = vec4( x.xy, y.xy );
 | ||
|   vec4 b1 = vec4( x.zw, y.zw );
 | ||
| 
 | ||
|   //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
 | ||
|   //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
 | ||
|   vec4 s0 = floor(b0)*2.0 + 1.0;
 | ||
|   vec4 s1 = floor(b1)*2.0 + 1.0;
 | ||
|   vec4 sh = -step(h, vec4(0.0));
 | ||
| 
 | ||
|   vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
 | ||
|   vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
 | ||
| 
 | ||
|   vec3 p0 = vec3(a0.xy,h.x);
 | ||
|   vec3 p1 = vec3(a0.zw,h.y);
 | ||
|   vec3 p2 = vec3(a1.xy,h.z);
 | ||
|   vec3 p3 = vec3(a1.zw,h.w);
 | ||
| 
 | ||
| //Normalise gradients
 | ||
|   vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
 | ||
|   p0 *= norm.x;
 | ||
|   p1 *= norm.y;
 | ||
|   p2 *= norm.z;
 | ||
|   p3 *= norm.w;
 | ||
| 
 | ||
| // Mix final noise value
 | ||
|   vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
 | ||
|   m = m * m;
 | ||
|   return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
 | ||
|                                 dot(p2,x2), dot(p3,x3) ) );
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| // Main
 | ||
| float fbm(vec3 p)
 | ||
| {
 | ||
| 	float final = snoise(p); 
 | ||
| 	p *= 1.94; final += snoise(p) * 0.5;
 | ||
| 	#ifdef DETAILED_NOISE
 | ||
| 	p *= 3.75; final += snoise(p) * 0.25;
 | ||
| 	return final / 1.75;
 | ||
| 	#else
 | ||
| 	return final / 1.5;
 | ||
| 	#endif
 | ||
| }
 | ||
| 
 | ||
| float waterHeight(vec3 p)
 | ||
| {
 | ||
| 	float d = length(p.xz);
 | ||
| 	float h = sin(d * 1.5 + iGlobalTime * 3.0) * 12.0 / d; // Island waves
 | ||
| 	#ifdef SMALL_WAVES
 | ||
| 	h += fbm(p*0.5); // Other waves
 | ||
| 	#endif
 | ||
| 	return h;
 | ||
| }
 | ||
| 
 | ||
| vec3 bump(vec3 pos, vec3 rayDir)
 | ||
| {
 | ||
| 	float s = 2.0;
 | ||
| 	
 | ||
| 	// Fade out waves to reduce aliasing
 | ||
| 	float dist = dot(pos, rayDir);
 | ||
| 	s *= dist < 2.0 ? 1.0 : 1.4142 / sqrt(dist);
 | ||
| 	
 | ||
| 	// Calculate normal from heightmap
 | ||
| 	vec2 e = vec2(1e-2, 0.0);
 | ||
| 	vec3 p = vec3(pos.x, iGlobalTime*0.5, pos.z)*0.7;
 | ||
| 	float m = waterHeight(p)*s;
 | ||
| 	return normalize(vec3(
 | ||
| 		waterHeight(p+e.xyy)*s-m,
 | ||
| 		1.0,
 | ||
| 		waterHeight(p+e.yxy)*s-m
 | ||
| 	));
 | ||
| }
 | ||
| 
 | ||
| // Ray intersections
 | ||
| vec4 intersectSphere(vec3 rpos, vec3 rdir, vec3 pos, float rad)
 | ||
| {
 | ||
| 	vec3 op = pos - rpos;
 | ||
| 	float b = dot(op, rdir); 
 | ||
| 	float det = b*b - dot(op, op) + rad*rad; 
 | ||
| 		
 | ||
| 	if (det > 0.0)
 | ||
| 	{
 | ||
| 		det = sqrt(det);
 | ||
| 		float t = b - det;
 | ||
| 		if (t > eps)
 | ||
| 			return vec4(-normalize(rpos+rdir*t-pos), t);
 | ||
| 	}
 | ||
| 	
 | ||
| 	return vec4(0.0);
 | ||
| }
 | ||
| 
 | ||
| vec4 intersectCylinder(vec3 rpos, vec3 rdir, vec3 pos, float rad)
 | ||
| {
 | ||
| 	vec3 op = pos - rpos;
 | ||
| 	vec2 rdir2 = normalize(rdir.yz);
 | ||
| 	float b = dot(op.yz, rdir2);
 | ||
| 	float det = b*b - dot(op.yz, op.yz) + rad*rad; 
 | ||
| 	
 | ||
| 	if (det > 0.0)
 | ||
| 	{
 | ||
| 		det = sqrt(det);
 | ||
| 		float t = b - det;
 | ||
| 		if (t > eps)
 | ||
| 			return vec4(-normalize(rpos.yz+rdir2*t-pos.yz), 0.0, t);
 | ||
| 		t = b + det;
 | ||
| 		if (t > eps)
 | ||
| 			return vec4(-normalize(rpos.yz+rdir2*t-pos.yz), 0.0, t);
 | ||
| 	}
 | ||
| 	
 | ||
| 	return vec4(0.0);
 | ||
| }
 | ||
| 
 | ||
| vec4 intersectPlane(vec3 rayPos, vec3 rayDir, vec3 n, float d)
 | ||
| {
 | ||
| 	float t = -(dot(rayPos, n) + d) / dot(rayDir, n);
 | ||
| 	return vec4(n * sign(dot(rayDir, n)), t);
 | ||
| }
 | ||
| 
 | ||
| // Helper functions
 | ||
| vec3 rotate(vec3 p, float theta)
 | ||
| {
 | ||
| 	float c = cos(theta), s = sin(theta);
 | ||
| 	return vec3(p.x * c + p.z * s, p.y,
 | ||
| 				p.z * c - p.x * s);
 | ||
| }
 | ||
| 
 | ||
| float impulse(float k, float x) // by iq
 | ||
| {
 | ||
|     float h = k*x;
 | ||
|     return h * exp(1.0 - h);
 | ||
| }
 | ||
| 
 | ||
| // Raymarched parts of scene
 | ||
| float grass(vec3 pos)
 | ||
| {
 | ||
| 	float h = length(pos - vec3(0.0, -7.0, 0.0)) - 8.0;
 | ||
| 	
 | ||
| 	if (h > 2.0) return h; // Optimization (Avoid noise if too far away)
 | ||
| 	
 | ||
| 	return h + snoise(pos * 3.0) * 0.1 + pos.y * 0.9;
 | ||
| }
 | ||
| 
 | ||
| float tree(vec3 pos)
 | ||
| {
 | ||
| 	pos.y -= 0.5;
 | ||
| 	float s = sin(pos.y*0.03);
 | ||
| 	float c = cos(pos.y*0.03);
 | ||
| 	mat2 m = mat2(c, -s, s, c);
 | ||
| 	vec3 p = vec3(m*pos.xy, pos.z);
 | ||
| 	
 | ||
| 	float width = 1.0 - pos.y * 0.02 - clamp(sin(pos.y * 8.0) * 0.1, 0.05, 0.1);
 | ||
| 	
 | ||
| 	return max(length(p.xz) - width, pos.y - 12.5);
 | ||
| }
 | ||
| 
 | ||
| vec2 scene(vec3 pos)
 | ||
| {
 | ||
| 	float vtree = tree(pos);
 | ||
| 	#ifdef GRASS
 | ||
| 	float vgrass = grass(pos);
 | ||
| 	float v = min(vtree, vgrass);
 | ||
| 	#else
 | ||
| 	float v = vtree;
 | ||
| 	#endif
 | ||
| 	return vec2(v, v == vtree ? 2.0 : 1.0);
 | ||
| }
 | ||
| 
 | ||
| vec3 normal(vec3 pos)
 | ||
| {
 | ||
| 	vec2 eps = vec2(1e-3, 0.0);
 | ||
| 	float h = scene(pos).x;
 | ||
| 	return normalize(vec3(
 | ||
| 		scene(pos-eps.xyy).x-h,
 | ||
| 		scene(pos-eps.yxy).x-h,
 | ||
| 		scene(pos-eps.yyx).x-h
 | ||
| 	));
 | ||
| }
 | ||
| 
 | ||
| float plantsShadow(vec3 rayPos, vec3 rayDir)
 | ||
| {
 | ||
| 	// Soft shadow taken from iq
 | ||
| 	float k = 6.0;
 | ||
| 	float t = 0.0;
 | ||
| 	float s = 1.0;	
 | ||
| 	for (int i = 0; i < 30; i++)
 | ||
| 	{
 | ||
| 		vec3 pos = rayPos+rayDir*t;	
 | ||
| 		vec2 res = scene(pos);		
 | ||
| 		if (res.x < 0.001) return 0.0;
 | ||
| 		s = min(s, k*res.x/t); 
 | ||
| 		t += max(res.x, 0.01);
 | ||
| 	}
 | ||
| 	
 | ||
| 	return s*s*(3.0 - 2.0*s);
 | ||
| }
 | ||
| 
 | ||
| // Ray-traced parts of scene
 | ||
| vec4 intersectWater(vec3 rayPos, vec3 rayDir)
 | ||
| {
 | ||
| 	float h = sin(20.5 + iGlobalTime * 2.0) * 0.03;
 | ||
| 	float t = -(rayPos.y + 2.5 + h) / rayDir.y;
 | ||
| 	return vec4(0.0, 1.0, 0.0, t);
 | ||
| }
 | ||
| 
 | ||
| vec4 intersectSand(vec3 rayPos, vec3 rayDir)
 | ||
| {
 | ||
| 	return intersectSphere(rayPos, rayDir, vec3(0.0,-24.1,0.0), 24.1);
 | ||
| }
 | ||
| 
 | ||
| vec4 intersectTreasure(vec3 rayPos, vec3 rayDir)
 | ||
| {
 | ||
| 	return vec4(0.0);
 | ||
| }
 | ||
| 
 | ||
| vec4 intersectLeaf(vec3 rayPos, vec3 rayDir, float openAmount)
 | ||
| {	
 | ||
| 	vec3 dir = normalize(vec3(0.0, 1.0, openAmount));
 | ||
| 	float offset = 0.0;
 | ||
| 			
 | ||
| 	vec4 res = intersectPlane(rayPos, rayDir, dir, 0.0);
 | ||
| 	vec3 pos = rayPos+rayDir*res.w;
 | ||
| 	#ifdef RAGGED_LEAVES
 | ||
| 	offset = snoise(pos*0.8) * 0.3;
 | ||
| 	#endif
 | ||
| 	if (pos.y > 0.0 || length(pos * vec3(0.9, 2.0, 1.0)) > 4.0 - offset) res.w = 0.0;
 | ||
| 	
 | ||
| 	vec4 res2 = intersectPlane(rayPos, rayDir, vec3(dir.xy, -dir.z), 0.0);
 | ||
| 	pos = rayPos+rayDir*res2.w;
 | ||
| 	#ifdef RAGGED_LEAVES
 | ||
| 	offset = snoise(pos*0.8) * 0.3;
 | ||
| 	#endif
 | ||
| 	if (pos.y > 0.0 || length(pos * vec3(0.9, 2.0, 1.0)) > 4.0 - offset) res2.w = 0.0;
 | ||
| 	
 | ||
| 	if (res2.w > 0.0 && res2.w < res.w || res.w <= 0.0)
 | ||
| 		res = res2;
 | ||
| 		
 | ||
| 	return res;
 | ||
| }
 | ||
| 
 | ||
| vec4 leaves(vec3 rayPos, vec3 rayDir)
 | ||
| {
 | ||
| 	float t = 1e20;
 | ||
| 	vec3 n = vec3(0.0);
 | ||
| 	
 | ||
| 	rayPos -= leavesPos;
 | ||
| 	
 | ||
| 	float sway = impulse(15.0, fract(iGlobalTime / PI * 0.125));
 | ||
| 	float upDownSway = sway * -sin(iGlobalTime) * 0.06;
 | ||
| 	float openAmount = sway * max(-cos(iGlobalTime) * 0.4, 0.0);
 | ||
| 	
 | ||
| 	float angleOffset = -0.1;	
 | ||
| 	for (float k = 0.0; k < 6.2; k += 0.75)
 | ||
| 	{
 | ||
| 		// Left-right
 | ||
| 		float alpha = k + (k - PI) * sway * 0.015;
 | ||
| 		vec3 p = rotate(rayPos, alpha);
 | ||
| 		vec3 d = rotate(rayDir, alpha);
 | ||
| 		
 | ||
| 		// Up-down
 | ||
| 		angleOffset *= -1.0;
 | ||
| 		float theta = -0.4 + 
 | ||
| 			angleOffset + 
 | ||
| 			cos(k) * 0.35 + 
 | ||
| 			upDownSway + 
 | ||
| 			sin(iGlobalTime+k*10.0) * 0.03 * (sway + 0.2);
 | ||
| 		
 | ||
| 		p = rotate(p.xzy, theta).xzy;
 | ||
| 		d = rotate(d.xzy, theta).xzy;
 | ||
| 	
 | ||
| 		// Shift
 | ||
| 		p -= vec3(5.4, 0.0, 0.0);
 | ||
| 		
 | ||
| 		// Intersect individual leaf
 | ||
| 		vec4 res = intersectLeaf(p, d, 1.0+openAmount);
 | ||
| 		if (res.w > 0.0 && res.w < t)
 | ||
| 		{
 | ||
| 			t = res.w;
 | ||
| 			n = res.xyz;
 | ||
| 		}
 | ||
| 	}
 | ||
| 	
 | ||
| 	return vec4(n, t);
 | ||
| }
 | ||
| 
 | ||
| // Lighting
 | ||
| float shadow(vec3 rayPos, vec3 rayDir)
 | ||
| {	
 | ||
| 	float s = 1.0;
 | ||
| 	
 | ||
| 	// Intersect sand
 | ||
| 	//vec4 resSand = intersectSand(rayPos, rayDir);
 | ||
| 	//if (resSand.w > 0.0) return 0.0;
 | ||
| 	
 | ||
| 	// Intersect plants
 | ||
| 	s = min(s, plantsShadow(rayPos, rayDir));
 | ||
| 	if (s < 0.0001) return 0.0;
 | ||
| 	
 | ||
| 	// Intersect leaves
 | ||
| 	vec4 resLeaves = leaves(rayPos, rayDir);
 | ||
| 	if (resLeaves.w > 0.0 && resLeaves.w < 1e7) return 0.0;
 | ||
| 	
 | ||
| 	return s;
 | ||
| }
 | ||
| 
 | ||
| vec3 light(vec3 p, vec3 n)
 | ||
| {
 | ||
| 	float s = 1.0;
 | ||
| 	
 | ||
| 	#ifdef SHADOWS
 | ||
| 	s = shadow(p-sunDir*0.01, -sunDir);
 | ||
| 	#endif
 | ||
| 	
 | ||
| 	vec3 col = sunCol * min(max(dot(n, sunDir), 0.0), s);
 | ||
| 	col += skyCol * (-n.y * 0.5 + 0.5) * 0.3;
 | ||
| 	return col;
 | ||
| }
 | ||
| 
 | ||
| vec3 lightLeaves(vec3 p, vec3 n)
 | ||
| {
 | ||
| 	float s = 1.0;
 | ||
| 	
 | ||
| 	#ifdef SHADOWS
 | ||
| 	s = shadow(p-sunDir*0.01, -sunDir);
 | ||
| 	#endif
 | ||
| 	
 | ||
| 	float ao = min(length(p - leavesPos) * 0.1, 1.0);
 | ||
| 	
 | ||
| 	float ns = dot(n, sunDir);
 | ||
| 	float d = sqrt(max(ns, 0.0));
 | ||
| 	vec3 col = sunCol * min(d, s);
 | ||
| 	col += sunCol * max(-ns, 0.0) * vec3(0.3, 0.3, 0.1) * ao;
 | ||
| 	col += skyCol * (-n.y * 0.5 + 0.5) * 0.3 * ao;
 | ||
| 	return col;
 | ||
| }
 | ||
| 
 | ||
| vec3 sky(vec3 n)
 | ||
| {
 | ||
| 	return skyCol * (1.0 - n.y * 0.8);
 | ||
| }
 | ||
| 
 | ||
| // Ray-marching
 | ||
| vec4 plants(vec3 rayPos, vec3 rayDir)
 | ||
| {
 | ||
| 	float t = 0.0;
 | ||
| 	
 | ||
| 	for (int i = 0; i < 40; i++)
 | ||
| 	{
 | ||
| 		vec3 pos = rayPos+rayDir*t;	
 | ||
| 		vec2 res = scene(pos);
 | ||
| 		float h = res.x;
 | ||
| 		
 | ||
| 		if (h < 0.001)
 | ||
| 		{
 | ||
| 			vec3 col = res.y == 2.0 ? treeCol : grassCol;
 | ||
| 			float uvFact = res.y == 2.0 ? 1.0 : 10.0;
 | ||
| 			
 | ||
| 			vec3 n = normal(pos);
 | ||
| 			vec2 uv = vec2(n.x, pos.y * 0.5) * 0.2 * uvFact;
 | ||
| 			vec3 tex = texture2D(iChannel0, uv).rgb * 0.6 + 0.4;
 | ||
| 			float ao = min(length(pos - leavesPos) * 0.1, 1.0);
 | ||
| 			return vec4(col * light(pos, n) * ao * tex, t);
 | ||
| 		}
 | ||
| 		
 | ||
| 		t += h;
 | ||
| 	}
 | ||
| 	
 | ||
| 	return vec4(sky(rayDir), 1e8);
 | ||
| }
 | ||
| 
 | ||
| // Final combination
 | ||
| vec3 traceReflection(vec3 rayPos, vec3 rayDir)
 | ||
| {
 | ||
| 	vec3 col = vec3(0.0);
 | ||
| 	float t = 1e20;
 | ||
| 			
 | ||
| 	// Intersect plants
 | ||
| 	vec4 resPlants = plants(rayPos, rayDir);
 | ||
| 	if (resPlants.w > 0.0 && resPlants.w < t)
 | ||
| 	{
 | ||
| 		t = resPlants.w;
 | ||
| 		col = resPlants.xyz;
 | ||
| 	}
 | ||
| 	
 | ||
| 	// Intersect leaves
 | ||
| 	vec4 resLeaves = leaves(rayPos, rayDir);
 | ||
| 	if (resLeaves.w > 0.0 && resLeaves.w < t)
 | ||
| 	{
 | ||
| 		vec3 pos = rayPos + rayDir * resLeaves.w;
 | ||
| 		vec2 uv = (pos.xz - leavesPos.xz) * 0.3;
 | ||
| 		float tex = texture2D(iChannel0, uv).r * 0.6 + 0.5;
 | ||
| 		
 | ||
| 		t = resLeaves.w;
 | ||
| 		col = leavesCol * lightLeaves(pos, resLeaves.xyz) * tex;
 | ||
| 	}
 | ||
| 		
 | ||
| 	if (t > 1e7) return sky(rayDir);
 | ||
| 	
 | ||
| 	return col;
 | ||
| }
 | ||
| 
 | ||
| vec3 trace(vec3 rayPos, vec3 rayDir)
 | ||
| {
 | ||
| 	vec3 col = vec3(0.0);
 | ||
| 	float t = 1e20;
 | ||
| 	
 | ||
| 	// Intersect sand
 | ||
| 	vec4 resSand = intersectSand(rayPos, rayDir);
 | ||
| 	if (resSand.w > 0.0)
 | ||
| 	{
 | ||
| 		vec3 pos = rayPos + rayDir * resSand.w;
 | ||
| 		t = resSand.w;
 | ||
| 
 | ||
| 		col = sandCol * light(pos, resSand.xyz);
 | ||
| 	}
 | ||
| 	
 | ||
| 	// Intersect treasure chest
 | ||
| 	vec4 resTreasure = intersectTreasure(rayPos, rayDir);
 | ||
| 	if (resTreasure.w > 0.0 && resTreasure.w < t)
 | ||
| 	{
 | ||
| 		vec3 pos = rayPos + rayDir * resTreasure.w;
 | ||
| 		t = resTreasure.w;
 | ||
| 		col = leavesCol * light(pos, resTreasure.xyz);
 | ||
| 	}
 | ||
| 	
 | ||
| 	// Intersect leaves
 | ||
| 	vec4 resLeaves = leaves(rayPos, rayDir);
 | ||
| 	if (resLeaves.w > 0.0 && resLeaves.w < t)
 | ||
| 	{
 | ||
| 		vec3 pos = rayPos + rayDir * resLeaves.w;
 | ||
| 		vec2 uv = (pos.xz - leavesPos.xz) * 0.3;
 | ||
| 		float tex = texture2D(iChannel0, uv).r * 0.6 + 0.5;
 | ||
| 		
 | ||
| 		t = resLeaves.w;
 | ||
| 		col = leavesCol * lightLeaves(pos, resLeaves.xyz) * tex;
 | ||
| 	}
 | ||
| 	
 | ||
| 	// Intersect plants
 | ||
| 	vec4 resPlants = plants(rayPos, rayDir);
 | ||
| 	if (resPlants.w > 0.0 && resPlants.w < t)
 | ||
| 	{
 | ||
| 		t = resPlants.w;
 | ||
| 		col = resPlants.xyz;
 | ||
| 	}
 | ||
| 		
 | ||
| 	// Intersect water	
 | ||
| 	vec4 resWater = intersectWater(rayPos, rayDir);
 | ||
| 	if (resWater.w > 0.0 && resWater.w < t)
 | ||
| 	{
 | ||
| 		vec3 pos = rayPos + rayDir * resWater.w;
 | ||
| 		float dist = t - resWater.w;
 | ||
| 		vec3 n = bump(pos, rayDir);
 | ||
| 		
 | ||
| 		float ct = -min(dot(n,rayDir), 0.0);
 | ||
| 		float fresnel = 0.9 - 0.9 * pow(1.0 - ct, 5.0);
 | ||
| 		
 | ||
| 		vec3 trans = col * exp(-dist * vec3(1.0, 0.7, 0.4) * 3.0);
 | ||
| 		vec3 reflDir = normalize(reflect(rayDir, n));
 | ||
| 		vec3 refl = sky(reflDir);
 | ||
| 		
 | ||
| 		#ifdef REFLECTIONS
 | ||
| 		if (dot(pos, rayDir) < -2.0)
 | ||
| 			refl = traceReflection(pos, reflDir).rgb;
 | ||
| 		#endif
 | ||
| 				
 | ||
| 		t = resWater.t;
 | ||
| 		col = mix(refl, trans, fresnel);
 | ||
| 	}
 | ||
| 	
 | ||
| 	if (t > 1e7) return sky(rayDir);
 | ||
| 	
 | ||
| 	return col;
 | ||
| }
 | ||
| 
 | ||
| // Ray-generation
 | ||
| vec3 camera(vec2 px)
 | ||
| {
 | ||
| 	vec2 rd = (px / iResolution.yy - vec2(iResolution.x/iResolution.y*0.5-0.5, 0.0)) * 2.0 - 1.0;
 | ||
| 	float t = sin(iGlobalTime * 0.1) * 0.2;
 | ||
| 	vec3 rayDir = normalize(vec3(rd.x, rd.y, 1.0));
 | ||
| 	vec3 rayPos = vec3(0.0, 3.0, -18.0);
 | ||
| 	return trace(rayPos, rayDir);
 | ||
| }
 | ||
| 
 | ||
| void main(void)
 | ||
| {
 | ||
| 	#ifdef HEAVY_AA
 | ||
| 		vec3 col = camera(gl_FragCoord.xy+vec2(0.0,0.5))*0.25;
 | ||
| 		col += camera(gl_FragCoord.xy+vec2(0.25,0.0))*0.25;
 | ||
| 		col += camera(gl_FragCoord.xy+vec2(0.5,0.75))*0.25;
 | ||
| 		col += camera(gl_FragCoord.xy+vec2(0.75,0.25))*0.25;
 | ||
| 	#else
 | ||
| 		vec3 col = camera(gl_FragCoord.xy);
 | ||
| 		#ifdef LIGHT_AA
 | ||
| 			col = col * 0.5 + camera(gl_FragCoord.xy+vec2(0.5,0.5))*0.5;
 | ||
| 		#endif
 | ||
| 	#endif
 | ||
| 	
 | ||
| 	#ifdef TONEMAP
 | ||
| 	// Optimized Haarm-Peter Duiker’s curve
 | ||
| 	vec3 x = max(vec3(0.0),col*exposure-0.004);
 | ||
| 	col = (x*(6.2*x+.5))/(x*(6.2*x+1.7)+0.06);
 | ||
| 	#else
 | ||
| 	col = pow(col, vec3(0.4545));
 | ||
| 	#endif
 | ||
| 	
 | ||
| 	gl_FragColor = vec4(col, 1.0);
 | ||
| } |