demo.html
HTML source for Colour Rendering, 961 lines. Raw file
<html>
<title>WebGL Fragment Shader Canvas</title>
<script type="text/javascript">
//<![CDATA[
/*
WebGL Fragment Framework
(c) Lewpen Kinross-Skeels 2011
www.lewpen.com
This provides a simple way to play with fragment shaders.
You provide an HTML canvas element and a fragment shader, and this shader is executed for each pixel in
the canvas. This is implemented by rendering one quad which takes up the whole area of the canvas.
Your fragment shader has 3 inputs:
varying vec3 vPosition; // Position of this pixel in the canvas - ranging from -1.0 to 1.0 in X and Y
uniform float uTime; // Time in seconds since the animaton started
uniform vec2 uMousePos; // Position of the mouse cursor over the canvas, from -1.0 to 1.0 in X and Y
*/
var TEXTURE_RES0 = 8;
var TEXTURE_RES1 = 16;
var TEXTURE_RES2 = 32;
var TEXTURE_RES3 = 64;
var TEXTURE_RES4 = 128;
var TEXTURE_RES5 = 256;
var TEXTURE_RES6 = 512;
var gl;
var fractal_shaderProgram;
var final_shaderProgram;
var aVertexPosition;
function initGL(canvas)
{
console.logFunction( 'initGL', [ canvas ] )
try
{
gl = canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
}
catch(e)
{
throw [ e, "Could not initialise WebGL, sorry :-(" ]
}
if (!gl)
{
throw "Could not initialise WebGL, sorry :-("
}
}
function createShaderProgram( gl, vs, fs )
{
console.logFunction( 'createShaderProgram', [ gl, vs, fs ] )
var shaderProgram = gl.createProgram()
// Create vertex shader
console.log( '* CREATING VSHADER' )
var vshader = gl.createShader( gl.VERTEX_SHADER )
gl.shaderSource( vshader, vs )
gl.compileShader( vshader )
if( !gl.getShaderParameter( vshader, gl.COMPILE_STATUS ) )
{
alert("Vertex shader compilation error\n"+gl.getShaderInfoLog(vshader)+"\n\n--\n"+vs);
return null
}
// Create fragment shader
console.log( '* CREATING FSHADER' )
var fshader = gl.createShader( gl.FRAGMENT_SHADER )
gl.shaderSource( fshader, fs )
gl.compileShader( fshader )
if( !gl.getShaderParameter( fshader, gl.COMPILE_STATUS ) )
{
alert("Fragment shader compilation error\n"+gl.getShaderInfoLog(fshader)+"\n\n--\n"+fs);
return null
}
// Create and link program
console.log( '* ATTACHING VSHADER' )
gl.attachShader( shaderProgram, vshader )
console.log( '* ATTACHING FSHADER' )
gl.attachShader( shaderProgram, fshader )
console.log( '* LINKING PROGRAM' )
gl.linkProgram( shaderProgram )
if( !gl.getProgramParameter(shaderProgram, gl.LINK_STATUS) )
{
console.log( '! LINKING FAILED: '+gl.getProgramInfoLog( shaderProgram ) )
return null
}
console.log( '* WORKED: ' + shaderProgram )
return shaderProgram
}
function getShaderFromElement( gl, id )
{
console.logFunction( 'getShaderFromElement', [ gl, id ] )
var shaderScript = document.getElementById( id )
if( !shaderScript ) return null
var str = "";
var k = shaderScript.firstChild;
while (k)
{
if (k.nodeType == 3)
str += k.textContent;
k = k.nextSibling;
}
var shader;
if (shaderScript.type == "x-shader/x-fragment")
{
shader = gl.createShader(gl.FRAGMENT_SHADER);
}
else if (shaderScript.type == "x-shader/x-vertex")
{
shader = gl.createShader(gl.VERTEX_SHADER);
}
else
{
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
{
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
function CreateFragmentShader( shader_element_id )
{
console.logFunction( 'CreateFragmentShader', [] )
vs =
'#ifdef GL_ES\nprecision mediump float;\n#endif\n' +
'attribute vec3 aVertexPosition; uniform float uTime; varying vec3 vPosition;' +
'void main(void) { gl_Position = vec4(aVertexPosition, 1.0); vPosition = aVertexPosition; }'
fs =
// '#ifdef GL_ES\nprecision mediump float;\n#endif\n' +
document.getElementById( shader_element_id ).textContent
var shader_program = createShaderProgram( gl, vs, fs )
// Create the vertex array buffers
gl.useProgram( shader_program );
var aVertexPosition = gl.getAttribLocation( shader_program, "aVertexPosition" )
gl.enableVertexAttribArray( aVertexPosition )
return shader_program
}
var vertexPositionBuffer
function initBuffers()
{
console.logFunction( 'initBuffers', [] )
vertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
var vertices = [
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
vertexPositionBuffer.itemSize = 3;
vertexPositionBuffer.numItems = 4;
}
// Resolution 0 is always a tiny texture containing zeroes (TEXTURE_RES0)
var fractal_res0_framebuffer
var fractal_res0_texture
// Resolution 1 is TEXTURE_RES1
var fractal_res1_framebuffer
var fractal_res1_texture
// Resolution 2 is TEXTURE_RES2
var fractal_res2_framebuffer
var fractal_res2_texture
// Resolution 3 is TEXTURE_RES3
var fractal_res3_framebuffer
var fractal_res3_texture
// Resolution 4 is TEXTURE_RES3
var fractal_res4_framebuffer
var fractal_res4_texture
// Resolution 5 is TEXTURE_RES3
var fractal_res5_framebuffer
var fractal_res5_texture
// Resolution 6 is TEXTURE_RES3
var fractal_res6_framebuffer
var fractal_res6_texture
function initFramebuffer( w, h )
{
var f
var t
console.log( 'initFrameBuffer '+w+' x '+h );
f = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, f);
f.width = w;
f.height = h;
t = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, t);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, f.width, f.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
var renderbuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, f.width, f.height);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, t, 0);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
return [f,t]
}
//---- webgl_timer
var webgl_statusElementName = false
var lastTime = 0
var normalisedTime = 0
var timer_count = 0
function webgl_timer()
{
// Play as fast as possible
if( window['mozRequestAnimationFrame'] ) mozRequestAnimationFrame( webgl_timer )
else if( window['webkitRequestAnimationFrame'] ) webkitRequestAnimationFrame( webgl_timer )
timer_count ++
if( timer_count == 1 )
{
console.log( 'START OF FIRST TIMER' )
}
var timeNow = new Date().getTime();
if (lastTime != 0)
{
var elapsed = timeNow - lastTime;
normalisedTime += elapsed;
if( webgl_statusElementName )
{
var status = document.getElementById( webgl_statusElementName )
var fps = (1000.0 / Math.max( elapsed, 0.0001 ));
fps = Math.floor( fps*1000 ) / 1000;
status.innerHTML = 'FPS: ' + fps;
}
}
lastTime = timeNow;
// var depth_texture = gl.getUniformLocation( fractal_shaderProgram, "depth_texture" )
//- Draw
//- LOW RES DEPTH TEXTURE
gl.useProgram( fractal_shaderProgram );
var timeUniform = gl.getUniformLocation( fractal_shaderProgram, "uTime" )
gl.uniform1f( timeUniform, normalisedTime / 1000.0 )
var render_fractal = function( current_framebuffer, previous_layer_texture, previous_layer_res )
{
gl.bindFramebuffer(gl.FRAMEBUFFER, current_framebuffer )
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, previous_layer_texture);
gl.uniform1i(gl.getUniformLocation( fractal_shaderProgram, "uPreviousLayerSampler" ), 0);
gl.viewport(0, 0, current_framebuffer.width, current_framebuffer.height);
gl.uniform1f(gl.getUniformLocation( fractal_shaderProgram, "uPreviousLayerResolution" ), previous_layer_res );
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT )
gl.bindBuffer( gl.ARRAY_BUFFER, vertexPositionBuffer )
gl.vertexAttribPointer( aVertexPosition, vertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0 )
gl.drawArrays( gl.TRIANGLE_STRIP, 0, vertexPositionBuffer.numItems )
}
// draw scene
render_fractal( fractal_res1_framebuffer, fractal_res0_texture, TEXTURE_RES0 )
render_fractal( fractal_res2_framebuffer, fractal_res1_texture, TEXTURE_RES1 )
render_fractal( fractal_res3_framebuffer, fractal_res2_texture, TEXTURE_RES2 )
render_fractal( fractal_res4_framebuffer, fractal_res3_texture, TEXTURE_RES3 )
render_fractal( fractal_res5_framebuffer, fractal_res4_texture, TEXTURE_RES4 )
render_fractal( fractal_res6_framebuffer, fractal_res5_texture, TEXTURE_RES5 )
//- NORMAL RESOLUTION DEPTH TEXTUEE
/*
gl.bindFramebuffer(gl.FRAMEBUFFER, null)
// draw scene
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, fractal_res1_texture);
gl.uniform1i(gl.getUniformLocation( fractal_shaderProgram, "uPreviousLayerSampler" ), 0);
gl.uniform1f(gl.getUniformLocation( fractal_shaderProgram, "uPreviousLayerResolution" ), TEXTURE_RES0 );
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT )
gl.bindBuffer( gl.ARRAY_BUFFER, vertexPositionBuffer )
gl.vertexAttribPointer( aVertexPosition, vertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0 )
gl.drawArrays( gl.TRIANGLE_STRIP, 0, vertexPositionBuffer.numItems )
*/
//- RGB FINAL OUTPUT
gl.useProgram( final_shaderProgram );
var timeUniform2 = gl.getUniformLocation( final_shaderProgram, "uTime" )
gl.uniform1f( timeUniform2, normalisedTime / 1000.0 )
gl.bindFramebuffer(gl.FRAMEBUFFER, null)
// draw scene
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, fractal_res6_texture);
gl.uniform1i(gl.getUniformLocation( final_shaderProgram, "uPreviousLayerSampler" ), 0);
gl.uniform1f(gl.getUniformLocation( final_shaderProgram, "uPreviousLayerResolution" ), TEXTURE_RES2 );
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT )
gl.bindBuffer( gl.ARRAY_BUFFER, vertexPositionBuffer )
gl.vertexAttribPointer( aVertexPosition, vertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0 )
gl.drawArrays( gl.TRIANGLE_STRIP, 0, vertexPositionBuffer.numItems )
//- DONE
if( timer_count == 1 )
{
console.log( 'END OF FIRST TIMER' )
}
}
//---- webgl_init
function webgl_init( canvasElementName, statusElementName )
{
console.logFunction( 'webgl_init', [ canvasElementName, statusElementName ] )
if( statusElementName ) webgl_statusElementName = statusElementName
var canvas = document.getElementById( canvasElementName );
initGL(canvas);
fractal_shaderProgram = CreateFragmentShader( 'shader' );
final_shaderProgram = CreateFragmentShader( 'finalshader' );
initBuffers();
var buf0 = initFramebuffer( TEXTURE_RES0, TEXTURE_RES0 ); // for render to texture
fractal_res0_framebuffer = buf0[0]
fractal_res0_texture = buf0[1]
var buf1 = initFramebuffer( TEXTURE_RES1, TEXTURE_RES1 ); // for render to texture
fractal_res1_framebuffer = buf1[0]
fractal_res1_texture = buf1[1]
var buf2 = initFramebuffer( TEXTURE_RES2, TEXTURE_RES2 ); // for render to texture
fractal_res2_framebuffer = buf2[0]
fractal_res2_texture = buf2[1]
var buf3 = initFramebuffer( TEXTURE_RES3, TEXTURE_RES3 ); // for render to texture
fractal_res3_framebuffer = buf3[0]
fractal_res3_texture = buf3[1]
var buf4 = initFramebuffer( TEXTURE_RES4, TEXTURE_RES4 ); // for render to texture
fractal_res4_framebuffer = buf4[0]
fractal_res4_texture = buf4[1]
var buf5 = initFramebuffer( TEXTURE_RES5, TEXTURE_RES5 ); // for render to texture
fractal_res5_framebuffer = buf5[0]
fractal_res5_texture = buf5[1]
var buf6 = initFramebuffer( TEXTURE_RES6, TEXTURE_RES6 ); // for render to texture
fractal_res6_framebuffer = buf6[0]
fractal_res6_texture = buf6[1]
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
console.log( 'STARTING TIMER' )
webgl_timer()
}
console.logFunction = function( fn_name, fn_args )
{
var msg = fn_name + '( '
for( var i=0; i<fn_args.length; i++ )
{
if( i > 0 ) msg = msg + ', '
msg = msg + fn_args[i]
}
console.log( msg )
}
//]]>
</script>
<script id="shader" type="x-shader/x-fragment">
#ifdef GL_ES
precision mediump float;
#endif
varying vec3 vPosition;
uniform float uTime;
uniform vec2 uMousePos;
// this will be the output from the previous loop
uniform sampler2D uPreviousLayerSampler;
uniform float uPreviousLayerResolution;
//ifs
float fu; //fractal_spheresubstract
float fd; //fractal_distancemult
vec3 cs; //fractal_csize
float fs; //fractal_size
vec3 fc; //fractal_c
vec2 rs; //resolution
//camera
vec3 cp; //camera position
mat3 cr; //camera rotation
float unpack(const in vec4 rgba_depth)
{
const vec4 bitShifts = vec4(1.0,
1.0 / 255.0,
1.0 / (255.0 * 255.0),
1.0 / (255.0 * 255.0 * 255.0));
return dot(rgba_depth, bitShifts);
}
/// <summary>
/// Pack a floating point value into an RGBA (32bpp).
/// Used by SSM, PCF, and ESM.
///
/// Note that video cards apply some sort of bias (error?) to pixels,
/// so we must correct for that by subtracting the next component's
/// value from the previous component.
/// </summary>
vec4 pack (float depth)
{
//return ( floor( (depth) * 255.0 ) / 255.0) * vec4( 1.0, 0.0, 0.0, 1.0 );
//return vec4( floor( fract( depth ) * 255.0 ) / 255.0, 0.0, 0.0, 0.0 );
const vec4 bias = vec4(1.0 / 255.0,
1.0 / 255.0,
1.0 / 255.0,
0.0);
float r = floor( depth * 255.0 );
float g = floor( fract( depth * 255.0 ) * 255.0);
float b = floor( fract( depth * 255.0 * 255.0) * 255.0);
float a = floor( fract( depth * 255.0 * 255.0 * 255.0) * 255.0);
vec4 colour = (1.0 / 255.0) * vec4(r, g, b, 255.0);
return colour;// - (colour.yzww * bias);
}
float dE(vec3 p) {
// peterb
// p.x += 0.00015*sin(p.y*8000.0+uTime*30.0)*(0.5+0.5*sin(uTime*30.0/8.0));
float dEfactor=1.0;
//int fractal_iterations = 12;
for(int i=0;i<16;i++){
//box folding
p=2.0*clamp(p, -cs, cs)-p;
//inversion
float k=max(fs/dot(p,p),1.0);
p*=k;
dEfactor*=k;
//julia seed
p+=fc;
}
//return 10.01*dot(p,p);
//call basic shape and scale its DE
//need to adjust fractal_distancemult with non zero julia seed
//return 0.1*dot(p,p);
float aa = 1.5;//length(p.xy);
float rxy=aa-fu;
//distance from pos to the pseudo kleinian basic shape ...
return
(fd*max(0.0,abs(length(p.xy)*p.z)/sqrt(dot(p,p)))
/
abs(dEfactor));
}
float rd(vec2 fragment_coordinates, float ray_length) {
//calculate ray direction from fragment coordinates ...
vec2 ray_position = fragment_coordinates;//(0.5*rs-fragment_coordinates)/vec2(rs.x,-rs.y);
ray_position.x *= (rs.x/rs.y); //aspect_ratio
vec3 ray_direction = normalize(cr * vec3(ray_position.x * vec3(1, 0, 0) + ray_position.y * vec3(0, 1, 0) - .9 * vec3(0, 0, 1)));
//sphere tracing initialization ...
//float ray_length = 0.0; // this is now provided in the function arguments
vec3 ray = cp+ray_length*ray_direction;
float epsilon = 0.0000006;//0.0000006;
float calculated_distance;
int tracingsteps = 0;
bool hit = false;
//magic :) DO NOT TOUCH!
float uCurrentLayerResolution = uPreviousLayerResolution * 2.0;//== 0.0 ? 128.0 : 512.0;
float eps_factor = 1.0*1.41423*(1.01/uCurrentLayerResolution);
// TODO: Use the pixel size as the cutoff point
//actual sphere tracing ...
//#define tracingsteps_max 200
float last_ray_length = ray_length;
for (int i=0; i<50; i++) {
// epsilon is set based on the distance
tracingsteps = i;
calculated_distance = dE(ray);
//small stepback to remove 'fuzzel'-structures near inside shooting range
//#define raylength_max 10000.0
/* if (hit && calculated_distance<epsilon || ray_length>10000.) {
tracingsteps--;
break;
}
hit = false;
*/
last_ray_length = ray_length;
ray_length += calculated_distance;
epsilon = ray_length * eps_factor;
if (calculated_distance<epsilon) {
// hit = true;
break;
}
ray = cp+ray_length*ray_direction;
}
//---
//intersects ?
//#define tracingsteps_max 200
// return float(tracingsteps)/float(40);
/*
float epsilon_normal = 1.5e-7;
vec3 normal = normalize(vec3(
dE(ray+vec3(epsilon_normal, 0, 0))-dE(ray-vec3(epsilon_normal, 0, 0)),
dE(ray+vec3(0, epsilon_normal, 0))-dE(ray-vec3(0, epsilon_normal, 0)),
dE(ray+vec3(0, 0, epsilon_normal))-dE(ray-vec3(0, 0, epsilon_normal)))
);
*/
// if( hit )
{
return last_ray_length;//1.0 - 1.0/( ray_length*30.0 + 1.0 );
// + 0.1 + 0.1 * dot( normal, vec3( 0.707, 0.0, 0.707 ) );
}
// else
// {
// return 0.5;
// }
}
//return rotation matrix for rotating around vector v by angle
mat3 mr(vec3 v, float angle) {
float c = cos(radians(angle));
float s = sin(radians(angle));
return mat3(c+(1.0-c)*v.x*v.x , (1.0-c)*v.x*v.y-s*v.z , (1.0-c)*v.x*v.z+s*v.y,
(1.0-c)*v.x*v.y+s*v.z, c+(1.0-c)*v.y*v.y , (1.0-c)*v.y*v.z-s*v.x,
(1.0-c)*v.x*v.z-s*v.y, (1.0 - c)*v.y*v.z+s*v.x, c+(1.0-c)*v.z*v.z);
}
void main(void)
{
float ray_length = 0.0;
if( uPreviousLayerResolution > 0.0 )
{
float uu1 = floor( (0.5+vPosition.x*0.5) * uPreviousLayerResolution ) / uPreviousLayerResolution;
float vv1 = floor( (0.5+vPosition.y*0.5) * uPreviousLayerResolution ) / uPreviousLayerResolution;
//float uu2 = floor( (0.5+vPosition.x*0.5) * uPreviousLayerResolution + 1.0 ) / uPreviousLayerResolution;
//float vv2 = floor( (0.5+vPosition.y*0.5) * uPreviousLayerResolution ) / uPreviousLayerResolution;
//float uu3 = floor( (0.5+vPosition.x*0.5) * uPreviousLayerResolution + 1.0 ) / uPreviousLayerResolution;
//float vv3 = floor( (0.5+vPosition.y*0.5) * uPreviousLayerResolution + 1.0 ) / uPreviousLayerResolution;
//float uu4 = floor( (0.5+vPosition.x*0.5) * uPreviousLayerResolution ) / uPreviousLayerResolution;
//float vv4 = floor( (0.5+vPosition.y*0.5) * uPreviousLayerResolution + 1.0 ) / uPreviousLayerResolution;
float l1 = unpack( texture2D( uPreviousLayerSampler, vec2(uu1, vv1) ) );
//float l2 = unpack( texture2D( uPreviousLayerSampler, vec2(uu2, vv2) ) );
//float l3 = unpack( texture2D( uPreviousLayerSampler, vec2(uu3, vv3) ) );
//float l4 = unpack( texture2D( uPreviousLayerSampler, vec2(uu4, vv4) ) );
ray_length = l1;
//if( l2 > ray_length ) ray_length = l2;
//if( l3 > ray_length ) ray_length = l3;
//if( l4 > ray_length ) ray_length = l4;
// TODO: Unpack and decode ray_length
//if( fract(floor(fract(uTime)*5.0)*0.5) > 0.25 )
{
// gl_FragColor = texture2D( uPreviousLayerSampler, vec2(uu, vv) );
//gl_FragColor = vec4( 1.0 ) * ray_length;//(1.0 - 1.0/( ray_length*30.0 + 1.0 ) );
// return;
}
}
float camera_roll = 0.;
float camera_pitch = 90.;
float camera_yaw = 0.;
vec2 custom_glFragCoord = gl_FragCoord.xy;
float temp_scenetimer = 200.0 - uTime * 0.10;
fu = 10.0;
fd = 0.763;
cs = vec3(0.80800,0.80800,1.16700);
fs = 1.0;
fc = vec3(0.0);
rs = vec2( 200.0, 200.0 );
camera_pitch = 23.9;
cp = vec3(0.8,-1.16339+16.0-temp_scenetimer*1.395,-1.80153);
cs.y = 0.58000;
fu = 1.21000;
cp = vec3(0.0007,0.02000,0.10000-temp_scenetimer*0.00028);
camera_pitch = 0.0;
camera_yaw = temp_scenetimer*0.009*180.0;
cs.x = 0.90000;
cr = mat3( 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 );
cr = mr(vec3(0, 1, 0), 180.0 - camera_yaw) * mr(vec3(1, 0, 0), -camera_pitch) * mr(vec3(0, 0, 1), camera_roll);
float a = rd( vec2( vPosition.x, vPosition.y ), ray_length );
gl_FragColor = pack(a); //vec4(1.0) * a * 10.0;//pack( a );
}
</script>
<script id="finalshader" type="x-shader/x-fragment">
#ifdef GL_ES
precision mediump float;
#endif
varying vec3 vPosition;
uniform float uTime;
uniform vec2 uMousePos;
uniform sampler2D uPreviousLayerSampler;
float unpack(const in vec4 rgba_depth)
{
const vec4 bitShifts = vec4(1.0,
1.0 / 255.0,
1.0 / (255.0 * 255.0),
0.0 / (255.0 * 255.0 * 255.0));
return dot(rgba_depth, bitShifts);
}
//ifs
float fu; //fractal_spheresubstract
float fd; //fractal_distancemult
vec3 cs; //fractal_csize
float fs; //fractal_size
vec3 fc; //fractal_c
vec2 rs; //resolution
//camera
vec3 cp; //camera position
mat3 cr; //camera rotation
vec3 dE(vec3 p) {
vec3 last_pos = p;
// peterb
// p.x += 0.00015*sin(p.y*8000.0+uTime*30.0)*(0.5+0.5*sin(uTime*30.0/8.0));
float dEfactor=1.0;
//int fractal_iterations = 12;
for(int i=0;i<20;i++)
{
//box folding
p=2.0*clamp(p, -cs, cs)-p;
//inversion
float k=max(fs/dot(p,p),1.0);
p*=k;
dEfactor*=k;
//julia seed
p+=fc;
last_pos += p;
}
return 0.5 + 0.5 * last_pos;
//float d = dot( last_pos, last_pos );
//return vec3(0.5) + 0.75*vec3
//(
// sin(d*0.154+2.317), sin(d*0.124+1.331), sin(d*0.172-1.22)
//);
return vec3( 0.5 ) + vec3( 0.5 ) * dot( last_pos, last_pos );
/*
//return 10.01*dot(p,p);
//call basic shape and scale its DE
//need to adjust fractal_distancemult with non zero julia seed
//return 0.1*dot(p,p);
float aa = 1.5;//length(p.xy);
float rxy=aa-fu;
//distance from pos to the pseudo kleinian basic shape ...
return
(fd*max(0.0,abs(length(p.xy)*p.z)/sqrt(dot(p,p)))
/
abs(dEfactor));
*/
}
vec3 raypos(vec2 fragment_coordinates, float ray_length )
{
//calculate ray direction from fragment coordinates ...
vec2 ray_position = fragment_coordinates;//(0.5*rs-fragment_coordinates)/vec2(rs.x,-rs.y);
ray_position.x *= (rs.x/rs.y); //aspect_ratio
vec3 ray_direction = normalize(cr * vec3(ray_position.x * vec3(1, 0, 0) + ray_position.y * vec3(0, 1, 0) - .9 * vec3(0, 0, 1)));
//sphere tracing initialization ...
//float ray_length = 0.0; // this is now provided in the function arguments
return cp+ray_length*ray_direction;
}
//return rotation matrix for rotating around vector v by angle
mat3 mr(vec3 v, float angle)
{
float c = cos(radians(angle));
float s = sin(radians(angle));
return mat3(c+(1.0-c)*v.x*v.x , (1.0-c)*v.x*v.y-s*v.z , (1.0-c)*v.x*v.z+s*v.y,
(1.0-c)*v.x*v.y+s*v.z, c+(1.0-c)*v.y*v.y , (1.0-c)*v.y*v.z-s*v.x,
(1.0-c)*v.x*v.z-s*v.y, (1.0 - c)*v.y*v.z+s*v.x, c+(1.0-c)*v.z*v.z);
}
vec4 colour( float ray_length )
{
float camera_roll = 0.;
float camera_pitch = 90.;
float camera_yaw = 0.;
vec2 custom_glFragCoord = gl_FragCoord.xy;
float temp_scenetimer = 200.0 - uTime * 0.10;
fu = 10.0;
fd = 0.763;
cs = vec3(0.80800,0.80800,1.16700);
fs = 1.0;
fc = vec3(0.0);
rs = vec2( 200.0, 200.0 );
camera_pitch = 23.9;
cp = vec3(0.8,-1.16339+16.0-temp_scenetimer*1.395,-1.80153);
cs.y = 0.58000;
cp = vec3(0.0007,0.02000,0.10000-temp_scenetimer*0.00028);
camera_pitch = 0.0;
camera_yaw = temp_scenetimer*0.009*180.0;
cs.x = 0.90000;
cr = mat3( 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 );
cr = mr(vec3(0, 1, 0), 180.0 - camera_yaw) * mr(vec3(1, 0, 0), -camera_pitch) * mr(vec3(0, 0, 1), camera_roll);
vec3 ray = raypos( vec2( vPosition.x, vPosition.y ), ray_length );
vec3 a = dE( ray );
return vec4( 0.5 + 0.1 * a.xyz, 1.0 );
}
void main(void)
{
// Texture lookup coordinates
float uu = 0.5 + vPosition.x*0.5;
float vv = 0.5 + vPosition.y*0.5;
// Unpack and decode ray_length
float ray_length = unpack( texture2D( uPreviousLayerSampler, vec2(uu, vv) ) );
float s = 1.0 / 512.0;
float ray_length1 = unpack( texture2D( uPreviousLayerSampler, vec2(uu-s, vv) ) );
float ray_length2 = unpack( texture2D( uPreviousLayerSampler, vec2(uu+s, vv) ) );
float ray_length3 = unpack( texture2D( uPreviousLayerSampler, vec2(uu, vv-s) ) );
float ray_length4 = unpack( texture2D( uPreviousLayerSampler, vec2(uu, vv+s) ) );
float ss = 1.0;
ss *= ray_length1 / ray_length;
ss *= ray_length2 / ray_length;
ss *= ray_length3 / ray_length;
ss *= ray_length4 / ray_length;
float ll = ray_length1 / ray_length;
ll = ll*ll*ll*ll*ll;
//ll = ll*ll*ll*ll*ll;
ss *= ss*(ss)*ss*ss;
//ss *= ss*(ss)*ss*ss;
if( ss < 0.0 ) ss = 0.0;
if( ss > 1.0 ) ss = 1.0;
gl_FragColor = (1.0 - 100.0 * ray_length) * vec4( 1.0 ) * colour( ray_length );// * ((log( ray_length * 1000000.0 )-0.5)*0.5+0.5);
//gl_FragColor = texture2D( uPreviousLayerSampler, vec2( uu, vv ) );
//gl_FragColor = vec4( 1.0, 0.5, 0.2, 1.0 );
}
</script>
<body onload="webgl_init( 'canvas', 'status' )" bgcolor="#000000">
<table cellspacing="0" cellpadding="0" border="0" width="100%" aheight="100%"><tr><td align="center" valign="middle">
<table cellspacing="0" cellpadding="0" border="0" width="200">
<tr>
<td style="padding:8px;background:#555555;color:#FFFFFF;font-family:arial;font-size:11px;font-weight:bold">
<div>WebGL Fragment Shader Test 2</div>
</td>
</tr>
<tr>
<td><canvas id="canvas" width="512" height="512" style="border:5px solid #FFFFFF"></canvas></td>
</tr><tr>
<td style="padding:8px;background:#555555;color:#FFFFFF;font-family:arial;font-size:11px;font-weight:bold">
<div id="status"> </div>
</td>
</tr>
</table>
</td></tr></table>
</body>
</html>