diff --git a/README.md b/README.md index da4c7e1..0627492 100644 --- a/README.md +++ b/README.md @@ -1,224 +1,62 @@ ------------------------------------------------------------------------------- -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. - -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: -------------------------------------------------------------------------------- - -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. - -------------------------------------------------------------------------------- -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: -------------------------------------------------------------------------------- -The deferred shader you will write 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 -* quad.vert -* diffuse.frag -* diagnostic.frag - -Stage 3 renders the post processing -* post.vert -* post.frag - -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 -* 1 - World Space Position -* 2 - Normals -* 3 - Color -* 4 - Depth -* 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 ---- - -Many thanks to Cheng-Tso Lin, whose framework for CIS700 we used for this -assignment. - -This project makes use of [three.js](http://www.threejs.org). +CIS 565 project 06 : Deferred shader +=================== + +## INTRODUCTION + +This project is an implementation of an OpenGL/GLSL deferred shading pipeline. First, various maps are rendered out to G-buffers, including positions, normals, colors, and depths for the visible fragments. Lighting and post-processing effects are then computed using the information stored in these G-buffers. In this project, I explore multiple shading models, screen-space ambient occlusion, a toon shader, and a bloom effect. + +## G-BUFFERS + +![alt tag](https://raw.githubusercontent.com/drerucha/Project6-DeferredShader/master/readme_images/monkey_gbuffer_positions.PNG) + +![alt tag](https://raw.githubusercontent.com/drerucha/Project6-DeferredShader/master/readme_images/monkey_gbuffer_normals.PNG) + +![alt tag](https://raw.githubusercontent.com/drerucha/Project6-DeferredShader/master/readme_images/monkey_gbuffer_colors.PNG) + +![alt tag](https://raw.githubusercontent.com/drerucha/Project6-DeferredShader/master/readme_images/monkey_gbuffer_depths.PNG) + +## LAMBERTIAN SHADING + +![alt tag](https://raw.githubusercontent.com/drerucha/Project6-DeferredShader/master/readme_images/monkey_lambertian.PNG) + +## BLINN-PHONG SHADING + +![alt tag](https://raw.githubusercontent.com/drerucha/Project6-DeferredShader/master/readme_images/monkey_blinn_phong.PNG) + +## SCREEN-SPACE AMBIENT OCCLUSION + +![alt tag](https://raw.githubusercontent.com/drerucha/Project6-DeferredShader/master/readme_images/monkey_ao.PNG) + +![alt tag](https://raw.githubusercontent.com/drerucha/Project6-DeferredShader/master/readme_images/monkey_blinn_phong.PNG) + +![alt tag](https://raw.githubusercontent.com/drerucha/Project6-DeferredShader/master/readme_images/monkey_blinn_phong_with_ao.PNG) + +## HORIZON-BASED AMBIENT OCCLUSION + +*Coming soon!* + +## TOON SHADING + +![alt tag](https://raw.githubusercontent.com/drerucha/Project6-DeferredShader/master/readme_images/monkey_toon_01.PNG) + +![alt tag](https://raw.githubusercontent.com/drerucha/Project6-DeferredShader/master/readme_images/monkey_toon_02.PNG) + +## BLOOM + +![alt tag](https://raw.githubusercontent.com/drerucha/Project6-DeferredShader/master/readme_images/monkey_bloom_01.PNG) + +![alt tag](https://raw.githubusercontent.com/drerucha/Project6-DeferredShader/master/readme_images/monkey_bloom_02.PNG) + +![alt tag](https://raw.githubusercontent.com/drerucha/Project6-DeferredShader/master/readme_images/monkey_bloom_03.PNG) + +## PERFORMANCE ANALYSIS + +*Coming soon!* + +*Note: As of 2014-11-13, I was having difficulties using WebGL Inspector and the Web Tracing Framework to time the execution of my shaders. Until I discover a workaround or an alternate tool to test performance, this section remains in-progress.* + +## SPECIAL THANKS + +I want to give a quick shout-out to Patrick Cozzi who led the fall 2014 CIS 565 course at Penn, Harmony Li who was the TA for the same course, and Cheng-Tso Lin who wrote much of the basecode. Thanks guys! + +Also, this project makes use of three.js, so thanks to the guys and gals responsible for that. \ No newline at end of file diff --git a/assets/shader/deferred/diffuse.frag b/assets/shader/deferred/diffuse.frag index ef0c5fc..7a37344 100644 --- a/assets/shader/deferred/diffuse.frag +++ b/assets/shader/deferred/diffuse.frag @@ -9,15 +9,186 @@ uniform float u_zFar; uniform float u_zNear; uniform int u_displayType; +uniform mat4 u_projection; + varying vec2 v_texcoord; +// Lighting constants. +const vec3 LIGHT_POS = vec3( 10.0, 0.0, 10.0 ); +const float LIGHT_INTENSITY = 1.0; +const vec3 LIGHT_COLOR = vec3( 1.0, 1.0, 1.0 ); +const vec3 AMBIENT_COLOR = vec3( 0.1, 0.0, 0.0 ); +const vec3 SPECULAR_COLOR = vec3( 1.0, 1.0, 1.0 ); +const float SPECULAR_EXPONENT = 32.0; + +// Horizon-based AO constants. +const int NUM_DIRECTIONS = 4; // Number of direction vectors to walk for each pixel. +const int NUM_SAMPLES = 6; // Number of steps to take along each direction vector to determine horizon. +const float STEP_SIZE = 0.001; // Distance to move along a direction vector for each sample. + +// Screen-space AO constants. +const float AO_NUM_SAMPLES = 8.0; +const float AO_RADIUS = 0.005; +const float AO_BOOST_FACTOR = 2.0; + +// Math constants. +const float PI = 3.1415926535; + +const float DEPTH_THRESHOLD = 0.99; + 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); -} + // DEBUG: Pass color through. + //gl_FragColor = vec4(texture2D(u_colorTex, v_texcoord).rgb, 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; + + vec3 normal_screen_space = normalize( u_projection * vec4( normal, 0.0 ) ).xyz; + + float base_depth = texture2D( u_depthTex, v_texcoord ).r; + + // If fragment is part of the background, then just pass the color through. + if ( linearizeDepth( base_depth, u_zNear, u_zFar ) >= DEPTH_THRESHOLD ) { + gl_FragColor = vec4( texture2D( u_colorTex, v_texcoord ).rgb, 1.0 ); + return; + } + + + /*********** IMAGE-SPACE HORIZON-BASED AMBIENT OCCLUSION ***********/ + // Implementation inspired by: http://developer.download.nvidia.com/presentations/2008/SIGGRAPH/HBAO_SIG08b.pdf + // Also inspired by: http://artis.inrialpes.fr/Membres/Olivier.Hoel/ssao/nVidiaHSAO/2317-abstract.pdf +/* + // Define base angle from current fragment coordinates. + float base_angle_deg = v_texcoord.s * v_texcoord.t; + //float base_angle_deg = 0.0; + + // TODO: I might be computing the tangent vector incorrectly. + + // Define tangent vector to normal of current fragment. + // Second vector of cross product is view direction. + vec3 t_vec = cross( normal, -position ); + vec2 t_dir = normalize( vec2( t_vec.x, t_vec.y ) ); + + float ao = 0.0; + + // Iterate through direction vectors emanating from current fragment. + for ( int i = 0; i < NUM_DIRECTIONS; ++i ) { + + // Compute current direction vector. + float angle_deg = base_angle_deg + ( float( i ) * ( 360.0 / float( NUM_DIRECTIONS ) ) ); + float angle_rad = angle_deg * ( PI / 180.0 ); + vec2 direction = normalize( vec2( cos( angle_rad ), sin( angle_rad ) ) ); + + float largest_depth_diff = 0.0; + + // Define horizon variables. + vec2 h_xy = v_texcoord; + float h_z = base_depth; + + // Define tangent variables. + vec2 t_xy = v_texcoord; + float t_z = base_depth; + + // Step along current direction vector. + for ( int step = 1; step <= NUM_SAMPLES; ++step ) { + + vec2 curr_pos = v_texcoord + ( float( step ) * direction ); + + // Compute depth at current step along direction vector. + float depth = texture2D( u_depthTex, curr_pos ).r; + + // If difference in depth compared to depth of current fragment is the largest seen so far. + if ( abs( depth - base_depth ) > largest_depth_diff ) { + + // Update horizon variables. + largest_depth_diff = abs( depth - base_depth ); + h_xy = curr_pos; + h_z = depth; + + // Update tangent variables. + t_xy = v_texcoord + ( float( step ) * t_dir ); + t_z = texture2D( u_depthTex, t_xy ).r; + } + } + + float h_angle = atan( h_z / length( h_xy - v_texcoord ) ); + float t_angle = atan( t_z / length( t_xy - v_texcoord ) ); + ao += sin( h_angle ) - sin( t_angle ); + } + + vec3 ao_contribution = vec3( 1.0 - ao, 1.0 - ao, 1.0 - ao ); + gl_FragColor = vec4( ao_contribution, 1.0 ); +*/ + + + /*********** SCREEN-SPACE AMBIENT OCCLUSION ***********/ + // Naive implementation inspired by: http://john-chapman-graphics.blogspot.co.uk/2013/01/ssao-tutorial.html + + float ao_total_samples = 0.0; + float ao_visible_samples = 0.0; + + vec3 fragment_point = vec3( v_texcoord, texture2D( u_depthTex, v_texcoord ).r ); + + // Generate random points on surface of sphere centered at origin. + for ( float theta = -PI / 2.0; theta < PI / 2.0; theta += PI / AO_NUM_SAMPLES ) { + for ( float phi = 0.0; phi < 2.0 * PI; phi += ( 2.0 * PI ) / AO_NUM_SAMPLES ) { + + // Convert spherical points to Cartesian points. + float x = AO_RADIUS * sin( phi ) * cos( theta ); + float y = AO_RADIUS * sin( phi ) * sin( theta ); + float z = AO_RADIUS * cos( phi ); + + vec3 spherical_point_dir = vec3( x, y, z ); + + // Skip point if it is not in the normal-aligned hemisphere. + if ( dot( spherical_point_dir, normal_screen_space ) >= 0.0 ) { + + // Get position and depth of point. + vec3 hemisphere_point = fragment_point + spherical_point_dir; + float gbuffer_depth = texture2D( u_depthTex, hemisphere_point.xy ).r; + + if ( hemisphere_point.z < gbuffer_depth && linearizeDepth( gbuffer_depth, u_zNear, u_zFar ) < DEPTH_THRESHOLD ) { + ao_visible_samples += 1.0; + } + + ao_total_samples += 1.0; + } + } + } + + vec3 ao_contribution = vec3( ( ao_visible_samples / ao_total_samples ) * AO_BOOST_FACTOR ); + + // More visible samples means fragment is less occluded and more light reaches it. + //gl_FragColor = vec4( vec3( ao_visible_samples / ao_total_samples ) * AO_BOOST_FACTOR, 1.0 ); + + + /*********** LAMBERTIAN SHADING ***********/ + + vec3 light_dir = normalize( LIGHT_POS - position ); + float diffuse = max( dot( normal, light_dir ), 0.0 ); + float specular = 0.0; + + if ( diffuse > 0.0 ) { + + vec3 view_dir = normalize( -position ); + + vec3 half_dir = normalize( light_dir + view_dir ); + float spec_angle = max( dot( half_dir, normal ), 0.0); + specular = pow( spec_angle, SPECULAR_EXPONENT ); + } + + vec3 blinn_phong_color = AMBIENT_COLOR + diffuse * color + specular * SPECULAR_COLOR; + gl_FragColor = vec4( blinn_phong_color * ao_contribution, 1.0 ); + +/* + float diffuse = max( dot( normal, normalize( LIGHT_POS - position ) ), 0.0 ); + vec3 lambertian_color = diffuse * color * LIGHT_INTENSITY; + gl_FragColor = vec4( lambertian_color * ao_contribution, 1.0 ); +*/ +} \ No newline at end of file diff --git a/assets/shader/deferred/post.frag b/assets/shader/deferred/post.frag index 52edda2..b5adcd1 100644 --- a/assets/shader/deferred/post.frag +++ b/assets/shader/deferred/post.frag @@ -1,17 +1,174 @@ precision highp float; +uniform sampler2D u_positionTex; +uniform sampler2D u_normalTex; +uniform sampler2D u_colorTex; +uniform sampler2D u_depthTex; + uniform sampler2D u_shadeTex; +uniform float u_zNear; +uniform float u_zFar; + varying vec2 v_texcoord; -float linearizeDepth( float exp_depth, float near, float far ){ - return ( 2.0 * near ) / ( far + near - exp_depth * ( far - near ) ); +// Math constants. +const float PI = 3.1415926535; +const float EULER = 2.7182818284; +const float SIGMA = 0.8; + +// Light constants. +const vec3 light_pos = vec3( 10.0, 0.0, 10.0 ); + +// Image dimensions. +const float WIDTH = 960.0; +const float HEIGHT = 540.0; + +// Pixel step sizes. +const float HORIZONTAL_STEP = 1.0 / WIDTH; +const float VERTICAL_STEP = 1.0 / HEIGHT; + +// Edge detection constants. +const float EDGE_DETECTION_THRESHOLD = 0.85; +const vec3 EDGE_COLOR = vec3( 0.0, 0.0, 0.0 ); + +// Blur constants. +const int CONVOLUTION_KERNEL_SIZE = 7; +const float GLOW_FACTOR_BLOOM = 1.0; +const float GLOW_FACTOR_BLUR = 1.0; +const int GLOW_WIDTH = 5; +const int GLOW_HEIGHT = 5; + +const float DEPTH_THRESHOLD = 0.99; + +float linearizeDepth( float exp_depth, float near, float far ) +{ + return ( 2.0 * near ) / ( far + near - exp_depth * ( far - near ) ); } -void main() +float computeGaussian( float x, float y ) { - // 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); + float part_1 = 1.0 / ( 2.0 * PI * pow( SIGMA, 2.0 ) ); + float part_2 = -1.0 * ( ( x * x + y * y ) / ( 2.0 * pow( SIGMA, 2.0 ) ) ); + return part_1 * pow( EULER, part_2 ); } + +void main() +{ + // DEBUG: Pass color through. + //gl_FragColor = vec4(texture2D( u_shadeTex, v_texcoord).rgb, 1.0); + + // Get fragment data. + vec3 position = texture2D( u_positionTex, v_texcoord ).xyz; + vec3 normal = texture2D( u_normalTex, v_texcoord ).xyz; + vec3 color = texture2D( u_colorTex, v_texcoord ).rgb; + float depth = texture2D( u_depthTex, v_texcoord ).r; + vec3 shade = texture2D( u_shadeTex, v_texcoord ).rgb; + + // If fragment is part of the background, then just pass the color through. + if ( linearizeDepth( depth, u_zNear, u_zFar ) >= DEPTH_THRESHOLD ) { + gl_FragColor = vec4( texture2D( u_shadeTex, v_texcoord ).rgb, 1.0 ); + return; + } + + + /*********** TOON SHADER ***********/ + // Implementation inspired by: http://www.lighthouse3d.com/tutorials/glsl-tutorial/toon-shader-version-ii/ +/* + // Compute angle between fragment normal and light. + float intensity = dot( normalize( light_pos - position ), normalize( normal ) ); + + // Get passed-in color. + vec3 toon_color = color; + + // Get normals of neighboring fragments. + vec3 neighbor_norm_1 = texture2D( u_normalTex, vec2( v_texcoord.s - HORIZONTAL_STEP, v_texcoord.t ) ).xyz; // Edge detection - Left. + vec3 neighbor_norm_2 = texture2D( u_normalTex, vec2( v_texcoord.s + HORIZONTAL_STEP, v_texcoord.t ) ).xyz; // Edge detection - Right. + vec3 neighbor_norm_3 = texture2D( u_normalTex, vec2( v_texcoord.s, v_texcoord.t - VERTICAL_STEP ) ).xyz; // Edge detection - Down. + vec3 neighbor_norm_4 = texture2D( u_normalTex, vec2( v_texcoord.s, v_texcoord.t + VERTICAL_STEP ) ).xyz; // Edge detection - Up. + + // Check for edges. + if ( dot( normal, neighbor_norm_1 ) < EDGE_DETECTION_THRESHOLD || + dot( normal, neighbor_norm_2 ) < EDGE_DETECTION_THRESHOLD || + dot( normal, neighbor_norm_3 ) < EDGE_DETECTION_THRESHOLD || + dot( normal, neighbor_norm_4 ) < EDGE_DETECTION_THRESHOLD ) + { + intensity = 1.0; + toon_color = EDGE_COLOR; + } + else { + + // Put colors into "buckets" based on intensity of light. + if ( intensity > 0.95 ) { + intensity = 1.0; + //toon_color = vec3( 1.0, 0.5, 0.5 ); + } + else if ( intensity > 0.5 ) { + intensity = 0.95; + //toon_color = vec3( 0.6, 0.3, 0.3 ); + } + else if ( intensity > 0.25 ) { + intensity = 0.5; + //toon_color = vec3( 0.4, 0.2, 0.2 ); + } + else { + intensity = 0.25; + //toon_color = vec3( 0.2, 0.1, 0.1 ); + } + } + + // Set fragement color. + gl_FragColor = vec4( toon_color * intensity, 1.0 ); +*/ + + + /*********** BLOOM ***********/ + // Apply a "glow" to edge fragments by blurring. + // Implementation inspired by: http://http.developer.nvidia.com/GPUGems/gpugems_ch21.html +/* + float blur_summation = 0.0; + + // Check for edges. + if ( dot( normal, neighbor_norm_1 ) < EDGE_DETECTION_THRESHOLD || + dot( normal, neighbor_norm_2 ) < EDGE_DETECTION_THRESHOLD || + dot( normal, neighbor_norm_3 ) < EDGE_DETECTION_THRESHOLD || + dot( normal, neighbor_norm_4 ) < EDGE_DETECTION_THRESHOLD ) + { + for ( int x = -CONVOLUTION_KERNEL_SIZE / 2; x < CONVOLUTION_KERNEL_SIZE / 2; ++x ) { + for ( int y = -CONVOLUTION_KERNEL_SIZE / 2; y < CONVOLUTION_KERNEL_SIZE / 2; ++y ) { + blur_summation += computeGaussian( abs( float( x ) ), abs( float( y ) ) ) * GLOW_FACTOR * texture2D( u_shadeTex, vec2( v_texcoord.s + ( float( x ) * HORIZONTAL_STEP ), v_texcoord.t + ( float( y ) * VERTICAL_STEP ) ) ).rgb; + } + } + } +*/ + +/* + float blur_summation = 0.0; + float intensity = dot( normalize( light_pos - position ), normalize( normal ) ); + + if ( intensity < 0.25 ) { + for ( int x = -CONVOLUTION_KERNEL_SIZE / 2; x < CONVOLUTION_KERNEL_SIZE / 2; ++x ) { + for ( int y = -CONVOLUTION_KERNEL_SIZE / 2; y < CONVOLUTION_KERNEL_SIZE / 2; ++y ) { + blur_summation += computeGaussian( abs( float( x ) ), abs( float( y ) ) ) * GLOW_FACTOR_BLOOM * texture2D( u_shadeTex, vec2( v_texcoord.s + ( float( x ) * HORIZONTAL_STEP ), v_texcoord.t + ( float( y ) * VERTICAL_STEP ) ) ).rgb; + } + } + } + + gl_FragColor = vec4( texture2D( u_shadeTex, v_texcoord ).rgb + blur_summation, 1.0 ); +*/ + + + /*********** BLUR ***********/ +/* + vec3 blur_color = vec3( 0.0, 0.0, 0.0 ); + for ( int x = -CONVOLUTION_KERNEL_SIZE / 2; x < CONVOLUTION_KERNEL_SIZE / 2; ++x ) { + for ( int y = -CONVOLUTION_KERNEL_SIZE / 2; y < CONVOLUTION_KERNEL_SIZE / 2; ++y ) { + blur_color += computeGaussian( abs( float( x ) ), abs( float( y ) ) ) * GLOW_FACTOR_BLUR * texture2D( u_shadeTex, vec2( v_texcoord.s + ( float( x ) * HORIZONTAL_STEP ), v_texcoord.t + ( float( y ) * VERTICAL_STEP ) ) ).rgb; + } + } + gl_FragColor = vec4( blur_color + blur_summation, 1.0 ); +*/ + + // DEBUG - Pass color through. + gl_FragColor = vec4( texture2D( u_shadeTex, v_texcoord ).rgb, 1.0 ); +} \ No newline at end of file diff --git a/js/core/fbo-util.js b/js/core/fbo-util.js index 42abe4c..03c6685 100644 --- a/js/core/fbo-util.js +++ b/js/core/fbo-util.js @@ -125,6 +125,7 @@ CIS565WEBGLCORE.createFBO = function(){ // 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); @@ -138,6 +139,7 @@ CIS565WEBGLCORE.createFBO = function(){ // 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); diff --git a/js/main.js b/js/main.js index 4140ae1..c66e7cf 100644 --- a/js/main.js +++ b/js/main.js @@ -170,12 +170,12 @@ var renderMulti = function () { drawModel(posProg, 1); - gl.disable(gl.DEPTH_TEST); + // gl.disable(gl.DEPTH_TEST); fbo.unbind(gl); gl.useProgram(null); fbo.bind(gl, FBO_GBUFFER_NORMAL); - gl.clear(gl.COLOR_BUFFER_BIT); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.useProgram(normProg.ref()); @@ -193,7 +193,7 @@ var renderMulti = function () { fbo.unbind(gl); fbo.bind(gl, FBO_GBUFFER_COLOR); - gl.clear(gl.COLOR_BUFFER_BIT); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.useProgram(colorProg.ref()); @@ -215,25 +215,25 @@ 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 ); drawQuad(shadeProg); @@ -283,6 +283,30 @@ var renderPost = function () { gl.bindTexture( gl.TEXTURE_2D, fbo.texture(4) ); gl.uniform1i(postProg.uShadeSamplerLoc, 4 ); + // Danny was here. + gl.activeTexture( gl.TEXTURE0 ); //position + gl.bindTexture( gl.TEXTURE_2D, fbo.texture(0) ); + gl.uniform1i( postProg.uPosSamplerLoc, 0 ); + + // Danny was here. + gl.activeTexture( gl.TEXTURE1 ); //normal + gl.bindTexture( gl.TEXTURE_2D, fbo.texture(1) ); + gl.uniform1i( postProg.uNormalSamplerLoc, 1 ); + + // Danny was here. + gl.activeTexture( gl.TEXTURE2 ); //color + gl.bindTexture( gl.TEXTURE_2D, fbo.texture(2) ); + gl.uniform1i( postProg.uColorSamplerLoc, 2 ); + + // Danny was here. + gl.activeTexture( gl.TEXTURE3 ); //depth + gl.bindTexture( gl.TEXTURE_2D, fbo.depthTexture() ); + gl.uniform1i( postProg.uDepthSamplerLoc, 3 ); + + // Danny was here. + gl.uniform1f( postProg.uZNearLoc, zNear ); + gl.uniform1f( postProg.uZFarLoc, zFar ); + drawQuad(postProg); }; @@ -346,6 +370,7 @@ var initObjs = function () { objloader = CIS565WEBGLCORE.createOBJLoader(); // Load the OBJ from file + //objloader.loadFromFile(gl, "assets/models/crytek-sponza/sponza.obj", "assets/models/crytek-sponza/sponza.mtl"); objloader.loadFromFile(gl, "assets/models/suzanne.obj", null); // Add callback to upload the vertices once loaded @@ -466,6 +491,8 @@ 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.uPerspLoc = gl.getUniformLocation( shadeProg.ref(), "u_projection" ); }); CIS565WEBGLCORE.registerAsyncObj(gl, shadeProg); @@ -477,6 +504,16 @@ var initShaders = function () { postProg.aVertexTexcoordLoc = gl.getAttribLocation( postProg.ref(), "a_texcoord" ); postProg.uShadeSamplerLoc = gl.getUniformLocation( postProg.ref(), "u_shadeTex"); + + // Danny was here. + 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"); + + // Danny was here. + postProg.uZNearLoc = gl.getUniformLocation( postProg.ref(), "u_zNear" ); + postProg.uZFarLoc = gl.getUniformLocation( postProg.ref(), "u_zFar" ); }); CIS565WEBGLCORE.registerAsyncObj(gl, postProg); }; diff --git a/readme_images/monkey_ao.PNG b/readme_images/monkey_ao.PNG new file mode 100644 index 0000000..40cdbbe Binary files /dev/null and b/readme_images/monkey_ao.PNG differ diff --git a/readme_images/monkey_blinn_phong.PNG b/readme_images/monkey_blinn_phong.PNG new file mode 100644 index 0000000..2916f02 Binary files /dev/null and b/readme_images/monkey_blinn_phong.PNG differ diff --git a/readme_images/monkey_blinn_phong_with_ao.PNG b/readme_images/monkey_blinn_phong_with_ao.PNG new file mode 100644 index 0000000..3dbcce7 Binary files /dev/null and b/readme_images/monkey_blinn_phong_with_ao.PNG differ diff --git a/readme_images/monkey_bloom_01.PNG b/readme_images/monkey_bloom_01.PNG new file mode 100644 index 0000000..df8f9b6 Binary files /dev/null and b/readme_images/monkey_bloom_01.PNG differ diff --git a/readme_images/monkey_bloom_02.PNG b/readme_images/monkey_bloom_02.PNG new file mode 100644 index 0000000..acd7172 Binary files /dev/null and b/readme_images/monkey_bloom_02.PNG differ diff --git a/readme_images/monkey_bloom_03.PNG b/readme_images/monkey_bloom_03.PNG new file mode 100644 index 0000000..88cdb8c Binary files /dev/null and b/readme_images/monkey_bloom_03.PNG differ diff --git a/readme_images/monkey_gbuffer_colors.PNG b/readme_images/monkey_gbuffer_colors.PNG new file mode 100644 index 0000000..00f1a52 Binary files /dev/null and b/readme_images/monkey_gbuffer_colors.PNG differ diff --git a/readme_images/monkey_gbuffer_depths.PNG b/readme_images/monkey_gbuffer_depths.PNG new file mode 100644 index 0000000..e57f8be Binary files /dev/null and b/readme_images/monkey_gbuffer_depths.PNG differ diff --git a/readme_images/monkey_gbuffer_normals.PNG b/readme_images/monkey_gbuffer_normals.PNG new file mode 100644 index 0000000..54c8723 Binary files /dev/null and b/readme_images/monkey_gbuffer_normals.PNG differ diff --git a/readme_images/monkey_gbuffer_positions.PNG b/readme_images/monkey_gbuffer_positions.PNG new file mode 100644 index 0000000..92e3956 Binary files /dev/null and b/readme_images/monkey_gbuffer_positions.PNG differ diff --git a/readme_images/monkey_lambertian.PNG b/readme_images/monkey_lambertian.PNG new file mode 100644 index 0000000..528c9f1 Binary files /dev/null and b/readme_images/monkey_lambertian.PNG differ diff --git a/readme_images/monkey_lambertian_with_ao.PNG b/readme_images/monkey_lambertian_with_ao.PNG new file mode 100644 index 0000000..7f37820 Binary files /dev/null and b/readme_images/monkey_lambertian_with_ao.PNG differ diff --git a/readme_images/monkey_toon_01.PNG b/readme_images/monkey_toon_01.PNG new file mode 100644 index 0000000..d281084 Binary files /dev/null and b/readme_images/monkey_toon_01.PNG differ diff --git a/readme_images/monkey_toon_02.PNG b/readme_images/monkey_toon_02.PNG new file mode 100644 index 0000000..1fabf9f Binary files /dev/null and b/readme_images/monkey_toon_02.PNG differ