diff --git a/README.md b/README.md index 09e7f12..fea5ce5 100644 --- a/README.md +++ b/README.md @@ -3,443 +3,88 @@ WebGL Deferred Shading **University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 6** -* (TODO) YOUR NAME HERE -* Tested on: (TODO) **Google Chrome 222.2** on - Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab) +* Ziwei Zong +* Tested on: **Google Chrome 46.0** on + Mac 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Personal) ### Live Online -[![](img/thumb.png)](http://TODO.github.io/Project6-WebGL-Deferred-Shading) +[![](img/FinalRender.png)](http://zammiez.github.io/Project6-WebGL-Deferred-Shading/) ### Demo Video -[![](img/video.png)](TODO) +[![](img/youtube.png)](https://www.youtube.com/watch?v=1ksnaoIVf08&feature=youtu.be) -### (TODO: Your README) - -*DO NOT* leave the README to the last minute! It is a crucial part of the -project, and we will not be able to grade you without a good README. - -This assignment has a considerable amount of performance analysis compared -to implementation work. Complete the implementation early to leave time! - - -Instructions (delete me) +Features ======================== -This is due at midnight on the evening of Tuesday, October 27. - -**Summary:** In this project, you'll be introduced to the basics of deferred -shading and WebGL. You'll use GLSL and WebGL to implement a deferred shading -pipeline and various lighting and visual effects. - -**Recommendations:** -Take screenshots as you go. Use them to document your progress in your README! - -Read (or at least skim) the full README before you begin, so that you know what -to expect and what to prepare for. - -### Running the code - -If you have Python, you should be able to run `server.py` to start a server. -Then, open [`http://localhost:10565/`](http://localhost:10565/) in your browser. - -This project requires a WebGL-capable web browser with support for -`WEBGL_draw_buffers`. You can check for support on -[WebGL Report](http://webglreport.com/). - -Google Chrome seems to work best on all platforms. If you have problems running -the starter code, use Chrome or Chromium, and make sure you have updated your -browser and video drivers. - -In Moore 100C, both Chrome and Firefox work. -See below for notes on profiling/debugging tools. +### Basics -Use the screenshot button to save a screenshot. +![](img/FinalRender.png) -## Requirements +**Debug Views** -**Ask on the mailing list for any clarifications.** +|Depth |Position |Geometry Normal +|:--------------------------:|:-------------------------:|:-------------------------: +|![](img/debug_0depth.png) |![](img/debug_1pos.png) |![](img/debug_2geonor.png) +|Texture Color |Normal Map |Surface Normal +|![](img/debug_3col.png ) |![](img/debug_4normap.png ) |![](img/debug_5nor.png ) -In this project, you are given code for: +### Post Effects -* Loading OBJ files and color/normal map textures -* Camera control -* Partial implementation of deferred shading including many helper functions +Implemented post effects are bloom effect, toon shading and motion blur. -### Required Tasks +####Bloom Effect -**Before doing performance analysis,** you must disable debug mode by changing -`debugMode` to `false` in `framework.js`. Keep it enabled when developing - it -helps find WebGL errors *much* more easily. +![](img/bloomEffect.png) -You will need to perform the following tasks: - -* Complete the deferred shading pipeline so that the Blinn-Phong and Post1 - shaders recieve the correct input. Go through the Starter Code Tour **before - continuing!** - -**Effects:** - -* Implement deferred Blinn-Phong shading (diffuse + specular) for point lights - * With normal mapping (code provided) - * For deferred shading, you want to use a lighting model for the point lights - which has a limited radius - so that adding a scissor or proxy geometry - will not cause parts of the lighting to disappear. It should look very - similar both with and without scissor/proxy optimization. Here is a - convenient lighting model, but you can also use others: - * `float attenuation = max(0.0, u_lightRad - dist_from_surface_to_light);` - -* Implement one of the following effects: - * Bloom using post-process blur (box or Gaussian) [1] - * Toon shading (with ramp shading + simple depth-edge detection for outlines) - -**Optimizations:** - -* Scissor test optimization: when accumulating shading from each point - light source, only render in a rectangle around the light. - * Show a debug view for this (showing scissor masks clearly), e.g. by - modifying and using `red.frag.glsl` with additive blending and alpha = 0.1. - * Code is provided to compute this rectangle for you, and there are - comments at the relevant place in `deferredRender.js` with more guidance. - * **NOTE:** The provided scissor function is not very accurate - it is a - quick hack which results in some errors (as can be seen in the live - demo). - -* Optimized g-buffer format - reduce the number and size of g-buffers: - * Ideas: - * Pack values together into vec4s - * Use 2-component normals - * Quantize values by using smaller texture types instead of gl.FLOAT - * Reduce number of properties passed via g-buffer, e.g. by: - * Applying the normal map in the `copy` shader pass instead of - copying both geometry normals and normal maps - * Reconstructing world space position using camera matrices and X/Y/depth - * For credit, you must show a good optimization effort and record the - performance of each version you test, in a simple table. - * It is expected that you won't need all 4 provided g-buffers for a basic - pipeline - make sure you disable the unused ones. - * See mainly: `copy.frag.glsl`, `deferred/*.glsl`, `deferredSetup.js` - -### Extra Tasks - -You must do at least **10 points** worth of extra features (effects or -optimizations/analysis). - -**Effects:** - -* (3pts) The effect you didn't choose above (bloom or toon shading) - -* (3pts) Screen-space motion blur (blur along velocity direction) [3] - -* (2pts) Allow variability in additional material properties - * Include other properties (e.g. specular coeff/exponent) in g-buffers - * Use this to render objects with different material properties - * These may be uniform across one model draw call, but you'll have to show - multiple models - -**Optimizations/Analysis:** - -* (2pts) Improved screen-space AABB for scissor test - (smaller/more accurate than provided - but beware of CPU/GPU tradeoffs) - -* (3pts) Two-pass **Gaussian** blur using separable convolution (using a second - postprocess render pass) to improve bloom or other 2D blur performance - -* (4-6pts) Light proxies - * (4pts) Instead of rendering a scissored full-screen quad for every light, - render some proxy geometry which covers the part of the screen affected by - the light (e.g. a sphere, for an attenuated point light). - * A model called `sphereModel` is provided which can be drawn in the same - way as the code in `drawScene`. (Must be drawn with a vertex shader which - scales it to the light radius and translates it to the light position.) - * (+2pts) To avoid lighting geometry far behind the light, render the proxy - geometry (e.g. sphere) using an inverted depth test - (`gl.depthFunc(gl.GREATER)`) with depth writing disabled (`gl.depthMask`). - This test will pass only for parts of the screen for which the backside of - the sphere appears behind parts of the scene. - * Note that the copy pass's depth buffer must be bound to the FBO during - this operation! - * Show a debug view for this (showing light proxies) - * Compare performance of this, naive, and scissoring. - -* (8pts) Tile-based deferred shading with detailed performance comparison - * On the CPU, check which lights overlap which tiles. Then, render each tile - just once for all lights (instead of once for each light), applying only - the overlapping lights. - * The method is described very well in - [Yuqin & Sijie's README](https://github.com/YuqinShao/Tile_Based_WebGL_DeferredShader/blob/master/README.md#algorithm-details). - * This feature requires allocating the global light list and tile light - index lists as shown at this link. These can be implemented as textures. - * Show a debug view for this (number of lights per tile) - -* (6pts) Deferred shading without multiple render targets - (i.e. without WEBGL_draw_buffers). - * Render the scene once for each target g-buffer, each time into a different - framebuffer object. - * Include a detailed performance analysis, comparing with/without - WEBGL_draw_buffers (like in the - [Mozilla blog article](https://hacks.mozilla.org/2014/01/webgl-deferred-shading/)). - -* (2-6pts) Compare performance to equivalently-lit forward-rendering: - * (2pts) With no forward-rendering optimizations - * (+2pts) Coarse, per-object back-to-front sorting of geometry for early-z - * (Of course) must render many objects to test - * (+2pts) Z-prepass for early-z - -This extra feature list is not comprehensive. If you have a particular idea -that you would like to implement, please **contact us first** (preferably on -the mailing list). - -**Where possible, all features should be switchable using the GUI panel in -`ui.js`.** - -### Performance & Analysis - -**Before doing performance analysis,** you must disable debug mode by changing -`debugMode` to `false` in `framework.js`. Keep it enabled when developing - it -helps find WebGL errors *much* more easily. - -Optimize your JavaScript and/or GLSL code. Chrome/Firefox's profiling tools -(see Resources section) will be useful for this. For each change -that improves performance, show the before and after render times. - -For each new *effect* feature (required or extra), please -provide the following analysis: - -* Concise overview write-up of the feature. -* Performance change due to adding the feature. - * If applicable, how do parameters (such as number of lights, etc.) - affect performance? Show data with simple graphs. - * Show timing in milliseconds, not FPS. -* If you did something to accelerate the feature, what did you do and why? -* How might this feature be optimized beyond your current implementation? - -For each *performance* feature (required or extra), please provide: - -* Concise overview write-up of the feature. -* Detailed performance improvement analysis of adding the feature - * What is the best case scenario for your performance improvement? What is - the worst? Explain briefly. - * Are there tradeoffs to this performance feature? Explain briefly. - * How do parameters (such as number of lights, tile size, etc.) affect - performance? Show data with graphs. - * Show timing in milliseconds, not FPS. - * Show debug views when possible. - * If the debug view correlates with performance, explain how. - -### Starter Code Tour - -You'll be working mainly in `deferredRender.js` using raw WebGL. Three.js is -included in the project for various reasons. You won't use it for much, but its -matrix/vector types may come in handy. - -It's highly recommended that you use the browser debugger to inspect variables -to get familiar with the code. At any point, you can also -`console.log(some_var);` to show it in the console and inspect it. - -The setup in `deferredSetup` is already done for you, for many of the features. -If you want to add uniforms (textures or values), you'll change them here. -Therefore, it is recommended that you review the comments to understand the -process, BEFORE starting work in `deferredRender`. - -In `deferredRender`, start at the **START HERE!** comment. -Work through the appropriate `TODO`s as you go - most of them are very -small. Test incrementally (after implementing each part, instead of testing -all at once). -* (The first thing you should be doing is implementing the fullscreen quad!) -* See the note in the Debugging section on how to test the first part of the - pipeline incrementally. - -Your _next_ first goal should be to get the debug views working. -Add code in `debug.frag.glsl` to examine your g-buffers before trying to -render them. (Set the debugView in the UI to show them.) - -For editing JavaScript, you can use a simple editor with syntax highlighting -such as Sublime, Vim, Emacs, etc., or the editor built into Chrome. - -* `js/`: JavaScript files for this project. - * `main.js`: Handles initialization of other parts of the program. - * `framework.js`: Loads the scene, camera, etc., and calls your setup/render - functions. Hopefully, you won't need to change anything here. - * `deferredSetup.js`: Deferred shading pipeline setup code. - * `createAndBind(Depth/Color)TargetTexture`: Creates empty textures for - binding to frame buffer objects as render targets. - * `deferredRender.js`: Your deferred shading pipeline execution code. - * `renderFullScreenQuad`: Renders a full-screen quad with the given shader - program. - * `ui.js`: Defines the UI using - [dat.GUI](https://workshop.chromeexperiments.com/examples/gui/). - * The global variable `cfg` can be accessed anywhere in the code to read - configuration values. - * `utils.js`: Utilities for JavaScript and WebGL. - * `abort`: Aborts the program and shows an error. - * `loadTexture`: Loads a texture from a URL into WebGL. - * `loadShaderProgram`: Loads shaders from URLs into a WebGL shader program. - * `loadModel`: Loads a model into WebGL buffers. - * `readyModelForDraw`: Configures the WebGL state to draw a model. - * `drawReadyModel`: Draws a model which has been readied. - * `getScissorForLight`: Computes an approximate scissor rectangle for a - light in world space. -* `glsl/`: GLSL code for each part of the pipeline: - * `clear.*.glsl`: Clears each of the `NUM_GBUFFERS` g-buffers. - * `copy.*.glsl`: Performs standard rendering without any fragment shading, - storing all of the resulting values into the `NUM_GBUFFERS` g-buffers. - * `quad.vert.glsl`: Minimal vertex shader for rendering a single quad. - * `deferred.frag.glsl`: Deferred shading pass (for lighting calculations). - Reads from each of the `NUM_GBUFFERS` g-buffers. - * `post1.frag.glsl`: First post-processing pass. -* `lib/`: JavaScript libraries. -* `models/`: OBJ models for testing. Sponza is the default. -* `index.html`: Main HTML page. -* `server.bat` (Windows) or `server.py` (OS X/Linux): - Runs a web server at `localhost:10565`. - -### The Deferred Shading Pipeline - -See the comments in `deferredSetup.js`/`deferredRender.js` for low-level guidance. - -In order to enable and disable effects using the GUI, upload a vec4 uniform -where each component is an enable/disable flag. In JavaScript, the state of the -UI is accessible anywhere as `cfg.enableEffect0`, etc. - -**Pass 1:** Renders the scene geometry and its properties to the g-buffers. -* `copy.vert.glsl`, `copy.frag.glsl` -* The framebuffer object `pass_copy.fbo` must be bound during this pass. -* Renders into `pass_copy.depthTex` and `pass_copy.gbufs[i]`, which need to be - attached to the framebuffer. - -**Pass 2:** Performs lighting and shading into the color buffer. -* `quad.vert.glsl`, `deferred/blinnphong-pointlight.frag.glsl` -* Takes the g-buffers `pass_copy.gbufs`/`depthTex` as texture inputs to the - fragment shader, on uniforms `u_gbufs` and `u_depth`. -* `pass_deferred.fbo` must be bound. -* Renders into `pass_deferred.colorTex`. - -**Pass 3:** Performs post-processing. -* `quad.vert.glsl`, `post/one.frag.glsl` -* Takes `pass_BlinnPhong_PointLight.colorTex` as a texture input `u_color`. -* Renders directly to the screen if there are no additional passes. - -More passes may be added for additional effects (e.g. combining bloom with -motion blur) or optimizations (e.g. two-pass Gaussian blur for bloom) - -#### Debugging - -If there is a WebGL error, it will be displayed on the developer console and -the renderer will be aborted. To find out where the error came from, look at -the backtrace of the error (you may need to click the triangle to expand the -message). The line right below `wrapper @ webgl-debug.js` will point to the -WebGL call that failed. - -When working in the early pipeline (before you have a lit render), it can be -useful to render WITHOUT post-processing. To do this, you have to make sure -that there is NO framebuffer bound while rendering to the screen (that is, bind -null) so that the output will display to the screen instead of saving into a -texture. Writing to gl_FragData[0] is the same as writing to gl_FragColor, so -you'll see whatever you were storing into the first g-buffer. - -#### Changing the number of g-buffers - -Note that the g-buffers are just `vec4`s - you can put any values you want into -them. However, if you want to change the total number of g-buffers (add more -for additional effects or remove some for performance), you will need to make -changes in a number of places: - -* `deferredSetup.js`/`deferredRender.js`: search for `NUM_GBUFFERS` -* `copy.frag.glsl` -* `deferred.frag.glsl` -* `clear.frag.glsl` - - -## Resources +Followed steps in [GPU Gems 3, Ch. 27](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch27.html),first get the lighting source, blur it and then add it with original picture. -* [1] Bloom: - [GPU Gems, Ch. 21](http://http.developer.nvidia.com/GPUGems/gpugems_ch21.html) -* [2] Screen-Space Ambient Occlusion: - [Floored Article](http://floored.com/blog/2013/ssao-screen-space-ambient-occlusion.html) -* [3] Post-Process Motion Blur: - [GPU Gems 3, Ch. 27](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch27.html) - -**Also see:** The articles linked in the course schedule. - -### Profiling and debugging tools - -Built into Firefox: -* Canvas inspector -* Shader Editor -* JavaScript debugger and profiler +|Masked Source| Gaussian blurred source| +|:--------------------------:|:-------------------------:| +|![](img/Bloom_srcMask_.png) |![](img/Bloom_srcMaskBlurred_.png) | -Built into Chrome: -* JavaScript debugger and profiler +####Toon Shading -Plug-ins: -* Web Tracing Framework - **Does not currently work with multiple render targets**, - which are used in the starter code. -* (Chrome) [Shader Editor](https://chrome.google.com/webstore/detail/shader-editor/ggeaidddejpbakgafapihjbgdlbbbpob) +![](img/toonShading.png) -Libraries: -* Stats.js (already included) +####Motion Blur -Firefox can also be useful - it has a canvas inspector, WebGL profiling and a -shader editor built in. +![](img/MotionBlur.png) -## README - -Replace the contents of this README.md in a clear manner with the following: +Optimizations +======================== -* A brief description of the project and the specific features you implemented. -* At least one screenshot of your project running. -* A 30+ second video of your project running showing all features. - [Open Broadcaster Software](http://obsproject.com) is recommended. - (Even though your demo can be seen online, using multiple render targets - means it won't run on many computers. A video will work everywhere.) -* A performance analysis (described below). +### Scissor Test -### Performance Analysis +![](img/Opt_ScissorDebug.png) -See above. +Instead of rendering the full quad, scissor test allows it to render only a bounding box in the frame (as shown in the debug image above). The performance if almost three times faster after using scissor test, as shown below. -### GitHub Pages +![](img/Opt_ScissorTest.png) -Since this assignment is in WebGL, you can make your project easily viewable by -taking advantage of GitHub's project pages feature. +### Two-pass Gaussian for Bloom Effect -Once you are done with the assignment, create a new branch: +Using the method in [[1]](http://http.developer.nvidia.com/GPUGems/gpugems_ch21.html) with a convolution widow of 7x7,first blur the masked source in X direction and then in Y direction. Though I haven't implement single pass method, I assume two-pass can improve the performance due to the reason that it total computs 7xres +7xres = 14res pixels while one-pass method computes 7x7xres = 49res pixels. -`git branch gh-pages` +### G-Buffer Optimization -Push the branch to GitHub: +![](img/Opt_G_Buff.png) -`git push origin gh-pages` +These two methods below are used to reduce the g-buffer size: -Now, you can go to `.github.io/` to see your -renderer online from anywhere. Add this link to your README. +* Apply geometry normal and normal map in copy.frag: doing so directly reduces one g-buffer. -## Submit +* Reduce normal size and pack them into position buffer and color buffer: only keep two elements in the normal vector, then put each of them into the pos.a and color.a relatively. The g-buffer size then reduced to only two. However, after reducing the normal size, there are some black spots on some surfaces. -1. Open a GitHub pull request so that we can see that you have finished. - The title should be "Submission: YOUR NAME". - * **ADDITIONALLY:** - In the body of the pull request, include a link to your repository. -2. Send an email to the TA (gmail: kainino1+cis565@) with: - * **Subject**: in the form of `[CIS565] Project N: PENNKEY`. - * Direct link to your pull request on GitHub. - * Estimate the amount of time you spent on the project. - * If there were any outstanding problems, briefly explain. - * **List the extra features you did.** - * Feedback on the project itself, if any. +![](img/Opt_G_Buff_bSpot.png) -### Third-Party Code Policy +Resources +======================== -* Use of any third-party code must be approved by asking on our mailing list. -* 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 path 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, at minimum, - result in you receiving an F for the semester. +* [1] Bloom: + [GPU Gems, Ch. 21](http://http.developer.nvidia.com/GPUGems/gpugems_ch21.html) +//* [2] Screen-Space Ambient Occlusion: +// [Floored Article](http://floored.com/blog/2013/ssao-screen-space-ambient-occlusion.html) +* [2] Post-Process Motion Blur: + [GPU Gems 3, Ch. 27](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch27.html) diff --git a/glsl/.DS_Store b/glsl/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/glsl/.DS_Store differ diff --git a/glsl/copy.frag.glsl b/glsl/copy.frag.glsl index 0f5f8f7..8089f59 100644 --- a/glsl/copy.frag.glsl +++ b/glsl/copy.frag.glsl @@ -10,6 +10,25 @@ varying vec3 v_position; varying vec3 v_normal; varying vec2 v_uv; +vec3 applyNormalMap(vec3 geomnor, vec3 normap) { + normap = normap * 2.0 - 1.0; + vec3 up = normalize(vec3(0.001, 1, 0.001)); + vec3 surftan = normalize(cross(geomnor, up)); + vec3 surfbinor = cross(geomnor, surftan); + return normap.y * surftan + normap.x * surfbinor + normap.z * geomnor; +} + void main() { // TODO: copy values into gl_FragData[0], [1], etc. + + vec3 geomnor = v_normal; + vec3 normap = texture2D(u_normap,v_uv).rgb; + vec3 nor = normalize(applyNormalMap(geomnor,normap)); + + gl_FragData[0] = vec4(v_position,nor.x); + + vec3 col = texture2D(u_colmap,v_uv).rgb*texture2D(u_colmap,v_uv).a; + gl_FragData[1] = vec4(col,nor.z); + //gl_FragData[2] = vec4(col,nor.z); + //gl_FragData[3] = vec4(texture2D(u_normap,v_uv)); } diff --git a/glsl/deferred/ambient.frag.glsl b/glsl/deferred/ambient.frag.glsl index 1fd4647..47a191e 100644 --- a/glsl/deferred/ambient.frag.glsl +++ b/glsl/deferred/ambient.frag.glsl @@ -3,7 +3,7 @@ precision highp float; precision highp int; -#define NUM_GBUFFERS 4 +#define NUM_GBUFFERS 2 uniform sampler2D u_gbufs[NUM_GBUFFERS]; uniform sampler2D u_depth; @@ -11,17 +11,20 @@ uniform sampler2D u_depth; varying vec2 v_uv; void main() { - vec4 gb0 = texture2D(u_gbufs[0], v_uv); - vec4 gb1 = texture2D(u_gbufs[1], v_uv); - vec4 gb2 = texture2D(u_gbufs[2], v_uv); - vec4 gb3 = texture2D(u_gbufs[3], v_uv); + //vec4 gb0 = texture2D(u_gbufs[0], v_uv); + //vec4 gb1 = texture2D(u_gbufs[1], v_uv); + vec4 gb2 = texture2D(u_gbufs[1], v_uv); + //vec4 gb3 = texture2D(u_gbufs[3], v_uv); float depth = texture2D(u_depth, v_uv).x; // TODO: Extract needed properties from the g-buffers into local variables - + vec3 colmap = gb2.xyz; + if (depth == 1.0) { gl_FragColor = vec4(0, 0, 0, 0); // set alpha to 0 return; } - gl_FragColor = vec4(0.1, 0.1, 0.1, 1); // TODO: replace this + // TODO: replace this + colmap = clamp(colmap,0.0,1.0); + gl_FragColor = vec4(0.2*colmap,1.0);//vec4(0.1, 0.1, 0.1, 1); } diff --git a/glsl/deferred/blinnphong-pointlight.frag.glsl b/glsl/deferred/blinnphong-pointlight.frag.glsl index b24a54a..bbad772 100644 --- a/glsl/deferred/blinnphong-pointlight.frag.glsl +++ b/glsl/deferred/blinnphong-pointlight.frag.glsl @@ -2,8 +2,10 @@ precision highp float; precision highp int; -#define NUM_GBUFFERS 4 +#define NUM_GBUFFERS 2 +uniform bool u_toon; +uniform vec3 u_camPos; uniform vec3 u_lightCol; uniform vec3 u_lightPos; uniform float u_lightRad; @@ -12,21 +14,26 @@ uniform sampler2D u_depth; varying vec2 v_uv; -vec3 applyNormalMap(vec3 geomnor, vec3 normap) { - normap = normap * 2.0 - 1.0; - vec3 up = normalize(vec3(0.001, 1, 0.001)); - vec3 surftan = normalize(cross(geomnor, up)); - vec3 surfbinor = cross(geomnor, surftan); - return normap.y * surftan + normap.x * surfbinor + normap.z * geomnor; -} - void main() { - vec4 gb0 = texture2D(u_gbufs[0], v_uv); - vec4 gb1 = texture2D(u_gbufs[1], v_uv); - vec4 gb2 = texture2D(u_gbufs[2], v_uv); - vec4 gb3 = texture2D(u_gbufs[3], v_uv); + vec4 gb0 = texture2D(u_gbufs[0], v_uv); //pos + //vec4 gb1 = texture2D(u_gbufs[1], v_uv); //nor + vec4 gb2 = texture2D(u_gbufs[1], v_uv); //colmap float depth = texture2D(u_depth, v_uv).x; - // TODO: Extract needed properties from the g-buffers into local variables + + vec3 pos = gb0.xyz; + vec3 diff = gb2.xyz; + vec3 nor = vec3(gb0.a,0.0,gb2.a); + + //nor.x = sqrt(1.0 - nor.y*nor.y - nor.z*nor.z); + nor.y = sqrt(1.0 - nor.x*nor.x - nor.z*nor.z); + //nor.z = sqrt(1.0-nor.x*nor.x-nor.y*nor.y); + vec3 viewDir = normalize(u_camPos - pos); + + if(dot(-viewDir,nor)<=0.0) nor.y = -nor.y; + + vec3 lightDir = normalize(u_lightPos - pos); + vec3 reflDir = reflect(-lightDir,nor); + // If nothing was rendered to this pixel, set alpha to 0 so that the // postprocessing step can render the sky color. @@ -34,6 +41,26 @@ void main() { gl_FragColor = vec4(0, 0, 0, 0); return; } - - gl_FragColor = vec4(0, 0, 1, 1); // TODO: perform lighting calculations + //http://www.mathematik.uni-marburg.de/~thormae/lectures/graphics1/code/WebGLShaderLightMat/ShaderLightMat.html + // TO_DO: perform lighting calculations + + float attenuation = max(0.0, u_lightRad - length(pos-u_lightPos)); + attenuation/=u_lightRad; + //attenuation*=attenuation; + float lamb = max(dot(lightDir,nor),0.0); + float spec = 0.0; + if(lamb>0.0) + { + float specAngle = max(dot(reflDir,viewDir),0.0); + spec = pow(specAngle,4.0); + } + if(u_toon)//toon + { + //lamb = lamb>0.5?1.0:0.0; + if(lamb<0.1) lamb = 0.0; + else if(lamb<0.6) lamb = 0.6; + else lamb = 1.0; + spec = spec>0.5?1.0:0.0; + } + gl_FragColor = vec4(attenuation*(lamb+spec)*diff*u_lightCol, 1.0); } diff --git a/glsl/deferred/debug.frag.glsl b/glsl/deferred/debug.frag.glsl index 9cbfae4..c6a15a0 100644 --- a/glsl/deferred/debug.frag.glsl +++ b/glsl/deferred/debug.frag.glsl @@ -2,7 +2,7 @@ precision highp float; precision highp int; -#define NUM_GBUFFERS 4 +#define NUM_GBUFFERS 2 uniform int u_debug; uniform sampler2D u_gbufs[NUM_GBUFFERS]; @@ -22,30 +22,26 @@ vec3 applyNormalMap(vec3 geomnor, vec3 normap) { void main() { vec4 gb0 = texture2D(u_gbufs[0], v_uv); - vec4 gb1 = texture2D(u_gbufs[1], v_uv); - vec4 gb2 = texture2D(u_gbufs[2], v_uv); - vec4 gb3 = texture2D(u_gbufs[3], v_uv); + //vec4 gb1 = texture2D(u_gbufs[1], v_uv); + vec4 gb2 = texture2D(u_gbufs[1], v_uv); + //vec4 gb3 = texture2D(u_gbufs[3], v_uv); float depth = texture2D(u_depth, v_uv).x; - // TODO: Extract needed properties from the g-buffers into local variables + // TO_DO: Extract needed properties from the g-buffers into local variables // These definitions are suggested for starting out, but you will probably want to change them. - vec3 pos; // World-space position - vec3 geomnor; // Normals of the geometry as defined, without normal mapping - vec3 colmap; // The color map - unlit "albedo" (surface color) - vec3 normap; // The raw normal map (normals relative to the surface they're on) - vec3 nor; // The true normals as we want to light them - with the normal map applied to the geometry normals (applyNormalMap above) + vec3 pos = gb0.xyz; // World-space position + vec3 colmap = gb2.xyz; // Normals of the geometry as defined, without normal mapping + vec3 nor = vec3(gb0.a,0.0,gb2.a); + nor.y = sqrt(1.0 - nor.x*nor.x - nor.z*nor.z); + if (u_debug == 0) { gl_FragColor = vec4(vec3(depth), 1.0); } else if (u_debug == 1) { gl_FragColor = vec4(abs(pos) * 0.1, 1.0); } else if (u_debug == 2) { - gl_FragColor = vec4(abs(geomnor), 1.0); + gl_FragColor = vec4(abs(nor), 1.0); } else if (u_debug == 3) { gl_FragColor = vec4(colmap, 1.0); - } else if (u_debug == 4) { - gl_FragColor = vec4(normap, 1.0); - } else if (u_debug == 5) { - gl_FragColor = vec4(abs(nor), 1.0); } else { gl_FragColor = vec4(1, 0, 1, 1); } diff --git a/glsl/deferred/untitled 2.txt b/glsl/deferred/untitled 2.txt new file mode 100644 index 0000000..e69de29 diff --git a/glsl/deferred/untitled.txt b/glsl/deferred/untitled.txt new file mode 100644 index 0000000..e69de29 diff --git a/glsl/post/bloomX.frag.glsl b/glsl/post/bloomX.frag.glsl new file mode 100644 index 0000000..acb7a23 --- /dev/null +++ b/glsl/post/bloomX.frag.glsl @@ -0,0 +1,33 @@ +#version 100 +precision highp float; +precision highp int; + +uniform sampler2D u_color; +uniform vec2 u_texSize; + +varying vec2 v_uv; + +const vec4 SKY_COLOR = vec4(0.01, 0.14, 0.42, 1.0); + +void main() { + + vec2 onePixel = vec2(1.0,1.0)/u_texSize; + vec4 gauss = vec4 (10.0,8.0,5.0,2.0) ; + gauss*=(1.0/25.0); + vec4 color = vec4 (0.0,0.0,0.0,0.0);//texture2D(u_color, v_uv); + + color += texture2D(u_color, v_uv + onePixel * vec2(0, 0))*gauss[0]; + + color += texture2D(u_color, v_uv + onePixel * vec2(-1, 0))*gauss[1]; + color += texture2D(u_color, v_uv + onePixel * vec2(-2, 0))*gauss[2]; + color += texture2D(u_color, v_uv + onePixel * vec2(-3, 0))*gauss[3]; + + color += texture2D(u_color, v_uv + onePixel * vec2(1, 0))*gauss[1]; + color += texture2D(u_color, v_uv + onePixel * vec2(2, 0))*gauss[2]; + color += texture2D(u_color, v_uv + onePixel * vec2(3, 0))*gauss[3]; + + + gl_FragColor = color; + + //gl_FragColor = texture2D(u_color, v_uv); +} diff --git a/glsl/post/bloomY.frag.glsl b/glsl/post/bloomY.frag.glsl new file mode 100644 index 0000000..4228a87 --- /dev/null +++ b/glsl/post/bloomY.frag.glsl @@ -0,0 +1,41 @@ +#version 100 +precision highp float; +precision highp int; + +uniform sampler2D u_color; +uniform sampler2D u_origCol; + +uniform int u_debug; +uniform vec2 u_texSize; + +varying vec2 v_uv; + +const vec4 SKY_COLOR = vec4(0.01, 0.14, 0.42, 1.0); + +void main() { + + vec2 onePixel = vec2(1.0,1.0)/u_texSize; + vec4 gauss = vec4 (10.0,8.0,5.0,2.0) ; + gauss*=(1.0/25.0); + vec4 color = vec4 (0.0,0.0,0.0,0.0);//texture2D(u_color, v_uv); + + color += texture2D(u_color, v_uv + onePixel * vec2(0, 0))*gauss[0]; + + color += texture2D(u_color, v_uv + onePixel * vec2(0, 1))*gauss[1]; + color += texture2D(u_color, v_uv + onePixel * vec2(0, 2))*gauss[2]; + color += texture2D(u_color, v_uv + onePixel * vec2(0, 3))*gauss[3]; + + color += texture2D(u_color, v_uv + onePixel * vec2(0, -1))*gauss[1]; + color += texture2D(u_color, v_uv + onePixel * vec2(0, -2))*gauss[2]; + color += texture2D(u_color, v_uv + onePixel * vec2(0, -3))*gauss[3]; + + + //gl_FragColor = color; + vec4 origCol = texture2D(u_origCol, v_uv); + if (origCol.a == 0.0) { + origCol = SKY_COLOR; + } + if(u_debug==5) origCol = vec4(0.0); + gl_FragColor = color+origCol; + +} diff --git a/glsl/post/motion.frag.glsl b/glsl/post/motion.frag.glsl new file mode 100644 index 0000000..ba64b40 --- /dev/null +++ b/glsl/post/motion.frag.glsl @@ -0,0 +1,59 @@ +#version 100 +precision highp float; +precision highp int; + +uniform sampler2D u_color; +uniform sampler2D u_pos; +//uniform sampler2D u_depthTex; + +uniform mat4 u_cameraMat; +uniform mat4 u_prevMat; + + +uniform vec3 u_crntEye; +uniform vec3 u_prevEye; + +uniform vec2 u_texSize; + +varying vec2 v_uv; + +const vec4 SKY_COLOR = vec4(0.01, 0.14, 0.42, 1.0); + +float rand(vec2 co){ + return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); +} + +void main() { + + vec2 oneP = vec2(1.0,1.0)/u_texSize; + + vec4 origCol = texture2D(u_color, v_uv); + + vec4 testM = vec4(0.5,0.5,0.5,1.0); + if(u_crntEye==u_prevEye) testM.r = 0.7; + //if(u_cameraMat==u_prevMat) testM.r = 0.7; + else testM.g = 0.7; + + vec3 vel = u_prevEye-u_crntEye; + vec3 pos = texture2D(u_pos, v_uv).xyz; + vec3 newPos = pos+vel; + + vec2 sc_pos = (vec4(pos,1.0)*u_prevMat).xy; + vec2 sc_newPos = (vec4(newPos,1.0)*u_cameraMat).xy; + + vec2 uv_vel = (sc_newPos-sc_pos).xy*0.5; + + origCol = vec4(0.0,0.0,0.0,0.0);//origCol*(1.0/11.0); + //v_uv += vel.xy*oneP; + + for(int i = 0; i < 10; ++i) + { + vec4 tempCol = texture2D(u_color, v_uv + float(i)*oneP*uv_vel); + origCol += tempCol/10.0; + } + + + gl_FragColor = origCol;//*testM; + + //gl_FragColor = texture2D(u_color, v_uv); +} diff --git a/glsl/post/one.frag.glsl b/glsl/post/one.frag.glsl index 94191cd..03e6d89 100644 --- a/glsl/post/one.frag.glsl +++ b/glsl/post/one.frag.glsl @@ -3,12 +3,12 @@ precision highp float; precision highp int; uniform sampler2D u_color; - varying vec2 v_uv; const vec4 SKY_COLOR = vec4(0.01, 0.14, 0.42, 1.0); void main() { + vec4 color = texture2D(u_color, v_uv); if (color.a == 0.0) { diff --git a/glsl/post/srcmask.frag.glsl b/glsl/post/srcmask.frag.glsl new file mode 100644 index 0000000..644041a --- /dev/null +++ b/glsl/post/srcmask.frag.glsl @@ -0,0 +1,27 @@ +#version 100 +precision highp float; +precision highp int; + +uniform sampler2D u_color; +uniform float u_thresh; +varying vec2 v_uv; + +const vec4 SKY_COLOR = vec4(0.01, 0.14, 0.42, 1.0); + +void main() { + + vec4 org_color = texture2D(u_color, v_uv); + vec4 color = org_color;//clamp(org_color,0.0,1.0); + float colMag = color.a*length(color.rgb); + + + //gl_FragColor = color; + //return; + + if (colMag>=u_thresh)//TODO: later,uniform + { + gl_FragColor = org_color; + } + else + gl_FragColor = vec4(0,0,0,0); +} diff --git a/glsl/post/toon.frag.glsl b/glsl/post/toon.frag.glsl new file mode 100644 index 0000000..60d2f07 --- /dev/null +++ b/glsl/post/toon.frag.glsl @@ -0,0 +1,79 @@ +#version 100 +precision highp float; +precision highp int; + +uniform sampler2D u_color; +uniform sampler2D u_depthTex; + +uniform vec2 u_texSize; +//uniform float u_thresh; +varying vec2 v_uv; + +const vec4 SKY_COLOR = vec4(0.01, 0.14, 0.42, 1.0); + +vec4 applyKernel(vec2 onePixel,mat3 kern) +{ + vec4 color = vec4 (0.0,0.0,0.0,0.0);//texture2D(u_color, v_uv); + + color += texture2D(u_depthTex, v_uv + onePixel * vec2(-1, -1))*kern[0][0]; + color += texture2D(u_depthTex, v_uv + onePixel * vec2(-1, 0))*kern[0][1]; + color += texture2D(u_depthTex, v_uv + onePixel * vec2(-1, 1))*kern[0][2]; + + color += texture2D(u_depthTex, v_uv + onePixel * vec2( 0, -1))*kern[1][0]; + color += texture2D(u_depthTex, v_uv + onePixel * vec2( 0, 0))*kern[1][1]; + color += texture2D(u_depthTex, v_uv + onePixel * vec2( 0, 1))*kern[1][2]; + + color += texture2D(u_depthTex, v_uv + onePixel * vec2( 1, -1))*kern[2][0]; + color += texture2D(u_depthTex, v_uv + onePixel * vec2( 1, 0))*kern[2][1]; + color += texture2D(u_depthTex, v_uv + onePixel * vec2( 1, 1))*kern[2][2]; + + return color; +} + +float discrete(float inCol,int level) +{ + inCol = clamp(inCol,0.0,1.0); + if(inCol>=0.2) return inCol; + if(inCol>=0.1) return 0.15; + if(inCol>=0.05) return 0.10; + else return 0.0; + return inCol; + /* + int temp = int(inCol*float(level)); + temp =temp - (temp/level)*level; + return float(temp); + */ +} + +void main() { + //edge + //http://www.greenbushlabs.com/ThreeJS/examples/webgl_postprocessing2.html + //https://en.wikipedia.org/wiki/Cel_shading#Process + vec2 oneP = vec2(1.0,1.0)/u_texSize; + + mat3 edgeX = mat3( + -1.0, 0.0, 1.0, + -2.0, 0.0, 2.0, + -1.0, 0.0, 1.0); + mat3 edgeY = mat3( + -1.0, -2.0, -1.0, + 0.0, 0.0, 0.0, + 1.0, 2.0, 1.0); + + vec4 edgeCol = applyKernel(oneP,edgeX); + edgeCol += applyKernel(oneP,edgeY); + + edgeCol = abs(edgeCol); + if(length(edgeCol.rgb)>0.05) edgeCol = vec4(0,0,0,1); + else edgeCol = vec4(1,1,1,1); + + vec4 color = texture2D(u_color, v_uv); + + color.r = discrete(color.r,3); + color.g = discrete(color.g,3); + color.b = discrete(color.b,3); + //color.a = 1.0;//discrete(color.a,3); + //if(length(color.rgb)<=0.3) color = vec4(0.1); + gl_FragColor = edgeCol*color; + +} diff --git a/glsl/red.frag.glsl b/glsl/red.frag.glsl index f8ef1ec..de9826b 100644 --- a/glsl/red.frag.glsl +++ b/glsl/red.frag.glsl @@ -3,5 +3,5 @@ precision highp float; precision highp int; void main() { - gl_FragColor = vec4(1, 0, 0, 1); + gl_FragColor = vec4(0.8, 0, 0.8, 0.1); } diff --git a/img/.DS_Store b/img/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/img/.DS_Store differ diff --git a/img/Bloom_srcMask.png b/img/Bloom_srcMask.png new file mode 100644 index 0000000..f7be36a Binary files /dev/null and b/img/Bloom_srcMask.png differ diff --git a/img/Bloom_srcMaskBlurred.png b/img/Bloom_srcMaskBlurred.png new file mode 100644 index 0000000..acbf892 Binary files /dev/null and b/img/Bloom_srcMaskBlurred.png differ diff --git a/img/Bloom_srcMaskBlurred_.png b/img/Bloom_srcMaskBlurred_.png new file mode 100644 index 0000000..9281425 Binary files /dev/null and b/img/Bloom_srcMaskBlurred_.png differ diff --git a/img/Bloom_srcMask_.png b/img/Bloom_srcMask_.png new file mode 100644 index 0000000..f94aaad Binary files /dev/null and b/img/Bloom_srcMask_.png differ diff --git a/img/FinalRender.png b/img/FinalRender.png new file mode 100644 index 0000000..4e41330 Binary files /dev/null and b/img/FinalRender.png differ diff --git a/img/MotionBlur.png b/img/MotionBlur.png new file mode 100644 index 0000000..3c202cd Binary files /dev/null and b/img/MotionBlur.png differ diff --git a/img/OptAna.xlsx b/img/OptAna.xlsx new file mode 100644 index 0000000..52c1cde Binary files /dev/null and b/img/OptAna.xlsx differ diff --git a/img/Opt_G_Buff.png b/img/Opt_G_Buff.png new file mode 100644 index 0000000..2d64485 Binary files /dev/null and b/img/Opt_G_Buff.png differ diff --git a/img/Opt_G_Buff_bSpot.png b/img/Opt_G_Buff_bSpot.png new file mode 100644 index 0000000..0c07730 Binary files /dev/null and b/img/Opt_G_Buff_bSpot.png differ diff --git a/img/Opt_ScissorDebug.png b/img/Opt_ScissorDebug.png new file mode 100644 index 0000000..ce81f78 Binary files /dev/null and b/img/Opt_ScissorDebug.png differ diff --git a/img/Opt_ScissorTest.png b/img/Opt_ScissorTest.png new file mode 100644 index 0000000..659cccf Binary files /dev/null and b/img/Opt_ScissorTest.png differ diff --git a/img/Screen Shot 2015-10-25 at 8.45.51 PM.png b/img/Screen Shot 2015-10-25 at 8.45.51 PM.png new file mode 100644 index 0000000..de57f98 Binary files /dev/null and b/img/Screen Shot 2015-10-25 at 8.45.51 PM.png differ diff --git a/img/Screen Shot 2015-10-27 at 12.07.14 PM.png b/img/Screen Shot 2015-10-27 at 12.07.14 PM.png new file mode 100644 index 0000000..1814ff9 Binary files /dev/null and b/img/Screen Shot 2015-10-27 at 12.07.14 PM.png differ diff --git a/img/bloomEffect.png b/img/bloomEffect.png new file mode 100644 index 0000000..5a30b14 Binary files /dev/null and b/img/bloomEffect.png differ diff --git a/img/bloom_source_mask.png b/img/bloom_source_mask.png new file mode 100644 index 0000000..9ab45fa Binary files /dev/null and b/img/bloom_source_mask.png differ diff --git a/img/debug_0depth.png b/img/debug_0depth.png new file mode 100644 index 0000000..0db5f7a Binary files /dev/null and b/img/debug_0depth.png differ diff --git a/img/debug_1pos.png b/img/debug_1pos.png new file mode 100644 index 0000000..4ec6a89 Binary files /dev/null and b/img/debug_1pos.png differ diff --git a/img/debug_2geonor.png b/img/debug_2geonor.png new file mode 100644 index 0000000..eb468b0 Binary files /dev/null and b/img/debug_2geonor.png differ diff --git a/img/debug_3col.png b/img/debug_3col.png new file mode 100644 index 0000000..12ee022 Binary files /dev/null and b/img/debug_3col.png differ diff --git a/img/debug_4normap.png b/img/debug_4normap.png new file mode 100644 index 0000000..158fa5a Binary files /dev/null and b/img/debug_4normap.png differ diff --git a/img/debug_5nor.png b/img/debug_5nor.png new file mode 100644 index 0000000..13a3f14 Binary files /dev/null and b/img/debug_5nor.png differ diff --git a/img/toonShading.png b/img/toonShading.png new file mode 100644 index 0000000..bc9569e Binary files /dev/null and b/img/toonShading.png differ diff --git a/img/toon_edgeDetect.png b/img/toon_edgeDetect.png new file mode 100644 index 0000000..dae0ccc Binary files /dev/null and b/img/toon_edgeDetect.png differ diff --git a/img/youtube.png b/img/youtube.png new file mode 100644 index 0000000..b6b0dbd Binary files /dev/null and b/img/youtube.png differ diff --git a/js/deferredRender.js b/js/deferredRender.js index b1f238b..3b4e2de 100644 --- a/js/deferredRender.js +++ b/js/deferredRender.js @@ -1,7 +1,13 @@ (function() { 'use strict'; // deferredSetup.js must be loaded first - + var statePrevMat = new Float32Array([ + 1.0,1.0,1.0,1.0, + 1.0,1.0,1.0,1.0, + 1.0,1.0,1.0,1.0, + 1.0,1.0,1.0,1.0 + ]); + var prevEye = new Float32Array([0.0,0.0,0.0]); R.deferredRender = function(state) { if (!aborted && ( !R.progCopy || @@ -10,7 +16,13 @@ !R.prog_Ambient || !R.prog_BlinnPhong_PointLight || !R.prog_Debug || - !R.progPost1)) { + !R.progPost1 || + !R.progSrcmask|| + !R.progBloomX|| + !R.progBloomY|| + !R.progToon|| + !R.progMotion + )) { console.log('waiting for programs to load...'); return; } @@ -27,26 +39,51 @@ // CHECKITOUT: START HERE! You can even uncomment this: //debugger; - - { // TODO: this block should be removed after testing renderFullScreenQuad +/* + { // TO_DO: this block should be removed after testing renderFullScreenQuad gl.bindFramebuffer(gl.FRAMEBUFFER, null); - // TODO: Implement/test renderFullScreenQuad first + // TO_DO: Implement/test renderFullScreenQuad first renderFullScreenQuad(R.progRed); return; } - +//*/ R.pass_copy.render(state); - if (cfg && cfg.debugView >= 0) { + if (cfg && cfg.debugView >= 0 && cfg.debugView<=3) { // Do a debug render instead of a regular render // Don't do any post-processing in debug mode R.pass_debug.render(state); } else { // * Deferred pass and postprocessing pass(es) // TODO: uncomment these - //R.pass_deferred.render(state); - //R.pass_post1.render(state); - + R.pass_deferred.render(state); + var finalRender = R.pass_deferred.colorTex; + if(cfg.bloomEffect) + { + R.pass_srcmask.render(state); + if(cfg.debugView==4) + { + finalRender = R.pass_srcmask.colorTex; + } + else + { + R.pass_bloomX.render(state); + R.pass_bloomY.render(state); + finalRender = R.pass_bloomY.colorTex; + } + + } + else if(cfg.toonEffect)//TODO:later if + { + R.pass_toon.render(state); + finalRender = R.pass_toon.colorTex; + } + else if(cfg.motionBlurEffect) + { + R.pass_motion.render(state); + finalRender = R.pass_motion.colorTex; + } + R.pass_post1.render(state,finalRender); // OPTIONAL TODO: call more postprocessing passes, if any } }; @@ -56,23 +93,26 @@ */ R.pass_copy.render = function(state) { // * Bind the framebuffer R.pass_copy.fbo - // TODO: ^ - + // TO_DO: ^ + gl.bindFramebuffer(gl.FRAMEBUFFER,R.pass_copy.fbo); // * Clear screen using R.progClear - TODO: renderFullScreenQuad(R.progClear); + //TO_DO: + renderFullScreenQuad(R.progClear); // * Clear depth buffer to value 1.0 using gl.clearDepth and gl.clear - // TODO: ^ - // TODO: ^ - + // TO_DO: ^ + gl.clearDepth(1.0); + // TO_DO: ^ + gl.clear(gl.DEPTH_BUFFER_BIT); // * "Use" the program R.progCopy.prog - // TODO: ^ + // TO_DO: ^ // TODO: Write glsl/copy.frag.glsl - + gl.useProgram(R.progCopy.prog); + var m = state.cameraMat.elements; // * Upload the camera matrix m to the uniform R.progCopy.u_cameraMat // using gl.uniformMatrix4fv - // TODO: ^ - + // TO_DO: ^ + gl.uniformMatrix4fv(R.progCopy.u_cameraMat,gl.FALSE,m); // * Draw the scene drawScene(state); }; @@ -108,18 +148,15 @@ R.pass_deferred.render = function(state) { // * Bind R.pass_deferred.fbo to write into for later postprocessing gl.bindFramebuffer(gl.FRAMEBUFFER, R.pass_deferred.fbo); - + //gl.bindFramebuffer(gl.FRAMEBUFFER, null); + // * Clear depth to 1.0 and color to black gl.clearColor(0.0, 0.0, 0.0, 0.0); gl.clearDepth(1.0); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); - - // * _ADD_ together the result of each lighting pass - - // Enable blending and use gl.blendFunc to blend with: - // color = 1 * src_color + 1 * dst_color - // TODO: ^ - + //http://learningwebgl.com/blog/?p=859 + gl.blendFunc(gl.SRC_ALPHA, gl.ONE); + gl.enable(gl.BLEND); // * Bind/setup the ambient pass, and render using fullscreen quad bindTexturesForLightPass(R.prog_Ambient); renderFullScreenQuad(R.prog_Ambient); @@ -127,10 +164,40 @@ // * Bind/setup the Blinn-Phong pass, and render using fullscreen quad bindTexturesForLightPass(R.prog_BlinnPhong_PointLight); - // TODO: add a loop here, over the values in R.lights, which sets the - // uniforms R.prog_BlinnPhong_PointLight.u_lightPos/Col/Rad etc., - // then does renderFullScreenQuad(R.prog_BlinnPhong_PointLight). - + if(cfg.scissor_test_optimization) + gl.enable(gl.SCISSOR_TEST); + //scissor: 118ms->52ms, but , hard edge + for (var i = 0; i < R.lights.length; i++) + { + var l = R.lights[i]; + var eye = [state.cameraPos.x,state.cameraPos.y,state.cameraPos.z]; + + //if(cfg.scissor_test_optimization) + var sc = getScissorForLight(state.viewMat, state.projMat, l); + if((sc!=null)||(!cfg.scissor_test_optimization)) + { + if(cfg && cfg.debugScissor) + { + if(cfg.scissor_test_optimization) + gl.scissor(sc[0],sc[1],sc[2],sc[3]); + renderFullScreenQuad(R.progRed); + } + else + { + if(cfg.scissor_test_optimization) + gl.scissor(sc[0],sc[1],sc[2],sc[3]); + + gl.uniform3fv(R.prog_BlinnPhong_PointLight.u_camPos,eye); + gl.uniform3fv(R.prog_BlinnPhong_PointLight.u_lightPos, l.pos); + gl.uniform3fv(R.prog_BlinnPhong_PointLight.u_lightCol, l.col); + gl.uniform1f(R.prog_BlinnPhong_PointLight.u_lightRad,l.rad); + gl.uniform1i(R.prog_BlinnPhong_PointLight.u_toon,cfg.toonEffect); + + renderFullScreenQuad(R.prog_BlinnPhong_PointLight); + } + } + } + gl.disable(gl.SCISSOR_TEST); // TODO: In the lighting loop, use the scissor test optimization // Enable gl.SCISSOR_TEST, render all lights, then disable it. // @@ -138,15 +205,15 @@ // Otherwise, it returns an array [xmin, ymin, width, height]. // // var sc = getScissorForLight(state.viewMat, state.projMat, light); - + // Disable blending so that it doesn't affect other code gl.disable(gl.BLEND); }; - + var bindTexturesForLightPass = function(prog) { gl.useProgram(prog.prog); - // * Bind all of the g-buffers and depth buffer as texture uniform + // * Bind all xof the g-buffers and depth buffer as texture uniform // inputs to the shader for (var i = 0; i < R.NUM_GBUFFERS; i++) { gl.activeTexture(gl['TEXTURE' + i]); @@ -161,7 +228,7 @@ /** * 'post1' pass: Perform (first) pass of post-processing */ - R.pass_post1.render = function(state) { + R.pass_post1.render = function(state,finalRender) { // * Unbind any existing framebuffer (if there are no more passes) gl.bindFramebuffer(gl.FRAMEBUFFER, null); @@ -174,16 +241,248 @@ // * Bind the deferred pass's color output as a texture input // Set gl.TEXTURE0 as the gl.activeTexture unit - // TODO: ^ + // TO_DO: ^ + gl.activeTexture(gl.TEXTURE0); // Bind the TEXTURE_2D, R.pass_deferred.colorTex to the active texture unit - // TODO: ^ + // TO_DO: ^ + //gl.bindTexture(gl.TEXTURE_2D, R.pass_deferred.colorTex); + gl.bindTexture(gl.TEXTURE_2D, finalRender); + + // Configure the R.progPost1.u_color uniform to point at texture unit 0 + gl.uniform1i(R.progPost1.u_color, 0); + // * Render a fullscreen quad to perform shading on + renderFullScreenQuad(R.progPost1); + }; + + R.pass_srcmask.render = function(state) { + // * Unbind any existing framebuffer (if there are no more passes) + gl.bindFramebuffer(gl.FRAMEBUFFER, R.pass_srcmask.fbo); + + // * Clear the framebuffer depth to 1.0 + gl.clearDepth(1.0); + gl.clear(gl.DEPTH_BUFFER_BIT); + + // * Bind the postprocessing shader program + gl.useProgram(R.progSrcmask.prog); + + // * Bind the deferred pass's color output as a texture input + // Set gl.TEXTURE0 as the gl.activeTexture unit + // TO_DO: ^ + gl.activeTexture(gl.TEXTURE0); + // Bind the TEXTURE_2D, R.pass_deferred.colorTex to the active texture unit + // TO_DO: ^ + gl.bindTexture(gl.TEXTURE_2D, R.pass_deferred.colorTex); // Configure the R.progPost1.u_color uniform to point at texture unit 0 - gl.uniform1i(R.progPost1.u_color, 0); + gl.uniform1i(R.progSrcmask.u_color, 0); + gl.uniform1f(R.progSrcmask.u_thresh, 15.0); + // * Render a fullscreen quad to perform shading on + renderFullScreenQuad(R.progSrcmask); + }; + + R.pass_bloomX.render = function(state) { + // * Unbind any existing framebuffer (if there are no more passes) + gl.bindFramebuffer(gl.FRAMEBUFFER, R.pass_bloomX.fbo); + + // * Clear the framebuffer depth to 1.0 + gl.clearDepth(1.0); + gl.clear(gl.DEPTH_BUFFER_BIT); + + // * Bind the postprocessing shader program + gl.useProgram(R.progBloomX.prog); + // * Bind the deferred pass's color output as a texture input + // Set gl.TEXTURE0 as the gl.activeTexture unit + // TO_DO: ^ + gl.activeTexture(gl.TEXTURE0); + // Bind the TEXTURE_2D, R.pass_deferred.colorTex to the active texture unit + // TO_DO: ^ + gl.bindTexture(gl.TEXTURE_2D, R.pass_srcmask.colorTex); + // Configure the R.progPost1.u_color uniform to point at texture unit 0 + gl.uniform1i(R.progBloomX.u_color, 0); + var tSize = [width,height]; + gl.uniform2fv(R.progBloomX.u_texSize,tSize); // * Render a fullscreen quad to perform shading on - renderFullScreenQuad(R.progPost1); + renderFullScreenQuad(R.progBloomX); + }; + + R.pass_bloomY.render = function(state) { + // * Unbind any existing framebuffer (if there are no more passes) + gl.bindFramebuffer(gl.FRAMEBUFFER, R.pass_bloomY.fbo); + + // * Clear the framebuffer depth to 1.0 + gl.clearDepth(1.0); + gl.clear(gl.DEPTH_BUFFER_BIT); + + // * Bind the postprocessing shader program + gl.useProgram(R.progBloomY.prog); + + // * Bind the deferred pass's color output as a texture input + // Set gl.TEXTURE0 as the gl.activeTexture unit + // TO_DO: ^ + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, R.pass_bloomX.colorTex); + + gl.activeTexture(gl.TEXTURE1); + gl.bindTexture(gl.TEXTURE_2D, R.pass_deferred.colorTex); + + gl.uniform1i(R.progBloomY.u_color, 0); + gl.uniform1i(R.progBloomY.u_origCol, 1); + + var tSize = [width,height]; + gl.uniform2fv(R.progBloomY.u_texSize,tSize); + gl.uniform1i(R.progBloomY.u_debug, cfg.debugView); + // * Render a fullscreen quad to perform shading on + renderFullScreenQuad(R.progBloomY); }; + + R.pass_toon.render = function(state) { + // * Unbind any existing framebuffer (if there are no more passes) + gl.bindFramebuffer(gl.FRAMEBUFFER, R.pass_toon.fbo); + + // * Clear the framebuffer depth to 1.0 + gl.clearDepth(1.0); + gl.clear(gl.DEPTH_BUFFER_BIT); + // * Bind the postprocessing shader program + gl.useProgram(R.progToon.prog); + + // * Bind the deferred pass's color output as a texture input + // Set gl.TEXTURE0 as the gl.activeTexture unit + // TO_DO: ^ + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, R.pass_deferred.colorTex); + // Configure the R.progPost1.u_color uniform to point at texture unit 0 + gl.activeTexture(gl.TEXTURE1); + gl.bindTexture(gl.TEXTURE_2D, R.pass_copy.depthTex); + + gl.uniform1i(R.progToon.u_color, 0); + // * Render a fullscreen quad to perform shading on + gl.uniform1i(R.progToon.u_depthTex, 1); + gl.uniform1f(R.progToon.u_thresh, 25.0); + + var tSize = [width,height]; + gl.uniform2fv(R.progToon.u_texSize,tSize); + + renderFullScreenQuad(R.progToon); + }; + + R.pass_motion.render = function(state) { + // * Unbind any existing framebuffer (if there are no more passes) + gl.bindFramebuffer(gl.FRAMEBUFFER, R.pass_motion.fbo); + + // * Clear the framebuffer depth to 1.0 + gl.clearDepth(1.0); + gl.clear(gl.DEPTH_BUFFER_BIT); + + // * Bind the postprocessing shader program + gl.useProgram(R.progMotion.prog); + + // * Bind the deferred pass's color output as a texture input + // Set gl.TEXTURE0 as the gl.activeTexture unit + // TO_DO: ^ + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, R.pass_deferred.colorTex); + //gl.bindTexture(gl.TEXTURE_2D, R.pass_copy.gbufs[0]); + + gl.activeTexture(gl.TEXTURE1); + gl.bindTexture(gl.TEXTURE_2D, R.pass_copy.gbufs[0]); + //gl.bindTexture(gl.TEXTURE_2D, R.pass_copy.gbufs[0]); + + gl.uniform1i(R.progMotion.u_color, 0); + gl.uniform1i(R.progMotion.u_pos, 1); + //gl.uniform1i(R.progBloomY.u_origCol, 1); + + var tSize = [width,height]; + gl.uniform2fv(R.progMotion.u_texSize,tSize); + var m = state.prevCamMat.elements;//state.cameraMat.elements; + gl.uniformMatrix4fv(R.progMotion.u_cameraMat,gl.FALSE,m); + //var prevM = state.prevCamMat.elements; + gl.uniformMatrix4fv(R.progMotion.u_prevMat,gl.FALSE,statePrevMat); + // * Render a fullscreen quad to perform shading on + var eye = [state.cameraPos.x,state.cameraPos.y,state.cameraPos.z]; + gl.uniform3fv(R.progMotion.u_crntEye,eye); + + gl.uniform3fv(R.progMotion.u_prevEye,prevEye); + + renderFullScreenQuad(R.progMotion); + + prevEye = [state.cameraPos.x,state.cameraPos.y,state.cameraPos.z]; + statePrevMat = m; + }; + + + var renderSphereProxy = (function() { + // The variables in this function are private to the implementation of + // renderFullScreenQuad. They work like static local variables in C++. + + // Create an array of floats, where each set of 3 is a vertex position. + // You can render in normalized device coordinates (NDC) so that the + // vertex shader doesn't have to do any transformation; draw two + // triangles which cover the screen over x = -1..1 and y = -1..1. + // This array is set up to use gl.drawArrays with gl.TRIANGLE_STRIP. + var positions = new Float32Array([ + 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, + 0.707, 0.707, 0.0, + + 1.0, 0.0, 0.0, + 0.707, -0.707, 0.0, + 0.0, 0.0, 0.0, + + 0.0, -1.0, 0.0, + -0.707, -0.707, 0.0, + -1.0, 0.0, 0.0, + + 0.0, 0.0, 0.0, + -0.707,0.707,0.0, + 0.0,1.0,0.0 + + //0.0,0.0,0.0 + ]); + + var vbo = null; + + var init = function() { + // Create a new buffer with gl.createBuffer, and save it as vbo. + // TO_DO: ^ + vbo = gl.createBuffer(); + // Bind the VBO as the gl.ARRAY_BUFFER + // TO_DO: ^ + gl.bindBuffer(gl.ARRAY_BUFFER,vbo); + // Upload the positions array to the currently-bound array buffer + // using gl.bufferData in static draw mode. + // TO_DO: ^ + gl.bufferData(gl.ARRAY_BUFFER,positions,gl.STATIC_DRAW); + }; + + return function(prog) { + if (!vbo) { + // If the vbo hasn't been initialized, initialize it. + init(); + } + + // Bind the program to use to draw the quad + gl.useProgram(prog.prog); + + // Bind the VBO as the gl.ARRAY_BUFFER + // TO_DO: ^ + gl.bindBuffer(gl.ARRAY_BUFFER,vbo); + // Enable the bound buffer as the vertex attrib array for + // prog.a_position, using gl.enableVertexAttribArray + // TO_DO: ^ + gl.enableVertexAttribArray(prog.a_position); + // Use gl.vertexAttribPointer to tell WebGL the type/layout for + // prog.a_position's access pattern. + // TO_DO: ^ + gl.vertexAttribPointer(prog.a_position,3,gl.FLOAT,false,0,0); + // Use gl.drawArrays (or gl.drawElements) to draw your quad. + // TO_DO: ^ + gl.drawArrays(gl.TRIANGLE_STRIP,0,12); + // Unbind the array buffer. + gl.bindBuffer(gl.ARRAY_BUFFER, null); + }; + })(); +//* var renderFullScreenQuad = (function() { // The variables in this function are private to the implementation of // renderFullScreenQuad. They work like static local variables in C++. @@ -204,13 +503,15 @@ var init = function() { // Create a new buffer with gl.createBuffer, and save it as vbo. - // TODO: ^ - + // TO_DO: ^ + vbo = gl.createBuffer(); // Bind the VBO as the gl.ARRAY_BUFFER - // TODO: ^ - // Upload the positions array to the currently-bound array buffer + // TO_DO: ^ + gl.bindBuffer(gl.ARRAY_BUFFER,vbo); + // Upload the positions array to the currently-bound array buffer // using gl.bufferData in static draw mode. - // TODO: ^ + // TO_DO: ^ + gl.bufferData(gl.ARRAY_BUFFER,positions,gl.STATIC_DRAW); }; return function(prog) { @@ -223,19 +524,22 @@ gl.useProgram(prog.prog); // Bind the VBO as the gl.ARRAY_BUFFER - // TODO: ^ - // Enable the bound buffer as the vertex attrib array for + // TO_DO: ^ + gl.bindBuffer(gl.ARRAY_BUFFER,vbo); + // Enable the bound buffer as the vertex attrib array for // prog.a_position, using gl.enableVertexAttribArray - // TODO: ^ + // TO_DO: ^ + gl.enableVertexAttribArray(prog.a_position); // Use gl.vertexAttribPointer to tell WebGL the type/layout for // prog.a_position's access pattern. - // TODO: ^ - + // TO_DO: ^ + gl.vertexAttribPointer(prog.a_position,3,gl.FLOAT,false,0,0); // Use gl.drawArrays (or gl.drawElements) to draw your quad. - // TODO: ^ - + // TO_DO: ^ + gl.drawArrays(gl.TRIANGLE_STRIP,0,4); // Unbind the array buffer. gl.bindBuffer(gl.ARRAY_BUFFER, null); }; })(); +//*/ })(); diff --git a/js/deferredSetup.js b/js/deferredSetup.js index 65136e0..34dd830 100644 --- a/js/deferredSetup.js +++ b/js/deferredSetup.js @@ -5,7 +5,12 @@ R.pass_copy = {}; R.pass_debug = {}; R.pass_deferred = {}; + R.pass_srcmask = {}; R.pass_post1 = {}; + R.pass_bloomX = {}; + R.pass_bloomY = {}; + R.pass_toon = {}; + R.pass_motion = {}; R.lights = []; R.NUM_GBUFFERS = 4; @@ -18,6 +23,11 @@ loadAllShaderPrograms(); R.pass_copy.setup(); R.pass_deferred.setup(); + R.pass_srcmask.setup(); + R.pass_bloomX.setup(); + R.pass_bloomY.setup(); + R.pass_toon.setup(); + R.pass_motion.setup(); }; // TODO: Edit if you want to change the light initial positions @@ -88,7 +98,7 @@ // * Create, bind, and store a single color target texture for the FBO R.pass_deferred.colorTex = createAndBindColorTargetTexture( R.pass_deferred.fbo, gl_draw_buffers.COLOR_ATTACHMENT0_WEBGL); - + // * Check for framebuffer errors abortIfFramebufferIncomplete(R.pass_deferred.fbo); // * Tell the WEBGL_draw_buffers extension which FBO attachments are @@ -98,6 +108,87 @@ gl.bindFramebuffer(gl.FRAMEBUFFER, null); }; + R.pass_srcmask.setup = function() { + // * Create the FBO + R.pass_srcmask.fbo = gl.createFramebuffer(); + // * Create, bind, and store a single color target texture for the FBO + R.pass_srcmask.colorTex = createAndBindColorTargetTexture( + R.pass_srcmask.fbo, gl_draw_buffers.COLOR_ATTACHMENT0_WEBGL); + + // * Check for framebuffer errors + abortIfFramebufferIncomplete(R.pass_srcmask.fbo); + // * Tell the WEBGL_draw_buffers extension which FBO attachments are + // being used. (This extension allows for multiple render targets.) + gl_draw_buffers.drawBuffersWEBGL([gl_draw_buffers.COLOR_ATTACHMENT0_WEBGL]); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + }; + + R.pass_bloomX.setup = function() { + // * Create the FBO + R.pass_bloomX.fbo = gl.createFramebuffer(); + // * Create, bind, and store a single color target texture for the FBO + R.pass_bloomX.colorTex = createAndBindColorTargetTexture( + R.pass_bloomX.fbo, gl_draw_buffers.COLOR_ATTACHMENT0_WEBGL); + + // * Check for framebuffer errors + abortIfFramebufferIncomplete(R.pass_bloomX.fbo); + // * Tell the WEBGL_draw_buffers extension which FBO attachments are + // being used. (This extension allows for multiple render targets.) + gl_draw_buffers.drawBuffersWEBGL([gl_draw_buffers.COLOR_ATTACHMENT0_WEBGL]); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + }; + + R.pass_bloomY.setup = function() { + // * Create the FBO + R.pass_bloomY.fbo = gl.createFramebuffer(); + // * Create, bind, and store a single color target texture for the FBO + R.pass_bloomY.colorTex = createAndBindColorTargetTexture( + R.pass_bloomY.fbo, gl_draw_buffers.COLOR_ATTACHMENT0_WEBGL); + + // * Check for framebuffer errors + abortIfFramebufferIncomplete(R.pass_bloomY.fbo); + // * Tell the WEBGL_draw_buffers extension which FBO attachments are + // being used. (This extension allows for multiple render targets.) + gl_draw_buffers.drawBuffersWEBGL([gl_draw_buffers.COLOR_ATTACHMENT0_WEBGL]); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + }; + + R.pass_toon.setup = function() { + // * Create the FBO + R.pass_toon.fbo = gl.createFramebuffer(); + // * Create, bind, and store a single color target texture for the FBO + R.pass_toon.colorTex = createAndBindColorTargetTexture( + R.pass_toon.fbo, gl_draw_buffers.COLOR_ATTACHMENT0_WEBGL); + + // * Check for framebuffer errors + abortIfFramebufferIncomplete(R.pass_toon.fbo); + // * Tell the WEBGL_draw_buffers extension which FBO attachments are + // being used. (This extension allows for multiple render targets.) + gl_draw_buffers.drawBuffersWEBGL([gl_draw_buffers.COLOR_ATTACHMENT0_WEBGL]); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + }; + + R.pass_motion.setup = function() { + // * Create the FBO + R.pass_motion.fbo = gl.createFramebuffer(); + // * Create, bind, and store a single color target texture for the FBO + R.pass_motion.colorTex = createAndBindColorTargetTexture( + R.pass_motion.fbo, gl_draw_buffers.COLOR_ATTACHMENT0_WEBGL); + + // * Check for framebuffer errors + abortIfFramebufferIncomplete(R.pass_motion.fbo); + // * Tell the WEBGL_draw_buffers extension which FBO attachments are + // being used. (This extension allows for multiple render targets.) + gl_draw_buffers.drawBuffersWEBGL([gl_draw_buffers.COLOR_ATTACHMENT0_WEBGL]); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + }; + + /** * Loads all of the shader programs used in the pipeline. */ @@ -141,6 +232,8 @@ p.u_lightPos = gl.getUniformLocation(p.prog, 'u_lightPos'); p.u_lightCol = gl.getUniformLocation(p.prog, 'u_lightCol'); p.u_lightRad = gl.getUniformLocation(p.prog, 'u_lightRad'); + p.u_camPos = gl.getUniformLocation(p.prog, 'u_camPos'); + p.u_toon = gl.getUniformLocation(p.prog, 'u_toon'); R.prog_BlinnPhong_PointLight = p; }); @@ -155,7 +248,51 @@ // Save the object into this variable for access later R.progPost1 = p; }); - + + loadPostProgram('srcmask', function(p) { + p.u_color = gl.getUniformLocation(p.prog, 'u_color'); + p.u_thresh = gl.getUniformLocation(p.prog, 'u_thresh'); + //p.u_texSize = gl.getUniformLocation(p.prog, 'u_texSize'); + // Save the object into this variable for access later + R.progSrcmask = p; + }); + + loadPostProgram('bloomX', function(p) { + p.u_color = gl.getUniformLocation(p.prog, 'u_color'); + p.u_texSize = gl.getUniformLocation(p.prog, 'u_texSize'); + // Save the object into this variable for access later + R.progBloomX = p; + }); + loadPostProgram('bloomY', function(p) { + p.u_color = gl.getUniformLocation(p.prog, 'u_color'); + p.u_origCol = gl.getUniformLocation(p.prog, 'u_origCol'); + p.u_texSize = gl.getUniformLocation(p.prog, 'u_texSize'); + p.u_debug = gl.getUniformLocation(p.prog, 'u_debug'); + // Save the object into this variable for access later + R.progBloomY = p; + }); + + loadPostProgram('toon', function(p) { + p.u_color = gl.getUniformLocation(p.prog, 'u_color'); + p.u_depthTex = gl.getUniformLocation(p.prog, 'u_depthTex'); + //p.u_origCol = gl.getUniformLocation(p.prog, 'u_origCol'); + p.u_texSize = gl.getUniformLocation(p.prog, 'u_texSize'); + // Save the object into this variable for access later + R.progToon = p; + }); + loadPostProgram('motion', function(p) { + p.u_color = gl.getUniformLocation(p.prog, 'u_color'); + p.u_pos = gl.getUniformLocation(p.prog, 'u_pos'); + //p.u_origCol = gl.getUniformLocation(p.prog, 'u_origCol'); + p.u_texSize = gl.getUniformLocation(p.prog, 'u_texSize'); + p.u_cameraMat = gl.getUniformLocation(p.prog, 'u_cameraMat'); + p.u_prevMat = gl.getUniformLocation(p.prog, 'u_prevMat'); + + p.u_crntEye = gl.getUniformLocation(p.prog, 'u_crntEye'); + p.u_prevEye = gl.getUniformLocation(p.prog, 'u_prevEye'); + // Save the object into this variable for access later + R.progMotion = p; + }); // TODO: If you add more passes, load and set up their shader programs. }; diff --git a/js/framework.js b/js/framework.js index 7c008df..2d38a6e 100644 --- a/js/framework.js +++ b/js/framework.js @@ -8,12 +8,13 @@ var width, height; var models = []; var cameraMat = new THREE.Matrix4(); - + var camPreMat = new THREE.Matrix4(); var render = function() { camera.updateMatrixWorld(); camera.matrixWorldInverse.getInverse(camera.matrixWorld); cameraMat.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse); R.deferredRender({ + prevCamMat: cameraMat,//camera.projectionMatrix, cameraMat: cameraMat, projMat: camera.projectionMatrix, viewMat: camera.matrixWorldInverse, @@ -30,6 +31,7 @@ var width, height; if (!aborted) { requestAnimationFrame(update); } + //camPreMat = cameraMat; }; var resize = function() { @@ -37,6 +39,7 @@ var width, height; camera.updateProjectionMatrix(); renderer.setSize(width, height); render(); + }; var initExtensions = function() { @@ -67,7 +70,7 @@ var width, height; var init = function() { // TODO: For performance measurements, disable debug mode! - var debugMode = true; + var debugMode = false; canvas = document.getElementById('canvas'); renderer = new THREE.WebGLRenderer({ diff --git a/js/ui.js b/js/ui.js index 05c1852..ffb50ed 100644 --- a/js/ui.js +++ b/js/ui.js @@ -8,6 +8,10 @@ var cfg; this.debugView = -1; this.debugScissor = false; this.enableEffect0 = false; + this.bloomEffect = false; + this.toonEffect = false; + this.motionBlurEffect = false; + this.scissor_test_optimization = true; }; var init = function() { @@ -19,15 +23,26 @@ var cfg; 'None': -1, '0 Depth': 0, '1 Position': 1, - '2 Geometry normal': 2, + '2 Surface Normal': 2, '3 Color map': 3, - '4 Normal map': 4, - '5 Surface normal': 5 + '4 Bloom source mask': 4, + '5 Bloom blurred src': 5 }); gui.add(cfg, 'debugScissor'); - - var eff0 = gui.addFolder('EFFECT NAME HERE'); - eff0.add(cfg, 'enableEffect0'); + + var opt0 = gui.addFolder('OPTIMIZATIONS'); + opt0.add(cfg,'scissor_test_optimization'); + + var eff0 = gui.addFolder('POST EFFECTS'); + //eff0.add(cfg, 'enableEffect0'); + eff0.add(cfg, 'bloomEffect'); + eff0.add(cfg, 'toonEffect'); + //http://http.developer.nvidia.com/GPUGems/gpugems_ch21.html + //https://docs.webplatform.org/wiki/tutorials/post-processing_with_webgl + //http://webglfundamentals.org/webgl/lessons/webgl-image-processing.html + //http://webglfundamentals.org/webgl/lessons/webgl-image-processing-continued.html + eff0.add(cfg, 'motionBlurEffect'); + //http://http.developer.nvidia.com/GPUGems3/gpugems3_ch27.html // TODO: add more effects toggles and parameters here };