diff --git a/Bloom.png b/Bloom.png new file mode 100644 index 0000000..8b06731 Binary files /dev/null and b/Bloom.png differ diff --git a/README.md b/README.md index da4c7e1..4947c80 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,36 @@ ------------------------------------------------------------------------------ CIS565: Project 6 -- Deferred Shader ------------------------------------------------------------------------------- -Fall 2014 -------------------------------------------------------------------------------- -Due Wed, 11/12/2014 at Noon -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -NOTE: -------------------------------------------------------------------------------- -This project requires any graphics card with support for a modern OpenGL -pipeline. Any AMD, NVIDIA, or Intel card from the past few years should work -fine, and every machine in the SIG Lab and Moore 100 is capable of running -this project. +[Video demo](https://www.youtube.com/watch?v=rO3hkOwMkNg&feature=youtu.be) -This project also requires a WebGL capable browser. The project is known to -have issues with Chrome on windows, but Firefox seems to run it fine. -------------------------------------------------------------------------------- -INTRODUCTION: -------------------------------------------------------------------------------- +###Diffuse & Blinn-Phong lighting +![](diffuse_blinn-phong.png) -In this project, you will get introduced to the basics of deferred shading. You will write GLSL and OpenGL code to perform various tasks in a deferred lighting pipeline such as creating and writing to a G-Buffer. +###Toon Shading with silhouetting +To implement toon shader, I calculated the dot product of the light and the normal of each screen point. Then I assigned different colors according to their dot product value, which is divided into 5 bins. For silhouetting, I just check the depth of each neighbours of a pixel, and make it black if the depth is larger than a threshold. + +![](Toon.png) + +###Bloom +I used the color from Diffuse and Blinn-Phong and made a gaussian convolution to add glow. +![](Bloom.png) + +###Screen Space Ambient Occlusion +For SSAO, I sampled 100 points around each screen points and check if their depth is larger than the screen point's depth. The ratio of points has larger depth is used as the color. +![](SSAO.png) + + +###Performance +| shader| FPS | +|:---------:|:-----------------:| +| Diffuse Blinn-Phong | 60 | +| Toon | 59 | +| Bloom | 13 | +| SSAO | 18| -------------------------------------------------------------------------------- -CONTENTS: -------------------------------------------------------------------------------- -The Project5 root directory contains the following subdirectories: - -* js/ contains the javascript files, including external libraries, necessary. -* assets/ contains the textures that will be used in the second half of the - assignment. -* resources/ contains the screenshots found in this readme file. - This Readme file edited as described above in the README section. ------------------------------------------------------------------------------- OVERVIEW: @@ -69,150 +66,14 @@ WASDRF - Movement (along w the arrow keys) * 2 - Normals * 3 - Color * 4 - Depth +* 5 - Diffuse&Blinn-Phong +* 6 - Toon shading +* 7 - Bloom shading +* 8 - SSAO * 0 - Full deferred pipeline There are also mouse controls for camera rotation. -------------------------------------------------------------------------------- -REQUIREMENTS: -------------------------------------------------------------------------------- - -In this project, you are given code for: -* Loading .obj file -* Deferred shading pipeline -* GBuffer pass - -You are required to implement: -* Either of the following effects - * Bloom - * "Toon" Shading (with basic silhouetting) -* Screen Space Ambient Occlusion -* Diffuse and Blinn-Phong shading - -**NOTE**: Implementing separable convolution will require another link in your pipeline and will count as an extra feature if you do performance analysis with a standard one-pass 2D convolution. The overhead of rendering and reading from a texture _may_ offset the extra computations for smaller 2D kernels. - -You must implement two of the following extras: -* The effect you did not choose above -* Compare performance to a normal forward renderer with - * No optimizations - * Coarse sort geometry front-to-back for early-z - * Z-prepass for early-z -* Optimize g-buffer format, e.g., pack things together, quantize, reconstruct z from normal x and y (because it is normalized), etc. - * Must be accompanied with a performance analysis to count -* Additional lighting and pre/post processing effects! (email first please, if they are good you may add multiple). - -------------------------------------------------------------------------------- -RUNNING THE CODE: -------------------------------------------------------------------------------- - -Since the code attempts to access files that are local to your computer, you -will either need to: - -* Run your browser under modified security settings, or -* Create a simple local server that serves the files - - -FIREFOX: change ``strict_origin_policy`` to false in about:config - -CHROME: run with the following argument : `--allow-file-access-from-files` - -(You can do this on OSX by running Chrome from /Applications/Google -Chrome/Contents/MacOS with `open -a "Google Chrome" --args ---allow-file-access-from-files`) - -* To check if you have set the flag properly, you can open chrome://version and - check under the flags - -RUNNING A SIMPLE SERVER: - -If you have Python installed, you can simply run a simple HTTP server off your -machine from the root directory of this repository with the following command: - -`python -m SimpleHTTPServer` - -------------------------------------------------------------------------------- -RESOURCES: -------------------------------------------------------------------------------- - -The following are articles and resources that have been chosen to help give you -a sense of each of the effects: - -* Bloom : [GPU Gems](http://http.developer.nvidia.com/GPUGems/gpugems_ch21.html) -* Screen Space Ambient Occlusion : [Floored - Article](http://floored.com/blog/2013/ssao-screen-space-ambient-occlusion.html) - -------------------------------------------------------------------------------- -README -------------------------------------------------------------------------------- -All students must replace or augment the contents of this Readme.md in a clear -manner with the following: - -* A brief description of the project and the specific features you implemented. -* At least one screenshot of your project running. -* A 30 second or longer video of your project running. To create the video you - can use [Open Broadcaster Software](http://obsproject.com) -* A performance evaluation (described in detail below). - -------------------------------------------------------------------------------- -PERFORMANCE EVALUATION -------------------------------------------------------------------------------- -The performance evaluation is where you will investigate how to make your -program more efficient using the skills you've learned in class. You must have -performed at least one experiment on your code to investigate the positive or -negative effects on performance. - -We encourage you to get creative with your tweaks. Consider places in your code -that could be considered bottlenecks and try to improve them. - -Each student should provide no more than a one page summary of their -optimizations along with tables and or graphs to visually explain any -performance differences. - -------------------------------------------------------------------------------- -THIRD PARTY CODE POLICY -------------------------------------------------------------------------------- -* Use of any third-party code must be approved by asking on the Google groups. - If it is approved, all students are welcome to use it. Generally, we approve - use of third-party code that is not a core part of the project. For example, - for the ray tracer, we would approve using a third-party library for loading - models, but would not approve copying and pasting a CUDA function for doing - refraction. -* Third-party code must be credited in README.md. -* Using third-party code without its approval, including using another - student's code, is an academic integrity violation, and will result in you - receiving an F for the semester. - -------------------------------------------------------------------------------- -SELF-GRADING -------------------------------------------------------------------------------- -* On the submission date, email your grade, on a scale of 0 to 100, to Harmony, - harmoli+cis565@seas.upenn.edu, with a one paragraph explanation. Be concise and - realistic. Recall that we reserve 30 points as a sanity check to adjust your - grade. Your actual grade will be (0.7 * your grade) + (0.3 * our grade). We - hope to only use this in extreme cases when your grade does not realistically - reflect your work - it is either too high or too low. In most cases, we plan - to give you the exact grade you suggest. -* Projects are not weighted evenly, e.g., Project 0 doesn't count as much as - the path tracer. We will determine the weighting at the end of the semester - based on the size of each project. - - ---- -SUBMISSION ---- -As with the previous projects, you should fork this project and work inside of -your fork. Upon completion, commit your finished project back to your fork, and -make a pull request to the master repository. You should include a README.md -file in the root directory detailing the following - -* A brief description of the project and specific features you implemented -* At least one screenshot of your project running. -* A link to a video of your project running. -* Instructions for building and running your project if they differ from the - base code. -* A performance writeup as detailed above. -* A list of all third-party code used. -* This Readme file edited as described above in the README section. --- ACKNOWLEDGEMENTS diff --git a/SSAO.png b/SSAO.png new file mode 100644 index 0000000..1dec625 Binary files /dev/null and b/SSAO.png differ diff --git a/Toon.png b/Toon.png new file mode 100644 index 0000000..3e8c53a Binary files /dev/null and b/Toon.png differ diff --git a/assets/shader/deferred/diffuse.frag b/assets/shader/deferred/diffuse.frag index ef0c5fc..af1befa 100644 --- a/assets/shader/deferred/diffuse.frag +++ b/assets/shader/deferred/diffuse.frag @@ -1,10 +1,15 @@ precision highp float; - +#define DISPLAY_DIFFUSE 5 +#define DISPLAY_TOON 6 +#define DISPLAY_BLOOM 7 +#define DISPLAY_SSAO 8 uniform sampler2D u_positionTex; uniform sampler2D u_normalTex; uniform sampler2D u_colorTex; uniform sampler2D u_depthTex; +uniform mat4 u_mvp; +uniform vec3 u_eye; uniform float u_zFar; uniform float u_zNear; uniform int u_displayType; @@ -12,12 +17,82 @@ uniform int u_displayType; varying vec2 v_texcoord; float linearizeDepth( float exp_depth, float near, float far ){ - return ( 2.0 * near ) / ( far + near - exp_depth * ( far - near ) ); + return ( 2.0 * near ) / ( far + near - exp_depth * ( far - near ) ); } + void main() { - // Write a diffuse shader and a Blinn-Phong shader - // NOTE : You may need to add your own normals to fulfill the second's requirements - gl_FragColor = vec4(texture2D(u_colorTex, v_texcoord).rgb, 1.0); + // Write a diffuse shader and a Blinn-Phong shader + // NOTE : You may need to add your own normals to fulfill the second's requirements + vec3 lightPos=vec3(u_mvp*vec4(2.0,3.0,6.0,1.0)); + vec3 lightCol=vec3(0.8,1.0,1.0); + vec3 normal=texture2D(u_normalTex,v_texcoord).xyz; + vec3 position=texture2D(u_positionTex,v_texcoord).xyz; + vec3 color=texture2D(u_colorTex,v_texcoord).rgb; + float depth=texture2D(u_depthTex,v_texcoord).x; + depth=linearizeDepth(depth,u_zNear,u_zFar); + vec3 L=normalize(lightPos-position); + vec3 N=normalize(normal); + vec3 V=normalize(u_eye-position); + vec3 H=normalize(V+L); + float diffuse=clamp(dot(N,L),0.0,1.0); + float specular=pow(max(dot(N,H),0.0),10.0); + if (u_displayType==DISPLAY_DIFFUSE||u_displayType==DISPLAY_BLOOM) { + + vec3 final_color=0.6*lightCol*diffuse*color+0.4*lightCol*specular; + + if(depth<0.99) + { + gl_FragColor = vec4(final_color, 1.0); + } + else + { + //background color + gl_FragColor=vec4(0.8,0.8,0.8,1.0); + } + } + else if(u_displayType==DISPLAY_TOON)//reference:http://www.lighthouse3d.com/tutorials/glsl-tutorial/toon-shader-version-ii/ + { + float intensity=dot(L,N); + vec4 color; + if (depth<0.99) { + if (intensity>0.8) { + color=vec4(0.6,0.8,0.6,1.0); + } else if(intensity>0.6) { + color=vec4(0.5,0.7,0.5,1.0); + } else if(intensity>0.4) + { + color=vec4(0.4,0.6,0.4,1.0); + }else if(intensity>0.2) + { + color=vec4(0.3,0.5,0.3,1.0); + } + else + { + color=vec4(0.2,0.4,0.2,1.0); + } + + } else { + //background color + color=vec4(0.8,0.8,0.8,1.0); + } + //edge + float c=0.002; + float threshold=0.999; + for (int i=-2; i<=2; i++) { + for (int j=-2;j<=2;j++) { + float depthdiff=texture2D(u_depthTex,v_texcoord+vec2(float(i)*c,float(j)*c)).x; + if (depthdiff>threshold) { + color=vec4(0.0,0.0,0.0,1.0); + break; + } + } + } + if(depth>0.9) + { + color=vec4(0.8,0.8,0.8,1.0); + } + gl_FragColor=color; + } } diff --git a/assets/shader/deferred/post.frag b/assets/shader/deferred/post.frag index 52edda2..d346194 100644 --- a/assets/shader/deferred/post.frag +++ b/assets/shader/deferred/post.frag @@ -1,6 +1,20 @@ precision highp float; +#define DISPLAY_DIFFUSE 5 +#define DISPLAY_TOON 6 +#define DISPLAY_BLOOM 7 +#define DISPLAY_SSAO 8 +#define KernelSize 11 +#define SampleSize 100 uniform sampler2D u_shadeTex; +uniform sampler2D u_positionTex; +uniform sampler2D u_normalTex; +uniform sampler2D u_colorTex; +uniform sampler2D u_depthTex; +uniform vec3 u_kernel[100]; +uniform float u_zFar; +uniform float u_zNear; +uniform int u_displayType; varying vec2 v_texcoord; @@ -8,10 +22,79 @@ float linearizeDepth( float exp_depth, float near, float far ){ return ( 2.0 * near ) / ( far + near - exp_depth * ( far - near ) ); } + + +float Gblur(int x,int y,int n) { + float sigma = 1.0; + float fx = float(x) - (float(n) - 1.0) / 2.0; + float fy = float(y) - (float(n) - 1.0) / 2.0; + return (exp(-abs(fx*fy)/ (2.0*sigma*sigma)))/ (2.0 * 3.1415926 *sigma*sigma); +} + +vec4 bloom() { + float offset=0.001; + vec3 color=vec3(0.0,0.0,0.0); + for (int i=0; i<=KernelSize; i++) { + for (int j=0;j<=KernelSize;j++) { + vec2 temp=v_texcoord; + temp.x=temp.x+(float(i)-float(KernelSize)/2.0+0.5)*offset; + temp.y=temp.y+(float(j)-float(KernelSize)/2.0+0.5)*offset; + color=color+Gblur(i,j,KernelSize)*texture2D(u_shadeTex,temp).rgb; + } + } + return vec4(color,1.0); +} +float rand(float co){ + return fract(sin(dot(vec2(co,co) ,vec2(12.9898,78.233))) * 43758.5453); +} + +vec4 SSAO() { + vec3 center=vec3(v_texcoord,texture2D(u_depthTex,v_texcoord).r); + float radius=0.01; + vec3 normal=texture2D(u_normalTex,v_texcoord).xyz; + float depth=texture2D(u_depthTex,v_texcoord).r; + float occlusion=0.0; + for(int i=0;i<=SampleSize;i++) + { + float x=rand(1.0+float(i)+sin(float(i))); + float y=rand(2.0+float(i)); + float z=rand(3.0+float(i)); + vec3 r=normalize(vec3(x,y,z)); + vec3 tangent=normalize(r-normal*dot(r,normal)); + vec3 bitangent=cross(normal,tangent); + vec3 position=center+radius*(tangent*r.x+bitangent*r.y+normal*r.z); + float depthS=texture2D(u_depthTex,position.xy).r; + if (depthS>depth) { + occlusion+=1.0/float(SampleSize); + } + } + if(depth>0.99) + { + occlusion=1.0; + } + return vec4(occlusion,occlusion,occlusion,1.0); +} + + void main() { // Currently acts as a pass filter that immmediately renders the shaded texture // Fill in post-processing as necessary HERE // NOTE : You may choose to use a key-controlled switch system to display one feature at a time - gl_FragColor = vec4(texture2D( u_shadeTex, v_texcoord).rgb, 1.0); + if (u_displayType==DISPLAY_DIFFUSE||u_displayType==DISPLAY_TOON) { + gl_FragColor = vec4(texture2D(u_shadeTex, v_texcoord).rgb, 1.0); + } + else if(u_displayType==DISPLAY_BLOOM) + { + gl_FragColor=bloom(); + + } + else if(u_displayType==DISPLAY_SSAO) + { + gl_FragColor=SSAO(); + } + + + + } diff --git a/diffuse_blinn-phong.png b/diffuse_blinn-phong.png new file mode 100644 index 0000000..d2ebd02 Binary files /dev/null and b/diffuse_blinn-phong.png differ diff --git a/index.html b/index.html index dd0ffef..bc8f2fe 100644 --- a/index.html +++ b/index.html @@ -14,7 +14,7 @@ - + diff --git a/js/core/camera.js b/js/core/camera.js index 11a995d..f793036 100644 --- a/js/core/camera.js +++ b/js/core/camera.js @@ -132,6 +132,9 @@ CIS565WEBGLCORE.createCamera = function(t){ mat4.invert( m, matrix ); return m; }; + getPos=function(){ + return position; + }; moveForward = function(){ vec3.scaleAndAdd( position, position, normal, -1.1 ); @@ -180,6 +183,6 @@ CIS565WEBGLCORE.createCamera = function(t){ newObj.moveRight = moveRight; newObj.moveUp = moveUp; newObj.moveDown = moveDown; - + newObj.getPos=getPos; return newObj; }; diff --git a/js/core/fbo-util.js b/js/core/fbo-util.js index 32f745a..fe9afbf 100644 --- a/js/core/fbo-util.js +++ b/js/core/fbo-util.js @@ -18,7 +18,7 @@ CIS565WEBGLCORE.createFBO = function(){ var depthTex = null; var fbo = []; - var multipleTargets = true; + var multipleTargets = false; function init( gl, width, height ){ gl.getExtension( "OES_texture_float" ); diff --git a/js/ext/Stats.js b/js/ext/Stats.js new file mode 100644 index 0000000..90b2a27 --- /dev/null +++ b/js/ext/Stats.js @@ -0,0 +1,149 @@ +/** + * @author mrdoob / http://mrdoob.com/ + */ + +var Stats = function () { + + var startTime = Date.now(), prevTime = startTime; + var ms = 0, msMin = Infinity, msMax = 0; + var fps = 0, fpsMin = Infinity, fpsMax = 0; + var frames = 0, mode = 0; + + var container = document.createElement( 'div' ); + container.id = 'stats'; + container.addEventListener( 'mousedown', function ( event ) { event.preventDefault(); setMode( ++ mode % 2 ) }, false ); + container.style.cssText = 'width:80px;opacity:0.9;cursor:pointer'; + + var fpsDiv = document.createElement( 'div' ); + fpsDiv.id = 'fps'; + fpsDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#002'; + container.appendChild( fpsDiv ); + + var fpsText = document.createElement( 'div' ); + fpsText.id = 'fpsText'; + fpsText.style.cssText = 'color:#0ff;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px'; + fpsText.innerHTML = 'FPS'; + fpsDiv.appendChild( fpsText ); + + var fpsGraph = document.createElement( 'div' ); + fpsGraph.id = 'fpsGraph'; + fpsGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0ff'; + fpsDiv.appendChild( fpsGraph ); + + while ( fpsGraph.children.length < 74 ) { + + var bar = document.createElement( 'span' ); + bar.style.cssText = 'width:1px;height:30px;float:left;background-color:#113'; + fpsGraph.appendChild( bar ); + + } + + var msDiv = document.createElement( 'div' ); + msDiv.id = 'ms'; + msDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;display:none'; + container.appendChild( msDiv ); + + var msText = document.createElement( 'div' ); + msText.id = 'msText'; + msText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px'; + msText.innerHTML = 'MS'; + msDiv.appendChild( msText ); + + var msGraph = document.createElement( 'div' ); + msGraph.id = 'msGraph'; + msGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0f0'; + msDiv.appendChild( msGraph ); + + while ( msGraph.children.length < 74 ) { + + var bar = document.createElement( 'span' ); + bar.style.cssText = 'width:1px;height:30px;float:left;background-color:#131'; + msGraph.appendChild( bar ); + + } + + var setMode = function ( value ) { + + mode = value; + + switch ( mode ) { + + case 0: + fpsDiv.style.display = 'block'; + msDiv.style.display = 'none'; + break; + case 1: + fpsDiv.style.display = 'none'; + msDiv.style.display = 'block'; + break; + } + + }; + + var updateGraph = function ( dom, value ) { + + var child = dom.appendChild( dom.firstChild ); + child.style.height = value + 'px'; + + }; + + return { + + REVISION: 12, + + domElement: container, + + setMode: setMode, + + begin: function () { + + startTime = Date.now(); + + }, + + end: function () { + + var time = Date.now(); + + ms = time - startTime; + msMin = Math.min( msMin, ms ); + msMax = Math.max( msMax, ms ); + + msText.textContent = ms + ' MS (' + msMin + '-' + msMax + ')'; + updateGraph( msGraph, Math.min( 30, 30 - ( ms / 200 ) * 30 ) ); + + frames ++; + + if ( time > prevTime + 1000 ) { + + fps = Math.round( ( frames * 1000 ) / ( time - prevTime ) ); + fpsMin = Math.min( fpsMin, fps ); + fpsMax = Math.max( fpsMax, fps ); + + fpsText.textContent = fps + ' FPS (' + fpsMin + '-' + fpsMax + ')'; + updateGraph( fpsGraph, Math.min( 30, 30 - ( fps / 100 ) * 30 ) ); + + prevTime = time; + frames = 0; + + } + + return time; + + }, + + update: function () { + + startTime = this.end(); + + } + + } + +}; + +if ( typeof module === 'object' ) { + + module.exports = Stats; + +} \ No newline at end of file diff --git a/js/ext/stats.min.js b/js/ext/stats.min.js new file mode 100644 index 0000000..52539f4 --- /dev/null +++ b/js/ext/stats.min.js @@ -0,0 +1,6 @@ +// stats.js - http://github.com/mrdoob/stats.js +var Stats=function(){var l=Date.now(),m=l,g=0,n=Infinity,o=0,h=0,p=Infinity,q=0,r=0,s=0,f=document.createElement("div");f.id="stats";f.addEventListener("mousedown",function(b){b.preventDefault();t(++s%2)},!1);f.style.cssText="width:80px;opacity:0.9;cursor:pointer";var a=document.createElement("div");a.id="fps";a.style.cssText="padding:0 0 3px 3px;text-align:left;background-color:#002";f.appendChild(a);var i=document.createElement("div");i.id="fpsText";i.style.cssText="color:#0ff;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px"; +i.innerHTML="FPS";a.appendChild(i);var c=document.createElement("div");c.id="fpsGraph";c.style.cssText="position:relative;width:74px;height:30px;background-color:#0ff";for(a.appendChild(c);74>c.children.length;){var j=document.createElement("span");j.style.cssText="width:1px;height:30px;float:left;background-color:#113";c.appendChild(j)}var d=document.createElement("div");d.id="ms";d.style.cssText="padding:0 0 3px 3px;text-align:left;background-color:#020;display:none";f.appendChild(d);var k=document.createElement("div"); +k.id="msText";k.style.cssText="color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px";k.innerHTML="MS";d.appendChild(k);var e=document.createElement("div");e.id="msGraph";e.style.cssText="position:relative;width:74px;height:30px;background-color:#0f0";for(d.appendChild(e);74>e.children.length;)j=document.createElement("span"),j.style.cssText="width:1px;height:30px;float:left;background-color:#131",e.appendChild(j);var t=function(b){s=b;switch(s){case 0:a.style.display= +"block";d.style.display="none";break;case 1:a.style.display="none",d.style.display="block"}};return{REVISION:12,domElement:f,setMode:t,begin:function(){l=Date.now()},end:function(){var b=Date.now();g=b-l;n=Math.min(n,g);o=Math.max(o,g);k.textContent=g+" MS ("+n+"-"+o+")";var a=Math.min(30,30-30*(g/200));e.appendChild(e.firstChild).style.height=a+"px";r++;b>m+1E3&&(h=Math.round(1E3*r/(b-m)),p=Math.min(p,h),q=Math.max(q,h),i.textContent=h+" FPS ("+p+"-"+q+")",a=Math.min(30,30-30*(h/100)),c.appendChild(c.firstChild).style.height= +a+"px",m=b,r=0);return b},update:function(){l=this.end()}}};"object"===typeof module&&(module.exports=Stats); diff --git a/js/main.js b/js/main.js index bf701d9..deb5df2 100644 --- a/js/main.js +++ b/js/main.js @@ -32,15 +32,21 @@ var zNear = 20; var zFar = 2000; var texToDisplay = 1; +var kernelSize=100; +var kernel=[]; + + var main = function (canvasId, messageId) { var canvas; - + stats=initStats(); // Initialize WebGL initGL(canvasId, messageId); // Set up camera initCamera(canvas); + initKernel(); + // Set up FBOs initFramebuffer(); @@ -57,6 +63,27 @@ var main = function (canvasId, messageId) { // Start the rendering loop CIS565WEBGLCORE.run(gl); }; +function initStats() { + stats = new Stats(); + stats.setMode(0); // 0: fps, 1: ms + + // Align top-left + stats.domElement.style.position = 'absolute'; + stats.domElement.style.left = '0px'; + stats.domElement.style.bottom = '0px'; + + document.body.appendChild(stats.domElement); + + + return stats; +} + +var initKernel = function () { + for (var i = 0; i < kernelSize; i++) { + kernel[i] = [Math.random()*2.0-1.0 , Math.random()*2.0-1.0 , Math.random() ]; + } +}; + var renderLoop = function () { window.requestAnimationFrame(renderLoop); @@ -64,6 +91,10 @@ var renderLoop = function () { }; var render = function () { + if(stats) + { + stats.update(); + } if (fbo.isMultipleTargets()) { renderPass(); } else { @@ -217,26 +248,29 @@ var renderShade = function () { gl.clear(gl.COLOR_BUFFER_BIT); // Bind necessary textures - //gl.activeTexture( gl.TEXTURE0 ); //position - //gl.bindTexture( gl.TEXTURE_2D, fbo.texture(0) ); - //gl.uniform1i( shadeProg.uPosSamplerLoc, 0 ); + gl.activeTexture( gl.TEXTURE0 ); //position + gl.bindTexture( gl.TEXTURE_2D, fbo.texture(0) ); + gl.uniform1i( shadeProg.uPosSamplerLoc, 0 ); - //gl.activeTexture( gl.TEXTURE1 ); //normal - //gl.bindTexture( gl.TEXTURE_2D, fbo.texture(1) ); - //gl.uniform1i( shadeProg.uNormalSamplerLoc, 1 ); + gl.activeTexture( gl.TEXTURE1 ); //normal + gl.bindTexture( gl.TEXTURE_2D, fbo.texture(1) ); + gl.uniform1i( shadeProg.uNormalSamplerLoc, 1 ); gl.activeTexture( gl.TEXTURE2 ); //color gl.bindTexture( gl.TEXTURE_2D, fbo.texture(2) ); gl.uniform1i( shadeProg.uColorSamplerLoc, 2 ); - //gl.activeTexture( gl.TEXTURE3 ); //depth - //gl.bindTexture( gl.TEXTURE_2D, fbo.depthTexture() ); - //gl.uniform1i( shadeProg.uDepthSamplerLoc, 3 ); + gl.activeTexture( gl.TEXTURE3 ); //depth + gl.bindTexture( gl.TEXTURE_2D, fbo.depthTexture() ); + gl.uniform1i( shadeProg.uDepthSamplerLoc, 3 ); // Bind necessary uniforms - //gl.uniform1f( shadeProg.uZNearLoc, zNear ); - //gl.uniform1f( shadeProg.uZFarLoc, zFar ); - + gl.uniform1f( shadeProg.uZNearLoc, zNear ); + gl.uniform1f( shadeProg.uZFarLoc, zFar ); + //new + gl.uniform1i(shadeProg.uDisplayTypeLoc,texToDisplay); + gl.uniform3fv(shadeProg.uEyeLoc,camera.getPos()); + gl.uniformMatrix4fv(shadeProg.uMVPLoc, false, camera.getViewTransform()); drawQuad(shadeProg); // Unbind FBO @@ -269,8 +303,8 @@ var renderDiagnostic = function () { // Bind necessary uniforms gl.uniform1f( diagProg.uZNearLoc, zNear ); gl.uniform1f( diagProg.uZFarLoc, zFar ); - gl.uniform1i( diagProg.uDisplayTypeLoc, texToDisplay ); - + gl.uniform1i( diagProg.uDisplayTypeLoc, texToDisplay ); + drawQuad(diagProg); }; @@ -285,6 +319,31 @@ var renderPost = function () { gl.bindTexture( gl.TEXTURE_2D, fbo.texture(4) ); gl.uniform1i(postProg.uShadeSamplerLoc, 4 ); + //new + // Bind necessary textures + gl.activeTexture( gl.TEXTURE0 ); //position + gl.bindTexture( gl.TEXTURE_2D, fbo.texture(0) ); + gl.uniform1i( postProg.uPosSamplerLoc, 0 ); + + gl.activeTexture( gl.TEXTURE1 ); //normal + gl.bindTexture( gl.TEXTURE_2D, fbo.texture(1) ); + gl.uniform1i( postProg.uNormalSamplerLoc, 1 ); + + gl.activeTexture( gl.TEXTURE2 ); //color + gl.bindTexture( gl.TEXTURE_2D, fbo.texture(2) ); + gl.uniform1i( postProg.uColorSamplerLoc, 2 ); + + gl.activeTexture( gl.TEXTURE3 ); //depth + gl.bindTexture( gl.TEXTURE_2D, fbo.depthTexture() ); + gl.uniform1i( postProg.uDepthSamplerLoc, 3 ); + + // Bind necessary uniforms + gl.uniform1f( postProg.uZNearLoc, zNear ); + gl.uniform1f( postProg.uZFarLoc, zFar ); + gl.uniform1i( postProg.uDisplayTypeLoc, texToDisplay ); + gl.uniform3fv(postProg.uKernelLoc,kernel); + + drawQuad(postProg); }; @@ -322,6 +381,7 @@ var initCamera = function () { switch(e.keyCode) { case 48: isDiagnostic = false; + texToDisplay=5; break; case 49: isDiagnostic = true; @@ -339,6 +399,22 @@ var initCamera = function () { isDiagnostic = true; texToDisplay = 4; break; + case 53://blinn-phong + isDiagnostic=false; + texToDisplay=5; + break; + case 54://toon + isDiagnostic=false; + texToDisplay=6; + break; + case 55://bloom + isDiagnostic=false; + texToDisplay=7; + break; + case 56://SSAO + isDiagnostic=false; + texToDisplay=8; + break; } } }; @@ -348,7 +424,7 @@ var initObjs = function () { objloader = CIS565WEBGLCORE.createOBJLoader(); // Load the OBJ from file - objloader.loadFromFile(gl, "assets/models/crytek-sponza/sponza.obj", null); + objloader.loadFromFile(gl, "assets/models/suzanne.obj", null); // Add callback to upload the vertices once loaded objloader.addCallback(function () { @@ -468,6 +544,9 @@ var initShaders = function () { shadeProg.uZNearLoc = gl.getUniformLocation( shadeProg.ref(), "u_zNear" ); shadeProg.uZFarLoc = gl.getUniformLocation( shadeProg.ref(), "u_zFar" ); shadeProg.uDisplayTypeLoc = gl.getUniformLocation( shadeProg.ref(), "u_displayType" ); + shadeProg.uMVPLoc = gl.getUniformLocation(shadeProg.ref(), "u_mvp"); + shadeProg.uEyeLoc=gl.getUniformLocation(shadeProg.ref(),"u_eye"); + }); CIS565WEBGLCORE.registerAsyncObj(gl, shadeProg); @@ -477,8 +556,16 @@ var initShaders = function () { postProg.addCallback( function() { postProg.aVertexPosLoc = gl.getAttribLocation( postProg.ref(), "a_pos" ); postProg.aVertexTexcoordLoc = gl.getAttribLocation( postProg.ref(), "a_texcoord" ); - postProg.uShadeSamplerLoc = gl.getUniformLocation( postProg.ref(), "u_shadeTex"); + postProg.uDisplayTypeLoc=gl.getUniformLocation(postProg.ref(),"u_displayType"); + postProg.uPosSamplerLoc = gl.getUniformLocation( postProg.ref(), "u_positionTex"); + postProg.uNormalSamplerLoc = gl.getUniformLocation( postProg.ref(), "u_normalTex"); + postProg.uColorSamplerLoc = gl.getUniformLocation( postProg.ref(), "u_colorTex"); + postProg.uDepthSamplerLoc = gl.getUniformLocation( postProg.ref(), "u_depthTex"); + postProg.uZNearLoc = gl.getUniformLocation( postProg.ref(), "u_zNear" ); + postProg.uZFarLoc = gl.getUniformLocation( postProg.ref(), "u_zFar" ); + postProg.uKernelLoc=gl.getUniformLocation(postProg.ref(),"u_kernel"); + }); CIS565WEBGLCORE.registerAsyncObj(gl, postProg); };