diff --git a/README.md b/README.md index f22c764..2188eb5 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,27 @@ ------------------------------------------------------------------------------- CIS565: Project 6: Deferred Shader ------------------------------------------------------------------------------- -Fall 2013 -------------------------------------------------------------------------------- -Due Friday 11/15/2013 -------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -NOTE: +RESULTS: ------------------------------------------------------------------------------- -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. - +![result](screenshots/cornell_box_normals.png) +![result](screenshots/cornell_box_depth.png) +![result](screenshots/cornell_box_toon.png) +![result](screenshots/cornell_box_bloom.png) +![result](screenshots/cornell_box_aa_diffuse.png) +![result](screenshots/cornell_box_specular.png) +![result](screenshots/cornell_box_diffuse_specular.png) +![result](screenshots/sponza_light.png) +![result](screenshots/sponza_normal.png) +![result](screenshots/sponza_toon.png) +![result](screenshots/sponza_bloom.png) +![result](screenshots/sponza_diffuse_specular.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. +In this project, I worked on implementing the basics of deferred shading. This is implemented with GLSL and OpenGL where various tasks such as +creating and writing to the G-Buffer were performed. Stage 1 renders the scene geometry to the G-Buffer * pass.vert @@ -67,8 +37,7 @@ 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. +Key binding overview: WASDQZ - Movement X - Toggle scissor test R - Reload shaders @@ -76,115 +45,37 @@ R - Reload shaders 2 - View eye space normals 3 - View Diffuse color 4 - View eye space positions -5 - View lighting debug mode +5 - View lighting +6 - View toon shading with silhouettes +7 - View scene with bloom effect +8 - View scene with anti-aliasing and diffuse lighting +9 - View specular map 0 - Standard view ------------------------------------------------------------------------------- -REQUIREMENTS: +FEATURES: ------------------------------------------------------------------------------- -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 +In this project, I have implemented the following features: -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). - -------------------------------------------------------------------------------- -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 http://www.microsoft.com/expression/products/Encoder4_Overview.aspx -* A performance evaluation (described in detail below). +* Bloom effect with one pass and two pass convolution +* Toon shading with silhouettes +* Displaying point light sources +* Additional G buffer slot to store specular map +* Anti-aliasing via averaging on contours ------------------------------------------------------------------------------- -PERFORMANCE EVALUATION +PERFORMANCE ANALYSIS ------------------------------------------------------------------------------- -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. +I made a run time comparison between the one pass and two pass convolution techniques. Below is the chart that displays +the results. -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. +![result](screenshots/perf_analysis.png) -------------------------------------------------------------------------------- -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 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 +As seen from above, when the size of the gaussian kernel is small, simply performing a one pass convolution is sufficient. However, +once the size increases past a certain point, the advantage of the two pass convolution technique becomes apparent. -* 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/base/PROJ_NIX/makefile b/base/PROJ_NIX/makefile deleted file mode 100755 index 195ef71..0000000 --- a/base/PROJ_NIX/makefile +++ /dev/null @@ -1,30 +0,0 @@ -LFLAGS := -lglut -lGL -lGLEW -CFLAGS := -Wall -IFLAGS := -I../../shared32/glm/ -I../../shared32/freeglut -I../../shared32/glew -I../src/SOIL -I../src/tiny_obj_loader - -565DefferedShader: Utility.o tiny_obj_loader.o main.o image_helper.o stb_image_aug.o image_DXT.o SOIL.o - g++ *.o -o 565DefferedShader $(LFLAGS) - -tiny_obj_loader.o: ../src/tiny_obj_loader/tiny_obj_loader.cc ../src/tiny_obj_loader/tiny_obj_loader.h - g++ ../src/tiny_obj_loader/tiny_obj_loader.cc -c - -SOIL.o: ../src/SOIL/SOIL.c ../src/SOIL/*.h - gcc ../src/SOIL/SOIL.c -c - -image_DXT.o: ../src/SOIL/image_DXT.c ../src/SOIL/*.h - gcc ../src/SOIL/image_DXT.c -c - -stb_image_aug.o: ../src/SOIL/stb_image_aug.c ../src/SOIL/*.h - gcc ../src/SOIL/stb_image_aug.c -c - -image_helper.o: ../src/SOIL/image_helper.c ../src/SOIL/*.h - gcc ../src/SOIL/image_helper.c -c - -main.o: ../src/main.cpp ../src/main.h ../src/Utility.h - g++ -g ../src/main.cpp $(IFLAGS) -c - -Utility.o: ../src/Utility.cpp ../src/Utility.h - g++ ../src/Utility.cpp $(IFLAGS) -c - -clean: - rm *.o 565DefferedShader diff --git a/base/PROJ_WIN/P6/P6/P6.vcxproj b/base/PROJ_WIN/P6/P6/P6.vcxproj index 61a6915..0d4ec91 100644 --- a/base/PROJ_WIN/P6/P6/P6.vcxproj +++ b/base/PROJ_WIN/P6/P6/P6.vcxproj @@ -19,12 +19,14 @@ Application true Unicode + v110 Application false true Unicode + v110 @@ -49,7 +51,7 @@ true - $(SolutionDir)$(Configuration);..\..\..\..\shared32\glew\lib;..\..\..\..\shared32\freeglut\lib;%(AdditionalLibraryDirectories) + $(SolutionDir)$(Configuration);..\..\..\..\shared32\glew\lib;..\..\..\..\shared32\freeglut\lib;..\debug\;%(AdditionalLibraryDirectories) SOIL.lib;freeglut.lib;glew32.lib;%(AdditionalDependencies) Console @@ -66,23 +68,27 @@ true true true - $(SolutionDir)$(Configuration);..\..\..\..\shared32\glew\lib;..\..\..\..\shared32\freeglut\lib;%(AdditionalLibraryDirectories) - freeglut.lib;glew32.lib;%(AdditionalDependencies) + $(SolutionDir)$(Configuration);..\..\..\..\shared32\glew\lib;..\..\..\..\shared32\freeglut\lib;..\release\;%(AdditionalLibraryDirectories) + freeglut.lib;glew32.lib;SOIL.lib;%(AdditionalDependencies) Console + + + + diff --git a/base/PROJ_WIN/P6/P6/P6.vcxproj.filters b/base/PROJ_WIN/P6/P6/P6.vcxproj.filters index 8fd6655..1d47685 100644 --- a/base/PROJ_WIN/P6/P6/P6.vcxproj.filters +++ b/base/PROJ_WIN/P6/P6/P6.vcxproj.filters @@ -27,6 +27,9 @@ tinyobjloader + + Source Files + @@ -38,6 +41,9 @@ Header Files + + Header Files + @@ -67,5 +73,11 @@ Resource Files + + Resource Files + + + Resource Files + \ No newline at end of file diff --git a/base/PROJ_WIN/P6/SOIL/SOIL.vcxproj b/base/PROJ_WIN/P6/SOIL/SOIL.vcxproj index f341f68..2cff1d2 100644 --- a/base/PROJ_WIN/P6/SOIL/SOIL.vcxproj +++ b/base/PROJ_WIN/P6/SOIL/SOIL.vcxproj @@ -20,10 +20,12 @@ StaticLibrary Unicode true + v110 StaticLibrary Unicode + v110 diff --git a/base/res/cornell/cornell_box.mtl b/base/res/cornell/cornell_box.mtl index aae8474..fbb9e40 100644 --- a/base/res/cornell/cornell_box.mtl +++ b/base/res/cornell/cornell_box.mtl @@ -2,23 +2,52 @@ newmtl white Ka 0 0 0 Kd 0.9 0.9 0.9 Ks 0 0 0 +Ns 0.0 newmtl red Ka 0 0 0 Kd 1 0 0 Ks 0 0 0 +Ns 0.0 newmtl green Ka 0 0 0 Kd 0 1 0 Ks 0 0 0 +Ns 0.0 newmtl blue Ka 0 0 0 Kd 0 0 1 Ks 0 0 0 +Ns 0.0 newmtl light Ka 20 20 20 Kd 1 1 1 Ks 0 0 0 +Ns 0.0 + +newmtl lightblue +Ka 0 0 0 +Kd 0.529 0.807 0.980 +Ks 0 0 0 +Ns 0.9 + +newmtl cyan +Ka 0 0 0 +Kd 0 1 1 +Ks 0 0 0 +Ns 0.0 + +newmtl yellow +Ka 0 0 0 +Kd 1 1 0 +Ks 0 0 0 +Ns 0.0 + +newmtl orange +Ka 0 0 0 +Kd 1 0.8 0 +Ks 0 0 0 +Ns 0.9 \ No newline at end of file diff --git a/base/res/cornell/cornell_box.obj b/base/res/cornell/cornell_box.obj index 43e021f..eb21e94 100644 --- a/base/res/cornell/cornell_box.obj +++ b/base/res/cornell/cornell_box.obj @@ -77,7 +77,7 @@ v 556.0 548.8 0.0 f -4 -3 -2 -1 o short_block -usemtl white +usemtl lightblue v 130.0 165.0 65.0 v 82.0 165.0 225.0 @@ -110,7 +110,7 @@ v 82.0 0.0 225.0 f -4 -3 -2 -1 o tall_block -usemtl white +usemtl orange v 423.0 330.0 247.0 v 265.0 330.0 296.0 @@ -118,7 +118,7 @@ v 314.0 330.0 456.0 v 472.0 330.0 406.0 f -4 -3 -2 -1 -usemtl white +usemtl orange v 423.0 0.0 247.0 v 423.0 330.0 247.0 v 472.0 330.0 406.0 diff --git a/base/res/cornell/cube.mtl b/base/res/cornell/cube.mtl index d3a1c7a..bd1b122 100644 --- a/base/res/cornell/cube.mtl +++ b/base/res/cornell/cube.mtl @@ -2,23 +2,28 @@ newmtl white Ka 0 0 0 Kd 1 1 1 Ks 0 0 0 +Ns 0 newmtl red Ka 0 0 0 Kd 1 0 0 Ks 0 0 0 +Ns 0 newmtl green Ka 0 0 0 Kd 0 1 0 Ks 0 0 0 +Ns 0 newmtl blue Ka 0 0 0 Kd 0 0 1 Ks 0 0 0 +Ns 0 newmtl light Ka 20 20 20 Kd 1 1 1 Ks 0 0 0 +Ns 0 diff --git a/base/res/shaders/ambient.frag b/base/res/shaders/ambient.frag index 69b878c..f32faf1 100644 --- a/base/res/shaders/ambient.frag +++ b/base/res/shaders/ambient.frag @@ -1,7 +1,7 @@ #version 330 //////////////////////////// -// ENUMERATIONS +// ENUMERATIONS //////////////////////////// #define DISPLAY_DEPTH 0 @@ -10,7 +10,10 @@ #define DISPLAY_COLOR 3 #define DISPLAY_TOTAL 4 #define DISPLAY_LIGHTS 5 - +#define DISPLAY_TOON 6 +#define DISPLAY_BLOOM 7 +#define DISPLAY_AA 8 +#define DISPLAY_SPECULAR 9 ///////////////////////////////////// // Uniforms, Attributes, and Outputs @@ -37,7 +40,9 @@ uniform float u_LightIl; in vec2 fs_Texcoord; -out vec4 out_Color; +out vec4 out_Color; // diffuse only +out vec4 out_Spec; +out vec4 out_BloomMap; /////////////////////////////////////// @@ -48,7 +53,7 @@ uniform float falloff = 0.1f; ///////////////////////////////////// -// UTILITY FUNCTIONS +// UTILITY FUNCTIONS ///////////////////////////////////// //Depth used in the Z buffer is not linearly related to distance from camera @@ -89,6 +94,23 @@ float getRandomScalar(vec2 texcoords) { texcoords.t*u_ScreenHeight/sz.y)).r; } +// Get toon color, given the current color and intensity of the light on the surface +vec3 getToonColor(float intensity, vec3 color) +{ + vec3 toonColor = vec3(0,0,0); + + if (intensity > 0.95) + toonColor = color; + else if (intensity > 0.5) + toonColor = 0.6 * color; + else if (intensity > 0.25) + toonColor = 0.4 * color; + else + toonColor = 0.2 * color; + + return toonColor; +} + /////////////////////////////////// // MAIN ////////////////////////////////// @@ -103,13 +125,46 @@ void main() { vec3 color = sampleCol(fs_Texcoord); 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); - } + + if (u_DisplayType == DISPLAY_LIGHTS) + { + out_Color = vec4(0,0,0,1); + } + else if (u_DisplayType != DISPLAY_TOON) + { + 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); + } + } + else // Ambient Toon Shading + { + float intensity = max(0.0, dot(normalize(light-position),normal)); + vec3 toonAmbColor = vec3(0.1,0.1,0.1); + vec3 toonColor = getToonColor(intensity, toonAmbColor); + out_Color = vec4(toonColor, 1.0f); + } + + if (u_DisplayType == DISPLAY_BLOOM) // Look here: Alpha value is being used to mark if an object will be bloomed or not + { + vec4 origColor = texture(u_Colortex, fs_Texcoord); + float shiny = origColor.a; + if (shiny >= 1 || shiny == 0) + out_BloomMap = vec4(0,0,0,0); + else + out_BloomMap = origColor; + } + else + { + out_BloomMap = vec4(0,0,0,0); + } + + + // No specular contribution for ambient + out_Spec = vec4(0,0,0,0); return; } diff --git a/base/res/shaders/bloomPass1.frag b/base/res/shaders/bloomPass1.frag new file mode 100644 index 0000000..6e66aed --- /dev/null +++ b/base/res/shaders/bloomPass1.frag @@ -0,0 +1,79 @@ +#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_TOON 6 +#define DISPLAY_BLOOM 7 +#define DISPLAY_AA 8 +#define DISPLAY_SPECULAR 9 + +///////////////////////////////////// +// Uniforms, Attributes, and Outputs +//////////////////////////////////// + +uniform sampler2D u_BloomMapTex; + + +uniform int u_ScreenWidth; +uniform int u_ScreenHeight; + +uniform int u_DisplayType; +uniform int u_Bound = 18; + +in vec2 fs_Texcoord; + +out vec4 out_Color; +/////////////////////////////////////// + + +uniform float zerothresh = 1.0; +uniform float falloff = 0.1; + + +// return the resulting color +vec3 applyHorzGaussianFilter(vec2 texcoords) +{ + float pi = 3.141592653589; + float sigma = 50.0; + + float sum = 0; // for normalization + float s = 2.0 * sigma * sigma; + vec3 result = vec3(0,0,0); + + int bound = u_Bound; + + for (int x = -bound ; x <= bound ; ++x) + { + float r = x*x; + float w = (exp(-r / s)) / (pi * s); + sum += w; + + ivec2 texSize = textureSize(u_BloomMapTex, 0); + float texOffsetS = float(x - 1) / float(texSize.x); + float texOffsetT = 0; + vec3 color = w * texture(u_BloomMapTex, texcoords + vec2(texOffsetS, texOffsetT)).rgb; + result += color; + } + + return result * (1 / sum); +} + + + +/////////////////////////////////// +// MAIN +////////////////////////////////// + +void main() { + + out_Color = vec4(applyHorzGaussianFilter(fs_Texcoord), 1); + return; +} diff --git a/base/res/shaders/bloomPass1.vert b/base/res/shaders/bloomPass1.vert new file mode 100644 index 0000000..2a74e46 --- /dev/null +++ b/base/res/shaders/bloomPass1.vert @@ -0,0 +1,11 @@ +#version 330 + +in vec3 Position; +in vec2 Texcoord; + +out vec2 fs_Texcoord; + +void main() { + fs_Texcoord = Texcoord; + gl_Position = vec4(Position,1.0f); +} diff --git a/base/res/shaders/diagnostic.frag b/base/res/shaders/diagnostic.frag index ac73727..21c536a 100644 --- a/base/res/shaders/diagnostic.frag +++ b/base/res/shaders/diagnostic.frag @@ -10,7 +10,10 @@ #define DISPLAY_COLOR 3 #define DISPLAY_TOTAL 4 #define DISPLAY_LIGHTS 5 - +#define DISPLAY_TOON 6 +#define DISPLAY_BLOOM 7 +#define DISPLAY_AA 8 +#define DISPLAY_SPECULAR 9 ///////////////////////////////////// // Uniforms, Attributes, and Outputs @@ -37,7 +40,9 @@ uniform float u_LightIl; in vec2 fs_Texcoord; -out vec4 out_Color; +out vec4 out_Color; // diffuse only +out vec4 out_Spec; +out vec4 out_BloomMap; /////////////////////////////////////// @@ -48,7 +53,7 @@ uniform float falloff = 0.1f; ///////////////////////////////////// -// UTILITY FUNCTIONS +// UTILITY FUNCTIONS ///////////////////////////////////// //Depth used in the Z buffer is not linearly related to distance from camera @@ -121,7 +126,9 @@ void main() { case(DISPLAY_TOTAL): break; } - + + out_Spec = vec4(0,0,0,0.0); + out_BloomMap = vec4(0,0,0,0); return; } diff --git a/base/res/shaders/pass.frag b/base/res/shaders/pass.frag index e37dcbf..59c5e30 100644 --- a/base/res/shaders/pass.frag +++ b/base/res/shaders/pass.frag @@ -1,7 +1,7 @@ #version 330 uniform float u_Far; -uniform vec3 u_Color; +uniform vec4 u_Color; in vec3 fs_Normal; in vec4 fs_Position; @@ -14,5 +14,5 @@ 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); + out_Color = u_Color; } diff --git a/base/res/shaders/point.frag b/base/res/shaders/point.frag index 98b90e0..7255a5e 100644 --- a/base/res/shaders/point.frag +++ b/base/res/shaders/point.frag @@ -1,7 +1,7 @@ #version 330 //////////////////////////// -// ENUMERATIONS +// ENUMERATIONS //////////////////////////// #define DISPLAY_DEPTH 0 @@ -10,7 +10,10 @@ #define DISPLAY_COLOR 3 #define DISPLAY_TOTAL 4 #define DISPLAY_LIGHTS 5 - +#define DISPLAY_TOON 6 +#define DISPLAY_BLOOM 7 +#define DISPLAY_AA 8 +#define DISPLAY_SPECULAR 9 ///////////////////////////////////// // Uniforms, Attributes, and Outputs @@ -26,6 +29,7 @@ uniform sampler2D u_RandomScalartex; uniform float u_Far; uniform float u_Near; +uniform int u_OcclusionType; uniform int u_DisplayType; uniform int u_ScreenWidth; @@ -36,7 +40,9 @@ uniform float u_LightIl; in vec2 fs_Texcoord; -out vec4 out_Color; +out vec4 out_Color; // diffuse only +out vec4 out_Spec; +out vec4 out_BloomMap; /////////////////////////////////////// @@ -45,9 +51,12 @@ out vec4 out_Color; uniform float zerothresh = 1.0f; uniform float falloff = 0.1f; +uniform float u_ks = 0.2; +uniform float u_specPower = 1.0; +uniform vec3 u_specColor = vec3(1,1,1); ///////////////////////////////////// -// UTILITY FUNCTIONS +// UTILITY FUNCTIONS ///////////////////////////////////// //Depth used in the Z buffer is not linearly related to distance from camera @@ -58,7 +67,7 @@ float linearizeDepth(float exp_depth, float near, float far) { //Helper function to automatically sample and unpack normals vec3 sampleNrm(vec2 texcoords) { - return texture(u_Normaltex,texcoords).xyz; + return normalize(texture(u_Normaltex,texcoords).xyz); } //Helper function to automicatlly sample and unpack positions @@ -88,6 +97,23 @@ float getRandomScalar(vec2 texcoords) { texcoords.t*u_ScreenHeight/sz.y)).r; } +// Get toon color, given the current color and intensity of the light on the surface +vec3 getToonColor(float intensity, vec3 color) +{ + vec3 toonColor = vec3(0,0,0); + + if (intensity > 0.95) + toonColor = color; + else if (intensity > 0.5) + toonColor = 0.6 * color; + else if (intensity > 0.25) + toonColor = 0.4 * color; + else + toonColor = 0.2 * color; + + return toonColor; +} + /////////////////////////////////// // MAIN ////////////////////////////////// @@ -102,15 +128,77 @@ void main() { vec3 color = sampleCol(fs_Texcoord); vec3 light = u_Light.xyz; float lightRadius = u_Light.w; - out_Color = vec4(0,0,0,1.0); + vec3 toLight = light - position; + float distToLight = length(toLight); + float attenCoefficient = 1.0 / (20.0 * distToLight * distToLight); + + + out_Color = vec4(0,0,0,1.0); + if( u_DisplayType == DISPLAY_LIGHTS ) { - //Put some code here to visualize the fragment associated with this point light + if (distToLight < lightRadius) + { + out_Color = attenCoefficient * vec4(1, 1, 1, 1); + //out_Color = (1.0 / (5.0 * lightRadius)) * vec4(1, 1, 1, 1); + out_Spec = vec4(0, 0, 0, 1); + } + } - else + else if (u_DisplayType == DISPLAY_TOON) + { + float intensity = max(0.0, dot(normalize(toLight),normal)); + vec3 toonColor = getToonColor(intensity, color); + out_Color = vec4(toonColor, 1.0); + out_Spec = vec4(0,0,0,1); + } + else { - //Put some code here to actually compute the light from the point light + if (distToLight < lightRadius) + { + //out_Color = attenCoefficient * vec4(1); + float atten = (1.0 / (2.0 * distToLight)); + + // compute diffuse color + + if (distToLight < 0.002) + { + out_Spec = vec4(0, 0, 0, 1); + out_Color = vec4(1); + } + else + { + float diffuse = min(max(0.0, dot(normalize(toLight), normal)), 1.0); + diffuse = clamp(dot(normal, normalize(toLight)), 0.0, 1.0); + + + out_Color = vec4(0.8*diffuse*color, 1.0f); + + // compute specular color + vec3 reflectDirection = vec3(0, 0, 0); + + // no specular reflection since light source is on the wrong side + if (dot(normal, toLight) < 0.0) + { + out_Spec = vec4(0, 0, 0, 1); + } + else + { + reflectDirection = reflect(toLight, normal); + vec3 viewDirection = normalize(position - vec3(0.0)); + vec3 specularHighlight = clamp(u_specColor * pow(max(0.0, dot(reflectDirection, viewDirection)), u_specPower), 0, 1); + out_Spec = vec4(u_ks*specularHighlight, 1.0); + } + } + } + else + { + out_Spec = vec4(0, 0, 0, 1); + out_Color = vec4(0, 0, 0, 1); + } } + + out_BloomMap = vec4(0,0,0,0); // no contribution + return; } - diff --git a/base/res/shaders/post.frag b/base/res/shaders/post.frag index 2bf5afc..9aea8d7 100644 --- a/base/res/shaders/post.frag +++ b/base/res/shaders/post.frag @@ -1,7 +1,7 @@ #version 330 //////////////////////////// -// ENUMERATIONS +// ENUMERATIONS //////////////////////////// #define DISPLAY_DEPTH 0 @@ -10,32 +10,41 @@ #define DISPLAY_COLOR 3 #define DISPLAY_TOTAL 4 #define DISPLAY_LIGHTS 5 - +#define DISPLAY_TOON 6 +#define DISPLAY_BLOOM 7 +#define DISPLAY_AA 8 +#define DISPLAY_SPECULAR 9 ///////////////////////////////////// // Uniforms, Attributes, and Outputs //////////////////////////////////// uniform sampler2D u_Posttex; +uniform sampler2D u_Normaltex; +uniform sampler2D u_SpecTex; +uniform sampler2D u_BloomMapTex; +uniform sampler2D u_BloomMapPass1Tex; 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; /////////////////////////////////////// +uniform float zerothresh = 1.0; +uniform float falloff = 0.1; - -uniform float zerothresh = 1.0f; -uniform float falloff = 0.1f; - +uniform bool isTwoPassBloom; +uniform int u_Bound = 18; ///////////////////////////////////// -// UTILITY FUNCTIONS +// UTILITY FUNCTIONS ///////////////////////////////////// //Helper function to automicatlly sample and unpack positions @@ -60,15 +69,257 @@ float getRandomScalar(vec2 texcoords) { texcoords.t*u_ScreenHeight/sz.y)).r; } +// helper method for applySobelOperator: Computes gradient in x and y direction +// by applying a convolution of [ -1 0 1 & [-1 -2 -1 +// -2 0 2 0 0 0 +// -1 0 1 ] 1 2 1 ] with the current image +vec2 computeGrad(vec2 texcoords, ivec2 texSize) +{ + mat3 mX = mat3 ( + -1, 0, 1, // first column + -2, 0, 2, // second column + -1, 0,1 // third column + ); + + mat3 mY = mat3 ( + -1, -2, -1, // first column + 0, 0, 0, // second column + 1, 2,1 // third column + ); + + float gradX = 0.0; + float gradY = 0.0; + + for (int i = 0 ; i < 3 ; ++i) + { + for (int j = 0 ; j < 3 ; ++j) + { + // get texture coordinates + float texOffsetS = float(i - 1) / float(texSize.x); + float texOffsetT = float(j - 1) / float(texSize.y); + vec3 color = texture(u_Normaltex, vec2(texOffsetS, texOffsetT) + texcoords).rgb; + //float colorFactor = length(abs(color)); + // convert to grayscale since I am using the normal map + float colorFactor = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b; + + + gradX += mX[i][j] * colorFactor; + gradY += mY[i][j] * colorFactor; + } + } + + return vec2(gradX, gradY); +} + +// Reference: http://image-processing-is-fun.blogspot.com/2011/11/one-of-first-edge-detection-filters-one.html +// applies the sobel operator to find edges. Returns the magnitude of the +// sum of gradient in x and y direction +float applySobelOperator(vec2 texcoords) +{ + vec2 gradient = computeGrad(texcoords, textureSize(u_Normaltex,0)); + return abs(gradient.x) + abs(gradient.y); // approx for greater efficiency +} + +// Used for anti-aliasing: This will compute the blur factor by inspecting the +// 8 pixels around the current texcoords. The blur factor is given by gradient * gradient +// where the gradient is the result of the Sobel Operator. +float computeBlurFactor(vec2 texcoords) +{ + float factor = 0.0; + + ivec2 normTexSize = textureSize(u_Normaltex,0); + + for (int i = 0 ; i < 3 ; ++i) + { + for (int j = 0 ; j < 3 ; ++j) + { + if (i == 1 && j == 1) + continue; + else + { + float texOffsetX = float(i - 1.0) / float(normTexSize.x); + float texOffsetY = float(j - 1.0 )/ float(normTexSize.y); + vec2 coords = texcoords + vec2(texOffsetX, texOffsetY); + float gradMag = applySobelOperator(coords); + factor += gradMag * gradMag; + } + } + } + + return factor; + +} + +// Apply anti-aliasing blur along the edges using blur factor +vec3 applyAABlur(vec2 texcoords, float blurFactor) +{ + + ivec2 postTexSize = textureSize(u_Posttex,0); + vec3 finalColor = vec3(0,0,0); + + blurFactor = min(1.0, blurFactor) ; + + //if (blurFactor > 2) + //return vec3(0,1,0); + //else if (blurFactor == 1.0) + //return vec3(0,0,1); + //else if (blurFactor < 2 && blurFactor > 1.0) + //return vec3(1,1,0); + //else if (blurFactor < 1.0) + //return vec3(1,1,1); + + if (blurFactor < 1.0) + return texture(u_Posttex, texcoords).rgb; + + for (int i = 0 ; i < 3 ; ++i) + { + for (int j = 0 ; j < 3 ; ++j) + { + if (i == 1 && j == 1) + continue; + + float texOffsetX = float(i - 1.0) / float(postTexSize.x); + float texOffsetY = float(j - 1.0)/ float(postTexSize.y); + + vec3 color = texture(u_Posttex, texcoords + vec2(texOffsetX, texOffsetY)).rgb; + finalColor += blurFactor * color; + } + } + + finalColor += 2.0 * texture(u_Posttex, texcoords).rgb; + finalColor = clamp(finalColor * 0.1, 0 , 1); + return finalColor; +} + + +// apply a 5x5 gaussian filter to the incoming texture coordinates +// return the resulting color +vec3 applyGaussianFilter(vec2 texcoords) +{ + float pi = 3.141592653589; + float sigma = 50.0; + + float sum = 0; // for normalization + float s = 2.0 * sigma * sigma; + vec3 result = vec3(0,0,0); + + int bound = 40; + + for (int x = -bound ; x <= bound ; ++x) + { + for (int y = -bound ; y <= bound ; ++y) + { + float r = x*x + y*y; + float w = (exp(-r / s)) / (pi * s); + sum += w; + + ivec2 texSize = textureSize(u_BloomMapTex, 0); + float texOffsetS = float(x - 1) / float(texSize.x); + float texOffsetT = float(y - 1) / float(texSize.y); + vec3 color = w * texture(u_BloomMapTex, texcoords + vec2(texOffsetS, texOffsetT)).rgb; + result += color; + } + } + + return result * (1 / sum); +} + +// apply vertical gaussian filter to the result of bloomPass1.frag +// return the resulting color +vec3 applyVertGaussianFilter(vec2 texcoords) +{ + float pi = 3.141592653589; + float sigma = 50.0; + + float sum = 0; // for normalization + float s = 2.0 * sigma * sigma; + vec3 result = vec3(0,0,0); + + int bound = u_Bound; + + for (int y = -bound ; y <= bound ; ++y) + { + float r = y*y; + float w = (exp(-r / s)) / (pi * s); + sum += w; + + ivec2 texSize = textureSize(u_BloomMapPass1Tex, 0); + float texOffsetS = 0; + float texOffsetT = float(y - 1) / float(texSize.y); + vec3 color = w * texture(u_BloomMapPass1Tex, texcoords + vec2(texOffsetS, texOffsetT)).rgb; + result += color; + } + + return result * (1 / sum); +} + + /////////////////////////////////// // MAIN ////////////////////////////////// -const float occlusion_strength = 1.5f; +const float occlusion_strength = 1.5; 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); - return; -} + vec3 color = sampleCol(fs_Texcoord); + if (u_DisplayType == DISPLAY_TOTAL) + { + 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); + out_Color = vec4(color, 1.0); + vec4 specColor = vec4(abs(texture(u_SpecTex, fs_Texcoord).rgb), 1.0); + out_Color = vec4(color, 1.0) + specColor; + } + else if (u_DisplayType == DISPLAY_TOON) + { + // apply sobel operator to get outlines + float gradMag = applySobelOperator(fs_Texcoord); + gradMag = clamp(gradMag, 0, 1.0); + float multiplier = 1.0 - gradMag; + //out_Color = vec4(abs(texture(u_Normaltex, fs_Texcoord).rgb), 1.0); + //out_Color = vec4(multiplier,multiplier,multiplier,1.0); + out_Color = vec4(multiplier,multiplier,multiplier,1.0) * vec4(color, 1.0); + } + else if (u_DisplayType == DISPLAY_BLOOM) + { + + vec4 specColor = vec4(abs(texture(u_SpecTex, fs_Texcoord).rgb), 1.0); + vec4 baseColor = vec4(color, 1.0); + + if (!isTwoPassBloom) + { + + out_Color = baseColor + vec4(applyGaussianFilter(fs_Texcoord), 1.0); + } + else + { + out_Color = baseColor + vec4(applyVertGaussianFilter(fs_Texcoord), 1.0); + } + } + else if (u_DisplayType == DISPLAY_AA) + { + float blurFactor = computeBlurFactor(fs_Texcoord); + vec3 blurColor = applyAABlur(fs_Texcoord, blurFactor); + //out_Color = vec4(blurFactor,blurFactor,blurFactor,1.0); + out_Color = vec4(blurColor, 1.0); + } + else if (u_DisplayType == DISPLAY_SPECULAR) + { + out_Color = vec4(abs(texture(u_SpecTex, fs_Texcoord).rgb), 1.0); + } + else + { + out_Color = vec4(color, 1.0) ; + } + + // testing if we can change the alpha value of the input textures as well + // turns out it doesnt work. Maybe it's because this stage, we are using the + // default framebuffer? + //vec4 specColorTest = texture(u_Posttex, fs_Texcoord); + //float sa = specColorTest.a; + //out_Color = vec4(sa,sa,sa,1.0); + //out_Color = specColorTest; + + + return; +} diff --git a/base/src/light.cpp b/base/src/light.cpp new file mode 100644 index 0000000..b6f3e01 --- /dev/null +++ b/base/src/light.cpp @@ -0,0 +1,32 @@ +#include +#include "light.h" + +Light::Light(vec3 pos, float str) : +m_position(pos), +m_strength(str), +m_rate(0), +m_sampleOffset(0) +{ +} + +Light::Light(vec3 pos, float str, float rate, float offset) : +m_position(pos), +m_strength(str), +m_rate(rate), +m_sampleOffset(offset) +{ +} + + +float Light::sampleStrength(float time) +{ + if (m_rate == 0) + return m_strength; + + float coeff = sin(1.0 * time / (m_rate) + m_sampleOffset); + + if (coeff < 0) + coeff = 0; + + return coeff * m_strength; +} \ No newline at end of file diff --git a/base/src/light.h b/base/src/light.h new file mode 100644 index 0000000..8638ac1 --- /dev/null +++ b/base/src/light.h @@ -0,0 +1,19 @@ +#include + +using glm::vec3; + +class Light +{ +public: + Light(vec3 position, float strength); + Light(vec3 position, float strength, float rate, float offset=0); + float sampleStrength(float time); + vec3 getPosition() { return m_position; } + float getStrength() { return m_strength; } + +private: + vec3 m_position; + float m_strength; + float m_rate; // rate at which the strength of the light fluctuates + float m_sampleOffset; +}; \ No newline at end of file diff --git a/base/src/main.cpp b/base/src/main.cpp index 9a0f6a0..4c05004 100644 --- a/base/src/main.cpp +++ b/base/src/main.cpp @@ -158,9 +158,10 @@ void initMesh() { mesh.indices.push_back(point++); } - mesh.color = vec3(shape.material.diffuse[0], + mesh.color = vec4(shape.material.diffuse[0], shape.material.diffuse[1], - shape.material.diffuse[2]); + shape.material.diffuse[2], + shape.material.shininess); mesh.texname = shape.material.diffuse_texname; draw_meshes.push_back(uploadMesh(mesh)); f=f+process; @@ -184,7 +185,6 @@ void initQuad() { glGenVertexArrays(1, &(device_quad.vertex_array)); glBindVertexArray(device_quad.vertex_array); - //Allocate vbos for data glGenBuffers(1,&(device_quad.vbo_data)); glGenBuffers(1,&(device_quad.vbo_indices)); @@ -207,30 +207,113 @@ void initQuad() { } +vector lights; +// initialize all point light sources +void initLights() +{ + float minI = 0.3; + float maxI = 5.3; + float minJ = 0.3; + float maxJ = 5.3; + float minK = 0.3; + float maxK = 5.3; + float step = 1; + float lightStr = 0.8; + + float botBaseRate = 300; + float topBaseRate = 300; + float leftBaseRate = 300; + float rightBaseRate = 300; + float backBaseRate = -300; + + float botOffset = 1; + float topOffset = 1; + float rightOffset = 1; + float leftOffset = 1; + float backOffset = 1; + + for (float j = minJ; j <= maxJ; j += step) + { + for (float i = minI; i <= maxI; i += step) + { + + Light L1(vec3(i, -j, minK), lightStr, botBaseRate, botOffset); // bottom plane + Light L2(vec3(i, -j, maxK), lightStr, topBaseRate, topOffset); // top plane + lights.push_back(L1); + lights.push_back(L2); + + + } + + botOffset += 0.5; + topOffset += 0.5; + } + + for (float i = minI; i <= maxI; i += step) + { + for (float k = minK+1; k <= maxK-1; k += step) // skip area that are already covered by the top / bottom plane of lights + { + Light L1(vec3(i, -maxJ, k), lightStr, backBaseRate); // back plane + lights.push_back(L1); + } + } + + for (float j = minJ; j <= maxJ-1; j += step) + { + for (float k = minK+1; k <= maxK-1; k += step) + { + Light L1(vec3(minI, -j, k), lightStr, leftBaseRate, leftOffset); // left plane + Light L2(vec3(maxI, -j, k), lightStr, rightBaseRate, rightOffset); // right plane + lights.push_back(L1); + lights.push_back(L2); + } + + rightOffset += 0.5; + leftOffset += 0.5; + } + + vec3 centerLight1Pos = vec3((minI + maxI) * 0.5, (minJ + maxJ) * -0.5, (minK + maxK) * 0.5); + + + float centerLight1Str = 2.5f; + float centerLightRate = 500; + float centerLightOffset = 1; + + Light centerLight(centerLight1Pos, centerLight1Str, centerLightRate); + lights.push_back(centerLight); +} + GLuint depthTexture = 0; GLuint normalTexture = 0; GLuint positionTexture = 0; GLuint colorTexture = 0; +GLuint specTexture = 0; +GLuint bloomMapTexture = 0; +GLuint bloomMapPass1Texture = 0; GLuint postTexture = 0; -GLuint FBO[2] = {0, 0}; - +GLuint FBO[3] = {0, 0, 0}; GLuint pass_prog; GLuint point_prog; GLuint ambient_prog; GLuint diagnostic_prog; GLuint post_prog; +GLuint bloompass1_prog; + void initShader() { #ifdef WIN32 const char * pass_vert = "../../../res/shaders/pass.vert"; const char * shade_vert = "../../../res/shaders/shade.vert"; const char * post_vert = "../../../res/shaders/post.vert"; + const char * bloomPass1_vert = "../../../res/shaders/bloomPass1.vert"; const char * pass_frag = "../../../res/shaders/pass.frag"; 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 * post_frag = "../../../res/shaders/post.frag"; + const char * bloomPass1_frag = "../../../res/shaders/bloomPass1.frag"; + #else const char * pass_vert = "../res/shaders/pass.vert"; const char * shade_vert = "../res/shaders/shade.vert"; @@ -242,43 +325,66 @@ void initShader() { const char * point_frag = "../res/shaders/point.frag"; const char * post_frag = "../res/shaders/post.frag"; #endif + + ///////////////////////////// + // pass_prog + Utility::shaders_t shaders = Utility::loadShaders(pass_vert, pass_frag); pass_prog = glCreateProgram(); glBindAttribLocation(pass_prog, mesh_attributes::POSITION, "Position"); glBindAttribLocation(pass_prog, mesh_attributes::NORMAL, "Normal"); - glBindAttribLocation(pass_prog, mesh_attributes::TEXCOORD, "Texcoord"); + //glBindAttribLocation(pass_prog, mesh_attributes::TEXCOORD, "Texcoord"); Utility::attachAndLinkProgram(pass_prog,shaders); + ///////////////////////////// + // diagnostic_prog shaders = Utility::loadShaders(shade_vert, diagnostic_frag); diagnostic_prog = glCreateProgram(); glBindAttribLocation(diagnostic_prog, quad_attributes::POSITION, "Position"); glBindAttribLocation(diagnostic_prog, quad_attributes::TEXCOORD, "Texcoord"); - + glBindFragDataLocation(diagnostic_prog, 0, "out_Color"); //LOOK: NEED TO DO THIS TO MAKE SURE THAT THE OUTPUTS ARE THE SAME INDEX + glBindFragDataLocation(diagnostic_prog, 1, "out_Spec"); //In initFBO, the portion where I am binding the output textures for these + glBindFragDataLocation(diagnostic_prog, 2, "out_BloomMap"); //shaders that need to write to the same textures, they need to have the same index + //for the output variable. + //out_BloomMap will hold the information of whether or not each pixel will be applied the bloom effect. + //this map is later taken in as input by bloomPass and post as u_BloomMapTex. To change which object + //should be applied the bloom effect, adjust alpha channel of the object material in the .mtl files that came w/ the obj file. Utility::attachAndLinkProgram(diagnostic_prog, shaders); + ///////////////////////////// + // ambient_prog shaders = Utility::loadShaders(shade_vert, ambient_frag); ambient_prog = glCreateProgram(); glBindAttribLocation(ambient_prog, quad_attributes::POSITION, "Position"); glBindAttribLocation(ambient_prog, quad_attributes::TEXCOORD, "Texcoord"); + glBindFragDataLocation(ambient_prog, 0, "out_Color"); //LOOK: NEED TO DO THIS TO MAKE SURE THAT THE OUTPUTS ARE THE SAME INDEX + glBindFragDataLocation(ambient_prog, 1, "out_Spec"); + glBindFragDataLocation(ambient_prog, 2, "out_BloomMap"); Utility::attachAndLinkProgram(ambient_prog, shaders); + ///////////////////////////// + // point_prog shaders = Utility::loadShaders(shade_vert, point_frag); point_prog = glCreateProgram(); glBindAttribLocation(point_prog, quad_attributes::POSITION, "Position"); glBindAttribLocation(point_prog, quad_attributes::TEXCOORD, "Texcoord"); - + glBindFragDataLocation(point_prog, 0, "out_Color"); //LOOK: NEED TO DO THIS TO MAKE SURE THAT THE OUTPUTS ARE THE SAME INDEX + glBindFragDataLocation(point_prog, 1, "out_Spec"); + glBindFragDataLocation(point_prog, 2, "out_BloomMap"); Utility::attachAndLinkProgram(point_prog, shaders); + ///////////////////////////// + // post_prog shaders = Utility::loadShaders(post_vert, post_frag); post_prog = glCreateProgram(); @@ -287,6 +393,20 @@ void initShader() { glBindAttribLocation(post_prog, quad_attributes::TEXCOORD, "Texcoord"); Utility::attachAndLinkProgram(post_prog, shaders); + + ///////////////////////////// + // BloomPass1_prog +#if IS_TWO_PASS_BLOOM == 1 + shaders = Utility::loadShaders(bloomPass1_vert, bloomPass1_frag); + + bloompass1_prog = glCreateProgram(); + glBindAttribLocation(bloompass1_prog, quad_attributes::POSITION, "Position"); + glBindAttribLocation(bloompass1_prog, quad_attributes::TEXCOORD, "Texcoord"); + + glBindFragDataLocation(bloompass1_prog, 0, "out_Color"); + + Utility::attachAndLinkProgram(bloompass1_prog, shaders); +#endif } void freeFBO() { @@ -295,8 +415,17 @@ void freeFBO() { glDeleteTextures(1,&positionTexture); glDeleteTextures(1,&colorTexture); glDeleteTextures(1,&postTexture); + glDeleteTextures(1,&bloomMapTexture); + glDeleteTextures(1,&specTexture); + +#if IS_TWO_PASS_BLOOM == 1 + glDeleteTextures(1,&bloomMapPass1Texture); + glDeleteFramebuffers(1,&FBO[2]); +#endif + glDeleteFramebuffers(1,&FBO[0]); glDeleteFramebuffers(1,&FBO[1]); + } void checkFramebufferStatus(GLenum framebufferStatus) { @@ -360,6 +489,8 @@ void initNoise() { void initFBO(int w, int h) { GLenum FBOstatus; + /////////////////////////////////////////////////////////////////// + // setting up framebuffer and textures for pass_prog to output to glActiveTexture(GL_TEXTURE9); glGenTextures(1, &depthTexture); @@ -377,7 +508,7 @@ void initFBO(int w, int h) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); - glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, w, h, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); + glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, w, h, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); // http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml //Set up normal FBO glBindTexture(GL_TEXTURE_2D, normalTexture); @@ -410,31 +541,34 @@ 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); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA32F , w, h, 0, GL_RGBA, GL_FLOAT,0); // Use GL_RGBA32F so I can pack things in the alpha ch. - // creatwwe a framebuffer object - glGenFramebuffers(1, &FBO[0]); - glBindFramebuffer(GL_FRAMEBUFFER, FBO[0]); + // create a framebuffer object + glGenFramebuffers(1, &FBO[0]); // http://www.opengl.org/sdk/docs/man/xhtml/glGenFramebuffers.xml + glBindFramebuffer(GL_FRAMEBUFFER, FBO[0]); // Instruct openGL that we won't bind a color texture with the currently bound FBO glReadBuffer(GL_NONE); GLint normal_loc = glGetFragDataLocation(pass_prog,"out_Normal"); GLint position_loc = glGetFragDataLocation(pass_prog,"out_Position"); GLint color_loc = glGetFragDataLocation(pass_prog,"out_Color"); + GLenum draws [3]; draws[normal_loc] = GL_COLOR_ATTACHMENT0; draws[position_loc] = GL_COLOR_ATTACHMENT1; draws[color_loc] = GL_COLOR_ATTACHMENT2; - glDrawBuffers(3, draws); + glDrawBuffers(3, draws); //This call will define an array of buffers into which outputs from the fragment shader data will be written + //http://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffers.xml // attach the texture to FBO depth attachment point + // Buffers (specific locations in the framebuffer) in FBOs are also called "attachment points"; they're the locations where images can be attached int test = GL_COLOR_ATTACHMENT0; glBindTexture(GL_TEXTURE_2D, depthTexture); - glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0); + glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0); // Look, GL_DEPTH_ATTACHMENT tells openGL to render depth information to depthTexture glBindTexture(GL_TEXTURE_2D, normalTexture); - glFramebufferTexture(GL_FRAMEBUFFER, draws[normal_loc], normalTexture, 0); - glBindTexture(GL_TEXTURE_2D, positionTexture); - glFramebufferTexture(GL_FRAMEBUFFER, draws[position_loc], positionTexture, 0); + glFramebufferTexture(GL_FRAMEBUFFER, draws[normal_loc], normalTexture, 0); // Note that draw[i] is already defined by glDrawBuffers as the locations where the outputs + glBindTexture(GL_TEXTURE_2D, positionTexture); // from the fragment shaders data will be written. If we bind these textures to the framebuffer, + glFramebufferTexture(GL_FRAMEBUFFER, draws[position_loc], positionTexture, 0); // we are essentially writing the output of the fragment shaders to these textures! Very cool! glBindTexture(GL_TEXTURE_2D, colorTexture); glFramebufferTexture(GL_FRAMEBUFFER, draws[color_loc], colorTexture, 0); @@ -445,10 +579,15 @@ void initFBO(int w, int h) { checkFramebufferStatus(FBOstatus); } - //Post Processing buffer! + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // setting up framebuffer and textures for ambient_prog, point_prog, and diagnostic_prog to output to + // Post Processing buffer! These are input textures to post.frag. Values are filled by the previous stage in the pipeline glActiveTexture(GL_TEXTURE9); glGenTextures(1, &postTexture); + glGenTextures(1, &specTexture); + glGenTextures(1, &bloomMapTexture); //Set up post FBO glBindTexture(GL_TEXTURE_2D, postTexture); @@ -459,23 +598,55 @@ 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); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA32F , w, h, 0, GL_RGBA, GL_FLOAT,0); + + //Set up spec FBO + glBindTexture(GL_TEXTURE_2D, specTexture); + + 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_RGBA32F , w, h, 0, GL_RGBA, GL_FLOAT,0); + + //Set up bloomMap FBO + glBindTexture(GL_TEXTURE_2D, bloomMapTexture); - // creatwwe a framebuffer object - glGenFramebuffers(1, &FBO[1]); + 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_RGBA32F , w, h, 0, GL_RGBA, GL_FLOAT,0); + + // create a framebuffer object and bind it to contex + glGenFramebuffers(1, &FBO[1]); glBindFramebuffer(GL_FRAMEBUFFER, FBO[1]); // Instruct openGL that we won't bind a color texture with the currently bound FBO - glReadBuffer(GL_BACK); - color_loc = glGetFragDataLocation(ambient_prog,"out_Color"); - GLenum draw[1]; + // LOOK: For FBO[1], the output texture is being set at ambient_prog's out_Color + //glReadBuffer(GL_BACK); + glReadBuffer(GL_NONE); + color_loc = glGetFragDataLocation(ambient_prog,"out_Color"); // LOOK: This works because in initShaders(), I am explicitly assigning the out_Color, + GLint spec_loc = glGetFragDataLocation(ambient_prog, "out_Spec"); // out_Spec, and out_BloomMap to have the same index. + GLint bloom_loc = glGetFragDataLocation(ambient_prog, "out_BloomMap"); + GLenum draw[3]; draw[color_loc] = GL_COLOR_ATTACHMENT0; - glDrawBuffers(1, draw); - - // attach the texture to FBO depth attachment point + draw[spec_loc] = GL_COLOR_ATTACHMENT1; + draw[bloom_loc] = GL_COLOR_ATTACHMENT2; + glDrawBuffers(3, draw); + + // attach the texture to FBO colfor attachment point test = GL_COLOR_ATTACHMENT0; glBindTexture(GL_TEXTURE_2D, postTexture); glFramebufferTexture(GL_FRAMEBUFFER, draw[color_loc], postTexture, 0); + glBindTexture(GL_TEXTURE_2D, specTexture); + glFramebufferTexture(GL_FRAMEBUFFER, draw[spec_loc], specTexture, 0); + glBindTexture(GL_TEXTURE_2D, bloomMapTexture); + glFramebufferTexture(GL_FRAMEBUFFER, draw[bloom_loc], bloomMapTexture, 0); // check FBO status FBOstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -484,12 +655,47 @@ void initFBO(int w, int h) { checkFramebufferStatus(FBOstatus); } - // switch back to window-system-provided framebuffer +#if IS_TWO_PASS_BLOOM == 1 + //////////////////////////////////////////////////////////////////////// + // setting up framebuffer and textures for bloompass1_prog to output to + glActiveTexture(GL_TEXTURE9); + glGenTextures(1, &bloomMapPass1Texture); + glBindTexture(GL_TEXTURE_2D, bloomMapPass1Texture); + + 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_RGBA32F , w, h, 0, GL_RGBA, GL_FLOAT,0); + + glGenFramebuffers(1, &FBO[2]); + glBindFramebuffer(GL_FRAMEBUFFER, FBO[2]); + glReadBuffer(GL_NONE); + color_loc = glGetFragDataLocation(bloompass1_prog, "out_Color"); + GLenum drawBuff[1]; + drawBuff[color_loc] = GL_COLOR_ATTACHMENT0; + glDrawBuffers(1, drawBuff); + + glBindTexture(GL_TEXTURE_2D, bloomMapPass1Texture); + glFramebufferTexture(GL_FRAMEBUFFER, drawBuff[color_loc], bloomMapPass1Texture, 0); + + // check FBO status + FBOstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if(FBOstatus != GL_FRAMEBUFFER_COMPLETE) { + printf("GL_FRAMEBUFFER_COMPLETE failed, CANNOT use FBO[2]\n"); + checkFramebufferStatus(FBOstatus); + } +#endif + + // switch back to window-system-provided framebuffer (i.e the default buffer provided by the OpenGL context) glClear(GL_DEPTH_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); } +// Given buf (index of the FBO array that we have created), this function will bind FBO[buf] to the current OpenGL contex void bindFBO(int buf) { glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,0); //Bad mojo to unbind the framebuffer using the texture @@ -511,7 +717,7 @@ void setTextures() { -Camera cam(vec3(2.5, 5, 2), +Camera cam(vec3(2.8, 6.7, 2.8), normalize(vec3(0,-1,0)), normalize(vec3(0,0,1))); @@ -571,6 +777,9 @@ mat4x4 get_mesh_world() { float FARP; float NEARP; + +// uses pass_prog (pass.vert and pass.frag) to compute position, normal, and color. +// The fragment shader will output those values to the corresponding textures. void draw_mesh() { FARP = 100.0f; NEARP = 0.1f; @@ -590,7 +799,7 @@ void draw_mesh() { glUniformMatrix4fv(glGetUniformLocation(pass_prog,"u_InvTrans") ,1,GL_FALSE,&inverse_transposed[0][0]); for(int i=0; i NEARP) - { - return; - } + //if( light.z > NEARP) + //{ + // return; + //} light.w = radius; glUniform4fv(glGetUniformLocation(point_prog, "u_Light"), 1, &(light[0])); glUniform1f(glGetUniformLocation(point_prog, "u_LightIl"), strength); @@ -685,7 +897,7 @@ void draw_light(vec3 pos, float strength, mat4 sc, mat4 vp, float NEARP) { float x = center.x-r; float y = center.y-r; - glScissor(x, y, 2*r, 2*r); + glScissor(x, y, 2*r, 2*r); // http://www.opengl.org/sdk/docs/man/xhtml/glScissor.xml draw_quad(); } @@ -704,11 +916,23 @@ void updateDisplayText(char * disp) { sprintf(disp, "Displaying Position"); break; case(DISPLAY_TOTAL): - sprintf(disp, "Displaying Diffuse"); + sprintf(disp, "Displaying Diffuse + Specular (TOTAL)"); break; case(DISPLAY_LIGHTS): sprintf(disp, "Displaying Lights"); break; + case(DISPLAY_TOON): + sprintf(disp, "Displaying Toon Shading"); + break; + case(DISPLAY_BLOOM): + sprintf(disp, "Displaying Bloom Effect"); + break; + case(DISPLAY_AA): + sprintf(disp, "Display Diffuse + AA"); + break; + case(DISPLAY_SPECULAR): + sprintf(disp, "Display Specular"); + break; } } @@ -735,6 +959,7 @@ void updateTitle() { glutSetWindowTitle(title); timebase = currenttime; frame = 0; + bloomBound = 18; } } @@ -747,16 +972,17 @@ void display(void) draw_mesh(); // Stage 2 -- RENDER TO P-BUFFER - setTextures(); + setTextures(); // unnecessary? bindFBO(1); - glEnable(GL_BLEND); + glEnable(GL_BLEND); // enable alpha value calculations glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); - glBlendFunc(GL_ONE, GL_ONE); + glBlendFunc(GL_ONE, GL_ONE); // This sums the outputs of the http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunc.xml glClear(GL_COLOR_BUFFER_BIT); - if(display_type == DISPLAY_LIGHTS || display_type == DISPLAY_TOTAL) + if(display_type == DISPLAY_LIGHTS || display_type == DISPLAY_TOTAL || display_type == DISPLAY_TOON || display_type == DISPLAY_BLOOM + || display_type == DISPLAY_AA || display_type == DISPLAY_SPECULAR) { - setup_quad(point_prog); + setup_quad(point_prog); // used to render the light source and compute light from point light if(doIScissor) glEnable(GL_SCISSOR_TEST); mat4 vp = perspective(45.0f,(float)width/(float)height,NEARP,FARP) * cam.get_view(); @@ -768,16 +994,32 @@ void display(void) 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.5, 0.5, 0.0, 1.0); +#if MULTI_LIGHTS == 1 + + for (int i = 0; i < lights.size(); ++i) + { + float str = 0; + if (pauseLightAnim) + str = lights[i].sampleStrength(currenttime); + else + str = lights[i].getStrength(); + + + //draw_light(lights[i].getPosition(), lights[i].getStrength(), sc, vp, NEARP); + draw_light(lights[i].getPosition(), str, sc, vp, NEARP); + } - draw_light(vec3(2.5, -2.5, 5.0), 0.50, sc, vp, NEARP); +#else + draw_light(vec3(2.5, -2.5, 5.0), 0.50, sc, vp, NEARP); +#endif 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; - setup_quad(ambient_prog); + setup_quad(ambient_prog); // render scene with directional light glUniform4fv(glGetUniformLocation(ambient_prog, "u_Light"), 1, &(dir_light[0])); glUniform1f(glGetUniformLocation(ambient_prog, "u_LightIl"), strength); draw_quad(); @@ -789,7 +1031,28 @@ void display(void) } glDisable(GL_BLEND); - //Stage 3 -- RENDER TO SCREEN +#if IS_TWO_PASS_BLOOM == 1 + //Stage 2.5 -- Perform first pass of bloom if enabled + setTextures(); + bindFBO(2); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glUseProgram(bloompass1_prog); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, bloomMapTexture); + glUniform1i(glGetUniformLocation(bloompass1_prog, "u_BloomMapTex"),0); + glUniform1i(glGetUniformLocation(bloompass1_prog, "u_ScreenHeight"), height); + glUniform1i(glGetUniformLocation(bloompass1_prog, "u_ScreenWidth"), width); + glUniform1i(glGetUniformLocation(bloompass1_prog, "u_DisplayType"), display_type); + glUniform1i(glGetUniformLocation(bloompass1_prog, "u_Bound"), bloomBound); + draw_quad(); + +#endif + + //Stage 3 -- RENDER TO SCREEN + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); setTextures(); glUseProgram(post_prog); @@ -800,7 +1063,19 @@ void display(void) glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, postTexture); glUniform1i(glGetUniformLocation(post_prog, "u_Posttex"),0); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, normalTexture); + glUniform1i(glGetUniformLocation(post_prog, "u_Normaltex"),1); + + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, specTexture); + glUniform1i(glGetUniformLocation(post_prog, "u_SpecTex"),2); + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, bloomMapTexture); + glUniform1i(glGetUniformLocation(post_prog, "u_BloomMapTex"),3); + glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_2D, random_normal_tex); glUniform1i(glGetUniformLocation(post_prog, "u_RandomNormaltex"),4); @@ -811,11 +1086,24 @@ void display(void) glUniform1i(glGetUniformLocation(post_prog, "u_ScreenHeight"), height); glUniform1i(glGetUniformLocation(post_prog, "u_ScreenWidth"), width); + glUniform1i(glGetUniformLocation(post_prog, "u_DisplayType"), display_type); + +#if IS_TWO_PASS_BLOOM == 1 + glUniform1i(glGetUniformLocation(post_prog, "isTwoPassBloom"), 1); + glActiveTexture(GL_TEXTURE6); + glBindTexture(GL_TEXTURE_2D, bloomMapPass1Texture); + glUniform1i(glGetUniformLocation(post_prog, "u_BloomMapPass1Tex"),6); + glUniform1i(glGetUniformLocation(post_prog, "u_Bound"), bloomBound); +#else + glUniform1i(glGetUniformLocation(post_prog, "isTwoPassBloom"), 0); +#endif + draw_quad(); + glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); updateTitle(); - + updateBloomBound(30,6); glutPostRedisplay(); glutSwapBuffers(); } @@ -908,6 +1196,18 @@ void keyboard(unsigned char key, int x, int y) { case('5'): display_type = DISPLAY_LIGHTS; break; + case('6'): + display_type = DISPLAY_TOON; + break; + case('7'): + display_type = DISPLAY_BLOOM; + break; + case('8'): + display_type = DISPLAY_AA; + break; + case('9'): + display_type = DISPLAY_SPECULAR; + break; case('0'): display_type = DISPLAY_TOTAL; break; @@ -917,6 +1217,12 @@ void keyboard(unsigned char key, int x, int y) { case('r'): initShader(); break; + case('l') : + pauseLightAnim ^= true; + break; + case('c') : + printCamPosition(); + break; } if (abs(tx) > 0 || abs(tz) > 0 || abs(ty) > 0) { @@ -924,6 +1230,25 @@ void keyboard(unsigned char key, int x, int y) { } } +void updateBloomBound(int max, int min) +{ + if (bloomBound > max) + incBloomBound = false; + + if (bloomBound < min) + incBloomBound = true; + + if (incBloomBound) + bloomBound++; + else + bloomBound--; +} + +void printCamPosition() +{ + cout << "Camera Position : " << cam.pos.x << "," << cam.pos.y << "," << cam.z << endl; +} + void init() { glEnable(GL_DEPTH_TEST); glClearColor(0.0f, 0.0f, 0.0f,1.0f); @@ -979,6 +1304,7 @@ int main (int argc, char* argv[]) init(); initMesh(); initQuad(); + initLights(); glutDisplayFunc(display); diff --git a/base/src/main.h b/base/src/main.h index 0a96a3a..f39e3f1 100644 --- a/base/src/main.h +++ b/base/src/main.h @@ -7,8 +7,16 @@ #include #include +#include "light.h" #include "tiny_obj_loader.h" +#define MULTI_LIGHTS 1 +#define IS_TWO_PASS_BLOOM 1 + +// obj paths +// mesh=../../../res/crytek-sponza/sponza.obj +// mesh=../../../res/cornell/cornell_box.obj + class Camera { public: Camera(glm::vec3 start_pos, glm::vec3 start_dir, glm::vec3 up) : @@ -36,7 +44,7 @@ typedef struct { std::vector texcoords; std::vector indices; std::string texname; - glm::vec3 color; + glm::vec4 color; // alpha position will store the shininess of the material (used for bloom) } mesh_t; typedef struct { @@ -46,7 +54,7 @@ typedef struct { unsigned int vbo_vertices; unsigned int vbo_normals; unsigned int vbo_texcoords; - glm::vec3 color; + glm::vec4 color; std::string texname; } device_mesh_t; @@ -83,7 +91,12 @@ enum Display { DISPLAY_POSITION = 2, DISPLAY_COLOR = 3, DISPLAY_TOTAL = 4, - DISPLAY_LIGHTS = 5 + DISPLAY_LIGHTS = 5, + DISPLAY_TOON = 6, + DISPLAY_BLOOM = 7, + DISPLAY_AA = 8, + DISPLAY_SPECULAR = 9, + DISPLAY_SEP_BLOOM = 10 }; char* loadFile(char *fname, GLint &fSize); @@ -91,14 +104,19 @@ void printShaderInfoLog(GLint shader); void printLinkInfoLog(GLint prog); void initShade(); void initPass(); - +void initLights(); void initMesh(); device_mesh_t uploadMesh(const mesh_t & mesh); void display(void); void keyboard(unsigned char, int, int); void reshape(int, int); - +void printCamPosition(); +void updateBloomBound(int max, int min); int main (int argc, char* argv[]); +bool pauseLightAnim = false; +bool incBloomBound = true; +int bloomBound = 18; + #endif diff --git a/screenshots/cornell_box_aa_diffuse.png b/screenshots/cornell_box_aa_diffuse.png new file mode 100644 index 0000000..6d0cd2b Binary files /dev/null and b/screenshots/cornell_box_aa_diffuse.png differ diff --git a/screenshots/cornell_box_bloom.png b/screenshots/cornell_box_bloom.png new file mode 100644 index 0000000..4880eec Binary files /dev/null and b/screenshots/cornell_box_bloom.png differ diff --git a/screenshots/cornell_box_bloom_scissor.png b/screenshots/cornell_box_bloom_scissor.png new file mode 100644 index 0000000..74d3555 Binary files /dev/null and b/screenshots/cornell_box_bloom_scissor.png differ diff --git a/screenshots/cornell_box_colors.png b/screenshots/cornell_box_colors.png new file mode 100644 index 0000000..55a55fc Binary files /dev/null and b/screenshots/cornell_box_colors.png differ diff --git a/screenshots/cornell_box_depth.png b/screenshots/cornell_box_depth.png new file mode 100644 index 0000000..c12f393 Binary files /dev/null and b/screenshots/cornell_box_depth.png differ diff --git a/screenshots/cornell_box_diffuse_specular.png b/screenshots/cornell_box_diffuse_specular.png new file mode 100644 index 0000000..61ede26 Binary files /dev/null and b/screenshots/cornell_box_diffuse_specular.png differ diff --git a/screenshots/cornell_box_lightss.png b/screenshots/cornell_box_lightss.png new file mode 100644 index 0000000..dab7b08 Binary files /dev/null and b/screenshots/cornell_box_lightss.png differ diff --git a/screenshots/cornell_box_normals.png b/screenshots/cornell_box_normals.png new file mode 100644 index 0000000..827a547 Binary files /dev/null and b/screenshots/cornell_box_normals.png differ diff --git a/screenshots/cornell_box_specular.png b/screenshots/cornell_box_specular.png new file mode 100644 index 0000000..1cfe9b9 Binary files /dev/null and b/screenshots/cornell_box_specular.png differ diff --git a/screenshots/cornell_box_toon.png b/screenshots/cornell_box_toon.png new file mode 100644 index 0000000..06245ea Binary files /dev/null and b/screenshots/cornell_box_toon.png differ diff --git a/screenshots/perf_analysis.png b/screenshots/perf_analysis.png new file mode 100644 index 0000000..fa5a3e6 Binary files /dev/null and b/screenshots/perf_analysis.png differ diff --git a/screenshots/sponza_aa_diffuse.png b/screenshots/sponza_aa_diffuse.png new file mode 100644 index 0000000..dc81efe Binary files /dev/null and b/screenshots/sponza_aa_diffuse.png differ diff --git a/screenshots/sponza_bloom.png b/screenshots/sponza_bloom.png new file mode 100644 index 0000000..05042d7 Binary files /dev/null and b/screenshots/sponza_bloom.png differ diff --git a/screenshots/sponza_depth.png b/screenshots/sponza_depth.png new file mode 100644 index 0000000..f2fc9ac Binary files /dev/null and b/screenshots/sponza_depth.png differ diff --git a/screenshots/sponza_diffuse_specular.png b/screenshots/sponza_diffuse_specular.png new file mode 100644 index 0000000..54584a8 Binary files /dev/null and b/screenshots/sponza_diffuse_specular.png differ diff --git a/screenshots/sponza_light.png b/screenshots/sponza_light.png new file mode 100644 index 0000000..5a3ca99 Binary files /dev/null and b/screenshots/sponza_light.png differ diff --git a/screenshots/sponza_normal.png b/screenshots/sponza_normal.png new file mode 100644 index 0000000..51037f2 Binary files /dev/null and b/screenshots/sponza_normal.png differ diff --git a/screenshots/sponza_specular.png b/screenshots/sponza_specular.png new file mode 100644 index 0000000..a356333 Binary files /dev/null and b/screenshots/sponza_specular.png differ diff --git a/screenshots/sponza_toon.png b/screenshots/sponza_toon.png new file mode 100644 index 0000000..b737878 Binary files /dev/null and b/screenshots/sponza_toon.png differ