Skip to content
Browse files

initial commit (texture load and blur)

projection mapping shader to follow...
  • Loading branch information...
0 parents commit 9f168325117227edaca7595d34af702c49a8d959 Felix Woitzel committed Oct 31, 2011
Showing with 5,131 additions and 0 deletions.
  1. +4,539 −0 PhiloGL.js
  2. BIN breakfastHQ.jpg
  3. BIN breakfastLQ.jpg
  4. +216 −0 index.html
  5. +286 −0 index.js
  6. +90 −0 style.css
4,539 PhiloGL.js
4,539 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
BIN breakfastHQ.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN breakfastLQ.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
216 index.html
@@ -0,0 +1,216 @@
+
+<!DOCTYPE html>
+<html>
+<head>
+<title>Image post-processing API example</title>
+<link href='http://fonts.googleapis.com/css?family=Crimson+Text'
+ rel='stylesheet' type='text/css'>
+<link rel="stylesheet" media="all" type="text/css" href="style.css" />
+<style type="text/css">
+canvas {
+ background: black;
+}
+</style>
+
+
+<script id="shader-vs" type="x-shader/x-vertex">
+ attribute vec3 position;
+ attribute vec2 texCoord1;
+
+ uniform mat4 worldMatrix;
+ uniform mat4 projectionMatrix;
+
+ varying vec2 pixel;
+ void main(void) {
+ gl_Position = projectionMatrix * worldMatrix * vec4(position, 1.);
+ pixel = texCoord1;
+ }
+</script>
+
+<script id="shader-fs-copy" type="x-shader/x-fragment">
+#ifdef GL_ES
+precision highp float;
+#endif
+ uniform sampler2D sampler_prev;
+ varying vec2 pixel;
+void main(void) {
+ gl_FragColor = texture2D(sampler_prev, pixel);
+ gl_FragColor.a = 1.;
+}
+</script>
+
+<script id="shader-fs-blur-horizontal" type="x-shader/x-fragment">
+#ifdef GL_ES
+precision highp float;
+#endif
+// original shader from http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/
+// horizontal blur fragment shader
+uniform sampler2D sampler1;//src_tex;
+varying vec2 pixel;
+uniform vec2 pixelSize;
+void main(void) // fragment
+{
+ float h = pixelSize.x;
+ vec4 sum = vec4(0.0);
+ sum += texture2D(sampler1, vec2(pixel.x - 4.0*h, pixel.y) ) * 0.05;
+ sum += texture2D(sampler1, vec2(pixel.x - 3.0*h, pixel.y) ) * 0.09;
+ sum += texture2D(sampler1, vec2(pixel.x - 2.0*h, pixel.y) ) * 0.12;
+ sum += texture2D(sampler1, vec2(pixel.x - 1.0*h, pixel.y) ) * 0.15;
+ sum += texture2D(sampler1, vec2(pixel.x + 0.0*h, pixel.y) ) * 0.16;
+ sum += texture2D(sampler1, vec2(pixel.x + 1.0*h, pixel.y) ) * 0.15;
+ sum += texture2D(sampler1, vec2(pixel.x + 2.0*h, pixel.y) ) * 0.12;
+ sum += texture2D(sampler1, vec2(pixel.x + 3.0*h, pixel.y) ) * 0.09;
+ sum += texture2D(sampler1, vec2(pixel.x + 4.0*h, pixel.y) ) * 0.05;
+ gl_FragColor.xyz = sum.xyz/0.98; // normalize
+ gl_FragColor.a = 1.;
+}
+</script>
+
+<script id="shader-fs-blur-vertical" type="x-shader/x-fragment">
+#ifdef GL_ES
+precision highp float;
+#endif
+// original shader from http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/
+// vertical blur fragment shader
+uniform sampler2D sampler1;//src_tex;
+varying vec2 pixel;
+uniform vec2 pixelSize;
+void main(void) // fragment
+{
+ float v = pixelSize.y;
+ vec4 sum = vec4(0.0);
+ sum += texture2D(sampler1, vec2(pixel.x, - 4.0*v + pixel.y) ) * 0.05;
+ sum += texture2D(sampler1, vec2(pixel.x, - 3.0*v + pixel.y) ) * 0.09;
+ sum += texture2D(sampler1, vec2(pixel.x, - 2.0*v + pixel.y) ) * 0.12;
+ sum += texture2D(sampler1, vec2(pixel.x, - 1.0*v + pixel.y) ) * 0.15;
+ sum += texture2D(sampler1, vec2(pixel.x, + 0.0*v + pixel.y) ) * 0.16;
+ sum += texture2D(sampler1, vec2(pixel.x, + 1.0*v + pixel.y) ) * 0.15;
+ sum += texture2D(sampler1, vec2(pixel.x, + 2.0*v + pixel.y) ) * 0.12;
+ sum += texture2D(sampler1, vec2(pixel.x, + 3.0*v + pixel.y) ) * 0.09;
+ sum += texture2D(sampler1, vec2(pixel.x, + 4.0*v + pixel.y) ) * 0.05;
+ gl_FragColor.xyz = sum.xyz/0.98;
+ gl_FragColor.a = 1.;
+}
+</script>
+<script id="shader-fs-advance" type="x-shader/x-fragment">
+ #ifdef GL_ES
+ precision highp float;
+ #endif
+
+ uniform sampler2D sampler1; // prev;
+ uniform sampler2D sampler2; // blur1;
+ uniform sampler2D sampler3; // blur2;
+ uniform sampler2D sampler4; // blur3;
+ uniform sampler2D sampler5; // blur4;
+ uniform sampler2D sampler6; // blur5;
+ uniform sampler2D sampler7; // panorama texture
+
+ varying vec2 pixel;
+ uniform vec2 mouse;
+
+ bool is_onscreen(vec2 uv){
+ return (uv.x < 1.) && (uv.x > 0.) && (uv.y < 1.) && (uv.y > 0.);
+ }
+
+ void main(void) {
+ vec2 c = vec2(-0.226,0.087);
+ vec2 tuning = vec2(1.77);
+ vec2 complexSquaredPlusC; // One steps towards the Julia Attractor
+ vec2 uv = (pixel - vec2(0.5))*tuning;
+ complexSquaredPlusC.x = (uv.x * uv.x - uv.y * uv.y + c.x + 0.5);
+ complexSquaredPlusC.y = (2. * uv.x * uv.y + c.y + 0.5);
+
+ if(is_onscreen(complexSquaredPlusC)){
+ vec4 old = texture2D(sampler1, complexSquaredPlusC);
+ gl_FragColor = old + vec4( -.0035, .0, .0, 1.); // decrement the red channel
+ }else{
+ // return border color
+ gl_FragColor = vec4(1., 0., 0., 1.); // out is red
+ }
+
+ // Do not dare to try a McCabeism implementation in the green or the blue channel here, Fnord.
+ // http://www.wblut.com/2011/07/13/mccabeism-turning-noise-into-a-thing-of-beauty/
+
+ gl_FragColor = texture2D(sampler7, pixel);
+ gl_FragColor.a = 1.;
+ }
+</script>
+
+<script id="shader-fs-composite" type="x-shader/x-fragment">
+ #ifdef GL_ES
+ precision highp float;
+ #endif
+
+ // e^5
+ #define E5 147.413159102576
+
+ uniform sampler2D sampler1; // plain
+ uniform sampler2D sampler2; // blur1
+ uniform sampler2D sampler3; // blur2
+ uniform sampler2D sampler4; // blur3
+ uniform sampler2D sampler5; // blur4
+ uniform sampler2D sampler6; // blur5
+ uniform sampler2D sampler7; // panorama texture
+
+ varying vec2 pixel;
+ uniform vec2 mouse;
+
+/**
+ * Blur with a fake linearly adjustable strength. Made for a smooth transistion through the blur levels.
+ * This function was considered as a simple demo and not a productive blur function first. It turned out quite nice though ^^
+ * @arg blur : blur strength, 0 no blur ..1 max
+ */
+vec4 lerp_blur(vec2 uv, float blur){
+
+ vec4 plain = texture2D(sampler1,uv);
+ vec4 blur1 = texture2D(sampler2,uv); // (1x) blur result from the two-pass algorithm shader program
+ vec4 blur2 = texture2D(sampler3,uv); // (2x) each blur texture has half the side length of its predecessor
+ vec4 blur3 = texture2D(sampler4,uv); // (4x) iteratively, we have an exponential increase of blur strength
+ vec4 blur4 = texture2D(sampler5,uv); // (8x)
+ vec4 blur5 = texture2D(sampler6,uv); // (16x)
+
+ blur = log(clamp(blur, 0., 1.)*E5+1.)/5.; // linearization of the exponential blur radius growth
+
+ blur = clamp(blur, 0., 1.)*5.;
+ if(blur < 1.){
+ return mix( plain, blur1, vec4(blur)); // linear interpolation between the first two textures
+ }else if(blur < 2.) {
+ return mix( blur1, blur2, vec4(blur-1.)); // and so on...
+ }else if(blur < 3.) {
+ return mix( blur2, blur3, vec4(blur-2.)); // see, this is not a change in radius at all
+ }else if(blur < 4.) {
+ return mix( blur3, blur4, vec4(blur-3.)); // just blending one texture over the other
+ }else {
+ return mix( blur4, blur5, vec4(blur-4.)); // fakey fog magic hurrah \:D/
+ }
+}
+
+ void main(void) {
+ gl_FragColor = vec4(lerp_blur(pixel, length(mouse-pixel)*2.-0.15));
+ //gl_FragColor = texture2D(sampler1, pixel);
+ gl_FragColor.a = 1.;
+ }
+</script>
+
+<script src="PhiloGL.js"></script>
+<script src="index.js"></script>
+
+</head>
+<body onload="load()">
+ <div id="container">
+ <div id="title">
+ <h1>Image post-processing API</h1>
+ </div>
+
+ <div class="controls">
+ Spherical texture mapping
+ by <a href="http://twitter.com/Flexi23/">Felix Woitzel</a> - Ported
+ to <a href="http://senchalabs.github.com/philogl/">PhiloGL API</a> -
+ <a id="fullscreen" href="#">Go fullscreen</a>
+ </div>
+ <canvas id="c" width="900" height="550"></canvas>
+ </div>
+</body>
+</html>
+
+
286 index.js
@@ -0,0 +1,286 @@
+PhiloGL.unpack();
+
+var halted = false;
+var it = 1;
+var mouseX = 0.5;
+var mouseY = 0.5;
+var sizeX = 1024;
+var sizeY = 1024;
+var viewX = 900;
+var viewY = 550;
+
+var $ = function(d) {
+ return document.getElementById(d);
+};
+
+function load() {
+ if (!PhiloGL.hasWebGL()) {
+ alert("Your browser does not support WebGL");
+ return;
+ }
+ $('fullscreen')
+ .addEventListener(
+ 'click',
+ function(e) {
+ var width = window.innerWidth, height = window.innerHeight, canvas = $('c'), style = canvas.style;
+
+ canvas.width = viewX = width;
+ canvas.height = viewY = height;
+
+ style.position = 'absolute';
+ style.top = '0px';
+ style.left = '0px';
+
+ document.body.appendChild(canvas);
+
+ var anchor = document.createElement('a'), astyle = anchor.style;
+ astyle.position = 'absolute';
+ astyle.top = astyle.left = '0px';
+ astyle.color = '#000';
+ astyle.display = 'block';
+ // astyle.backgroundColor = 'black';
+ anchor.innerHTML = 'Click here to leave fullscreen';
+ anchor.href = '#';
+ document.body.appendChild(anchor);
+
+ anchor.addEventListener('click', function() {
+ canvas.width = viewX = 900;
+ canvas.height = viewY = 550;
+ canvas.style.position = 'static';
+ $('container').appendChild(canvas);
+ anchor.parentNode.removeChild(anchor);
+ }, false);
+
+ });
+ mouseX = 0;
+ mouseY = 0;
+
+ PhiloGL('c', {
+ program : [ {
+ id : 'advance',
+ from : 'ids',
+ vs : 'shader-vs',
+ fs : 'shader-fs-advance'
+ }, {
+ id : 'composite',
+ from : 'ids',
+ vs : 'shader-vs',
+ fs : 'shader-fs-composite'
+ }, {
+ id : 'copy',
+ from : 'ids',
+ vs : 'shader-vs',
+ fs : 'shader-fs-copy'
+ }, {
+ id : 'blur-h',
+ from : 'ids',
+ vs : 'shader-vs',
+ fs : 'shader-fs-blur-horizontal'
+ }, {
+ id : 'blur-v',
+ from : 'ids',
+ vs : 'shader-vs',
+ fs : 'shader-fs-blur-vertical'
+ } ],
+ textures : {
+ src : [ 'breakfastLQ.jpg', 'breakfastHQ.jpg' ],
+ parameters : [ {
+ name : 'TEXTURE_MAG_FILTER',
+ value : 'LINEAR'
+ }, {
+ name : 'TEXTURE_MIN_FILTER',
+ value : 'LINEAR_MIPMAP_NEAREST',
+ generateMipmap : true
+ } ]
+ },
+ events : {
+ centerOrigin : false,
+ onMouseMove : function(e) {
+ mouseX = e.x / viewX;
+ mouseY = 1 - e.y / viewY;
+ },
+ // onClick : function(e) {
+ // halted = !halted;
+ // }
+ },
+ onError : function(e) {
+ alert(e);
+ },
+ onLoad : function(app) {
+
+ // Set framebuffers
+ function fbosetting(scale) { // general settings
+ return {
+ width : sizeX / scale,
+ height : sizeY / scale,
+ bindToTexture : {
+ parameters : [ {
+ name : 'TEXTURE_MAG_FILTER',
+ value : 'LINEAR'
+ }, {
+ name : 'TEXTURE_MIN_FILTER',
+ value : 'LINEAR',
+ generateMipmap : false
+ } ]
+ },
+ bindToRenderBuffer : false
+ };
+ }
+
+ panoSettingsLQ = {
+ width : 1024,
+ height : 512,
+ bindToTexture : {
+ parameters : [ {
+ name : 'TEXTURE_MAG_FILTER',
+ value : 'LINEAR'
+ }, {
+ name : 'TEXTURE_MIN_FILTER',
+ value : 'LINEAR',
+ generateMipmap : false
+ } ]
+ },
+ bindToRenderBuffer : false
+ };
+
+ panoSettingsHQ = {
+ width : 2048,
+ height : 1024,
+ bindToTexture : {
+ parameters : [ {
+ name : 'TEXTURE_MAG_FILTER',
+ value : 'LINEAR'
+ }, {
+ name : 'TEXTURE_MIN_FILTER',
+ value : 'LINEAR',
+ generateMipmap : false
+ } ]
+ },
+ bindToRenderBuffer : false
+ };
+
+ var fbo1 = fbosetting(1); // fbos for multi-resolution
+ var fbo2 = fbosetting(2);
+ var fbo3 = fbosetting(4);
+ var fbo4 = fbosetting(8);
+ var fbo5 = fbosetting(16);
+ var fboPanoHQ = panoSettingsHQ;
+ var fboPanoLQ = panoSettingsLQ;
+
+ app.setFrameBuffer('main', fbo1).setFrameBuffer('main2', fbo1)
+ .setFrameBuffer('blur1', fbo1).setFrameBuffer('temp1', fbo1)
+ .setFrameBuffer('blur2', fbo2).setFrameBuffer('temp2', fbo2)
+ .setFrameBuffer('blur3', fbo3).setFrameBuffer('temp3', fbo3)
+ .setFrameBuffer('blur4', fbo4).setFrameBuffer('temp4', fbo4)
+ .setFrameBuffer('blur5', fbo5).setFrameBuffer('temp5', fbo5)
+ .setFrameBuffer('panoHQ', fboPanoHQ).setFrameBuffer('panoLQ',
+ fboPanoLQ);
+
+
+ Media.Image.postProcess({ // load PanoLQ buffer
+ width : 1024,
+ height : 512,
+ fromTexture : 'breakfastLQ.jpg',
+ toFrameBuffer : 'panoLQ',
+ program : 'copy',
+ aspectRatio : 1, // stretch to canvas size
+ }).postProcess({ // load PanoHQ buffer
+ width : 2048,
+ height : 1024,
+ fromTexture : 'breakfastHQ.jpg',
+ toFrameBuffer : 'panoHQ',
+// program : 'copy',
+// aspectRatio : 1, // stretch to canvas size
+ });
+
+ anim();
+
+ function draw() {
+ if (it > 0) {
+ advance('main', 'main2');
+ calculateBlurTextures('main2');
+ composite('main2');
+ } else {
+ advance('main2', 'main');
+ calculateBlurTextures('main');
+ composite('main');
+ }
+ it = -it;
+ }
+
+ function advance(source, target) {
+ Media.Image.postProcess({
+ width : sizeX,
+ height : sizeY,
+ fromTexture : [ source + '-texture', 'blur1-texture',
+ 'blur2-texture', 'blur3-texture', 'blur4-texture',
+ 'blur5-texture', 'panoLQ-texture', 'panoHQ-texture' ],
+ toFrameBuffer : target,
+ program : 'advance',
+ uniforms : getUniforms(1)
+ });
+ }
+
+ function composite(source) {
+ Media.Image.postProcess({
+ width : viewX,
+ height : viewY,
+ fromTexture : [ source + '-texture', 'blur1-texture',
+ 'blur2-texture', 'blur3-texture', 'blur4-texture',
+ 'blur5-texture', 'panoLQ-texture', 'panoHQ-texture' ],
+ toScreen : true,
+ aspectRatio : 1, // stretch to canvas size
+ program : 'composite',
+ uniforms : getUniforms(1)
+ });
+ }
+
+ function calculateBlurTextures(source) {
+ calculateBlurTexture(source, 'blur1', 'temp1', 1);
+ calculateBlurTexture('blur1', 'blur2', 'temp2', 2);
+ calculateBlurTexture('blur2', 'blur3', 'temp3', 4);
+ calculateBlurTexture('blur3', 'blur4', 'temp4', 8);
+ calculateBlurTexture('blur4', 'blur5', 'temp5', 16);
+ }
+
+ function calculateBlurTexture(source, target, helper, scale) {
+ Media.Image.postProcess({
+ width : sizeX / scale,
+ height : sizeY / scale,
+ fromTexture : source + '-texture',
+ toFrameBuffer : target,
+ program : 'copy',
+ uniforms : getUniforms(scale)
+ }).postProcess({
+ width : sizeX / scale,
+ height : sizeY / scale,
+ fromTexture : target + '-texture',
+ toFrameBuffer : helper,
+ program : 'blur-h',
+ uniforms : getUniforms(scale)
+ }).postProcess({
+ width : sizeX / scale,
+ height : sizeY / scale,
+ fromTexture : helper + '-texture',
+ toFrameBuffer : target,
+ program : 'blur-v',
+ uniforms : getUniforms(scale)
+ });
+ }
+
+ function getUniforms(factor) {
+ return {
+ 'mouse' : [ mouseX, mouseY ],
+ 'pixelSize' : [ factor / sizeX, factor / sizeY ]
+ };
+ }
+
+ function anim() {
+ if (!halted) {
+ draw();
+ }
+ Fx.requestAnimationFrame(anim);
+ }
+ }
+ });
+}
90 style.css
@@ -0,0 +1,90 @@
+html, body {
+ text-align: center;
+ font-family: 'Crimson Text', Verdana;
+ margin: 0;
+ padding: 0;
+}
+
+input, select {
+ font-size: 15px;
+ font-family: 'Crimson Text', Verdana;
+ max-width: 80px;
+}
+
+#fxy {
+ width: 550px;
+ max-width: 550px;
+}
+
+input.error {
+ background: #ffdddd;
+}
+
+#container {
+ width: 900px;
+ margin: auto;
+}
+
+body.no-webgl #container {
+ display: none;
+}
+
+div.fallback {
+ display: none;
+}
+
+body.no-webgl div.fallback {
+ display: block;
+}
+
+.description {
+ width: 200px;
+ font-size: 13px;
+ position: absolute;
+ padding: 5px;
+ text-align: left;
+ right: 8px;
+ top: 8px;
+ border: 1px solid #ccc;
+ background-color: rgb(255, 241, 168);
+}
+
+#title {
+
+}
+
+h1 {
+ text-shadow: rgba(0, 0, 0, 0.2) 0 0 3px;
+ margin: 5px;
+}
+
+.controls {
+ position: relative;
+ background: #E0ECFF;
+ padding: 7px;
+ border: 1px solid #ccc;
+ margin: 7px 0;
+/* text-align: left;*/
+}
+
+.controls table tr td {
+ text-align: left;
+ margin: auto;
+ font-size: 15px;
+}
+
+#canvas-container {
+ margin: auto;
+}
+
+canvas {
+ -webkit-box-shadow: #333 0 0 10px;
+ -o-box-shadow: #333 0 0 10px;
+ -moz-box-shadow: #333 0 0 10px;
+ box-shadow: #333 0 0 10px;
+}
+
+.footer {
+ margin: 4px;
+ font-size: 13px;
+}

0 comments on commit 9f16832

Please sign in to comment.
Something went wrong with that request. Please try again.