diff --git a/README.md b/README.md index f22c764..b56a893 100644 --- a/README.md +++ b/README.md @@ -1,192 +1,187 @@ -------------------------------------------------------------------------------- -CIS565: Project 6: Deferred Shader -------------------------------------------------------------------------------- -Fall 2013 -------------------------------------------------------------------------------- -Due Friday 11/15/2013 +------------------------------------------------------------------------------------ +Project 6: Deferred Shader +==================================================================================== +Ricky Arietta Fall 2013 ------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -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. +![Image](https://raw.github.com/rarietta/Project6-DeferredShader/master/readme_imgs/header.png) -------------------------------------------------------------------------------- +------------------------------------------------------------------------------------ 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 Project6 root directory contains the following subdirectories: - -* base/ - * PROJ_WIN/ contains the vs2010 project files - * PROJ_NIX/ contains makefile for building (tested on ubuntu 12.04 LTS) - * res/ contains resources including shader source and obj files - * src/ contains the c++ code for the project along with SOIL and tiny_obj_loader -* shared32/ contains freeglut, glm, and glew. - ---- -BASE CODE TOUR ---- - -Most of your edits will be confined to the various fragment shader programs and main.cpp. - -Some methods worth exploring are: - -[initShader](https://github.com/CIS565-Fall-2013/Project6-DeferredShader/blob/master/base/src/main.cpp#L223): -This method initializes each shader program from specified source files. Note that the source name is declared inside a `#ifdef WIN32` guard block. This is done to reflect the relative directory structure between the linux and windows versions of the code. - -[initFBO](https://github.com/CIS565-Fall-2013/Project6-DeferredShader/blob/master/base/src/main.cpp#L360): -This method initializes the framebuffer objects used as render targets for the first and second stage of the pipeline. When you go to add another slot to the G buffer you will need to modify to first FBO accordingly. Try finding all the places where `colorTexture` is used (ctrl+F in windows will be helpful) and look at how textures are created, freed, added to the FBO, and assigned to the appropriate shader programs before adding your own. Also keep in mind that textures can be reused as inputs in other pipeline stages, for instance you might want access to the normals both in the lighting stage and in the post process stage. - -[draw_mesh](https://github.com/CIS565-Fall-2013/Project6-DeferredShader/blob/master/base/src/main.cpp#L574), -[draw_quad](https://github.com/CIS565-Fall-2013/Project6-DeferredShader/blob/master/base/src/main.cpp#L647), -[draw_light](https://github.com/CIS565-Fall-2013/Project6-DeferredShader/blob/master/base/src/main.cpp#L657): -These methods render the scene geometry, viewing quad, and point light quad to the screen. The draw_light method in particular is interesting because it will set up the scissor window for efficient rendering of point lights. - -[display](https://github.com/CIS565-Fall-2013/Project6-DeferredShader/blob/master/base/src/main.cpp#L742): -This is where the graphical work of your program is done. The method is separated into three stages with the majority of work being done in stage 2. - -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 -* diagnostic.frag - -Stage 3 renders the post processing -* post.vert -* post.frag - -[keyboard](https://github.com/CIS565-Fall-2013/Project6-DeferredShader/blob/master/base/src/main.cpp#L870): -This is a good reference for the key mappings in the program. -WASDQZ - Movement -X - Toggle scissor test -R - Reload shaders -1 - View depth -2 - View eye space normals -3 - View Diffuse color -4 - View eye space positions -5 - View lighting debug mode -0 - Standard view +This project implements a deferred shader using OpenGL/GLSL. Scene attributes +are rendered out independently to various G-Buffers (i.e. Z-Depth, Normals, +Camera Space Positions, Color, Ambient Occlusion Maps) and then utilized for +post-process lighting and rendering calculations. In this project, I explore +how to use these G-Buffers for rendering multiple point light sources, as well +as calculating screen space ambient occlusion and rendering the scene using +a toon shader (or "cel shader"). + +------------------------------------------------------------------------------------ +NOTES: +==================================================================================== + +Here are the Keyboard Controls for the program: + +"0": Display Full Lit Diffuse Image +"1": Display Z-Depth Buffer +"2": Display Normals Buffer +"3": Display Color Buffer +"4": Display Camera Space Position Buffer +"5": Display Lights Visualization +"6": Display Ambient Occlusion Buffer +"7": Display Toon Shaded Image +"8": Display Full Lit Diffuse + Luminance-Based Specular Image +"9": Display Image With Bloom/Glow +"Q": Move Camera Up +"Z": Move Camera Down +"W": Move Camera In +"S": Move Camera Out +"A": Move Camera Left +"D": Move Camera Right" +"X": Enable/Disable Scissor Test For Lighting + +------------------------------------------------------------------------------------ +PART 1: Required Features +==================================================================================== ------------------------------------------------------------------------------- -REQUIREMENTS: +Multiple Point Lighting ------------------------------------------------------------------------------- -In this project, you are given code for: -* Loading .obj files -* Rendering to a minimal G buffer: - * Depth - * Normal - * Color - * Eye space position -* Rendering simple ambient and directional lighting to texture -* Example post process shader to add a vignette - -You are required to implement: -* Either of the following effects - * Bloom (feel free to use [GPU Gems](http://http.developer.nvidia.com/GPUGems/gpugems_ch21.html) as a rough guide) - * "Toon" Shading (with basic silhouetting) -* Point light sources -* An additional G buffer slot and some effect showing it off - -**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 -* Screen space ambient occlusion -* 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). +By pulling data from the normal, color, and position buffers, rendering point +light sources becomes a highly parallel and possible in the fragment shader. For +each light, we define an area of influence based on its strength and perform +a scissor test, thereby rendering a screen quad covering only that area of +influence. Within each light render, we compute the distance and direction from +the light to the fragment (from the position buffer) and calculate a diffuse +coefficient (using the normal and color data) and color the fragment appropriately. + +In the images below, I have set up a grid of point lights in the scene, evenly +spaced within the bounds of the Cornell box. Their influence can be seen in the +final render. + +![Image](https://raw.github.com/rarietta/Project6-DeferredShader/master/readme_imgs/box_notoon1.png) ------------------------------------------------------------------------------- -README +Toon Shading ------------------------------------------------------------------------------- -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 http://www.microsoft.com/expression/products/Encoder4_Overview.aspx -* A performance evaluation (described in detail below). +To implement toon shading, I simply analyzed the normals of each fragment +in relation to its cardinal neighbors. If the angle between the normals was +great enough, I assumed this to be an edge and rendered it as a black line. +Otherwise, I discretized the luminance of the fragment to one of five +predefined bucket values. The results are below. + +![Image](https://raw.github.com/rarietta/Project6-DeferredShader/master/readme_imgs/toon_side_by_side.png) +![Image](https://raw.github.com/rarietta/Project6-DeferredShader/master/readme_imgs/toon_side_by_side2.png) ------------------------------------------------------------------------------- -PERFORMANCE EVALUATION +Additional G-Buffer: Luminance Based Specularity ------------------------------------------------------------------------------- -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. +For my implementation of an additional G-Buffer, I stored the luminance of each +fragment computed as: + + L = 0.2126*color.r + 0.7152*color.g + 0.0722*color.b + +Here is a visualization of the luminance on the cornell box scene: + +![Image](https://raw.github.com/rarietta/Project6-DeferredShader/master/readme_imgs/luminance.png) + +Using this luminance buffer, I computed specular lighting for the scene in +addition to the diffuse lighting calculations. I used the luminance value +for each fragment as both the specular exponent and the specular coefficient. +You can see the difference in lighting below, and notice that the specularity +is not uniform across the scene. The specular lighting on the red surface +is the least, since this surface had the lowest luminance value, while the +specularity on the white surfaces is highest, since this surface had the +highest luminance. + +![Image](https://raw.github.com/rarietta/Project6-DeferredShader/master/readme_imgs/diffuse_vs_specular.png) -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. +------------------------------------------------------------------------------------ +PART 2: Additional Features +==================================================================================== ------------------------------------------------------------------------------- -THIRD PARTY CODE POLICY +Screen Space Ambient Occlusion ------------------------------------------------------------------------------- -* 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. + +![Image](https://raw.github.com/rarietta/Project6-DeferredShader/master/readme_imgs/AOpass.png) + +To compute screen space ambient occlusion, I implemented a method described by +NVidia (here: http://www.nvidia.com/object/siggraph-2008-HBAO.html) called +Horizon Based Ambient Occlusion. This method finds the horizon angle from each +fragment to its neighbors along a set of sampling axes (in my implementation +I simply used the 4 axes in X, Y, -X, and -Y and sampled 6 fragments in each +direction). These sampled angles are used to compute the occlusion value of any one +fragment and multiplied with the ambient light in a scene. You can see the +difference between the two sets of images below: the ones on the left were +rendered with no occlusion, while the ones on the right include HBAO. + +![Image](https://raw.github.com/rarietta/Project6-DeferredShader/master/readme_imgs/occlusion_demo.png) ------------------------------------------------------------------------------- -SELF-GRADING +Light Bloom ------------------------------------------------------------------------------- -* 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. - - ---- -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 ---- -This project makes use of [tinyobjloader](http://syoyo.github.io/tinyobjloader/) and [SOIL](http://lonesock.net/soil.html) + +To achieve this effect, I once again utilized the additional Luminance G-Buffer, +this time using it as a glow for the scene (i.e. the amount of glow from each +surface fragment was dictated by its luminance value). By blurring the product +of this simple luminance value and the original color values over a Gaussian +distribution in screen-space X and Y, I was able to achieve a bloom or glow +value each fragment. (The algorithm usuall calls for a Gaussian blur in all +directions, but I found comparable effects by simply blurring once in the X +direction and once in the Y direction and summing the components. This ran much +faster than a standard square kernel, which would cause a timeout on the +graphics card even at small sizes. I developed this as a simplification hack +of 2-D convolution). + +You can see the results below. Here is the original image without and bloom: + +![Image](https://raw.github.com/rarietta/Project6-DeferredShader/master/readme_imgs/bloom0.png) + +And here is the bloom image with glow values equal to luminance. Notice how +the white surfaces glow more than the green, and more so than the red: + +![Image](https://raw.github.com/rarietta/Project6-DeferredShader/master/readme_imgs/bloom1.png) + +To further illustrate how the bloom utilized the luminance buffer, I inverted +the luminance and calculated bloom again. Notice in this version how the surfaces +with lower luminance glow the most. Though it may seem less natural, it shows +how the shader is implemented: + +![Image](https://raw.github.com/rarietta/Project6-DeferredShader/master/readme_imgs/bloom2.png) + +------------------------------------------------------------------------------------ +PART 3: Performance Analysis +==================================================================================== + +In my analysis of this project, I compared runtime FPS in Bloom shading for a traditional +square 2D kernel versus my modified 2-Axis 1D kernel. Here is what I mean by the +kernels: + +![Image](https://raw.github.com/rarietta/Project6-DeferredShader/master/readme_imgs/kernel_shapes.png) + +Here is the difference in runtime between mine and the original 2D kernel I +originally attempted to implement: + +![Image](https://raw.github.com/rarietta/Project6-DeferredShader/master/readme_imgs/kernel_fps_chart.png) + +![Image](https://raw.github.com/rarietta/Project6-DeferredShader/master/readme_imgs/kernel_fps_graph.png) + +Notice how the program does not even run for a 2D kernel of size greater than +9x9. Unfortunately, the bloom effects are not even really visible until the kernel +width is greater than 20, as judged by the modified 1D kernel implementation. + +------------------------------------------------------------------------------------ +ACKNOWLEDGMENTS: +==================================================================================== + +As noted above, Horizon Based Ambient Occlusion was adapted from an NVidia +presentation found here: http://www.nvidia.com/object/siggraph-2008-HBAO.html + +This project was built on a basic framework provided by Patrick Cozzi and Liam +Boone for CIS 565 at The University of Pennsylvania, Fall 2013. \ No newline at end of file diff --git a/base/res/shaders/ambient.frag b/base/res/shaders/ambient.frag index 69b878c..218471a 100644 --- a/base/res/shaders/ambient.frag +++ b/base/res/shaders/ambient.frag @@ -10,6 +10,9 @@ #define DISPLAY_COLOR 3 #define DISPLAY_TOTAL 4 #define DISPLAY_LIGHTS 5 +#define DISPLAY_AO 6 +#define DISPLAY_TOON 7 +#define DISPLAY_SPEC 8 ///////////////////////////////////// @@ -67,7 +70,7 @@ vec3 samplePos(vec2 texcoords) { return texture(u_Positiontex,texcoords).xyz; } -//Helper function to automicatlly sample and unpack positions +//Helper function to automicatlly sample and unpack colors vec3 sampleCol(vec2 texcoords) { return texture(u_Colortex,texcoords).xyz; } @@ -95,21 +98,86 @@ float getRandomScalar(vec2 texcoords) { const float occlusion_strength = 1.5f; void main() { + // depth data float exp_depth = texture(u_Depthtex, fs_Texcoord).r; float lin_depth = linearizeDepth(exp_depth,u_Near,u_Far); + // fragment data vec3 normal = sampleNrm(fs_Texcoord); vec3 position = samplePos(fs_Texcoord); vec3 color = sampleCol(fs_Texcoord); + + // ambient light data vec3 light = u_Light.xyz; float strength = u_Light.w; - if (lin_depth > 0.99f) { - out_Color = vec4(vec3(0.0), 1.0); - } else { - float ambient = u_LightIl; - float diffuse = max(0.0, dot(normalize(light),normal)); - out_Color = vec4(color*(strength*diffuse + ambient),1.0f); - } + + // computer SSAO (screen space ambient occlusion) + // float occl = sampleBlurredDepth(fs_Texcoord); + + vec2 sz = textureSize(u_Positiontex, 0); + + float hup = 0.0; float tup = 0.0; + float hdown = 0.0; float tdown = 0.0; + float hleft = 0.0; float tleft = 0.0; + float hright = 0.0; float tright = 0.0; + + for (float i = 1.0; i <= 6.0; i += 1.0) { + + // neighbor positions + vec3 posUp = samplePos(vec2(fs_Texcoord.s, fs_Texcoord.t + (1.0 / sz.y))); + vec3 posDown = samplePos(vec2(fs_Texcoord.s, fs_Texcoord.t - (1.0 / sz.y))); + vec3 posRight = samplePos(vec2(fs_Texcoord.s + (1.0 / sz.y), fs_Texcoord.t)); + vec3 posLeft = samplePos(vec2(fs_Texcoord.s - (1.0 / sz.y), fs_Texcoord.t)); + + // up occlusion + vec3 Hup = posUp - position; + vec3 Tup = cross(normal, vec3(0,1,0)); + if (Hup.z > 0.01) { + hup += atan(Hup.z / length(Hup.xy)) / 6.0; + tup += atan(Tup.z / length(Tup.xy)) / 6.0; + } + + // down occlusion + vec3 Hdown = posDown - position; + vec3 Tdown = cross(normal, vec3(0,-1,0)); + if (Hdown.z > 0.01) { + hdown += atan(Hdown.z / length(Hdown.xy)) / 6.0; + tdown += atan(Tdown.z / length(Tdown.xy)) / 6.0; + } + + // right occlusion + vec3 Hright = posRight - position; + vec3 Tright = cross(normal, vec3(1,0,0)); + if (Hright.z > 0.01) { + hright += atan(Hright.z / length(Hright.xy)) / 6.0; + tright += atan(Tright.z / length(Tright.xy)) / 6.0; + } + + // left occlusion + vec3 Hleft = posLeft - position; + vec3 Tleft = cross(normal, vec3(-1,0,0)); + if (Hleft.z > 0.01) { + hleft += atan(Hleft.z / length(Hleft.xy)) / 6.0; + tleft += atan(Tleft.z / length(Tleft.xy)) / 6.0; + } + } + + // ambient occlusion term + float occl = (sin(hup) - sin(tup)) / 4.0 + (sin(hdown) - sin(tdown)) / 4.0 + (sin(hright) - sin(tright)) / 4.0 + (sin(hleft) - sin(tleft)) / 4.0; + + if (u_DisplayType == DISPLAY_AO) { + out_Color = vec4(1.0-occl); + } + else { + // compute final color + if (lin_depth > 0.99f) { + out_Color = vec4(vec3(0.0), 1.0); + } else { + float ambient = u_LightIl; + float diffuse = max(0.0, dot(normalize(light),normal)); + out_Color = vec4(color*(strength*diffuse + ambient*(1.0-occl)),1.0f); + } + } return; } diff --git a/base/res/shaders/diagnostic.frag b/base/res/shaders/diagnostic.frag index ac73727..91ae388 100644 --- a/base/res/shaders/diagnostic.frag +++ b/base/res/shaders/diagnostic.frag @@ -10,6 +10,9 @@ #define DISPLAY_COLOR 3 #define DISPLAY_TOTAL 4 #define DISPLAY_LIGHTS 5 +#define DISPLAY_AO 6 +#define DISPLAY_TOON 7 +#define DISPLAY_SPEC 8 ///////////////////////////////////// diff --git a/base/res/shaders/directional.frag b/base/res/shaders/directional.frag index a34daab..058673b 100644 --- a/base/res/shaders/directional.frag +++ b/base/res/shaders/directional.frag @@ -10,6 +10,9 @@ #define DISPLAY_COLOR 3 #define DISPLAY_TOTAL 4 #define DISPLAY_LIGHTS 5 +#define DISPLAY_AO 6 +#define DISPLAY_TOON 7 +#define DISPLAY_SPEC 8 ///////////////////////////////////// diff --git a/base/res/shaders/pass.frag b/base/res/shaders/pass.frag index e37dcbf..6108d70 100644 --- a/base/res/shaders/pass.frag +++ b/base/res/shaders/pass.frag @@ -9,10 +9,13 @@ in vec4 fs_Position; out vec4 out_Normal; out vec4 out_Position; out vec4 out_Color; +out vec4 out_Glow; 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 + float lum = 0.2126*u_Color.r + 0.7152*u_Color.g + 0.0722*u_Color.b; + out_Glow = vec4(vec3(lum), 1.0); out_Color = vec4(u_Color,1.0); } diff --git a/base/res/shaders/point.frag b/base/res/shaders/point.frag index 98b90e0..14e0c96 100644 --- a/base/res/shaders/point.frag +++ b/base/res/shaders/point.frag @@ -10,6 +10,9 @@ #define DISPLAY_COLOR 3 #define DISPLAY_TOTAL 4 #define DISPLAY_LIGHTS 5 +#define DISPLAY_AO 6 +#define DISPLAY_TOON 7 +#define DISPLAY_SPEC 8 ///////////////////////////////////// @@ -21,6 +24,7 @@ uniform sampler2D u_Depthtex; uniform sampler2D u_Normaltex; uniform sampler2D u_Positiontex; uniform sampler2D u_Colortex; +uniform sampler2D u_Glowtex; uniform sampler2D u_RandomNormaltex; uniform sampler2D u_RandomScalartex; @@ -71,6 +75,11 @@ vec3 sampleCol(vec2 texcoords) { return texture(u_Colortex,texcoords).xyz; } +//Helper function to automicatlly sample and unpack positions +vec3 sampleGlow(vec2 texcoords) { + return texture(u_Glowtex,texcoords).xyz; +} + //Get a random normal vector given a screen-space texture coordinate //Actually accesses a texture of random vectors vec3 getRandomNormal(vec2 texcoords) { @@ -100,17 +109,70 @@ void main() { vec3 normal = sampleNrm(fs_Texcoord); vec3 position = samplePos(fs_Texcoord); vec3 color = sampleCol(fs_Texcoord); + float glow = sampleGlow(fs_Texcoord).r; + vec3 light = u_Light.xyz; float lightRadius = u_Light.w; - out_Color = vec4(0,0,0,1.0); + out_Color = vec4(0, 0, 0, 0); if( u_DisplayType == DISPLAY_LIGHTS ) { - //Put some code here to visualize the fragment associated with this point light + out_Color += vec4(0, 0, 0.4, 0); } + else if (u_DisplayType == DISPLAY_TOON ) + { + ivec2 sz = textureSize(u_Normaltex,0); + vec3 normal_up = sampleNrm(vec2(fs_Texcoord.x+(1.0/sz.x), fs_Texcoord.y)); + vec3 normal_down = sampleNrm(vec2(fs_Texcoord.x-(1.0/sz.x), fs_Texcoord.y)); + vec3 normal_right = sampleNrm(vec2(fs_Texcoord.x, fs_Texcoord.y+(1.0/sz.y))); + vec3 normal_left = sampleNrm(vec2(fs_Texcoord.x, fs_Texcoord.y-(1.0/sz.y))); + + if ( dot(normal, normal_up) <= 0.96 || + dot(normal, normal_down) <= 0.96 || + dot(normal, normal_right) <= 0.96 || + dot(normal, normal_left) <= 0.96) + { + out_Color = vec4(vec3(0), 1.0f); + } + + else + { + vec3 dirToLight = vec3(light.xyz - position.xyz); + float distFromLight = length(dirToLight); + if (distFromLight < lightRadius) + { + float I = max(0.0, dot(normal, normalize(dirToLight)))*u_Light.w / (distFromLight / (lightRadius - distFromLight)); + + // toon shading + if (I <= 0.05) { I = 0.1; } + else if (I <= 0.10) { I = 0.3; } + else if (I <= 0.15) { I = 0.5; } + else if (I <= 0.20) { I = 0.7; } + else { I = 0.9; } + + out_Color += vec4(I); + out_Color *= vec4(color, 1.0); + } + } + } else { - //Put some code here to actually compute the light from the point light + vec3 dirToLight = vec3(light.xyz - position.xyz); + float distFromLight = length(dirToLight); + if (distFromLight < lightRadius) { + float I = max(0.0, dot(normal, normalize(dirToLight)))*u_Light.w / (distFromLight / (lightRadius - distFromLight)); + + float diffuse = max(0.0, dot(normalize(dirToLight),normal)); + + out_Color += diffuse*vec4(vec3(I), 1.0)*vec4(color, 1.0); + + if (u_DisplayType == DISPLAY_SPEC) { + vec3 specRefl = 2.0 * dot(normal, dirToLight) * normal - dirToLight; + float specular = clamp(pow(dot(-position, specRefl), glow), 0.0, 1.0); + out_Color += glow*glow*specular*vec4(vec3(I), 1.0)*vec4(color,1.0); + } + } } + return; } diff --git a/base/res/shaders/post.frag b/base/res/shaders/post.frag index 2bf5afc..ef790a4 100644 --- a/base/res/shaders/post.frag +++ b/base/res/shaders/post.frag @@ -10,18 +10,25 @@ #define DISPLAY_COLOR 3 #define DISPLAY_TOTAL 4 #define DISPLAY_LIGHTS 5 +#define DISPLAY_AO 6 +#define DISPLAY_TOON 7 +#define DISPLAY_SPEC 8 +#define DISPLAY_GLOW 9 ///////////////////////////////////// // Uniforms, Attributes, and Outputs //////////////////////////////////// uniform sampler2D u_Posttex; +uniform sampler2D u_Glowtex; uniform sampler2D u_RandomNormaltex; uniform sampler2D u_RandomScalartex; uniform int u_ScreenWidth; uniform int u_ScreenHeight; +uniform int u_DisplayType; + in vec2 fs_Texcoord; out vec4 out_Color; @@ -43,6 +50,11 @@ vec3 sampleCol(vec2 texcoords) { return texture(u_Posttex,texcoords).xyz; } +//Helper function to automicatlly sample and unpack positions +vec3 sampleGlow(vec2 texcoords) { + return texture(u_Glowtex,texcoords).xyz; +} + //Get a random normal vector given a screen-space texture coordinate //Actually accesses a texture of random vectors vec3 getRandomNormal(vec2 texcoords) { @@ -68,7 +80,83 @@ void main() { vec3 color = sampleCol(fs_Texcoord); float gray = dot(color, vec3(0.2125, 0.7154, 0.0721)); float vin = min(2*distance(vec2(0.5), fs_Texcoord), 1.0); - out_Color = vec4(mix(pow(color,vec3(1.0/1.8)),vec3(gray),vin), 1.0); + vec3 glow = sampleGlow(fs_Texcoord); + + if (u_DisplayType == DISPLAY_GLOW) + { + vec2 glowWidth = textureSize(u_Glowtex, 0); + + int sz = 49; + float gaussKernel[49] = float[]( + 0.010463550522761987, + 0.01131615298268607, + 0.012197501949023151, + 0.013103742011676042, + 0.014030466903471261, + 0.014972739372363077, + 0.01592512163091689, + 0.016881716501857894, + 0.01783621912965036, + 0.018781978866145247, + 0.019712070670514083, + 0.020619375097847215, + 0.021496665695212178, + 0.022336702387036944, + 0.02313232922160704, + 0.023876574674941628, + 0.024562752574221497, + 0.02518456161604963, + 0.02573618141953292, + 0.026212363073296496, + 0.02660851221015391, + 0.026920762772496484, + 0.027146039812917307, + 0.02728210990372968, + 0.02732761799978166, + 0.02728210990372968, + 0.027146039812917307, + 0.026920762772496484, + 0.02660851221015391, + 0.026212363073296496, + 0.02573618141953292, + 0.02518456161604963, + 0.024562752574221497, + 0.023876574674941628, + 0.02313232922160704, + 0.022336702387036944, + 0.021496665695212178, + 0.020619375097847215, + 0.019712070670514083, + 0.018781978866145247, + 0.01783621912965036, + 0.016881716501857894, + 0.01592512163091689, + 0.014972739372363077, + 0.014030466903471261, + 0.013103742011676042, + 0.012197501949023151, + 0.01131615298268607, + 0.010463550522761987 + ); + + float accum = 0.0; + for (float i = -sz/2; i <= sz/2; i += 1.0) { + int index = int(i) + sz/2; + accum += gaussKernel[index] + * sampleGlow(vec2(fs_Texcoord.s + (i/glowWidth.x), fs_Texcoord.t)) + * sampleCol(vec2(fs_Texcoord.s + (i/glowWidth.x), fs_Texcoord.t)); + accum += gaussKernel[index] + * sampleGlow(vec2(fs_Texcoord.s, fs_Texcoord.t + (i/glowWidth.y))) + * sampleCol(vec2(fs_Texcoord.s, fs_Texcoord.t + (i/glowWidth.y))); + } + + vec3 c = accum + color; + out_Color = vec4(c, 1.0); + } + else + { + out_Color = vec4(color,1.0);//vec4(mix(pow(color,vec3(1.0/1.8)),vec3(gray),vin), 1.0); + } return; } diff --git a/base/res/shaders/toon.frag b/base/res/shaders/toon.frag new file mode 100644 index 0000000..4879f93 --- /dev/null +++ b/base/res/shaders/toon.frag @@ -0,0 +1,199 @@ +#version 330 + +//////////////////////////// +// 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 DISPLAY_AO 6 +#define DISPLAY_TOON 7 +#define DISPLAY_SPEC 8 + + +///////////////////////////////////// +// Uniforms, Attributes, and Outputs +//////////////////////////////////// +uniform mat4 u_Persp; + +uniform sampler2D u_Depthtex; +uniform sampler2D u_Normaltex; +uniform sampler2D u_Positiontex; +uniform sampler2D u_Colortex; +uniform sampler2D u_RandomNormaltex; +uniform sampler2D u_RandomScalartex; + +uniform float u_Far; +uniform float u_Near; +uniform int u_DisplayType; + +uniform int u_ScreenWidth; +uniform int u_ScreenHeight; + +uniform vec4 u_Light; +uniform float u_LightIl; + +in vec2 fs_Texcoord; + +out vec4 out_Color; +/////////////////////////////////////// + + + + +uniform float zerothresh = 1.0f; +uniform float falloff = 0.1f; + + +///////////////////////////////////// +// UTILITY FUNCTIONS +///////////////////////////////////// + +//Depth used in the Z buffer is not linearly related to distance from camera +//This restores linear depth +float linearizeDepth(float exp_depth, float near, float far) { + return (2 * near) / (far + near - exp_depth * (far - near)); +} + +//Helper function to automatically sample and unpack normals +vec3 sampleNrm(vec2 texcoords) { + return texture(u_Normaltex,texcoords).xyz; +} + +//Helper function to automicatlly sample and unpack positions +vec3 samplePos(vec2 texcoords) { + return texture(u_Positiontex,texcoords).xyz; +} + +//Helper function to automicatlly sample and unpack positions +vec3 sampleCol(vec2 texcoords) { + return texture(u_Colortex,texcoords).xyz; +} + +//Get a random normal vector given a screen-space texture coordinate +//Actually accesses a texture of random vectors +vec3 getRandomNormal(vec2 texcoords) { + ivec2 sz = textureSize(u_RandomNormaltex,0); + return texture(u_RandomNormaltex,vec2(texcoords.s* (u_ScreenWidth)/sz.x, + (texcoords.t)*(u_ScreenHeight)/sz.y)).rgb; +} + + +//Get a random scalar given a screen-space texture coordinate +//Fetches from a random texture +float getRandomScalar(vec2 texcoords) { + ivec2 sz = textureSize(u_RandomScalartex,0); + return texture(u_RandomScalartex,vec2(texcoords.s*u_ScreenWidth/sz.x, + texcoords.t*u_ScreenHeight/sz.y)).r; +} + +/////////////////////////////////// +// MAIN +////////////////////////////////// +const float occlusion_strength = 1.5f; +void main() { + + float exp_depth = texture(u_Depthtex, fs_Texcoord).r; + float lin_depth = linearizeDepth(exp_depth,u_Near,u_Far); + + vec3 normal = sampleNrm(fs_Texcoord); + vec3 position = samplePos(fs_Texcoord); + vec3 color = sampleCol(fs_Texcoord); + + // ambient light data + vec3 light = u_Light.xyz; + float strength = u_Light.w; + + // computer SSAO (screen space ambient occlusion) + // float occl = sampleBlurredDepth(fs_Texcoord); + + vec2 sz = textureSize(u_Positiontex, 0); + + float hup = 0.0; float tup = 0.0; + float hdown = 0.0; float tdown = 0.0; + float hleft = 0.0; float tleft = 0.0; + float hright = 0.0; float tright = 0.0; + + for (float i = 1.0; i <= 6.0; i += 1.0) { + + // neighbor positions + vec3 posUp = samplePos(vec2(fs_Texcoord.s, fs_Texcoord.t + (1.0 / sz.y))); + vec3 posDown = samplePos(vec2(fs_Texcoord.s, fs_Texcoord.t - (1.0 / sz.y))); + vec3 posRight = samplePos(vec2(fs_Texcoord.s + (1.0 / sz.y), fs_Texcoord.t)); + vec3 posLeft = samplePos(vec2(fs_Texcoord.s - (1.0 / sz.y), fs_Texcoord.t)); + + // up occlusion + vec3 Hup = posUp - position; + vec3 Tup = cross(normal, vec3(0,1,0)); + if (Hup.z > 0.01) { + hup += atan(Hup.z / length(Hup.xy)) / 6.0; + tup += atan(Tup.z / length(Tup.xy)) / 6.0; + } + + // down occlusion + vec3 Hdown = posDown - position; + vec3 Tdown = cross(normal, vec3(0,-1,0)); + if (Hdown.z > 0.01) { + hdown += atan(Hdown.z / length(Hdown.xy)) / 6.0; + tdown += atan(Tdown.z / length(Tdown.xy)) / 6.0; + } + + // right occlusion + vec3 Hright = posRight - position; + vec3 Tright = cross(normal, vec3(1,0,0)); + if (Hright.z > 0.01) { + hright += atan(Hright.z / length(Hright.xy)) / 6.0; + tright += atan(Tright.z / length(Tright.xy)) / 6.0; + } + + // left occlusion + vec3 Hleft = posLeft - position; + vec3 Tleft = cross(normal, vec3(-1,0,0)); + if (Hleft.z > 0.01) { + hleft += atan(Hleft.z / length(Hleft.xy)) / 6.0; + tleft += atan(Tleft.z / length(Tleft.xy)) / 6.0; + } + } + + // ambient occlusion term + float occl = (sin(hup) - sin(tup)) / 4.0 + (sin(hdown) - sin(tdown)) / 4.0 + (sin(hright) - sin(tright)) / 4.0 + (sin(hleft) - sin(tleft)) / 4.0; + + if( u_DisplayType == DISPLAY_TOON ) { + + ivec2 sz = textureSize(u_Normaltex,0); + vec3 normal_up = sampleNrm(vec2(fs_Texcoord.x+(1.0/sz.x), fs_Texcoord.y)); + vec3 normal_down = sampleNrm(vec2(fs_Texcoord.x-(1.0/sz.x), fs_Texcoord.y)); + vec3 normal_right = sampleNrm(vec2(fs_Texcoord.x, fs_Texcoord.y+(1.0/sz.y))); + vec3 normal_left = sampleNrm(vec2(fs_Texcoord.x, fs_Texcoord.y-(1.0/sz.y))); + + if ( dot(normal, normal_up) <= 0.96 || + dot(normal, normal_down) <= 0.96 || + dot(normal, normal_right) <= 0.96 || + dot(normal, normal_left) <= 0.96) + { + out_Color = vec4(vec3(0), 1.0f); + } + + else + { + float ambient = u_LightIl; + float diffuse = max(0.0, dot(normalize(light),normal)); + + // toon shading of ambient + if (diffuse <= 0.1) { diffuse = 0.2; } + else if (diffuse <= 0.3) { diffuse = 0.4; } + else if (diffuse <= 0.5) { diffuse = 0.6; } + else if (diffuse <= 0.7) { diffuse = 0.8; } + else { diffuse = 1.0; } + + out_Color = vec4(color*(strength*diffuse + ambient*(1.0-occl)),1.0f); + } + } + + return; +} + diff --git a/base/src/main.cpp b/base/src/main.cpp index 9a0f6a0..f4234da 100644 --- a/base/src/main.cpp +++ b/base/src/main.cpp @@ -211,7 +211,9 @@ GLuint depthTexture = 0; GLuint normalTexture = 0; GLuint positionTexture = 0; GLuint colorTexture = 0; +GLuint glowTexture = 0; GLuint postTexture = 0; +GLuint toonTexture = 0; GLuint FBO[2] = {0, 0}; @@ -219,6 +221,7 @@ GLuint pass_prog; GLuint point_prog; GLuint ambient_prog; GLuint diagnostic_prog; +GLuint toon_prog; GLuint post_prog; void initShader() { #ifdef WIN32 @@ -230,6 +233,7 @@ void initShader() { const char * diagnostic_frag = "../../../res/shaders/diagnostic.frag"; const char * ambient_frag = "../../../res/shaders/ambient.frag"; const char * point_frag = "../../../res/shaders/point.frag"; + const char * toon_frag = "../../../res/shaders/toon.frag"; const char * post_frag = "../../../res/shaders/post.frag"; #else const char * pass_vert = "../res/shaders/pass.vert"; @@ -240,8 +244,13 @@ void initShader() { const char * diagnostic_frag = "../res/shaders/diagnostic.frag"; const char * ambient_frag = "../res/shaders/ambient.frag"; const char * point_frag = "../res/shaders/point.frag"; + const char * toon_frag = "../res/shaders/toon.frag"; const char * post_frag = "../res/shaders/post.frag"; #endif + + //------------------------------------------------------------------------------- + // pass shader program + //------------------------------------------------------------------------------- Utility::shaders_t shaders = Utility::loadShaders(pass_vert, pass_frag); pass_prog = glCreateProgram(); @@ -252,6 +261,9 @@ void initShader() { Utility::attachAndLinkProgram(pass_prog,shaders); + //------------------------------------------------------------------------------- + // disgnostics shader program + //------------------------------------------------------------------------------- shaders = Utility::loadShaders(shade_vert, diagnostic_frag); diagnostic_prog = glCreateProgram(); @@ -260,7 +272,10 @@ void initShader() { glBindAttribLocation(diagnostic_prog, quad_attributes::TEXCOORD, "Texcoord"); Utility::attachAndLinkProgram(diagnostic_prog, shaders); - + + //------------------------------------------------------------------------------- + // ambient shader program + //------------------------------------------------------------------------------- shaders = Utility::loadShaders(shade_vert, ambient_frag); ambient_prog = glCreateProgram(); @@ -269,7 +284,10 @@ void initShader() { glBindAttribLocation(ambient_prog, quad_attributes::TEXCOORD, "Texcoord"); Utility::attachAndLinkProgram(ambient_prog, shaders); - + + //------------------------------------------------------------------------------- + // point shader program + //------------------------------------------------------------------------------- shaders = Utility::loadShaders(shade_vert, point_frag); point_prog = glCreateProgram(); @@ -278,7 +296,22 @@ void initShader() { glBindAttribLocation(point_prog, quad_attributes::TEXCOORD, "Texcoord"); Utility::attachAndLinkProgram(point_prog, shaders); + + //------------------------------------------------------------------------------- + // toon shader program + //------------------------------------------------------------------------------- + shaders = Utility::loadShaders(shade_vert, toon_frag); + + toon_prog = glCreateProgram(); + + glBindAttribLocation(point_prog, quad_attributes::POSITION, "Position"); + glBindAttribLocation(point_prog, quad_attributes::TEXCOORD, "Texcoord"); + Utility::attachAndLinkProgram(toon_prog, shaders); + + //------------------------------------------------------------------------------- + // post shader program + //------------------------------------------------------------------------------- shaders = Utility::loadShaders(post_vert, post_frag); post_prog = glCreateProgram(); @@ -294,6 +327,7 @@ void freeFBO() { glDeleteTextures(1,&normalTexture); glDeleteTextures(1,&positionTexture); glDeleteTextures(1,&colorTexture); + glDeleteTextures(1,&glowTexture); glDeleteTextures(1,&postTexture); glDeleteFramebuffers(1,&FBO[0]); glDeleteFramebuffers(1,&FBO[1]); @@ -366,6 +400,7 @@ void initFBO(int w, int h) { glGenTextures(1, &normalTexture); glGenTextures(1, &positionTexture); glGenTextures(1, &colorTexture); + glGenTextures(1, &glowTexture); //Set up depth FBO glBindTexture(GL_TEXTURE_2D, depthTexture); @@ -410,6 +445,17 @@ void initFBO(int w, int h) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB32F , w, h, 0, GL_RGBA, GL_FLOAT,0); + + //Set up color FBO + glBindTexture(GL_TEXTURE_2D, glowTexture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB32F , w, h, 0, GL_RGBA, GL_FLOAT,0); // creatwwe a framebuffer object @@ -420,12 +466,14 @@ void initFBO(int w, int h) { glReadBuffer(GL_NONE); GLint normal_loc = glGetFragDataLocation(pass_prog,"out_Normal"); GLint position_loc = glGetFragDataLocation(pass_prog,"out_Position"); + GLint glow_loc = glGetFragDataLocation(pass_prog,"out_Glow"); GLint color_loc = glGetFragDataLocation(pass_prog,"out_Color"); - GLenum draws [3]; + GLenum draws [4]; draws[normal_loc] = GL_COLOR_ATTACHMENT0; draws[position_loc] = GL_COLOR_ATTACHMENT1; - draws[color_loc] = GL_COLOR_ATTACHMENT2; - glDrawBuffers(3, draws); + draws[glow_loc] = GL_COLOR_ATTACHMENT2; + draws[color_loc] = GL_COLOR_ATTACHMENT3; + glDrawBuffers(4, draws); // attach the texture to FBO depth attachment point int test = GL_COLOR_ATTACHMENT0; @@ -435,6 +483,8 @@ void initFBO(int w, int h) { glFramebufferTexture(GL_FRAMEBUFFER, draws[normal_loc], normalTexture, 0); glBindTexture(GL_TEXTURE_2D, positionTexture); glFramebufferTexture(GL_FRAMEBUFFER, draws[position_loc], positionTexture, 0); + glBindTexture(GL_TEXTURE_2D, glowTexture); + glFramebufferTexture(GL_FRAMEBUFFER, draws[glow_loc], glowTexture, 0); glBindTexture(GL_TEXTURE_2D, colorTexture); glFramebufferTexture(GL_FRAMEBUFFER, draws[color_loc], colorTexture, 0); @@ -589,7 +639,7 @@ void draw_mesh() { glUniformMatrix4fv(glGetUniformLocation(pass_prog,"u_Persp"),1,GL_FALSE,&persp[0][0]); glUniformMatrix4fv(glGetUniformLocation(pass_prog,"u_InvTrans") ,1,GL_FALSE,&inverse_transposed[0][0]); - for(int i=0; i= -6.0f; j -= 0.75f) { + for (float k = 0.2f; k <= 6.0f; k += 0.85f) { + draw_light(vec3(i,j,k), 0.5f, sc, vp, NEARP); + } + } + } + + glDisable(GL_SCISSOR_TEST); + vec4 dir_light(0.1, 1.0, 1.0, 0.0); + dir_light = cam.get_view() * dir_light; + dir_light = normalize(dir_light); + dir_light.w = 0.3f; + float strength = 0.09f; + setup_quad(ambient_prog); + glUniform4fv(glGetUniformLocation(ambient_prog, "u_Light"), 1, &(dir_light[0])); + glUniform1f(glGetUniformLocation(ambient_prog, "u_LightIl"), strength); + draw_quad(); + } + else if (display_type == DISPLAY_TOON) + { + setup_quad(point_prog); + + if(doIScissor) glEnable(GL_SCISSOR_TEST); + mat4 vp = perspective(45.0f,(float)width/(float)height,NEARP,FARP) * + cam.get_view(); + mat4 sc = mat4(width, 0.0, 0.0, 0.0, + 0.0, height, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0) * + mat4(0.5, 0.0, 0.0, 0.0, + 0.0, 0.5, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.5, 0.5, 0.0, 1.0); + for (float i = 0.2f; i <= 6.0f; i += 0.85f) { + for (float j = -0.0f; j >= -6.0f; j -= 0.75f) { + for (float k = 0.2f; k <= 6.0f; k += 0.85f) { + draw_light(vec3(i,j,k), 0.5f, sc, vp, NEARP); + } + } + } + + glDisable(GL_SCISSOR_TEST); + vec4 dir_light(0.1, 1.0, 1.0, 0.0); + dir_light = cam.get_view() * dir_light; + dir_light = normalize(dir_light); + dir_light.w = 0.3f; + float strength = 0.09f; + setup_quad(toon_prog); + glUniform4fv(glGetUniformLocation(toon_prog, "u_Light"), 1, &(dir_light[0])); + glUniform1f(glGetUniformLocation(toon_prog, "u_LightIl"), strength); + + draw_quad(); + } + else if (display_type == DISPLAY_AO) + { glDisable(GL_SCISSOR_TEST); vec4 dir_light(0.1, 1.0, 1.0, 0.0); dir_light = cam.get_view() * dir_light; dir_light = normalize(dir_light); - dir_light.w = 0.3; - float strength = 0.09; + dir_light.w = 0.3f; + float strength = 0.09f; setup_quad(ambient_prog); glUniform4fv(glGetUniformLocation(ambient_prog, "u_Light"), 1, &(dir_light[0])); glUniform1f(glGetUniformLocation(ambient_prog, "u_LightIl"), strength); draw_quad(); } - else + else { setup_quad(diagnostic_prog); draw_quad(); @@ -808,9 +929,14 @@ void display(void) glActiveTexture(GL_TEXTURE5); glBindTexture(GL_TEXTURE_2D, random_scalar_tex); glUniform1i(glGetUniformLocation(post_prog, "u_RandomScalartex"),5); + + glActiveTexture(GL_TEXTURE6); + glBindTexture(GL_TEXTURE_2D, glowTexture); + glUniform1i(glGetUniformLocation(post_prog, "u_Glowtex"),6); glUniform1i(glGetUniformLocation(post_prog, "u_ScreenHeight"), height); glUniform1i(glGetUniformLocation(post_prog, "u_ScreenWidth"), width); + glUniform1i(glGetUniformLocation(post_prog, "u_DisplayType"), display_type); draw_quad(); glEnable(GL_DEPTH_TEST); @@ -868,30 +994,30 @@ void motion(int x, int y) } void keyboard(unsigned char key, int x, int y) { - float tx = 0; - float ty = 0; - float tz = 0; + float tx = 0.0f; + float ty = 0.0f; + float tz = 0.0f; switch(key) { case(27): - exit(0.0); + exit(0); break; case('w'): - tz = 0.1; + tz = 0.1f; break; case('s'): - tz = -0.1; + tz = -0.1f; break; case('d'): - tx = -0.1; + tx = -0.1f; break; case('a'): - tx = 0.1; + tx = 0.1f; break; case('q'): - ty = 0.1; + ty = 0.1f; break; case('z'): - ty = -0.1; + ty = -0.1f; break; case('1'): display_type = DISPLAY_DEPTH; @@ -908,6 +1034,18 @@ void keyboard(unsigned char key, int x, int y) { case('5'): display_type = DISPLAY_LIGHTS; break; + case('6'): + display_type = DISPLAY_AO; + break; + case('7'): + display_type = DISPLAY_TOON; + break; + case('8'): + display_type = DISPLAY_SPEC; + break; + case('9'): + display_type = DISPLAY_GLOW; + break; case('0'): display_type = DISPLAY_TOTAL; break; diff --git a/base/src/main.h b/base/src/main.h index 0a96a3a..aa74f0c 100644 --- a/base/src/main.h +++ b/base/src/main.h @@ -83,7 +83,11 @@ enum Display { DISPLAY_POSITION = 2, DISPLAY_COLOR = 3, DISPLAY_TOTAL = 4, - DISPLAY_LIGHTS = 5 + DISPLAY_LIGHTS = 5, + DISPLAY_AO = 6, + DISPLAY_TOON = 7, + DISPLAY_SPEC = 8, + DISPLAY_GLOW = 9 }; char* loadFile(char *fname, GLint &fSize); diff --git a/readme_imgs/AOpass.png b/readme_imgs/AOpass.png new file mode 100644 index 0000000..ce0fdab Binary files /dev/null and b/readme_imgs/AOpass.png differ diff --git a/readme_imgs/bloom0.png b/readme_imgs/bloom0.png new file mode 100644 index 0000000..b3f1cee Binary files /dev/null and b/readme_imgs/bloom0.png differ diff --git a/readme_imgs/bloom1.png b/readme_imgs/bloom1.png new file mode 100644 index 0000000..fde8cf7 Binary files /dev/null and b/readme_imgs/bloom1.png differ diff --git a/readme_imgs/bloom2.png b/readme_imgs/bloom2.png new file mode 100644 index 0000000..ebd4553 Binary files /dev/null and b/readme_imgs/bloom2.png differ diff --git a/readme_imgs/box_notoon1.png b/readme_imgs/box_notoon1.png new file mode 100644 index 0000000..1d4f486 Binary files /dev/null and b/readme_imgs/box_notoon1.png differ diff --git a/readme_imgs/box_toon1.png b/readme_imgs/box_toon1.png new file mode 100644 index 0000000..e360745 Binary files /dev/null and b/readme_imgs/box_toon1.png differ diff --git a/readme_imgs/color.png b/readme_imgs/color.png new file mode 100644 index 0000000..9f0b98d Binary files /dev/null and b/readme_imgs/color.png differ diff --git a/readme_imgs/diffuse_vs_specular.png b/readme_imgs/diffuse_vs_specular.png new file mode 100644 index 0000000..a0a339e Binary files /dev/null and b/readme_imgs/diffuse_vs_specular.png differ diff --git a/readme_imgs/header.png b/readme_imgs/header.png new file mode 100644 index 0000000..32c9e4a Binary files /dev/null and b/readme_imgs/header.png differ diff --git a/readme_imgs/kernel_fps_chart.png b/readme_imgs/kernel_fps_chart.png new file mode 100644 index 0000000..c92d10e Binary files /dev/null and b/readme_imgs/kernel_fps_chart.png differ diff --git a/readme_imgs/kernel_fps_graph.png b/readme_imgs/kernel_fps_graph.png new file mode 100644 index 0000000..3d3d1d7 Binary files /dev/null and b/readme_imgs/kernel_fps_graph.png differ diff --git a/readme_imgs/kernel_shapes.png b/readme_imgs/kernel_shapes.png new file mode 100644 index 0000000..8e0ed69 Binary files /dev/null and b/readme_imgs/kernel_shapes.png differ diff --git a/readme_imgs/luminance.png b/readme_imgs/luminance.png new file mode 100644 index 0000000..fcea53a Binary files /dev/null and b/readme_imgs/luminance.png differ diff --git a/readme_imgs/no_occlusion.png b/readme_imgs/no_occlusion.png new file mode 100644 index 0000000..3f1e91d Binary files /dev/null and b/readme_imgs/no_occlusion.png differ diff --git a/readme_imgs/no_occlusion2.png b/readme_imgs/no_occlusion2.png new file mode 100644 index 0000000..93d59dc Binary files /dev/null and b/readme_imgs/no_occlusion2.png differ diff --git a/readme_imgs/no_occlusion3.png b/readme_imgs/no_occlusion3.png new file mode 100644 index 0000000..3d2c9bf Binary files /dev/null and b/readme_imgs/no_occlusion3.png differ diff --git a/readme_imgs/no_toon.png b/readme_imgs/no_toon.png new file mode 100644 index 0000000..0941384 Binary files /dev/null and b/readme_imgs/no_toon.png differ diff --git a/readme_imgs/normals.png b/readme_imgs/normals.png new file mode 100644 index 0000000..37bbe3d Binary files /dev/null and b/readme_imgs/normals.png differ diff --git a/readme_imgs/occlusion.png b/readme_imgs/occlusion.png new file mode 100644 index 0000000..3a90d2f Binary files /dev/null and b/readme_imgs/occlusion.png differ diff --git a/readme_imgs/occlusion2.png b/readme_imgs/occlusion2.png new file mode 100644 index 0000000..c4c91c9 Binary files /dev/null and b/readme_imgs/occlusion2.png differ diff --git a/readme_imgs/occlusion3.png b/readme_imgs/occlusion3.png new file mode 100644 index 0000000..3aaa846 Binary files /dev/null and b/readme_imgs/occlusion3.png differ diff --git a/readme_imgs/occlusion_demo.png b/readme_imgs/occlusion_demo.png new file mode 100644 index 0000000..4eb297f Binary files /dev/null and b/readme_imgs/occlusion_demo.png differ diff --git a/readme_imgs/position.png b/readme_imgs/position.png new file mode 100644 index 0000000..1a943a6 Binary files /dev/null and b/readme_imgs/position.png differ diff --git a/readme_imgs/toon.png b/readme_imgs/toon.png new file mode 100644 index 0000000..5edc4cc Binary files /dev/null and b/readme_imgs/toon.png differ diff --git a/readme_imgs/toon1.png b/readme_imgs/toon1.png new file mode 100644 index 0000000..b122171 Binary files /dev/null and b/readme_imgs/toon1.png differ diff --git a/readme_imgs/toon_side_by_side.png b/readme_imgs/toon_side_by_side.png new file mode 100644 index 0000000..f595672 Binary files /dev/null and b/readme_imgs/toon_side_by_side.png differ diff --git a/readme_imgs/toon_side_by_side2.png b/readme_imgs/toon_side_by_side2.png new file mode 100644 index 0000000..2fabcf9 Binary files /dev/null and b/readme_imgs/toon_side_by_side2.png differ diff --git a/readme_imgs/with_specular.png b/readme_imgs/with_specular.png new file mode 100644 index 0000000..b7f7489 Binary files /dev/null and b/readme_imgs/with_specular.png differ diff --git a/readme_imgs/without_specular.png b/readme_imgs/without_specular.png new file mode 100644 index 0000000..21a2a0e Binary files /dev/null and b/readme_imgs/without_specular.png differ diff --git a/readme_imgs/zdepth.png b/readme_imgs/zdepth.png new file mode 100644 index 0000000..1f325c2 Binary files /dev/null and b/readme_imgs/zdepth.png differ