Code: Select all
dim as string SCODE
SCODE &= !"/** \n"
SCODE &= !" * Created by revers - 2016 \n"
SCODE &= !" * \n"
SCODE &= !" * Licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. \n"
SCODE &= !" * \n"
SCODE &= !" * This shader is based on iq's brilliant ""Elevated"" (https://www.shadertoy.com/view/MdX3Rr), \n"
SCODE &= !" * but I've used my own terrain heightmap (without derivatives), added water and own version of clouds. \n"
SCODE &= !" * I've also tried to use own texture patterns. \n"
SCODE &= !" * The rest of code is created by iq. Notably: hash and noise functions, raymarching, great outdoors lighting \n"
SCODE &= !" * (see also http://iquilezles.org/www/articles/outdoorslighting/outdoorslighting.htm ) \n"
SCODE &= !" * \n"
SCODE &= !" * It is great pleasure to learn from the best. Thanks for sharing your code, iq! \n"
SCODE &= !" * \n"
SCODE &= !" * The shader was created and exported from Synthclipse (http://synthclipse.sourceforge.net/) \n"
SCODE &= !" */ \n"
SCODE &= !" \n"
SCODE &= !"const vec3 LightDir = vec3(0.15037532, -0.31434754, -0.93732226); \n"
SCODE &= !"const float MarchDumping = 0.39999998; \n"
SCODE &= !"const float Far = 864.20496; \n"
SCODE &= !"const int MaxSteps = 156; \n"
SCODE &= !"const vec2 PulseSize = vec2(431.0138, 311.53772); \n"
SCODE &= !"const float PulseHeight = 111.24439; \n"
SCODE &= !"const float PulseProbability = 0.6; \n"
SCODE &= !"const float MaxTerrainMul = 60.88; \n"
SCODE &= !"const float MinTerrainMul = 0.0; \n"
SCODE &= !"const float TerrainPower = 0.85950005; \n"
SCODE &= !"const float TerrainHeightMul = 1.838; \n"
SCODE &= !"const float WaterLevel = -9.119999; \n"
SCODE &= !"const float WaterWaveHeight = 0.24681002; \n"
SCODE &= !"const float WaterMaxVisibleDepth = 12.8991; \n"
SCODE &= !"const vec3 WaterColor = vec3(0.007843138, 0.0627451, 0.09019608); \n"
SCODE &= !"const float NormalFactor = 0.399; \n"
SCODE &= !" \n"
SCODE &= !"#define TIME_SHIFT 30.0 \n"
SCODE &= !" \n"
SCODE &= !"#define M_NONE -1.0 \n"
SCODE &= !"#define M_TERRAIN 1.0 \n"
SCODE &= !"#define M_WATER 3.0 \n"
SCODE &= !" \n"
SCODE &= !"vec3 lig = vec3(0.0, -1.0, 0.0); \n"
SCODE &= !"float TerrainParam = 0.0; \n"
SCODE &= !" \n"
SCODE &= !"float hash(vec2 n) { \n"
SCODE &= !" return fract(sin(dot(n, vec2(1.0, 113.0))) * 43758.5453123); \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"/** \n"
SCODE &= !" * From ""Hash-without-Sine"" by Dave Hoskins \n"
SCODE &= !" * https://www.shadertoy.com/view/4djSRW \n"
SCODE &= !" */ \n"
SCODE &= !"vec2 hash22(vec2 p) { \n"
SCODE &= !" p = fract(p * vec2(5.3983, 5.4427)); \n"
SCODE &= !" p += dot(p.yx, p.xy + vec2(21.5351, 14.3137)); \n"
SCODE &= !" return fract(vec2(p.x * p.y * 95.4337, p.x * p.y * 97.597)); \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"float noise(vec2 p) { \n"
SCODE &= !" vec2 i = floor(p); \n"
SCODE &= !" vec2 f = fract(p); \n"
SCODE &= !" \n"
SCODE &= !" vec2 u = f * f * (3.0 - 2.0 * f); \n"
SCODE &= !" \n"
SCODE &= !" vec2 a = vec2(0.0, 0.0); \n"
SCODE &= !" vec2 b = vec2(1.0, 0.0); \n"
SCODE &= !" vec2 c = vec2(0.0, 1.0); \n"
SCODE &= !" vec2 d = vec2(1.0, 1.0); \n"
SCODE &= !" \n"
SCODE &= !" float n0 = hash(i + a); \n"
SCODE &= !" float n1 = hash(i + b); \n"
SCODE &= !" float n2 = hash(i + c); \n"
SCODE &= !" float n3 = hash(i + d); \n"
SCODE &= !" \n"
SCODE &= !" float ix0 = mix(n0, n1, u.x); \n"
SCODE &= !" float ix1 = mix(n2, n3, u.x); \n"
SCODE &= !" \n"
SCODE &= !" return mix(ix0, ix1, u.y); \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"vec2 min2(vec2 a, vec2 b) { \n"
SCODE &= !" return a.x < b.x ? a : b; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"/** \n"
SCODE &= !" * http://iquilezles.org/www/articles/functions/functions.htm \n"
SCODE &= !" */ \n"
SCODE &= !"float cubicPulse(float w, float x) { \n"
SCODE &= !" x = abs(x); \n"
SCODE &= !" if (x > w) \n"
SCODE &= !" return 0.0; \n"
SCODE &= !" x /= w; \n"
SCODE &= !" return 1.0 - x * x * (3.0 - 2.0 * x); \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"float pulse(vec2 p) { \n"
SCODE &= !" vec2 q = mod(p, 2.0 * PulseSize) - PulseSize; \n"
SCODE &= !" vec2 id = floor(p / (2.0 * PulseSize)); \n"
SCODE &= !" \n"
SCODE &= !" vec2 r2 = hash22(id); \n"
SCODE &= !" float r = step(PulseProbability, r2.x) * step(PulseProbability, r2.y); \n"
SCODE &= !" \n"
SCODE &= !" float h = cubicPulse(PulseSize.x, q.x) * cubicPulse(PulseSize.y, q.y) * PulseHeight; \n"
SCODE &= !" return mix(h, 0.0, r); \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"float fbmL(vec2 p, float baseAmplitude) { \n"
SCODE &= !" float f = 0.0; \n"
SCODE &= !" float a = baseAmplitude; \n"
SCODE &= !" for (int i = 0; i < 2; i++) { \n"
SCODE &= !" f += a * noise(p); \n"
SCODE &= !" p *= 2.0; \n"
SCODE &= !" a *= 0.5; \n"
SCODE &= !" } \n"
SCODE &= !" return f; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"float fbmM(vec2 p, float baseAmplitude) { \n"
SCODE &= !" float f = 0.0; \n"
SCODE &= !" float a = baseAmplitude; \n"
SCODE &= !" for (int i = 0; i < 4; i++) { \n"
SCODE &= !" f += a * noise(p); \n"
SCODE &= !" p *= 2.0; \n"
SCODE &= !" a *= 0.5; \n"
SCODE &= !" } \n"
SCODE &= !" return f; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"float fbmH(vec2 p, float baseAmplitude) { \n"
SCODE &= !" float f = 0.0; \n"
SCODE &= !" float a = baseAmplitude; \n"
SCODE &= !" for (int i = 0; i < 7; i++) { \n"
SCODE &= !" f += a * noise(p); \n"
SCODE &= !" p *= 2.0; \n"
SCODE &= !" a *= 0.5; \n"
SCODE &= !" } \n"
SCODE &= !" return f; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"float hole(vec2 p) { \n"
SCODE &= !" float f = noise(p); \n"
SCODE &= !" p *= 2.01; \n"
SCODE &= !" f += 0.5 * noise(p); \n"
SCODE &= !" p *= 2.02; \n"
SCODE &= !" f += 0.25 * noise(p); \n"
SCODE &= !" p *= 2.00; \n"
SCODE &= !" f += 0.125 * noise(p); \n"
SCODE &= !" \n"
SCODE &= !" return f; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"float terrainL(vec2 p) { \n"
SCODE &= !" vec2 g = vec2(0.01, 0.012); \n"
SCODE &= !" vec2 q = p * g; \n"
SCODE &= !" \n"
SCODE &= !" float a = 0.5; \n"
SCODE &= !" float f0 = noise(q); \n"
SCODE &= !" a *= 0.5; \n"
SCODE &= !" q *= 2.0; \n"
SCODE &= !" \n"
SCODE &= !" float f = fbmL(q, a); \n"
SCODE &= !" float t = smoothstep(0.5, 1.0, TerrainParam); \n"
SCODE &= !" f = pow(f, TerrainPower + t * 2.0); \n"
SCODE &= !" \n"
SCODE &= !" float k = smoothstep(TerrainParam, 1.0, f0); \n"
SCODE &= !" float res = mix(f * MinTerrainMul, f * MaxTerrainMul, k) * TerrainHeightMul; \n"
SCODE &= !" \n"
SCODE &= !" float m = smoothstep(0.0, 0.4, k); \n"
SCODE &= !" res = mix(res - hole(q) * 12.0, res, m); \n"
SCODE &= !" \n"
SCODE &= !" res += pulse(p) * fbmM(p * 0.01 + 452.15, 0.5); \n"
SCODE &= !" return res; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"float terrainM(vec2 p) { \n"
SCODE &= !" vec2 g = vec2(0.01, 0.012); \n"
SCODE &= !" vec2 q = p * g; \n"
SCODE &= !" \n"
SCODE &= !" float a = 0.5; \n"
SCODE &= !" float f0 = noise(q); \n"
SCODE &= !" a *= 0.5; \n"
SCODE &= !" q *= 2.0; \n"
SCODE &= !" \n"
SCODE &= !" float f = fbmM(q, a); \n"
SCODE &= !" float t = smoothstep(0.5, 1.0, TerrainParam); \n"
SCODE &= !" f = pow(f, TerrainPower + t * 2.0); \n"
SCODE &= !" \n"
SCODE &= !" float k = smoothstep(TerrainParam, 1.0, f0); \n"
SCODE &= !" float res = mix(f * MinTerrainMul, f * MaxTerrainMul, k) * TerrainHeightMul; \n"
SCODE &= !" \n"
SCODE &= !" float m = smoothstep(0.0, 0.4, k); \n"
SCODE &= !" res = mix(res - hole(q) * 12.0, res, m); \n"
SCODE &= !" \n"
SCODE &= !" res += pulse(p) * fbmM(p * 0.01 + 452.15, 0.5); \n"
SCODE &= !" return res; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"float terrainH(vec2 p) { \n"
SCODE &= !" vec2 g = vec2(0.01, 0.012); \n"
SCODE &= !" vec2 q = p * g; \n"
SCODE &= !" \n"
SCODE &= !" float a = 0.5; \n"
SCODE &= !" float f0 = noise(q); \n"
SCODE &= !" a *= 0.5; \n"
SCODE &= !" q *= 2.0; \n"
SCODE &= !" \n"
SCODE &= !" float f = fbmH(q, a); \n"
SCODE &= !" float t = smoothstep(0.5, 1.0, TerrainParam); \n"
SCODE &= !" f = pow(f, TerrainPower + t * 2.0); \n"
SCODE &= !" \n"
SCODE &= !" float k = smoothstep(TerrainParam, 1.0, f0); \n"
SCODE &= !" float res = mix(f * MinTerrainMul, f * MaxTerrainMul, k) * TerrainHeightMul; \n"
SCODE &= !" \n"
SCODE &= !" float m = smoothstep(0.0, 0.4, k); \n"
SCODE &= !" res = mix(res - hole(q) * 12.0, res, m); \n"
SCODE &= !" \n"
SCODE &= !" res += pulse(p) * fbmH(p * 0.01 + 333452.15, 0.5); \n"
SCODE &= !" return res; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"vec2 map(vec3 p) { \n"
SCODE &= !" vec2 res = vec2(p.y - terrainM(p.xz), M_TERRAIN); \n"
SCODE &= !" return res; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"vec2 castRay(vec3 ro, vec3 rd) { \n"
SCODE &= !" float tmin = 0.0; \n"
SCODE &= !" float tmax = Far; \n"
SCODE &= !" \n"
SCODE &= !" float precis = 0.002; \n"
SCODE &= !" float t = tmin; \n"
SCODE &= !" float m = -1.0; \n"
SCODE &= !" \n"
SCODE &= !" for (int i = 0; i < MaxSteps; i++) { \n"
SCODE &= !" vec2 res = map(ro + rd * t); \n"
SCODE &= !" if (res.x < precis || t > tmax) { \n"
SCODE &= !" break; \n"
SCODE &= !" } \n"
SCODE &= !" t += res.x * MarchDumping; \n"
SCODE &= !" m = res.y; \n"
SCODE &= !" } \n"
SCODE &= !" if (t > tmax) { \n"
SCODE &= !" m = -1.0; \n"
SCODE &= !" } \n"
SCODE &= !" return vec2(t, m); \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"float softshadow(vec3 ro, vec3 rd, float mint, float tmax) { \n"
SCODE &= !" float res = 1.0; \n"
SCODE &= !" float t = mint; \n"
SCODE &= !" \n"
SCODE &= !" for (int i = 0; i < 16; i++) { \n"
SCODE &= !" float h = map(ro + rd * t).x; \n"
SCODE &= !" \n"
SCODE &= !" res = min(res, 8.0 * h / t); \n"
SCODE &= !" t += clamp(h, 0.02, 0.10); \n"
SCODE &= !" \n"
SCODE &= !" if (h < 0.001 || t > tmax) { \n"
SCODE &= !" break; \n"
SCODE &= !" } \n"
SCODE &= !" } \n"
SCODE &= !" return clamp(res, 0.0, 1.0); \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"vec3 calcNormal(vec3 pos) { \n"
SCODE &= !" float t = 0.1; \n"
SCODE &= !" vec2 eps = vec2(0.02 * t, 0.0); \n"
SCODE &= !" \n"
SCODE &= !" return normalize( \n"
SCODE &= !" vec3(terrainH(pos.xz - eps.xy) - terrainH(pos.xz + eps.xy), \n"
SCODE &= !" 2.0 * eps.x, \n"
SCODE &= !" terrainH(pos.xz - eps.yx) - terrainH(pos.xz + eps.yx))); \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"#define lodbias -100.0 \n"
SCODE &= !" \n"
SCODE &= !"vec4 texcube(sampler2D sam, vec3 p, vec3 n) { \n"
SCODE &= !" vec4 x = texture2D(sam, p.yz, lodbias); \n"
SCODE &= !" vec4 y = texture2D(sam, p.zx, lodbias); \n"
SCODE &= !" vec4 z = texture2D(sam, p.xy, lodbias); \n"
SCODE &= !" return x * abs(n.x) + y * abs(n.y) + z * abs(n.z); \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"float water(vec2 q) { \n"
SCODE &= !" float f; \n"
SCODE &= !" f = 0.5000 * noise(q); \n"
SCODE &= !" q = q * 2.02; \n"
SCODE &= !" f += 0.2500 * noise(q); \n"
SCODE &= !" q -= iGlobalTime * 0.3; \n"
SCODE &= !" q = q * 2.03; \n"
SCODE &= !" f += 0.1250 * noise(q); \n"
SCODE &= !" q -= iGlobalTime * 2.0; \n"
SCODE &= !" q = q * 2.01; \n"
SCODE &= !" f += 0.0625 * noise(q); \n"
SCODE &= !" \n"
SCODE &= !" return f * WaterWaveHeight; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"vec3 waterBottomColor(vec3 ro, vec3 rd, float t) { \n"
SCODE &= !" vec3 pos = ro + t * rd; \n"
SCODE &= !" vec3 nor = calcNormal(pos); \n"
SCODE &= !" \n"
SCODE &= !" vec3 bn = -1.0 + 2.0 * texcube(iChannel0, pos * 0.3, nor).xyz; \n"
SCODE &= !" nor = normalize(nor + 0.2 * bn); \n"
SCODE &= !" \n"
SCODE &= !" vec3 col = vec3(0.009); \n"
SCODE &= !" float hh = smoothstep(0.0, 10.0, pos.y); \n"
SCODE &= !" \n"
SCODE &= !" col += 2.0 * vec3(0.722, 0.396, 0.165) \n"
SCODE &= !" * texcube(iChannel1, pos * vec3(0.1, 0.3, 0.1), nor).rgb; \n"
SCODE &= !" \n"
SCODE &= !" float dif = max(dot(nor, lig), 0.0); \n"
SCODE &= !" return dif * col * 0.5; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"float clouds(vec3 ro, vec3 rd) { \n"
SCODE &= !" vec2 uv = rd.xz / rd.y; \n"
SCODE &= !" uv *= 70.0; \n"
SCODE &= !" \n"
SCODE &= !" uv *= vec2(3.0, 3.0) * 0.005; \n"
SCODE &= !" vec2 st = uv; \n"
SCODE &= !" \n"
SCODE &= !" uv.x += iGlobalTime * 0.2; \n"
SCODE &= !" \n"
SCODE &= !" float f = 0.5 * noise(uv); \n"
SCODE &= !" uv *= 2.04; \n"
SCODE &= !" f += 0.25 * noise(uv); \n"
SCODE &= !" uv *= 2.01; \n"
SCODE &= !" f += 0.125 * noise(uv); \n"
SCODE &= !" float res = f; \n"
SCODE &= !" res = smoothstep(0.4, 1.0, res); \n"
SCODE &= !" \n"
SCODE &= !" st += vec2(12.0, 34.5); \n"
SCODE &= !" st.x += iGlobalTime * 0.3; \n"
SCODE &= !" float g = 0.5 * noise(st); \n"
SCODE &= !" st *= 2.00; \n"
SCODE &= !" g += 0.25 * noise(st); \n"
SCODE &= !" st *= 2.03; \n"
SCODE &= !" g += 0.125 * noise(st); \n"
SCODE &= !" st *= 2.04; \n"
SCODE &= !" g += 0.0625 * noise(st); \n"
SCODE &= !" \n"
SCODE &= !" res += 0.5 * smoothstep(0.5, 0.9, g); \n"
SCODE &= !" \n"
SCODE &= !" return res * 0.8; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"vec3 skyColor(vec3 ro, vec3 rd) { \n"
SCODE &= !" float sundot = max(0.0, dot(rd, lig)); \n"
SCODE &= !" vec3 col = vec3(0.396, 0.678, 0.878) * (0.9 - 0.9 * rd.y) * 1.5; \n"
SCODE &= !" col += pow(sundot, 120.0) * vec3(1.0, 0.937, 0.71) * 0.75; \n"
SCODE &= !" \n"
SCODE &= !" col = mix(col, vec3(2.0), clouds(ro, rd) * rd.y); \n"
SCODE &= !" return col; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"#define OFFSET 10.0 \n"
SCODE &= !"#define GROUND_LEVEL_MIN (-20.0 + OFFSET) \n"
SCODE &= !"#define GROUND_LEVEL_MAX (-5.0 + OFFSET) \n"
SCODE &= !" \n"
SCODE &= !"#define GRASS_LEVEL_MIN (-5.0 + OFFSET) \n"
SCODE &= !"#define GRASS_LEVEL_MAX (25.0 + OFFSET) \n"
SCODE &= !" \n"
SCODE &= !"#define SNOW_LEVEL_MIN (20.0 + OFFSET) \n"
SCODE &= !"#define SNOW_LEVEL_MAX (60.0 + OFFSET) \n"
SCODE &= !" \n"
SCODE &= !"vec3 terrainColor(vec3 ro, vec3 rd, vec3 pos, vec3 nor) { \n"
SCODE &= !" vec3 col = vec3(0.009); \n"
SCODE &= !" \n"
SCODE &= !" vec3 rock = 1.0 * vec3(0.5) \n"
SCODE &= !" * texcube(iChannel1, pos * vec3(0.1, 0.4, 0.1) * 0.2, nor).rgb; \n"
SCODE &= !" float rockFactor = (1.0 - nor.y); \n"
SCODE &= !" col += mix(rock, vec3(0.01), rockFactor); \n"
SCODE &= !" \n"
SCODE &= !" float r = texture2D(iChannel0, pos.xz * 0.1).r; \n"
SCODE &= !" \n"
SCODE &= !" vec3 ground = 0.1 * vec3(0.7, 0.4, 0.2); \n"
SCODE &= !" float k = texture2D(iChannel0, pos.xz * 0.0005).r * 10.0; \n"
SCODE &= !" float groundFactor = (1.0 - smoothstep(GROUND_LEVEL_MIN, GROUND_LEVEL_MAX, pos.y - k)); \n"
SCODE &= !" col = mix(col, ground, groundFactor); \n"
SCODE &= !" \n"
SCODE &= !" vec3 grass = 0.4 * mix(vec3(0.04, 0.3, 0.0), vec3(0.0, 0.1, 0.0), \n"
SCODE &= !" smoothstep(0.0, 0.5, texcube(iChannel2, pos * 0.04 + r, nor).r)); \n"
SCODE &= !" float grassFactor = (0.6 + 0.4 * r) * groundFactor; \n"
SCODE &= !" col = mix(col, grass, grassFactor); \n"
SCODE &= !" \n"
SCODE &= !" grass = vec3(0.02, 0.06, 0.0); \n"
SCODE &= !" grassFactor = smoothstep(NormalFactor, 1.0, nor.y) \n"
SCODE &= !" * (1.0 - smoothstep(GRASS_LEVEL_MIN, GRASS_LEVEL_MAX, pos.y)) \n"
SCODE &= !" * (1.0 - groundFactor); \n"
SCODE &= !" col = mix(col, grass, grassFactor); \n"
SCODE &= !" \n"
SCODE &= !" vec3 snow = vec3(1.0); \n"
SCODE &= !" float snowFactor = smoothstep(SNOW_LEVEL_MIN, SNOW_LEVEL_MAX, pos.y) \n"
SCODE &= !" * smoothstep(0.1, 1.0, nor.y); \n"
SCODE &= !" col = mix(col, snow, snowFactor); \n"
SCODE &= !" \n"
SCODE &= !" return col; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"vec3 doLighting(vec3 rd, vec3 pos, vec3 nor) { \n"
SCODE &= !" vec3 ref = reflect(rd, nor); \n"
SCODE &= !" \n"
SCODE &= !" float amb = clamp(0.5 + 0.5 * nor.y, 0.0, 1.0); \n"
SCODE &= !" float dif = clamp(dot(nor, lig), 0.0, 1.0); \n"
SCODE &= !" float bac = clamp(dot(nor, normalize(vec3(-lig.x, 0.0, -lig.z))), 0.0, \n"
SCODE &= !" 1.0) * clamp(1.0 - pos.y, 0.0, 1.0); \n"
SCODE &= !" float dom = smoothstep(-0.1, 0.1, ref.y); \n"
SCODE &= !" float fre = pow(clamp(1.0 + dot(nor, rd), 0.0, 1.0), 2.0); \n"
SCODE &= !" float spe = pow(clamp(dot(ref, lig), 0.0, 1.0), 16.0); \n"
SCODE &= !" \n"
SCODE &= !" dif *= softshadow(pos, lig, 0.02, 2.5); \n"
SCODE &= !" dom *= softshadow(pos, ref, 0.02, 2.5); \n"
SCODE &= !" \n"
SCODE &= !" vec3 brdf = vec3(0.0); \n"
SCODE &= !" brdf += 1.20 * dif * vec3(1.00, 0.90, 0.60); \n"
SCODE &= !" brdf += 1.20 * spe * vec3(1.00, 0.90, 0.60) * dif; \n"
SCODE &= !" brdf += 0.30 * amb * vec3(0.50, 0.70, 1.00); \n"
SCODE &= !" brdf += 0.40 * dom * vec3(0.50, 0.70, 1.00); \n"
SCODE &= !" brdf += 0.30 * bac * vec3(0.25, 0.25, 0.25); \n"
SCODE &= !" brdf += 0.20 * fre * vec3(1.00, 1.00, 1.00); \n"
SCODE &= !" brdf += 0.02; \n"
SCODE &= !" \n"
SCODE &= !" return brdf; \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"vec3 render(vec3 ro, vec3 rd) { \n"
SCODE &= !" vec3 col = vec3(0.0); \n"
SCODE &= !" \n"
SCODE &= !" vec2 res = castRay(ro, rd); \n"
SCODE &= !" float t = res.x; \n"
SCODE &= !" float m = res.y; \n"
SCODE &= !" \n"
SCODE &= !" float wt = (WaterLevel - ro.y) / rd.y; \n"
SCODE &= !" \n"
SCODE &= !" bool isWater = false; \n"
SCODE &= !" float waterBlendFactor = 1.0; \n"
SCODE &= !" vec3 bottomColor = vec3(0.0); \n"
SCODE &= !" \n"
SCODE &= !" if (wt > 0.0 && wt < t) { \n"
SCODE &= !" // water \n"
SCODE &= !" float k = (t - wt) / WaterMaxVisibleDepth; \n"
SCODE &= !" waterBlendFactor = min(k * k, 1.0); \n"
SCODE &= !" vec3 pos = ro + wt * rd; \n"
SCODE &= !" \n"
SCODE &= !" vec2 e = vec2(wt * 0.05, 0.0); \n"
SCODE &= !" vec2 p = pos.xz * 2.0; \n"
SCODE &= !" float x0 = water(p); \n"
SCODE &= !" vec2 grad = vec2(water(p + e.xy) - x0, \n"
SCODE &= !" water(p + e.yx) - x0) / e.x; \n"
SCODE &= !" \n"
SCODE &= !" vec3 nor = normalize(vec3(grad.x, 1.0, grad.y)); \n"
SCODE &= !" bottomColor = waterBottomColor(ro, rd, t); \n"
SCODE &= !" \n"
SCODE &= !" rd = reflect(rd, nor); \n"
SCODE &= !" ro = pos + rd * 0.2; \n"
SCODE &= !" \n"
SCODE &= !" res = castRay(ro, rd); \n"
SCODE &= !" t = res.x; \n"
SCODE &= !" m = res.y; \n"
SCODE &= !" \n"
SCODE &= !" isWater = true; \n"
SCODE &= !" } \n"
SCODE &= !" \n"
SCODE &= !" if (m > M_NONE) { \n"
SCODE &= !" vec3 pos = ro + t * rd; \n"
SCODE &= !" vec3 nor = calcNormal(pos); \n"
SCODE &= !" \n"
SCODE &= !" col = terrainColor(ro, rd, pos, nor); \n"
SCODE &= !" vec3 brdf = doLighting(rd, pos, nor); \n"
SCODE &= !" \n"
SCODE &= !" col = col * brdf; \n"
SCODE &= !" \n"
SCODE &= !" if (isWater) { \n"
SCODE &= !" col += bottomColor * (1.0 - waterBlendFactor); \n"
SCODE &= !" col += WaterColor * 0.5; \n"
SCODE &= !" } \n"
SCODE &= !" // fog \n"
SCODE &= !" col = mix(col, vec3(0.5), 1.0 - exp(-0.000001 * t * t)); \n"
SCODE &= !" } else { \n"
SCODE &= !" col = skyColor(ro, rd); \n"
SCODE &= !" if (isWater) { \n"
SCODE &= !" col += bottomColor * (1.0 - waterBlendFactor); \n"
SCODE &= !" col += WaterColor * 0.1; \n"
SCODE &= !" \n"
SCODE &= !" } \n"
SCODE &= !" } \n"
SCODE &= !" return vec3(clamp(col, 0.0, 1.0)); \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"vec3 camPath(float time) { \n"
SCODE &= !" time *= 2.0; \n"
SCODE &= !" return 1100.0 * vec3(cos(0.0 + 0.23 * time), 0.0, cos(1.5 + 0.21 * time)); \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"mat3 setCamera(vec3 ro, vec3 ta, float cr) { \n"
SCODE &= !" vec3 cw = normalize(ta - ro); \n"
SCODE &= !" vec3 cp = vec3(sin(cr), cos(cr), 0.0); \n"
SCODE &= !" vec3 cu = normalize(cross(cw, cp)); \n"
SCODE &= !" vec3 cv = normalize(cross(cu, cw)); \n"
SCODE &= !" return mat3(cu, cv, cw); \n"
SCODE &= !"} \n"
SCODE &= !" \n"
SCODE &= !"void mainImage(out vec4 fragColor, in vec2 fragCoord) { \n"
SCODE &= !" lig = normalize(-LightDir); \n"
SCODE &= !" TerrainParam = (sin(iGlobalTime * 0.2 + TIME_SHIFT) * 0.5 + 0.5); \n"
SCODE &= !" \n"
SCODE &= !" vec2 q = fragCoord / iResolution.xy; \n"
SCODE &= !" vec2 xy = -1.0 + 2.0 * q; \n"
SCODE &= !" vec2 s = xy * vec2(iResolution.x / iResolution.y, 1.0); \n"
SCODE &= !" \n"
SCODE &= !" float time = iGlobalTime * 0.15 + 0.3 + TIME_SHIFT + 4.0 * iMouse.x / iResolution.x; \n"
SCODE &= !" \n"
SCODE &= !" vec3 ro = camPath(time); \n"
SCODE &= !" vec3 ta = camPath(time + 3.0); \n"
SCODE &= !" ro.y = terrainL(ro.xz) + 11.0; \n"
SCODE &= !" ta.y = ro.y - 20.0; \n"
SCODE &= !" float cameraRoll = 0.2 * cos(0.1 * time); \n"
SCODE &= !" \n"
SCODE &= !" // camera2world transform \n"
SCODE &= !" mat3 cam = setCamera(ro, ta, cameraRoll); \n"
SCODE &= !" \n"
SCODE &= !" // camera ray \n"
SCODE &= !" vec3 rd = cam * normalize(vec3(s.xy, 1.5)); \n"
SCODE &= !" vec3 col = render(ro, rd); \n"
SCODE &= !" \n"
SCODE &= !" col = pow(col, vec3(0.4545)); \n"
SCODE &= !" col += 0.07; \n"
SCODE &= !" // vignette \n"
SCODE &= !" //col *= 0.25 + 0.75 * pow(16.0 * q.x * q.y * (1.0 - q.x) * (1.0 - q.y), 0.07); \n"
SCODE &= !" \n"
SCODE &= !" fragColor = vec4(col, 1.0); \n"
SCODE &= !"} \n"
#include once "fbgfx.bi"
#include once "GL/gl.bi"
#include once "GL/glext.bi"
#ifndef NULL
#define NULL 0
#endif
type vec3
as GLfloat x,y,z
end type
sub ErrorExit(msg as string)
if screenptr() then screen 0
dim as integer w,h
screeninfo w,h : w*=0.75:h*=0.75
screenres w,h
print msg
print "press any key to quit ..."
beep : sleep : end 1
end sub
' define OpenGL proc's
#define glDefine(n) dim shared as PFN##n##PROC n
' texture
'glDefine(glActiveTexture)
' shader
glDefine(glCreateShader)
glDefine(glDeleteShader)
glDefine(glShaderSource)
glDefine(glCompileShader)
glDefine(glGetShaderiv)
glDefine(glGetShaderInfoLog)
' program
glDefine(glCreateProgram)
glDefine(glDeleteProgram)
glDefine(glAttachShader)
glDefine(glDetachShader)
glDefine(glLinkProgram)
glDefine(glGetProgramiv)
glDefine(glGetProgramInfoLog)
glDefine(glUseProgram)
' uniform
glDefine(glGetUniformLocation)
glDefine(glUniform1f)
glDefine(glUniform2f)
glDefine(glUniform3f)
glDefine(glUniform4f)
glDefine(glUniform1i)
#undef glDefine
sub glScreen(w as integer=640, h as integer=360, b as integer=32, d as integer=24, s as integer=0, f as integer=0)
if ScreenPtr() then screen 0
ScreenControl FB.SET_GL_STENCIL_BITS,s
ScreenControl FB.SET_GL_DEPTH_BITS ,d
if ScreenRes(w,h,b,,FB.GFX_OPENGL or iif(f<>0,FB.GFX_FULLSCREEN,0)) then
ErrorExit("screenres(" & w & "," & h &") failed !")
end if
Windowtitle "offline shadertoy.com"
flip
' get OpenGL proc's (abort if something goes wrong)
#define glProc(n) n = ScreenGLProc(#n) : if n = 0 then ErrorExit(#n)
' texture
'glProc(glActiveTexture)
' shader
glProc(glCreateShader)
glProc(glDeleteShader)
glProc(glShaderSource)
glProc(glCompileShader)
glProc(glGetShaderiv)
glProc(glGetShaderInfoLog)
' program
glProc(glCreateProgram)
glProc(glDeleteProgram)
glProc(glAttachShader)
glProc(glDetachShader)
glProc(glLinkProgram)
glProc(glGetProgramiv)
glProc(glGetProgramInfoLog)
glProc(glUseProgram)
' uniform
glProc(glGetUniformLocation)
glProc(glUniform1f)
glProc(glUniform2f)
glProc(glUniform3f)
glProc(glUniform4f)
glProc(glUniform1i)
#undef glProc
end sub
type ShaderToy
declare destructor
declare function CompileFile(Filename as string) as boolean
declare function CompileCode(Code as string) as boolean
as GLuint FragmentShader
as GLuint ProgramObject
as string Shaderlog
end type
destructor ShaderToy
if ProgramObject then
glUseprogram(0)
if FragmentShader then
glDetachShader(ProgramObject,FragmentShader)
glDeleteShader(FragmentShader)
end if
glDeleteProgram(ProgramObject)
end if
end destructor
function ShaderToy.CompileFile(filename as string) as boolean
dim as string code
var hFile = FreeFile()
if open(filename,for input, as #hFile) then
ShaderLog = "can't read shader: " & chr(34) & filename & chr(34) & " !"
return false
end if
while not eof(hFile)
dim as string aLine
line input #hFile,aLine
code &= aLine & !"\n"
wend
close #hFile
return CompileCode(code)
end function
function ShaderToy.CompileCode(UserCode as string) as boolean
dim as GLint logSize
dim as GLint status
dim as string FragmentProlog
FragmentProlog & =!"uniform float iGlobalTime; // shader playback time (in seconds)\n"
FragmentProlog & =!"uniform vec3 iResolution; // viewport resolution (in pixels)\n"
FragmentProlog & =!"uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down), zw: click\n"
FragmentProlog & =!"uniform vec4 iDate; // (year, month, day, time in seconds)\n"
FragmentProlog & =!"uniform sampler2D iChannel0;\n"
FragmentProlog & =!"uniform sampler2D iChannel1;\n"
FragmentProlog & =!"uniform sampler2D iChannel2;\n"
FragmentProlog & =!"uniform sampler2D iChannel3;\n"
dim as string FragmentEpilog
FragmentEpilog &= !"void main() {\n"
FragmentEpilog &= !" vec4 color;\n"
FragmentEpilog &= !" // call user shader\n"
FragmentEpilog &= !" mainImage(color, gl_FragCoord.xy);\n"
FragmentEpilog &= !" color.w = 1.0;\n"
FragmentEpilog &= !" gl_FragColor = color;\n"
FragmentEpilog &= !"}\n"
dim as string FragmentCode = FragmentProlog & UserCode & FragmentEpilog
FragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
if FragmentShader=0 then
ShaderLog = "glCreateShader(GL_FRAGMENT_SHADER) failed !"
return false
end if
dim as GLchar ptr pCode=strptr(FragmentCode)
glShaderSource (FragmentShader, 1, @pCode, NULL)
glCompileShader(FragmentShader)
glGetShaderiv (FragmentShader, GL_COMPILE_STATUS, @status)
if status = GL_FALSE then
glGetShaderiv(FragmentShader, GL_INFO_LOG_LENGTH, @logSize)
ShaderLog = space(logSize)
glGetShaderInfoLog(FragmentShader, logSize, NULL, cptr(GLchar ptr,strptr(ShaderLog)) )
ShaderLog = !"glCompileShader(FragmentShader) failed !\n" & Shaderlog
glDeleteShader(FragmentShader) : FragmentShader = 0
return false
end if
ProgramObject = glCreateProgram()
if ProgramObject=0 then
ShaderLog = "glCreateProgram() failed !"
glDeleteShader(FragmentShader) : FragmentShader = 0
return false
end if
glAttachShader(ProgramObject,FragmentShader)
glLinkProgram (ProgramObject)
glGetProgramiv(ProgramObject, GL_LINK_STATUS, @status)
if (status = GL_FALSE) then
glGetProgramiv(ProgramObject, GL_INFO_LOG_LENGTH, @logSize)
ShaderLog = space(logSize)
glGetProgramInfoLog (ProgramObject, logSize, NULL, cptr(GLchar ptr,strptr(ShaderLog)) )
ShaderLog = !"glLinkProgram() failed !\n" & Shaderlog
glDeleteShader(FragmentShader) : FragmentShader = 0
return false
end if
return true
end function
'
' main
'
' init Screenres, create the OpenGL context and load some OpenGL procs.
dim as integer pixels=640
' wide screen 16:9
glScreen pixels,pixels/16*9
' get curent resolution
dim as integer scr_w,scr_h
screeninfo scr_w,scr_h
dim as vec3 v3
v3.x=scr_w ' width in pixle
v3.y=scr_h '`height in pixle
v3.z=v3.x/v3.y ' pixel ratio
dim as ShaderToy Shader
if Shader.CompileCode(SCODE)=false then
ErrorExit Shader.ShaderLog
end if
' enable shader
glUseProgram(Shader.ProgramObject)
' get uniforms locations in shader program
var iGlobalTime = glGetUniformLocation(Shader.ProgramObject,"iGlobalTime")
var iResolution = glGetUniformLocation(Shader.ProgramObject,"iResolution")
var iMouse = glGetUniformLocation(Shader.ProgramObject,"iMouse")
' set vec3 iResolution
glUniform3f(iResolution,v3.x,v3.y,v3.z)
dim as integer mx,my,mb,frames,fps
dim as double tStart = Timer()
dim as double tLast=tStart
while inkey=""
dim as double tNow=Timer()
' set uniform float iGlobalTime
glUniform1f(iGlobalTime,tNow-tStart)
/'
if frames mod 3=0 then
' set vec4 iMouse
if getMouse(mx,my,,mb)=0 then
if mb then
glUniform4f(iResolution,mx,scr_h-my,1,1)
else
glUniform4f(iResolution,0,0,0,0)
end if
end if
end if
'/
'glClear(GL_COLOR_BUFFER_BIT)
' draw a rectangle (2 triangles over the whole screen)
glRectf(-1,-1,1,1)
flip ' swap the buffers
frames+=1
' update fps
if frames mod 24=0 then
fps=24/(tNow-tLast)
windowtitle "fps: " & fps
tLast=tNow
end if
wend
' disable shader
glUseProgram(0)