mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-29 17:50:22 +00:00
Merge pull request #599 from larsbrinkhoff/glsl
Add OpenGL Shading Language.
This commit is contained in:
@@ -476,6 +476,18 @@ GAS:
|
|||||||
extensions:
|
extensions:
|
||||||
- .S
|
- .S
|
||||||
|
|
||||||
|
GLSL:
|
||||||
|
group: C
|
||||||
|
type: programming
|
||||||
|
primary_extension: .glsl
|
||||||
|
extensions:
|
||||||
|
- .fp
|
||||||
|
- .frag
|
||||||
|
- .geom
|
||||||
|
- .glslv
|
||||||
|
- .shader
|
||||||
|
- .vert
|
||||||
|
|
||||||
Genshi:
|
Genshi:
|
||||||
primary_extension: .kid
|
primary_extension: .kid
|
||||||
|
|
||||||
|
|||||||
161
samples/GLSL/SyLens.glsl
Normal file
161
samples/GLSL/SyLens.glsl
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
#version 120
|
||||||
|
|
||||||
|
/*
|
||||||
|
Original Lens Distortion Algorithm from SSontech (Syntheyes)
|
||||||
|
http://www.ssontech.com/content/lensalg.htm
|
||||||
|
|
||||||
|
r2 is radius squared.
|
||||||
|
|
||||||
|
r2 = image_aspect*image_aspect*u*u + v*v
|
||||||
|
f = 1 + r2*(k + kcube*sqrt(r2))
|
||||||
|
u' = f*u
|
||||||
|
v' = f*v
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Controls
|
||||||
|
uniform float kCoeff, kCube, uShift, vShift;
|
||||||
|
uniform float chroma_red, chroma_green, chroma_blue;
|
||||||
|
uniform bool apply_disto;
|
||||||
|
|
||||||
|
// Uniform inputs
|
||||||
|
uniform sampler2D input1;
|
||||||
|
uniform float adsk_input1_w, adsk_input1_h, adsk_input1_aspect, adsk_input1_frameratio;
|
||||||
|
uniform float adsk_result_w, adsk_result_h;
|
||||||
|
|
||||||
|
float distortion_f(float r) {
|
||||||
|
float f = 1 + (r*r)*(kCoeff + kCube * r);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float inverse_f(float r)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Build a lookup table on the radius, as a fixed-size table.
|
||||||
|
// We will use a vec3 since we will store the multipled number in the Z coordinate.
|
||||||
|
// So to recap: x will be the radius, y will be the f(x) distortion, and Z will be x * y;
|
||||||
|
vec3[48] lut;
|
||||||
|
|
||||||
|
// Since out LUT is shader-global check if it's been computed alrite
|
||||||
|
// Flame has no overflow bbox so we can safely max out at the image edge, plus some cushion
|
||||||
|
float max_r = sqrt((adsk_input1_frameratio * adsk_input1_frameratio) + 1) + 0.1;
|
||||||
|
float incr = max_r / 48;
|
||||||
|
float lut_r = 0;
|
||||||
|
float f;
|
||||||
|
for(int i=0; i < 48; i++) {
|
||||||
|
f = distortion_f(lut_r);
|
||||||
|
lut[i] = vec3(lut_r, f, lut_r * f);
|
||||||
|
lut_r += incr;
|
||||||
|
}
|
||||||
|
|
||||||
|
float t;
|
||||||
|
// Now find the nehgbouring elements
|
||||||
|
// only iterate to 46 since we will need
|
||||||
|
// 47 as i+1
|
||||||
|
for(int i=0; i < 47; i++) {
|
||||||
|
if(lut[i].z < r && lut[i+1].z > r) {
|
||||||
|
// BAM! our value is between these two segments
|
||||||
|
// get the T interpolant and mix
|
||||||
|
t = (r - lut[i].z) / (lut[i+1].z - lut[i]).z;
|
||||||
|
return mix(lut[i].y, lut[i+1].y, t );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float aberrate(float f, float chroma)
|
||||||
|
{
|
||||||
|
return f + (f * chroma);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 chromaticize_and_invert(float f)
|
||||||
|
{
|
||||||
|
vec3 rgb_f = vec3(aberrate(f, chroma_red), aberrate(f, chroma_green), aberrate(f, chroma_blue));
|
||||||
|
// We need to DIVIDE by F when we redistort, and x / y == x * (1 / y)
|
||||||
|
if(apply_disto) {
|
||||||
|
rgb_f = 1 / rgb_f;
|
||||||
|
}
|
||||||
|
return rgb_f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
vec2 px, uv;
|
||||||
|
float f = 1;
|
||||||
|
float r = 1;
|
||||||
|
|
||||||
|
px = gl_FragCoord.xy;
|
||||||
|
|
||||||
|
// Make sure we are still centered
|
||||||
|
px.x -= (adsk_result_w - adsk_input1_w) / 2;
|
||||||
|
px.y -= (adsk_result_h - adsk_input1_h) / 2;
|
||||||
|
|
||||||
|
// Push the destination coordinates into the [0..1] range
|
||||||
|
uv.x = px.x / adsk_input1_w;
|
||||||
|
uv.y = px.y / adsk_input1_h;
|
||||||
|
|
||||||
|
|
||||||
|
// And to Syntheyes UV which are [1..-1] on both X and Y
|
||||||
|
uv.x = (uv.x *2 ) - 1;
|
||||||
|
uv.y = (uv.y *2 ) - 1;
|
||||||
|
|
||||||
|
// Add UV shifts
|
||||||
|
uv.x += uShift;
|
||||||
|
uv.y += vShift;
|
||||||
|
|
||||||
|
// Make the X value the aspect value, so that the X coordinates go to [-aspect..aspect]
|
||||||
|
uv.x = uv.x * adsk_input1_frameratio;
|
||||||
|
|
||||||
|
// Compute the radius
|
||||||
|
r = sqrt(uv.x*uv.x + uv.y*uv.y);
|
||||||
|
|
||||||
|
// If we are redistorting, account for the oversize plate in the input, assume that
|
||||||
|
// the input aspect is the same
|
||||||
|
if(apply_disto) {
|
||||||
|
r = r / (float(adsk_input1_w) / float(adsk_result_w));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply or remove disto, per channel honoring chromatic aberration
|
||||||
|
if(apply_disto) {
|
||||||
|
f = inverse_f(r);
|
||||||
|
} else {
|
||||||
|
f = distortion_f(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2[3] rgb_uvs = vec2[](uv, uv, uv);
|
||||||
|
|
||||||
|
// Compute distortions per component
|
||||||
|
vec3 rgb_f = chromaticize_and_invert(f);
|
||||||
|
|
||||||
|
// Apply the disto coefficients, per component
|
||||||
|
rgb_uvs[0] = rgb_uvs[0] * rgb_f.rr;
|
||||||
|
rgb_uvs[1] = rgb_uvs[1] * rgb_f.gg;
|
||||||
|
rgb_uvs[2] = rgb_uvs[2] * rgb_f.bb;
|
||||||
|
|
||||||
|
// Convert all the UVs back to the texture space, per color component
|
||||||
|
for(int i=0; i < 3; i++) {
|
||||||
|
uv = rgb_uvs[i];
|
||||||
|
|
||||||
|
// Back from [-aspect..aspect] to [-1..1]
|
||||||
|
uv.x = uv.x / adsk_input1_frameratio;
|
||||||
|
|
||||||
|
// Remove UV shifts
|
||||||
|
uv.x -= uShift;
|
||||||
|
uv.y -= vShift;
|
||||||
|
|
||||||
|
// Back to OGL UV
|
||||||
|
uv.x = (uv.x + 1) / 2;
|
||||||
|
uv.y = (uv.y + 1) / 2;
|
||||||
|
|
||||||
|
rgb_uvs[i] = uv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sample the input plate, per component
|
||||||
|
vec4 sampled;
|
||||||
|
sampled.r = texture2D(input1, rgb_uvs[0]).r;
|
||||||
|
sampled.g = texture2D(input1, rgb_uvs[1]).g;
|
||||||
|
sampled.b = texture2D(input1, rgb_uvs[2]).b;
|
||||||
|
|
||||||
|
// and assign to the output
|
||||||
|
gl_FragColor.rgba = vec4(sampled.rgb, 1.0 );
|
||||||
|
}
|
||||||
630
samples/GLSL/islandScene.glsl
Normal file
630
samples/GLSL/islandScene.glsl
Normal file
@@ -0,0 +1,630 @@
|
|||||||
|
//// 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);
|
||||||
|
}
|
||||||
68
samples/GLSL/shader.fp
Normal file
68
samples/GLSL/shader.fp
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Josh A. Beam
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||||
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
* WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||||
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const int NUM_LIGHTS = 3;
|
||||||
|
const vec3 AMBIENT = vec3(0.1, 0.1, 0.1);
|
||||||
|
const float MAX_DIST = 2.5;
|
||||||
|
const float MAX_DIST_SQUARED = MAX_DIST * MAX_DIST;
|
||||||
|
|
||||||
|
uniform vec3 lightColor[NUM_LIGHTS];
|
||||||
|
|
||||||
|
varying vec3 fragmentNormal;
|
||||||
|
varying vec3 cameraVector;
|
||||||
|
varying vec3 lightVector[NUM_LIGHTS];
|
||||||
|
|
||||||
|
void
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
// initialize diffuse/specular lighting
|
||||||
|
vec3 diffuse = vec3(0.0, 0.0, 0.0);
|
||||||
|
vec3 specular = vec3(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
// normalize the fragment normal and camera direction
|
||||||
|
vec3 normal = normalize(fragmentNormal);
|
||||||
|
vec3 cameraDir = normalize(cameraVector);
|
||||||
|
|
||||||
|
// loop through each light
|
||||||
|
for(int i = 0; i < NUM_LIGHTS; ++i) {
|
||||||
|
// calculate distance between 0.0 and 1.0
|
||||||
|
float dist = min(dot(lightVector[i], lightVector[i]), MAX_DIST_SQUARED) / MAX_DIST_SQUARED;
|
||||||
|
float distFactor = 1.0 - dist;
|
||||||
|
|
||||||
|
// diffuse
|
||||||
|
vec3 lightDir = normalize(lightVector[i]);
|
||||||
|
float diffuseDot = dot(normal, lightDir);
|
||||||
|
diffuse += lightColor[i] * clamp(diffuseDot, 0.0, 1.0) * distFactor;
|
||||||
|
|
||||||
|
// specular
|
||||||
|
vec3 halfAngle = normalize(cameraDir + lightDir);
|
||||||
|
vec3 specularColor = min(lightColor[i] + 0.5, 1.0);
|
||||||
|
float specularDot = dot(normal, halfAngle);
|
||||||
|
specular += specularColor * pow(clamp(specularDot, 0.0, 1.0), 16.0) * distFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 sample = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
gl_FragColor = vec4(clamp(sample.rgb * (diffuse + AMBIENT) + specular, 0.0, 1.0), sample.a);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user