diff --git a/Image/AllEffects.gif b/Image/AllEffects.gif new file mode 100644 index 0000000..43622b3 Binary files /dev/null and b/Image/AllEffects.gif differ diff --git a/Image/BlinnPhong.png b/Image/BlinnPhong.png new file mode 100644 index 0000000..0294aa8 Binary files /dev/null and b/Image/BlinnPhong.png differ diff --git a/Image/BlinnPhongVsUnsharp.gif b/Image/BlinnPhongVsUnsharp.gif new file mode 100644 index 0000000..fbc32b7 Binary files /dev/null and b/Image/BlinnPhongVsUnsharp.gif differ diff --git a/Image/Blinn_Phong.gif b/Image/Blinn_Phong.gif new file mode 100644 index 0000000..da07df9 Binary files /dev/null and b/Image/Blinn_Phong.gif differ diff --git a/Image/Bloom.png b/Image/Bloom.png new file mode 100644 index 0000000..c1c260f Binary files /dev/null and b/Image/Bloom.png differ diff --git a/Image/Compare.png b/Image/Compare.png new file mode 100644 index 0000000..a3716f6 Binary files /dev/null and b/Image/Compare.png differ diff --git a/Image/DebugView.gif b/Image/DebugView.gif new file mode 100644 index 0000000..e4d746a Binary files /dev/null and b/Image/DebugView.gif differ diff --git a/Image/Performance.png b/Image/Performance.png new file mode 100644 index 0000000..036122a Binary files /dev/null and b/Image/Performance.png differ diff --git a/Image/SSAO.png b/Image/SSAO.png new file mode 100644 index 0000000..fc3a19f Binary files /dev/null and b/Image/SSAO.png differ diff --git a/Image/Toon.png b/Image/Toon.png new file mode 100644 index 0000000..63dd3b3 Binary files /dev/null and b/Image/Toon.png differ diff --git a/Image/Unsharp.png b/Image/Unsharp.png new file mode 100644 index 0000000..de0f795 Binary files /dev/null and b/Image/Unsharp.png differ diff --git a/Image/VisualEffects.gif b/Image/VisualEffects.gif new file mode 100644 index 0000000..2665d5c Binary files /dev/null and b/Image/VisualEffects.gif differ diff --git a/README.md b/README.md index 5c59b2f..319740c 100644 --- a/README.md +++ b/README.md @@ -21,36 +21,36 @@ have issues with Chrome on windows, but Firefox seems to run it fine. INTRODUCTION: ------------------------------------------------------------------------------- -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. +In this project, I implemented the basic deferred shader. I write GLSL and OpenGL code to perform various tasks in a deferred lighting pipeline such as creating and writing to a G-Buffer. -NOTE : The Crytek-Sponza scene is still broken, and I will be pushing a fix for -it soon. +The live demo can be found here: +[Live demo](https://cdn.rawgit.com/chiwsy/Project6-DeferredShader/master/index.html) -------------------------------------------------------------------------------- -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. +Some of the results from this project: +![Blinn-Phong](https://github.com/chiwsy/Project6-DeferredShader/blob/master/Image/BlinnPhong.png) +![Unsharp](https://github.com/chiwsy/Project6-DeferredShader/blob/master/Image/Unsharp.png) +![Comparing Bling-Phong with Unsharp](https://github.com/chiwsy/Project6-DeferredShader/blob/master/Image/Compare.png) +![Bloom](https://github.com/chiwsy/Project6-DeferredShader/blob/master/Image/Bloom.png) +![Toon](https://github.com/chiwsy/Project6-DeferredShader/blob/master/Image/Toon.png) +![SSAO](https://github.com/chiwsy/Project6-DeferredShader/blob/master/Image/SSAO.png) +![All effects in sequence](https://github.com/chiwsy/Project6-DeferredShader/blob/master/Image/AllEffects.gif) +![Debug View](https://github.com/chiwsy/Project6-DeferredShader/blob/master/Image/DebugView.gif) +![Blinn-Phong](https://github.com/chiwsy/Project6-DeferredShader/blob/master/Image/Blinn_Phong.gif) +![More Visual Effects](https://github.com/chiwsy/Project6-DeferredShader/blob/master/Image/VisualEffects.gif) +![Blinn-Phong VS. Unsharp](https://github.com/chiwsy/Project6-DeferredShader/blob/master/Image/BlinnPhongVsUnsharp.gif) ------------------------------------------------------------------------------- OVERVIEW: ------------------------------------------------------------------------------- -The deferred shader you will write will have the following stages: +The deferred shader here will have the following stages: Stage 1 renders the scene geometry to the G-Buffer * pass.vert * pass.frag Stage 2 renders the lighting passes and accumulates to the P-Buffer -* shade.vert -* ambient.frag -* point.frag +* quad.vert +* diffuse.frag * diagnostic.frag Stage 3 renders the post processing @@ -59,52 +59,48 @@ Stage 3 renders the post processing The keyboard controls are as follows: WASDRF - Movement (along w the arrow keys) -W - Zoom in -S - Zoom out -A - Left -D - Right -R - Up -F - Down -^ - Up -v - Down -< - Left -> - Right +* W - Zoom in +* S - Zoom out +* A - Left +* D - Right +* R - Up +* F - Down +* ^ - Up +* v - Down +* < - Left +* > - Right +* 1 - World Space Position +* 2 - Normals +* 3 - Color +* 4 - Depth +* 5 - Blinn-Phong +* 6 - Bloom +* 7 - Toon +* 8 - SSAO +* 9 - Unsharp +* 0 - Full deferred pipeline There are also mouse controls for camera rotation. ------------------------------------------------------------------------------- -REQUIREMENTS: +Functions: ------------------------------------------------------------------------------- In this project, you are given code for: * Loading .obj file -* Forward shading pipeline +* Deferred shading pipeline +* GBuffer pass -NOTE : The full deferred pipeline will be released on Friday. If you set up -your deferred pipeline for extra credit, please submit a pull request by Friday. -If it is partially done, we will give partial extra credit. +I have implemented: +* Bloom +* "Toon" Shading (with basic silhouetting) +* Screen Space Ambient Occlusion +* Diffuse and Blinn-Phong shading -The baseline OpenGL shaders for the rest of the pipeline have been provided to give you -a sense of what will be neede in subsequent passes. +And one additional post effect: +* Unsharp Mask -You are required to implement: -* Either of the following effects - * Bloom - * "Toon" Shading (with basic silhouetting) -* Point light sources -* Screen Space Ambient Occlusion -**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 one 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: @@ -147,77 +143,12 @@ a sense of each of the effects: 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 +Performance: ------------------------------------------------------------------------------- -* 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 Liam, - liamboone@gmail.com, 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. +For my browser, I cannot take advantage of the draw buffer. Therefore the program reduced to multi-pass version which is very slow when it comes to the performance part. +![Performance](https://github.com/chiwsy/Project6-DeferredShader/blob/master/Image/Performance.png) ---- -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/assets/deferred/colorPass.frag b/assets/deferred/colorPass.frag new file mode 100644 index 0000000..c151235 --- /dev/null +++ b/assets/deferred/colorPass.frag @@ -0,0 +1,7 @@ +precision highp float; + +uniform sampler2D u_sampler; + +void main(void){ + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); +} diff --git a/assets/deferred/colorPass.vert b/assets/deferred/colorPass.vert new file mode 100644 index 0000000..9c3901c --- /dev/null +++ b/assets/deferred/colorPass.vert @@ -0,0 +1,9 @@ +precision highp float; + +attribute vec3 a_pos; + +uniform mat4 u_mvp; + +void main(void){ + gl_Position = u_mvp * vec4( a_pos, 1.0 ); +} diff --git a/assets/deferred/diagnostic.frag b/assets/deferred/diagnostic.frag new file mode 100644 index 0000000..d47a5e9 --- /dev/null +++ b/assets/deferred/diagnostic.frag @@ -0,0 +1,40 @@ +precision highp float; + +#define DISPLAY_POS 1 +#define DISPLAY_NORMAL 2 +#define DISPLAY_COLOR 3 +#define DISPLAY_DEPTH 4 + +uniform sampler2D u_positionTex; +uniform sampler2D u_normalTex; +uniform sampler2D u_colorTex; +uniform sampler2D u_depthTex; + +uniform float u_zFar; +uniform float u_zNear; +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 ) ); +} + +void main() +{ + vec3 normal = texture2D( u_normalTex, v_texcoord ).xyz; + vec3 position = texture2D( u_positionTex, v_texcoord ).xyz; + vec4 color = texture2D( u_colorTex, v_texcoord ); + float depth = texture2D( u_depthTex, v_texcoord ).x; + + depth = linearizeDepth( depth, u_zNear, u_zFar ); + + if( u_displayType == DISPLAY_DEPTH ) + gl_FragColor = vec4( depth, depth, depth, 1 ); + else if( u_displayType == DISPLAY_COLOR ) + gl_FragColor = color; + else if( u_displayType == DISPLAY_NORMAL ) + gl_FragColor = vec4( normal, 1 ); + else + gl_FragColor = vec4( position, 1 ); +} diff --git a/assets/deferred/diffuse.frag b/assets/deferred/diffuse.frag new file mode 100644 index 0000000..ef0c5fc --- /dev/null +++ b/assets/deferred/diffuse.frag @@ -0,0 +1,23 @@ +precision highp float; + +uniform sampler2D u_positionTex; +uniform sampler2D u_normalTex; +uniform sampler2D u_colorTex; +uniform sampler2D u_depthTex; + +uniform float u_zFar; +uniform float u_zNear; +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 ) ); +} + +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); +} diff --git a/assets/deferred/normPass.frag b/assets/deferred/normPass.frag new file mode 100644 index 0000000..b41d6ed --- /dev/null +++ b/assets/deferred/normPass.frag @@ -0,0 +1,7 @@ +precision highp float; + +varying vec3 v_normal; + +void main(void){ + gl_FragColor = vec4(v_normal, 1.0); +} diff --git a/assets/deferred/normPass.vert b/assets/deferred/normPass.vert new file mode 100644 index 0000000..9a0b4b4 --- /dev/null +++ b/assets/deferred/normPass.vert @@ -0,0 +1,15 @@ +precision highp float; + +attribute vec3 a_pos; +attribute vec3 a_normal; + +uniform mat4 u_mvp; +uniform mat4 u_normalMat; + +varying vec3 v_normal; + +void main(void){ + gl_Position = u_mvp * vec4( a_pos, 1.0 ); + + v_normal = vec3( u_normalMat * vec4(a_normal, 0.0) ); +} diff --git a/assets/deferred/pass.frag b/assets/deferred/pass.frag new file mode 100644 index 0000000..2416199 --- /dev/null +++ b/assets/deferred/pass.frag @@ -0,0 +1,16 @@ +#extension GL_EXT_draw_buffers: require +precision highp float; + +uniform sampler2D u_sampler; + +varying vec4 v_pos; +varying vec3 v_normal; +varying vec2 v_texcoord; +varying float v_depth; + +void main(void){ + gl_FragData[0] = v_pos; + gl_FragData[1] = vec4( normalize(v_normal), 1.0 ); + gl_FragData[2] = vec4( 1.0, 0.0, 0.0, 1.0 ); + gl_FragData[3] = vec4( v_depth, 0, 0, 0 ); +} diff --git a/assets/deferred/pass.vert b/assets/deferred/pass.vert new file mode 100644 index 0000000..861cb1a --- /dev/null +++ b/assets/deferred/pass.vert @@ -0,0 +1,26 @@ +precision highp float; + +attribute vec3 a_pos; +attribute vec3 a_normal; +attribute vec2 a_texcoord; + +uniform mat4 u_projection; +uniform mat4 u_modelview; +uniform mat4 u_mvp; +uniform mat4 u_normalMat; + +varying vec4 v_pos; +varying vec3 v_normal; +varying vec2 v_texcoord; +varying float v_depth; + +void main(void){ + gl_Position = u_mvp * vec4( a_pos, 1.0 ); + + v_pos = u_modelview * vec4( a_pos, 1.0 ); + v_normal = vec3( u_normalMat * vec4(a_normal,0.0) ); + + v_texcoord = a_texcoord; + + v_depth = ( gl_Position.z / gl_Position.w + 1.0 ) / 2.0; +} diff --git a/assets/deferred/posPass.frag b/assets/deferred/posPass.frag new file mode 100644 index 0000000..645a521 --- /dev/null +++ b/assets/deferred/posPass.frag @@ -0,0 +1,8 @@ +precision highp float; + +varying vec4 v_pos; +varying float v_depth; + +void main(void){ + gl_FragColor = v_pos; +} diff --git a/assets/deferred/posPass.vert b/assets/deferred/posPass.vert new file mode 100644 index 0000000..ece8cc4 --- /dev/null +++ b/assets/deferred/posPass.vert @@ -0,0 +1,15 @@ +precision highp float; + +attribute vec3 a_pos; + +uniform mat4 u_modelview; +uniform mat4 u_mvp; + +varying vec4 v_pos; +varying float v_depth; + +void main(void){ + gl_Position = u_mvp * vec4( a_pos, 1.0 ); + v_pos = u_modelview * vec4( a_pos, 1.0 ); + v_depth = ( gl_Position.z / gl_Position.w + 1.0 ) / 2.0; +} diff --git a/assets/deferred/post.frag b/assets/deferred/post.frag new file mode 100644 index 0000000..18ac4d8 --- /dev/null +++ b/assets/deferred/post.frag @@ -0,0 +1,182 @@ +precision highp float; +#define DISPLAY_TOON 5 +#define DISPLAY_BLOOM 6 +#define DISPLAY_BLINN 7 +#define DISPLAY_SSAO 8 +#define DISPLAY_BLUR 9 + +#define KERNEL_SIZE 21 +#define SAMPLEKERNEL_SIZE 100 + +uniform sampler2D u_shadeTex; + +varying vec2 v_texcoord; + +//Added +uniform sampler2D u_positionTex; +uniform sampler2D u_normalTex; +uniform sampler2D u_colorTex; +uniform sampler2D u_depthTex; + +uniform float u_zFar; +uniform float u_zNear; +uniform int u_displayType; +uniform float u_ScreenWidth; +uniform float u_ScreenHeight; + +uniform mat4 u_projection; +uniform float u_radius; +uniform vec3 u_samplekernel[100]; + + +float linearizeDepth( float exp_depth, float near, float far ){ + return ( 2.0 * near ) / ( far + near - exp_depth * ( far - near ) ); +} + + +float gaussian2d(int x,int y,int n) { + float sigma = 2.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 bloomShader() { + float offsetw = 1.0 / u_ScreenWidth; + float offseth = 1.0 / u_ScreenHeight; + float width = (float(KERNEL_SIZE) - 1.0) / 2.0; + vec3 c = vec3(0.0,0.0,0.0); + + for(int i=0; i< KERNEL_SIZE; i++){ + for(int j=0; j< KERNEL_SIZE; j++){ + vec2 tc = v_texcoord; + tc.y += (float(i)-width)*offseth; + tc.x += (float(j)-width)*offsetw; + c += gaussian2d(i,j,KERNEL_SIZE) * texture2D(u_shadeTex, tc).rgb; + } + } + + return vec4(c,1.0); +} + +//SSAO +float rand(float co){ + return fract(sin(dot(vec2(co,co) ,vec2(12.9898,78.233))) * 43758.5453); +} + +//http://john-chapman-graphics.blogspot.co.uk/2013/01/ssao-tutorial.html +vec4 SSAO() { +/* + vec3 normal = texture2D(u_normalTex, v_texcoord).xyz; + vec3 position = texture2D(u_positionTex, v_texcoord).xyz; + float depth = texture2D(u_depthTex, v_texcoord).r; + depth = linearizeDepth( depth, u_zNear, u_zFar ); + float occlusion = 0.0; + vec3 origin = vec3(position.x, position.y, depth); + + for(int i = 0; i < SAMPLEKERNEL_SIZE; ++i){ + + vec3 rvec = normalize(u_samplekernel[i]); + vec3 tangent = normalize(rvec - normal * dot(rvec, normal)); + vec3 bitangent = cross(normal, tangent); + mat3 tbn = mat3(tangent, bitangent, normal); + + vec3 kernelv = vec3(rand(position.x),rand(position.y),(rand(position.z)+1.0) / 2.0); + kernelv = normalize(kernelv); + float scale = float(i) / float(SAMPLEKERNEL_SIZE); + scale = mix(0.1, 1.0, scale * scale); + kernelv = kernelv * scale ; + + vec3 sample = tbn * kernelv; + float sampleDepth = texture2D(u_depthTex, v_texcoord + vec2(sample.x,sample.y)* u_radius).r; + sampleDepth = linearizeDepth( sampleDepth, u_zNear, u_zFar ); + + float samplez = origin.z - (sample * u_radius).z / 2.0; + + //rangeCheck helps to prevent erroneous occlusion between large depth discontinuities: + float rangeCheck = abs(origin.z - sampleDepth) < u_radius ? 1.0 : 0.0; + + if(sampleDepth <= samplez) + occlusion += 1.0 * rangeCheck; + } + + occlusion = 1.0 - (occlusion / float(SAMPLEKERNEL_SIZE)); + + return vec4(vec3(occlusion,occlusion,occlusion), 1.0); + */ + vec3 nml = texture2D( u_normalTex, v_texcoord ).xyz; + vec3 pos = texture2D(u_positionTex, v_texcoord).xyz; + float dp = texture2D(u_depthTex, v_texcoord).r; + dp = linearizeDepth( dp, u_zNear, u_zFar ); + float occ=0.0; + vec3 ori=vec3(pos.x,pos.y,dp); + + for(int i=0;i.8) + outClr=clr0; + else if(toonSel>.6) + outClr=mix(clr0,clr1,toonSel*2.5-1.0); + else if(toonSel>.4) + outClr=mix(clr0,clr1,(toonSel)*1.25); + else if(toonSel>.2) + outClr=mix(clr0,clr1,(toonSel)*.625); + else + outClr=mix(clr0,clr1,(toonSel)*.3125); + + float mag=0.0; + + for(int i=-1;i<=3;i++){ + for(int j=-1;j<=3;j++){ + float x=(float(i)-1.0)/1024.0; + float y=(float(j)-1.0)/512.0; + + float Nearby=texture2D(u_depthTex,v_texcoord+vec2(x,y)).x; + + if(Nearby>.99){ + outClr=vec3(0.0); + break; + } + } + } + } + if(clr.x > .5) + gl_FragColor = vec4(outClr, 1.0); + else + gl_FragColor = vec4(.8,.8,.8,1.0); +} diff --git a/assets/shader/deferred/normPass.frag b/assets/shader/deferred/normPass.frag new file mode 100644 index 0000000..b41d6ed --- /dev/null +++ b/assets/shader/deferred/normPass.frag @@ -0,0 +1,7 @@ +precision highp float; + +varying vec3 v_normal; + +void main(void){ + gl_FragColor = vec4(v_normal, 1.0); +} diff --git a/assets/shader/deferred/normPass.vert b/assets/shader/deferred/normPass.vert new file mode 100644 index 0000000..9a0b4b4 --- /dev/null +++ b/assets/shader/deferred/normPass.vert @@ -0,0 +1,15 @@ +precision highp float; + +attribute vec3 a_pos; +attribute vec3 a_normal; + +uniform mat4 u_mvp; +uniform mat4 u_normalMat; + +varying vec3 v_normal; + +void main(void){ + gl_Position = u_mvp * vec4( a_pos, 1.0 ); + + v_normal = vec3( u_normalMat * vec4(a_normal, 0.0) ); +} diff --git a/assets/shader/deferred/pass.frag b/assets/shader/deferred/pass.frag index e37dcbf..2416199 100644 --- a/assets/shader/deferred/pass.frag +++ b/assets/shader/deferred/pass.frag @@ -1,18 +1,16 @@ -#version 330 +#extension GL_EXT_draw_buffers: require +precision highp float; -uniform float u_Far; -uniform vec3 u_Color; +uniform sampler2D u_sampler; -in vec3 fs_Normal; -in vec4 fs_Position; +varying vec4 v_pos; +varying vec3 v_normal; +varying vec2 v_texcoord; +varying float v_depth; -out vec4 out_Normal; -out vec4 out_Position; -out vec4 out_Color; - -void main(void) -{ - out_Normal = vec4(normalize(fs_Normal),0.0f); - out_Position = vec4(fs_Position.xyz,1.0f); //Tuck position into 0 1 range - out_Color = vec4(u_Color,1.0); +void main(void){ + gl_FragData[0] = v_pos; + gl_FragData[1] = vec4( normalize(v_normal), 1.0 ); + gl_FragData[2] = vec4( 1.0, 0.0, 0.0, 1.0 ); + gl_FragData[3] = vec4( v_depth, 0, 0, 0 ); } diff --git a/assets/shader/deferred/pass.vert b/assets/shader/deferred/pass.vert index e36825f..861cb1a 100644 --- a/assets/shader/deferred/pass.vert +++ b/assets/shader/deferred/pass.vert @@ -1,21 +1,26 @@ -#version 330 +precision highp float; +attribute vec3 a_pos; +attribute vec3 a_normal; +attribute vec2 a_texcoord; -uniform mat4x4 u_Model; -uniform mat4x4 u_View; -uniform mat4x4 u_Persp; -uniform mat4x4 u_InvTrans; +uniform mat4 u_projection; +uniform mat4 u_modelview; +uniform mat4 u_mvp; +uniform mat4 u_normalMat; -in vec3 Position; -in vec3 Normal; +varying vec4 v_pos; +varying vec3 v_normal; +varying vec2 v_texcoord; +varying float v_depth; -out vec3 fs_Normal; -out vec4 fs_Position; +void main(void){ + gl_Position = u_mvp * vec4( a_pos, 1.0 ); -void main(void) { - fs_Normal = (u_InvTrans*vec4(Normal,0.0f)).xyz; - vec4 world = u_Model * vec4(Position, 1.0); - vec4 camera = u_View * world; - fs_Position = camera; - gl_Position = u_Persp * camera; + v_pos = u_modelview * vec4( a_pos, 1.0 ); + v_normal = vec3( u_normalMat * vec4(a_normal,0.0) ); + + v_texcoord = a_texcoord; + + v_depth = ( gl_Position.z / gl_Position.w + 1.0 ) / 2.0; } diff --git a/assets/shader/deferred/posPass.frag b/assets/shader/deferred/posPass.frag new file mode 100644 index 0000000..645a521 --- /dev/null +++ b/assets/shader/deferred/posPass.frag @@ -0,0 +1,8 @@ +precision highp float; + +varying vec4 v_pos; +varying float v_depth; + +void main(void){ + gl_FragColor = v_pos; +} diff --git a/assets/shader/deferred/posPass.vert b/assets/shader/deferred/posPass.vert new file mode 100644 index 0000000..ece8cc4 --- /dev/null +++ b/assets/shader/deferred/posPass.vert @@ -0,0 +1,15 @@ +precision highp float; + +attribute vec3 a_pos; + +uniform mat4 u_modelview; +uniform mat4 u_mvp; + +varying vec4 v_pos; +varying float v_depth; + +void main(void){ + gl_Position = u_mvp * vec4( a_pos, 1.0 ); + v_pos = u_modelview * vec4( a_pos, 1.0 ); + v_depth = ( gl_Position.z / gl_Position.w + 1.0 ) / 2.0; +} diff --git a/assets/shader/deferred/post.frag b/assets/shader/deferred/post.frag index 2bf5afc..5eb8c5e 100644 --- a/assets/shader/deferred/post.frag +++ b/assets/shader/deferred/post.frag @@ -1,74 +1,150 @@ -#version 330 +precision highp float; +#define DIFFUSE 5 +#define BLOOM 6 +#define TOON 7 +#define SSAO 8 +#define UNSHARP 9 -//////////////////////////// -// ENUMERATIONS -//////////////////////////// -#define DISPLAY_DEPTH 0 -#define DISPLAY_NORMAL 1 -#define DISPLAY_POSITION 2 -#define DISPLAY_COLOR 3 -#define DISPLAY_TOTAL 4 -#define DISPLAY_LIGHTS 5 +#define SIZE 31 +#define SAMPLER_SIZE 80 +uniform sampler2D u_positionTex; +uniform sampler2D u_normalTex; +uniform sampler2D u_colorTex; +uniform sampler2D u_depthTex; -///////////////////////////////////// -// Uniforms, Attributes, and Outputs -//////////////////////////////////// -uniform sampler2D u_Posttex; -uniform sampler2D u_RandomNormaltex; -uniform sampler2D u_RandomScalartex; +uniform float u_zFar; +uniform float u_zNear; +uniform int u_displayType; -uniform int u_ScreenWidth; -uniform int u_ScreenHeight; +uniform sampler2D u_shadeTex; -in vec2 fs_Texcoord; +varying vec2 v_texcoord; -out vec4 out_Color; -/////////////////////////////////////// +uniform float u_rad; +uniform vec3 u_sampler[80]; -uniform float zerothresh = 1.0f; -uniform float falloff = 0.1f; + +float gaussian(int x,int y,int n) { + float sigma = 2.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); +} -///////////////////////////////////// -// UTILITY FUNCTIONS -///////////////////////////////////// +float linearizeDepth( float exp_depth, float near, float far ){ + return ( 2.0 * near ) / ( far + near - exp_depth * ( far - near ) ); +} + +vec4 Bloom(){ + float x=1.0/1024.0; + float y=1.0/512.0; + + float wid=(float(SIZE)-1.0)/2.0; + vec3 cc=vec3(0.0); + + for(int i=0;iCIS 565 WebGL Deferred Shader +

FPS=0

WebGL unavailable. @@ -17,6 +18,7 @@ + diff --git a/js/core/fbo-util.js b/js/core/fbo-util.js new file mode 100644 index 0000000..32f745a --- /dev/null +++ b/js/core/fbo-util.js @@ -0,0 +1,201 @@ +//A wrapper for creating framebuffer objects + +//CIS565WEBGLCORE is a core function interface +var CIS565WEBGLCORE = CIS565WEBGLCORE || {}; + +var FBO_GBUFFER = 0; +var FBO_PBUFFER = 10; +var FBO_GBUFFER_POSITION = 0; +var FBO_GBUFFER_NORMAL = 1; +var FBO_GBUFFER_COLOR = 2; +var FBO_GBUFFER_DEPTH = 3; +var FBO_GBUFFER_TEXCOORD = 4; + +CIS565WEBGLCORE.createFBO = function(){ + "use strict" + + var textures = []; + var depthTex = null; + var fbo = []; + + var multipleTargets = true; + + function init( gl, width, height ){ + gl.getExtension( "OES_texture_float" ); + gl.getExtension( "OES_texture_float_linear" ); + var extDrawBuffers = gl.getExtension( "WEBGL_draw_buffers"); + var extDepthTex = gl.getExtension( "WEBGL_depth_texture" ); + + if( !extDepthTex ) { + alert("WARNING : Depth texture extension unavailabe on your browser!"); + return false; + } + + if ( !extDrawBuffers ){ + alert("WARNING : Draw buffer extension unavailable on your browser! Defaulting to multiple render pases."); + multipleTargets = false; + } + + //Create depth texture + depthTex = gl.createTexture(); + gl.bindTexture( gl.TEXTURE_2D, depthTex ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, width, height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null); + + // Create textures for FBO attachment + for( var i = 0; i < 5; ++i ){ + textures[i] = gl.createTexture() + gl.bindTexture( gl.TEXTURE_2D, textures[i] ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.FLOAT, null); + } + + // Create GBuffer FBO + if (multipleTargets) { + fbo[FBO_GBUFFER] = gl.createFramebuffer(); + gl.bindFramebuffer( gl.FRAMEBUFFER, fbo[FBO_GBUFFER] ); + + // Create render target; + var drawbuffers = []; + drawbuffers[0] = extDrawBuffers.COLOR_ATTACHMENT0_WEBGL; + drawbuffers[1] = extDrawBuffers.COLOR_ATTACHMENT1_WEBGL; + drawbuffers[2] = extDrawBuffers.COLOR_ATTACHMENT2_WEBGL; + drawbuffers[3] = extDrawBuffers.COLOR_ATTACHMENT3_WEBGL; + extDrawBuffers.drawBuffersWEBGL( drawbuffers ); + + //Attach textures to FBO + gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTex, 0 ); + gl.framebufferTexture2D( gl.FRAMEBUFFER, drawbuffers[0], gl.TEXTURE_2D, textures[0], 0 ); + gl.framebufferTexture2D( gl.FRAMEBUFFER, drawbuffers[1], gl.TEXTURE_2D, textures[1], 0 ); + gl.framebufferTexture2D( gl.FRAMEBUFFER, drawbuffers[2], gl.TEXTURE_2D, textures[2], 0 ); + gl.framebufferTexture2D( gl.FRAMEBUFFER, drawbuffers[3], gl.TEXTURE_2D, textures[3], 0 ); + + var FBOstatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if( FBOstatus !== gl.FRAMEBUFFER_COMPLETE ){ + console.log( "GBuffer FBO incomplete! Initialization failed!" ); + return false; + } + + // Create PBuffer FBO + fbo[FBO_PBUFFER] = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo[FBO_PBUFFER]); + + // Attach textures + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textures[4], 0); + + FBOstatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if(FBOstatus !== gl.FRAMEBUFFER_COMPLETE) { + console.log("PBuffer FBO incomplete! Initialization failed!"); + return false; + } + } else { + fbo[FBO_GBUFFER_POSITION] = gl.createFramebuffer(); + + // Set up GBuffer Position + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo[FBO_GBUFFER_POSITION]); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTex, 0); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textures[0], 0); + + var FBOstatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if (FBOstatus !== gl.FRAMEBUFFER_COMPLETE) { + console.log("GBuffer Position FBO incomplete! Init failed!"); + return false; + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + fbo[FBO_PBUFFER] = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo[FBO_PBUFFER]); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textures[4], 0); + + FBOstatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if (FBOstatus !== gl.FRAMEBUFFER_COMPLETE) { + console.log("PBuffer FBO incomplete! Init failed!"); + return false; + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + // Set up GBuffer Normal + fbo[FBO_GBUFFER_NORMAL] = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo[FBO_GBUFFER_NORMAL]); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTex, 0); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textures[1], 0); + + FBOstatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if (FBOstatus !== gl.FRAMEBUFFER_COMPLETE) { + console.log("GBuffer Normal FBO incomplete! Init failed!"); + return false; + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + // Set up GBuffer Color + fbo[FBO_GBUFFER_COLOR] = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo[FBO_GBUFFER_COLOR]); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTex, 0); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textures[2], 0); + + FBOstatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if (FBOstatus !== gl.FRAMEBUFFER_COMPLETE) { + console.log("GBuffer Color FBO incomplete! Init failed!"); + return false; + } + } + + gl.bindFramebuffer( gl.FRAMEBUFFER, null ); + gl.bindTexture( gl.TEXTURE_2D, null ); + + return true; + } + + return { + ref: function(buffer){ + return fbo[buffer]; + }, + initialize: function( gl, width, height ){ + return init( gl, width, height ); + }, + bind: function(gl, buffer){ + gl.bindFramebuffer( gl.FRAMEBUFFER, fbo[buffer] ); + }, + unbind: function(gl){ + gl.bindFramebuffer( gl.FRAMEBUFFER, null ); + }, + texture: function(i){ + return textures[i]; + }, + depthTexture: function(){ + return depthTex; + }, + isMultipleTargets: function(){ + return multipleTargets; + }, + ///// The following 3 functions should be implemented for all objects + ///// whose resources are retrieved asynchronously + isReady: function(){ + var isReady = ready; + for( var i = 0; i < textures.length; ++i ){ + isReady &= textures[i].ready; + } + console.log( isReady ); + return isReady; + }, + addCallback: function( functor ){ + callbackFunArray[callbackFunArray.length] = functor; + }, + executeCallBackFunc: function(){ + var i; + for( i = 0; i < callbackFunArray.length; ++i ){ + callbackFunArray[i](); + } + } + }; +}; + diff --git a/js/ext/threejs/OBJLoader.js b/js/ext/threejs/OBJLoader.js index 3b47f23..dee9b5b 100644 --- a/js/ext/threejs/OBJLoader.js +++ b/js/ext/threejs/OBJLoader.js @@ -1,12 +1,11 @@ /** + * Loads a Wavefront .obj file with materials + * * @author mrdoob / http://mrdoob.com/ + * @author angelxuanchang */ -THREE.OBJLoader = function ( manager ) { - - this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; - -}; +THREE.OBJLoader = function () {}; THREE.OBJLoader.prototype = { @@ -17,26 +16,30 @@ THREE.OBJLoader.prototype = { var scope = this; var loader = new THREE.XHRLoader( scope.manager ); - loader.setCrossOrigin( this.crossOrigin ); - loader.load( url, function ( text ) { - - onLoad( scope.parse( text ) ); - - } ); - + loader.setCrossOrigin( this.crossOrigin ); + loader.load( url, function (text) { + onLoad (scope.parse(text) ); + } ); }, - parse: function ( text ) { + /** + * Parses loaded .obj file + * @param data - content of .obj file + * @param mtllibCallback - callback to handle mtllib declaration (optional) + * @return {THREE.Object3D} - Object3D (with default material) + */ + + parse: function ( data ) { function vector( x, y, z ) { - return new THREE.Vector3( parseFloat( x ), parseFloat( y ), parseFloat( z ) ); + return new THREE.Vector3( x, y, z ); } function uv( u, v ) { - return new THREE.Vector2( parseFloat( u ), parseFloat( v ) ); + return new THREE.Vector2( u, v ); } @@ -45,54 +48,73 @@ THREE.OBJLoader.prototype = { return new THREE.Face3( a, b, c, normals ); } - - var object = new THREE.Object3D(); - var geometry, material, mesh; - function parseVertexIndex( index ) { + var face_offset = 0; - index = parseInt( index ); + function meshN( meshName, materialName ) { - return index >= 0 ? index - 1 : index + vertices.length; + if ( vertices.length > 0 ) { - } + geometry.vertices = vertices; + + geometry.mergeVertices(); + geometry.computeCentroids(); + geometry.computeFaceNormals(); + geometry.computeBoundingSphere(); - function parseNormalIndex( index ) { + object.add( mesh ); - index = parseInt( index ); + geometry = new THREE.Geometry(); + mesh = new THREE.Mesh( geometry, material ); + verticesCount = 0; - return index >= 0 ? index - 1 : index + normals.length; + } - } + if ( meshName !== undefined ) mesh.name = meshName; - function parseUVIndex( index ) { + if ( materialName !== undefined ) { - index = parseInt( index ); + material = new THREE.MeshLambertMaterial(); + material.name = materialName; - return index >= 0 ? index - 1 : index + uvs.length; + mesh.material = material; + + } } - + + var group = new THREE.Object3D(); + var object = group; + + var geometry = new THREE.Geometry(); + var material = new THREE.MeshLambertMaterial(); + var mesh = new THREE.Mesh( geometry, material ); + + var vertices = []; + var verticesCount = 0; + var normals = []; + var uvs = []; + function add_face( a, b, c, normals_inds ) { if ( normals_inds === undefined ) { geometry.faces.push( face3( - vertices[ parseVertexIndex( a ) ] - 1, - vertices[ parseVertexIndex( b ) ] - 1, - vertices[ parseVertexIndex( c ) ] - 1 + parseInt( a ) - (face_offset + 1), + parseInt( b ) - (face_offset + 1), + parseInt( c ) - (face_offset + 1) ) ); } else { geometry.faces.push( face3( - vertices[ parseVertexIndex( a ) ] - 1, - vertices[ parseVertexIndex( b ) ] - 1, - vertices[ parseVertexIndex( c ) ] - 1, + parseInt( a ) - (face_offset + 1), + parseInt( b ) - (face_offset + 1), + parseInt( c ) - (face_offset + 1), [ - normals[ parseNormalIndex( normals_inds[ 0 ] ) ].clone(), - normals[ parseNormalIndex( normals_inds[ 1 ] ) ].clone(), - normals[ parseNormalIndex( normals_inds[ 2 ] ) ].clone() + normals[ parseInt( normals_inds[ 0 ] ) - 1 ].clone(), + normals[ parseInt( normals_inds[ 1 ] ) - 1 ].clone(), + normals[ parseInt( normals_inds[ 2 ] ) - 1 ].clone() ] ) ); @@ -101,42 +123,40 @@ THREE.OBJLoader.prototype = { } function add_uvs( a, b, c ) { - + geometry.faceVertexUvs[ 0 ].push( [ - uvs[ parseUVIndex( a ) ].clone(), - uvs[ parseUVIndex( b ) ].clone(), - uvs[ parseUVIndex( c ) ].clone() + uvs[ parseInt( a ) - 1 ].clone(), + uvs[ parseInt( b ) - 1 ].clone(), + uvs[ parseInt( c ) - 1 ].clone() ] ); } function handle_face_line(faces, uvs, normals_inds) { - + if ( faces[ 3 ] === undefined ) { add_face( faces[ 0 ], faces[ 1 ], faces[ 2 ], normals_inds ); - if ( uvs !== undefined && uvs.length > 0 ) { - + if (!(uvs === undefined) && uvs.length > 0) { add_uvs( uvs[ 0 ], uvs[ 1 ], uvs[ 2 ] ); - } } else { - if ( normals_inds !== undefined && normals_inds.length > 0 ) { + if (!(normals_inds === undefined) && normals_inds.length > 0) { - add_face( faces[ 0 ], faces[ 1 ], faces[ 3 ], [ normals_inds[ 0 ], normals_inds[ 1 ], normals_inds[ 3 ] ] ); - add_face( faces[ 1 ], faces[ 2 ], faces[ 3 ], [ normals_inds[ 1 ], normals_inds[ 2 ], normals_inds[ 3 ] ] ); + add_face( faces[ 0 ], faces[ 1 ], faces[ 3 ], [ normals_inds[ 0 ], normals_inds[ 1 ], normals_inds[ 3 ] ]); + add_face( faces[ 1 ], faces[ 2 ], faces[ 3 ], [ normals_inds[ 1 ], normals_inds[ 2 ], normals_inds[ 3 ] ]); } else { - add_face( faces[ 0 ], faces[ 1 ], faces[ 3 ] ); - add_face( faces[ 1 ], faces[ 2 ], faces[ 3 ] ); + add_face( faces[ 0 ], faces[ 1 ], faces[ 3 ]); + add_face( faces[ 1 ], faces[ 2 ], faces[ 3 ]); } - if ( uvs !== undefined && uvs.length > 0 ) { + if (!(uvs === undefined) && uvs.length > 0) { add_uvs( uvs[ 0 ], uvs[ 1 ], uvs[ 3 ] ); add_uvs( uvs[ 1 ], uvs[ 2 ], uvs[ 3 ] ); @@ -147,20 +167,6 @@ THREE.OBJLoader.prototype = { } - // create mesh if no objects in text - - if ( /^o /gm.test( text ) === false ) { - - geometry = new THREE.Geometry(); - material = new THREE.MeshLambertMaterial(); - mesh = new THREE.Mesh( geometry, material ); - object.add( mesh ); - - } - - var vertices = []; - var normals = []; - var uvs = []; // v float float float @@ -176,23 +182,23 @@ THREE.OBJLoader.prototype = { // f vertex vertex vertex ... - var face_pattern1 = /f( +-?\d+)( +-?\d+)( +-?\d+)( +-?\d+)?/; + var face_pattern1 = /f( +\d+)( +\d+)( +\d+)( +\d+)?/; // f vertex/uv vertex/uv vertex/uv ... - var face_pattern2 = /f( +(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+))?/; + var face_pattern2 = /f( +(\d+)\/(\d+))( +(\d+)\/(\d+))( +(\d+)\/(\d+))( +(\d+)\/(\d+))?/; // f vertex/uv/normal vertex/uv/normal vertex/uv/normal ... - var face_pattern3 = /f( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))?/; + var face_pattern3 = /f( +(\d+)\/(\d+)\/(\d+))( +(\d+)\/(\d+)\/(\d+))( +(\d+)\/(\d+)\/(\d+))( +(\d+)\/(\d+)\/(\d+))?/; // f vertex//normal vertex//normal vertex//normal ... - var face_pattern4 = /f( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))?/ + var face_pattern4 = /f( +(\d+)\/\/(\d+))( +(\d+)\/\/(\d+))( +(\d+)\/\/(\d+))( +(\d+)\/\/(\d+))?/ // - var lines = text.split( '\n' ); + var lines = data.split( "\n" ); for ( var i = 0; i < lines.length; i ++ ) { @@ -209,41 +215,36 @@ THREE.OBJLoader.prototype = { // ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"] - vertices.push( - geometry.vertices.push( - vector( - result[ 1 ], result[ 2 ], result[ 3 ] - ) - ) - ); + vertices.push( vector( + parseFloat( result[ 1 ] ), + parseFloat( result[ 2 ] ), + parseFloat( result[ 3 ] ) + ) ); } else if ( ( result = normal_pattern.exec( line ) ) !== null ) { // ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"] - normals.push( - vector( - result[ 1 ], result[ 2 ], result[ 3 ] - ) - ); + normals.push( vector( + parseFloat( result[ 1 ] ), + parseFloat( result[ 2 ] ), + parseFloat( result[ 3 ] ) + ) ); } else if ( ( result = uv_pattern.exec( line ) ) !== null ) { // ["vt 0.1 0.2", "0.1", "0.2"] - uvs.push( - uv( - result[ 1 ], result[ 2 ] - ) - ); + uvs.push( uv( + parseFloat( result[ 1 ] ), + parseFloat( result[ 2 ] ) + ) ); } else if ( ( result = face_pattern1.exec( line ) ) !== null ) { // ["f 1 2 3", "1", "2", "3", undefined] - handle_face_line( - [ result[ 1 ], result[ 2 ], result[ 3 ], result[ 4 ] ] - ); + handle_face_line([ result[ 1 ], result[ 2 ], result[ 3 ], result[ 4 ] ]); } else if ( ( result = face_pattern2.exec( line ) ) !== null ) { @@ -276,22 +277,26 @@ THREE.OBJLoader.prototype = { } else if ( /^o /.test( line ) ) { - geometry = new THREE.Geometry(); - material = new THREE.MeshLambertMaterial(); - - mesh = new THREE.Mesh( geometry, material ); - mesh.name = line.substring( 2 ).trim(); - object.add( mesh ); + // object + + meshN(); + face_offset = face_offset + vertices.length; + vertices = []; + object = new THREE.Object3D(); + object.name = line.substring( 2 ).trim(); + group.add( object ); } else if ( /^g /.test( line ) ) { // group + meshN( line.substring( 2 ).trim(), undefined ); + } else if ( /^usemtl /.test( line ) ) { // material - material.name = line.substring( 7 ).trim(); + meshN( undefined, line.substring( 7 ).trim() ); } else if ( /^mtllib /.test( line ) ) { @@ -299,30 +304,23 @@ THREE.OBJLoader.prototype = { } else if ( /^s /.test( line ) ) { - // smooth shading + // Smooth shading } else { - // console.log( "THREE.OBJLoader: Unhandled line " + line ); + console.log( "THREE.OBJMTLLoader: Unhandled line " + line ); } } - var children = object.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - var geometry = children[ i ].geometry; - - geometry.computeCentroids(); - geometry.computeFaceNormals(); - geometry.computeBoundingSphere(); - - } + //Add last object + meshN(undefined, undefined); - return object; + return group; } -}; \ No newline at end of file +}; + +THREE.EventDispatcher.prototype.apply( THREE.OBJLoader.prototype ); diff --git a/js/lighting.js b/js/lighting.js new file mode 100644 index 0000000..f20a81c --- /dev/null +++ b/js/lighting.js @@ -0,0 +1,10 @@ +var Lighting = function (type) {}; + +var LIGHTING_ARRAY = 1; +var LIGHTING_RANDOM = 2; + +Lighting.prototype = { + constructor: Lighting, + + +}; diff --git a/js/main.js b/js/main.js index 128651e..1f7be4c 100644 --- a/js/main.js +++ b/js/main.js @@ -1,5 +1,5 @@ // Written by Harmony Li. Based on Cheng-Tso Lin's CIS 700 starter engine. -// cIS 565 : GPU Programming, Fall 2014. +// CIS 565 : GPU Programming, Fall 2014. // University of Pennsvylania (c) 2014. // Global Variables @@ -13,9 +13,35 @@ var objloader; // OBJ loader var model; // Model object var quad = {}; // Empty object for full-screen quad -// Shader programs -var modelProg; // Model shader program object +// Framebuffer +var fbo = null; +// Shader programs +var passProg; // Shader program for G-Buffer +var shadeProg; // Shader program for P-Buffer +var diagProg; // Shader program from diagnostic +var postProg; // Shader for post-process effects + +// Multi-Pass programs +var posProg; +var normProg; +var colorProg; + +var isDiagnostic = true; +var zNear = 20; +var zFar = 2000; +var texToDisplay = 1; +var lgtClr=[0.8,0.5,0.2]; +var lgtPos=[0.0,0.0,10.0]; +var sampler = []; +var kernelSize = 80; +var radius=0.05; + +var FPS=0; +var ticks=0; +var lastFPS=0; + + var main = function (canvasId, messageId) { var canvas; @@ -25,9 +51,14 @@ var main = function (canvasId, messageId) { // Set up camera initCamera(canvas); + // Set up FBOs + initFramebuffer(); +//Generate kernel + initKernel(); // Set up models initObjs(); - + + // Set up shaders initShaders(); @@ -36,38 +67,286 @@ var main = function (canvasId, messageId) { CIS565WEBGLCORE.renderLoop = renderLoop; // Start the rendering loop - CIS565WEBGLCORE.run(gl);}; + CIS565WEBGLCORE.run(gl); +}; var renderLoop = function () { window.requestAnimationFrame(renderLoop); render(); + var now=Date.now(); + if(now-lastFPS>=1000){ + lastFPS=now; + FPS=ticks; + ticks=0; + document.getElementById("FPS").innerHTML='FPS='+FPS; + } + ticks++; }; var render = function () { - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); - gl.useProgram(modelProg.ref()); + if (fbo.isMultipleTargets()) { + renderPass(); + } else { + renderMulti(); + } - gl.uniformMatrix4fv(modelProg.uPerspLoc, false, persp); - gl.uniformMatrix4fv(modelProg.uModelViewLoc, false, camera.getViewTransform()); + if (!isDiagnostic) { + renderShade(); + renderPost(); + } else { + renderDiagnostic(); + } + + gl.useProgram(null); +}; +var drawModel = function (program, mask) { // Bind attributes for(var i = 0; i < model.numGroups(); i++) { - gl.bindBuffer(gl.ARRAY_BUFFER, model.vbo(i)); - gl.vertexAttribPointer(modelProg.aVertexPosLoc, 3, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribArray(modelProg.aVertexPosLoc); - - gl.bindBuffer(gl.ARRAY_BUFFER, model.nbo(i)); - gl.vertexAttribPointer(modelProg.aNormalLoc, 3, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribArray(modelProg.aNormalLoc); + if (mask & 0x1) { + gl.bindBuffer(gl.ARRAY_BUFFER, model.vbo(i)); + gl.vertexAttribPointer(program.aVertexPosLoc, 3, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(program.aVertexPosLoc); + } + + if (mask & 0x2) { + gl.bindBuffer(gl.ARRAY_BUFFER, model.nbo(i)); + gl.vertexAttribPointer(program.aVertexNormalLoc, 3, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(program.aVertexNormalLoc); + } gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.ibo(i)); gl.drawElements(gl.TRIANGLES, model.iboLength(i), gl.UNSIGNED_SHORT, 0); } + if (mask & 0x1) gl.disableVertexAttribArray(program.aVertexPosLoc); + if (mask & 0x2) gl.disableVertexAttribArray(program.aVertexNormalLoc); + gl.bindBuffer(gl.ARRAY_BUFFER, null); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); +}; + +var drawQuad = function (program) { + gl.bindBuffer(gl.ARRAY_BUFFER, quad.vbo); + gl.vertexAttribPointer(program.aVertexPosLoc, 3, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(program.aVertexPosLoc); + + gl.bindBuffer(gl.ARRAY_BUFFER, quad.tbo); + gl.vertexAttribPointer(program.aVertexTexcoordLoc, 2, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(program.aVertexTexcoordLoc); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, quad.ibo); + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); + + gl.disableVertexAttribArray(program.aVertexPosLoc); + gl.disableVertexAttribArray(program.aVertexTexcoordLoc); + + gl.bindBuffer(gl.ARRAY_BUFFER, null); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); +}; + +var renderPass = function () { + // Bind framebuffer object for gbuffer + fbo.bind(gl, FBO_GBUFFER); + + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + gl.enable(gl.DEPTH_TEST); + + gl.useProgram(passProg.ref()); + + //update the model-view matrix + var mvpMat = mat4.create(); + mat4.multiply( mvpMat, persp, camera.getViewTransform() ); + + //update the normal matrix + var nmlMat = mat4.create(); + mat4.invert( nmlMat, camera.getViewTransform() ); + mat4.transpose( nmlMat, nmlMat); + + gl.uniformMatrix4fv( passProg.uModelViewLoc, false, camera.getViewTransform()); + gl.uniformMatrix4fv( passProg.uMVPLoc, false, mvpMat ); + gl.uniformMatrix4fv( passProg.uNormalMatLoc, false, nmlMat ); + + //gl.uniformMatrix4fv(shadeProg.uModelViewLoc,false,camera.getViewTransform()); + drawModel(passProg, 0x3); + + // Unbind framebufferww + fbo.unbind(gl); +}; + +var renderMulti = function () { + fbo.bind(gl, FBO_GBUFFER_POSITION); + + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + gl.enable(gl.DEPTH_TEST); + + gl.useProgram(posProg.ref()); + + //update the model-view matrix + var mvpMat = mat4.create(); + mat4.multiply( mvpMat, persp, camera.getViewTransform() ); + + gl.uniformMatrix4fv( posProg.uModelViewLoc, false, camera.getViewTransform()); + gl.uniformMatrix4fv( posProg.uMVPLoc, false, mvpMat ); + + drawModel(posProg, 1); + +// gl.disable(gl.DEPTH_TEST); + fbo.unbind(gl); + gl.useProgram(null); + + fbo.bind(gl, FBO_GBUFFER_NORMAL); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + gl.enable(gl.DEPTH_TEST); + + gl.useProgram(normProg.ref()); + + //update the normal matrix + var nmlMat = mat4.create(); + mat4.invert( nmlMat, camera.getViewTransform() ); + mat4.transpose( nmlMat, nmlMat); + + gl.uniformMatrix4fv(normProg.uMVPLoc, false, mvpMat); + gl.uniformMatrix4fv(normProg.uNormalMatLoc, false, nmlMat); + + drawModel(normProg, 3); + + gl.useProgram(null); + fbo.unbind(gl); + + fbo.bind(gl, FBO_GBUFFER_COLOR); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + gl.enable(gl.DEPTH_TEST); + + gl.useProgram(colorProg.ref()); + + gl.uniformMatrix4fv(colorProg.uMVPLoc, false, mvpMat); + + drawModel(colorProg, 1); gl.useProgram(null); + fbo.unbind(gl); +}; + +var renderShade = function () { + gl.useProgram(shadeProg.ref()); + gl.disable(gl.DEPTH_TEST); + + // Bind FBO + fbo.bind(gl, FBO_PBUFFER); + + 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.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.uniformMatrix4fv(shadeProg.uModelViewLoc,false,camera.getViewTransform()); + 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.uniform1i( shadeProg.uDisplayTypeLoc, texToDisplay ); + + gl.uniform3fv(shadeProg.uLgtPosLoc,lgtPos); + gl.uniform3fv(shadeProg.uLgtClrLoc,lgtClr); + drawQuad(shadeProg); + + // Unbind FBO + fbo.unbind(gl); +}; + +var renderDiagnostic = function () { + gl.useProgram(diagProg.ref()); + + gl.disable(gl.DEPTH_TEST); + gl.clear(gl.COLOR_BUFFER_BIT); + + // Bind necessary textures + gl.activeTexture( gl.TEXTURE0 ); //position + gl.bindTexture( gl.TEXTURE_2D, fbo.texture(0) ); + gl.uniform1i( diagProg.uPosSamplerLoc, 0 ); + + gl.activeTexture( gl.TEXTURE1 ); //normal + gl.bindTexture( gl.TEXTURE_2D, fbo.texture(1) ); + gl.uniform1i( diagProg.uNormalSamplerLoc, 1 ); + + gl.activeTexture( gl.TEXTURE2 ); //color + gl.bindTexture( gl.TEXTURE_2D, fbo.texture(2) ); + gl.uniform1i( diagProg.uColorSamplerLoc, 2 ); + + gl.activeTexture( gl.TEXTURE3 ); //depth + gl.bindTexture( gl.TEXTURE_2D, fbo.depthTexture() ); + gl.uniform1i( diagProg.uDepthSamplerLoc, 3 ); + + // Bind necessary uniforms + gl.uniform1f( diagProg.uZNearLoc, zNear ); + gl.uniform1f( diagProg.uZFarLoc, zFar ); + gl.uniform1i( diagProg.uDisplayTypeLoc, texToDisplay ); + + drawQuad(diagProg); +}; + +var initKernel = function () { + for (var i = 0; i < kernelSize; i++) { + var x = Math.random() * 2.0 - 1.0; + var y = Math.random() * 2.0 - 1.0; + var z = Math.random(); + + sampler[i] = [Math.random() * x, Math.random() * y, Math.random() * z]; + } +}; + + +var renderPost = function () { + gl.useProgram(postProg.ref()); + + gl.disable(gl.DEPTH_TEST); + gl.clear(gl.COLOR_BUFFER_BIT); + + // 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); + + gl.activeTexture( gl.TEXTURE4 ); + gl.bindTexture( gl.TEXTURE_2D, fbo.texture(4) ); + gl.uniform1i(postProg.uShadeSamplerLoc, 4 ); + gl.uniform1i(postProg.uDisplayTypeLoc,texToDisplay); + + + + gl.uniform1f(postProg.uZNearLoc, zNear); + gl.uniform1f(postProg.uZFarLoc, zFar); + gl.uniform1f(postProg.uRadLoc,radius); + + gl.uniform3fv(postProg.uSamplerLocation, sampler); + + drawQuad(postProg); }; var initGL = function (canvasId, messageId) { @@ -92,11 +371,57 @@ var initGL = function (canvasId, messageId) { var initCamera = function () { // Setup camera persp = mat4.create(); - mat4.perspective(persp, todeg(60), canvas.width / canvas.height, 0.1, 1000); + mat4.perspective(persp, todeg(60), canvas.width / canvas.height, 0.1, 2000); camera = CIS565WEBGLCORE.createCamera(CAMERA_TRACKING_TYPE); camera.goHome([0, 0, 4]); interactor = CIS565WEBGLCORE.CameraInteractor(camera, canvas); + + // Add key-input controls + window.onkeydown = function (e) { + interactor.onKeyDown(e); + switch(e.keyCode) { + case 48: + isDiagnostic = false; + break; + case 49: + isDiagnostic = true; + texToDisplay = 1; + break; + case 50: + isDiagnostic = true; + texToDisplay = 2; + break; + case 51: + isDiagnostic = true; + texToDisplay = 3; + break; + case 52: + isDiagnostic = true; + texToDisplay = 4; + break; + case 53: + isDiagnostic = false; + texToDisplay = 5; + break; + case 54: + isDiagnostic = false; + texToDisplay = 6; + break; + case 55: + isDiagnostic = false; + texToDisplay = 7; + break; + case 56: + isDiagnostic = false; + texToDisplay = 8; + break; + case 57: + isDiagnostic = false; + texToDisplay = 9; + break; + } + } }; var initObjs = function () { @@ -104,8 +429,9 @@ var initObjs = function () { objloader = CIS565WEBGLCORE.createOBJLoader(); // Load the OBJ from file - objloader.loadFromFile(gl, "assets/models/suzanne.obj", null); - + //objloader.loadFromFile(gl, "assets/models/crytek-sponza/sponza.obj", "assets/models/crytek-sponza/sponza.mtl"); + objloader.loadFromFile(gl, "assets/models/suzanne.obj", null); + //objloader.loadFromFile(gl, "assets/models/teapot.obj", null); // Add callback to upload the vertices once loaded objloader.addCallback(function () { model = new Model(gl, objloader); @@ -113,25 +439,156 @@ var initObjs = function () { // Register callback item CIS565WEBGLCORE.registerAsyncObj(gl, objloader); + + // Initialize full-screen quad + quad.vbo = gl.createBuffer(); + quad.ibo = gl.createBuffer(); + quad.tbo = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, quad.vbo); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(screenQuad.vertices), gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, quad.tbo); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(screenQuad.texcoords), gl.STATIC_DRAW); + gl.bindBuffer(gl.ARRAY_BUFFER, null) + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, quad.ibo); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(screenQuad.indices), gl.STATIC_DRAW); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); }; + var initShaders = function () { - // Create a shader program for rendering the object we are loading - modelProg = CIS565WEBGLCORE.createShaderProgram(); - - // Load the shader source asynchronously - modelProg.loadShader(gl, "assets/shader/forward.vert", "assets/shader/forward.frag"); - - // Register the necessary callback functions - modelProg.addCallback( function() { - gl.useProgram(modelProg.ref()); - - // Add uniform locations - modelProg.aVertexPosLoc = gl.getAttribLocation(modelProg.ref(), "v_position"); - modelProg.aNormalLoc = gl.getAttribLocation(modelProg.ref(), "v_normal"); - modelProg.uPerspLoc = gl.getUniformLocation(modelProg.ref(), "u_persp"); - modelProg.uModelViewLoc = gl.getUniformLocation(modelProg.ref(), "u_modelView"); + if (fbo.isMultipleTargets()) { + // Create a shader program for rendering the object we are loading + passProg = CIS565WEBGLCORE.createShaderProgram(); + + // Load the shader source asynchronously + passProg.loadShader(gl, "assets/shader/deferred/pass.vert", "assets/shader/deferred/pass.frag"); + + // Register the necessary callback functions + passProg.addCallback( function() { + gl.useProgram(passProg.ref()); + + // Add uniform locations + passProg.aVertexPosLoc = gl.getAttribLocation( passProg.ref(), "a_pos" ); + passProg.aVertexNormalLoc = gl.getAttribLocation( passProg.ref(), "a_normal" ); + passProg.aVertexTexcoordLoc = gl.getAttribLocation( passProg.ref(), "a_texcoord" ); + + passProg.uPerspLoc = gl.getUniformLocation( passProg.ref(), "u_projection" ); + passProg.uModelViewLoc = gl.getUniformLocation( passProg.ref(), "u_modelview" ); + passProg.uMVPLoc = gl.getUniformLocation( passProg.ref(), "u_mvp" ); + passProg.uNormalMatLoc = gl.getUniformLocation( passProg.ref(), "u_normalMat"); + passProg.uSamplerLoc = gl.getUniformLocation( passProg.ref(), "u_sampler"); + }); + + CIS565WEBGLCORE.registerAsyncObj(gl, passProg); + } else { + posProg = CIS565WEBGLCORE.createShaderProgram(); + posProg.loadShader(gl, "assets/shader/deferred/posPass.vert", "assets/shader/deferred/posPass.frag"); + posProg.addCallback(function() { + posProg.aVertexPosLoc = gl.getAttribLocation(posProg.ref(), "a_pos"); + + posProg.uModelViewLoc = gl.getUniformLocation(posProg.ref(), "u_modelview"); + posProg.uMVPLoc = gl.getUniformLocation(posProg.ref(), "u_mvp"); + }); + + CIS565WEBGLCORE.registerAsyncObj(gl, posProg); + + normProg = CIS565WEBGLCORE.createShaderProgram(); + normProg.loadShader(gl, "assets/shader/deferred/normPass.vert", "assets/shader/deferred/normPass.frag"); + normProg.addCallback(function() { + normProg.aVertexPosLoc = gl.getAttribLocation(normProg.ref(), "a_pos"); + normProg.aVertexNormalLoc = gl.getAttribLocation(normProg.ref(), "a_normal"); + + normProg.uMVPLoc = gl.getUniformLocation(normProg.ref(), "u_mvp"); + normProg.uNormalMatLoc = gl.getUniformLocation(normProg.ref(), "u_normalMat"); + }); + + CIS565WEBGLCORE.registerAsyncObj(gl, normProg); + + colorProg = CIS565WEBGLCORE.createShaderProgram(); + colorProg.loadShader(gl, "assets/shader/deferred/colorPass.vert", "assets/shader/deferred/colorPass.frag"); + colorProg.addCallback(function(){ + colorProg.aVertexPosLoc = gl.getAttribLocation(colorProg.ref(), "a_pos"); + + colorProg.uMVPLoc = gl.getUniformLocation(colorProg.ref(), "u_mvp"); + }); + + CIS565WEBGLCORE.registerAsyncObj(gl, colorProg); + } + + // Create shader program for diagnostic + diagProg = CIS565WEBGLCORE.createShaderProgram(); + diagProg.loadShader(gl, "assets/shader/deferred/quad.vert", "assets/shader/deferred/diagnostic.frag"); + diagProg.addCallback( function() { + diagProg.aVertexPosLoc = gl.getAttribLocation( diagProg.ref(), "a_pos" ); + diagProg.aVertexTexcoordLoc = gl.getAttribLocation( diagProg.ref(), "a_texcoord" ); + + diagProg.uPosSamplerLoc = gl.getUniformLocation( diagProg.ref(), "u_positionTex"); + diagProg.uNormalSamplerLoc = gl.getUniformLocation( diagProg.ref(), "u_normalTex"); + diagProg.uColorSamplerLoc = gl.getUniformLocation( diagProg.ref(), "u_colorTex"); + diagProg.uDepthSamplerLoc = gl.getUniformLocation( diagProg.ref(), "u_depthTex"); + + diagProg.uZNearLoc = gl.getUniformLocation( diagProg.ref(), "u_zNear" ); + diagProg.uZFarLoc = gl.getUniformLocation( diagProg.ref(), "u_zFar" ); + diagProg.uDisplayTypeLoc = gl.getUniformLocation( diagProg.ref(), "u_displayType" ); + }); + CIS565WEBGLCORE.registerAsyncObj(gl, diagProg); + + // Create shader program for shade + shadeProg = CIS565WEBGLCORE.createShaderProgram(); + shadeProg.loadShader(gl, "assets/shader/deferred/quad.vert", "assets/shader/deferred/diffuse.frag"); + shadeProg.addCallback( function() { + + shadeProg.uModelViewLoc = gl.getUniformLocation(shadeProg.ref(), "u_modelview"); + + + shadeProg.aVertexPosLoc = gl.getAttribLocation( shadeProg.ref(), "a_pos" ); + shadeProg.aVertexTexcoordLoc = gl.getAttribLocation( shadeProg.ref(), "a_texcoord" ); + + shadeProg.uPosSamplerLoc = gl.getUniformLocation( shadeProg.ref(), "u_positionTex"); + shadeProg.uNormalSamplerLoc = gl.getUniformLocation( shadeProg.ref(), "u_normalTex"); + shadeProg.uColorSamplerLoc = gl.getUniformLocation( shadeProg.ref(), "u_colorTex"); + shadeProg.uDepthSamplerLoc = gl.getUniformLocation( shadeProg.ref(), "u_depthTex"); + + 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.uLgtPosLoc=gl.getUniformLocation(shadeProg.ref(), "lgtPos"); + shadeProg.uLgtClrLoc=gl.getUniformLocation(shadeProg.ref(), "lgtClr"); + }); + CIS565WEBGLCORE.registerAsyncObj(gl, shadeProg); + + // Create shader program for post-process + postProg = CIS565WEBGLCORE.createShaderProgram(); + postProg.loadShader(gl, "assets/shader/deferred/quad.vert", "assets/shader/deferred/post.frag"); + 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.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.uDisplayTypeLoc = gl.getUniformLocation( postProg.ref(), "u_displayType" ); + + postProg.uRadLoc=gl.getUniformLocation(postProg.ref(),"u_rad"); + postProg.uSamplerLocation=gl.getUniformLocation(postProg.ref(),"u_sampler"); }); + CIS565WEBGLCORE.registerAsyncObj(gl, postProg); +}; - CIS565WEBGLCORE.registerAsyncObj(gl, modelProg); +var initFramebuffer = function () { + fbo = CIS565WEBGLCORE.createFBO(); + if (!fbo.initialize(gl, canvas.width, canvas.height)) { + console.log("FBO Initialization failed"); + return; + } }; diff --git a/js/screenQuad.js b/js/screenQuad.js index 49af62b..f33bfdf 100644 --- a/js/screenQuad.js +++ b/js/screenQuad.js @@ -2,20 +2,20 @@ var screenQuad ={ vertices: [ - -1.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, - 1.0, 1.0, 0.0 + 1.0, 1.0, 0.0, + -1.0, 1.0, 0.0 ], texcoords:[ - -1.0, 1.0, - -1.0, -1.0, - 1.0, -1.0, - 1.0, 1.0 + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0 ], indices: [ - 0, 1, 2, - 0, 2, 3 + 0, 1, 3, + 3, 1, 2 ] }; diff --git a/performance.xls b/performance.xls new file mode 100644 index 0000000..c699ce9 Binary files /dev/null and b/performance.xls differ