tag:blogger.com,1999:blog-11489943363728788572024-02-20T03:13:27.391-05:00bits and pixelsUpdates on projects I'm working on!Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.comBlogger85125tag:blogger.com,1999:blog-1148994336372878857.post-79426556413154368512014-06-08T18:53:00.001-04:002018-08-30T16:08:24.223-04:00WebGL GPU ParticlesWeekend project I started about a month ago, a WebGL GPU particle simulator, simulating 1 million particles at 60 fps!<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEXx3t2GQbzJ1E0DhV4h7HQXmtd0q4QMGC9Wpt6x2dFfloJ-n799UyoapF8L-aoDSfhJgjE2wYVE3rI7O47g7_MSJPV-yIwg-FUQB6oaMwnmK3AqBHgM8vjxgHkTQ-hWbGSo2P_PQSxrI/s1600/webgl-particles-05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="110" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEXx3t2GQbzJ1E0DhV4h7HQXmtd0q4QMGC9Wpt6x2dFfloJ-n799UyoapF8L-aoDSfhJgjE2wYVE3rI7O47g7_MSJPV-yIwg-FUQB6oaMwnmK3AqBHgM8vjxgHkTQ-hWbGSo2P_PQSxrI/s1600/webgl-particles-05.png" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv0aqd8DGXQpIQA1Xmlae7Vu4b1h36xjk5wVuBLmtM0EoAXehUUHA-1QBCyLcPim9UKuZUwNRPigtVkLJTuEaT3Urc7ER4ITy-WzdLglugRG5Ro1ATpZ6-2w5OwzJptDH6jhEFd7xhWyA/s1600/webgl-particles-08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv0aqd8DGXQpIQA1Xmlae7Vu4b1h36xjk5wVuBLmtM0EoAXehUUHA-1QBCyLcPim9UKuZUwNRPigtVkLJTuEaT3Urc7ER4ITy-WzdLglugRG5Ro1ATpZ6-2w5OwzJptDH6jhEFd7xhWyA/s1600/webgl-particles-08.png" width="200" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYJwTOYJ-gk9NJ-5PnBjffwxTlP581u6OO_C1sDrf4g2SZ1z6Z3dhh_9HbOztalmhdiZdySyvQV9FnhdyKfKIMUnGkELEmZTZk9Wkt7GKbj8OjLPi5ynSiWEE9dXGLQR0rbapUCXA2-sU/s1600/webgl-particles-10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYJwTOYJ-gk9NJ-5PnBjffwxTlP581u6OO_C1sDrf4g2SZ1z6Z3dhh_9HbOztalmhdiZdySyvQV9FnhdyKfKIMUnGkELEmZTZk9Wkt7GKbj8OjLPi5ynSiWEE9dXGLQR0rbapUCXA2-sU/s1600/webgl-particles-10.png" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_hqqj_4Bv7QQeuKXOTj0e7fqSt_UMIV0IO85Ym9egtnhSXy4PClnYuZ3iYAzucuCtnyKznCKqY_g9KYcM9RTA4mUltGj8PwLM27X9R-7HOYQ63IxlsDewuxIRZF0Q7Y1PI921A06jK8c/s1600/webgl-particles-11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_hqqj_4Bv7QQeuKXOTj0e7fqSt_UMIV0IO85Ym9egtnhSXy4PClnYuZ3iYAzucuCtnyKznCKqY_g9KYcM9RTA4mUltGj8PwLM27X9R-7HOYQ63IxlsDewuxIRZF0Q7Y1PI921A06jK8c/s1600/webgl-particles-11.png" width="200" /></a></div>
<br />
Live code: <a href="http://iamnop.com/particles-mrt/">http://iamnop.com/particles-mrt/</a><br />
Click to set the gravity point. Hold Alt for Maya camera controls.<br />
(Requires webgl_draw_buffers extension. <a href="http://blog.tojicode.com/2013/06/webgl-draft-extensions-in-chrome.html">More info</a> on how to enable.)<br />
<br />
Video: <a href="https://www.youtube.com/watch?v=IyM0YxizdnY">https://www.youtube.com/watch?v=IyM0YxizdnY</a><br />
<br />
GitHub: <a href="https://github.com/nopjia/particles-mrt">https://github.com/nopjia/particles-mrt</a><br />
<br />
<b>Technical Details</b><br />
This demo can be broken into two parts: 1) the compute and 2) the view.<br />
<br />
The compute part is where most of the work happens to simulate the particles. There are three textures representing each of the particles states: position, velocity, and color. Each particle is then represented by a UV coordinate into these textures, essentially a pixel, where its states are stored. A point to note here is that the position and velocity textures have to be float textures in order to represent the large range of numbers. At first I tried scaling up the range of a regular byte texture but there just wasn't enough resolution for the simulation.<br />
<br />
The heavy lifting is done through a GLSL shader which I use as a compute shader. It reads in the three state textures (nearest filtering of course, wouldn't make sense otherwise) and performs a simulation step. Then it writes the results back to the corresponding framebuffers, all at once thanks to the webgl_draw_buffers extension. Because OpenGL doesn't allow writing to the same textures that you are reading from, I needed a duplicate set of framebuffers/textures to swap between every frame.<br />
<br />
The view part is responsible for the actual drawing of the particles onto the screen. The number of particles is determined by the size of the compute textures (e.g., 1024x1024 textures would give us ~1 million particles!) As mentioned earlier, each particle is represented only by a pixel location in the state textures, so all I had to do for each vertex is to submit a UV coordinate. Then in the vertex shader, I simply use the UV to look up its position from the position texture and its color from the color texture. (The velocity texture is only used by the compute shader to run the simulation and isn't used here.)<br />
<br />
In order to ensure smoothness, the simulation runs on a different loop than the rendering. The simulation step has to run at a fixed time step, independent of the frame rate, otherwise a variable time step would introduce irregularities in the simulation, which becomes quite apparent when there are a million particles. Putting the simulation on a fixed update step not only produces smooth results but also allows for consistent results no matter the frame rate.<br />
<br />
<b>WIP!</b><br />
This is a work in progress, and I'm planning to add more features. Most important is to add support for not having the webgl_draw_buffers extension so any up-to-date browser can run this. Then I'm planning to add a few post-processing effects like ghost trails and bloom to make it look even more awesome. Finally, I'll need better UI to expose more settings to play with!<br />
<br />
<b>Note on Live Demo!</b><br />
It is not guaranteed to work on all machines! The demo is using a draft extension which might not be supported on your hardware. Here's how to <i>try</i> to get it to work:<br />
<ol>
<li>Get the latest version of Chrome</li>
<li>Go to chrome://flags/</li>
<li>Enable "WebGL Draft Extensions" (chrome://flags/#enable-webgl-draft-extensions)</li>
<li>For Windows, you might also need to enable D3D11 (chrome://flags/#enable-d3d11)</li>
</ol>
<div>
If it doesn't work, try again with Firefox? I'm sorry but I promise I will add support for no extension soon!</div>
Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com5tag:blogger.com,1999:blog-1148994336372878857.post-53513877671686160252013-07-25T12:46:00.003-04:002013-07-25T12:50:03.971-04:00CUDA Path Tracer<div class="separator" style="clear: both; text-align: left;">
Interactive real-time path tracer in CUDA.</div>
<div class="separator" style="clear: both; text-align: left;">
Advanced Rendering Seminar</div>
<div class="separator" style="clear: both; text-align: left;">
University of Pennsylvania, Spring 2013. </div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<div class="separator" style="clear: both; text-align: left;">
My last school project, ever! (hopefully)</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6asFIBIfVswh0HU1XPcKgZMdvGC2Qux5320fdlP1ZOFqBOz5THKjZ52cmBkD4FXhPOd6z6PVJhSrwrguhSTEaxl7ICXrj-B_q5zbLax6IwaXRDE_p8qcTuBubXGl66uFrP9Dtka0r4vc/s1600/tracer+2013-07-21+14-53-21-02.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6asFIBIfVswh0HU1XPcKgZMdvGC2Qux5320fdlP1ZOFqBOz5THKjZ52cmBkD4FXhPOd6z6PVJhSrwrguhSTEaxl7ICXrj-B_q5zbLax6IwaXRDE_p8qcTuBubXGl66uFrP9Dtka0r4vc/s320/tracer+2013-07-21+14-53-21-02.bmp" width="320" /></a></div>
<br />
Github: <a href="https://github.com/nopjia/tracer">https://github.com/nopjia/tracer</a><br />
Images: <a href="https://www.dropbox.com/sh/s84z7zrgsmnzt5p/IUVtvwegdP#/">Dropbox Link</a><br />
Video: <a href="http://www.youtube.com/watch?v=mbpqxlJHaBE">http://www.youtube.com/watch?v=mbpqxlJHaBE</a><br />
<br />
This was my first ever attempt at writing a path tracer, and of course, making things real-time (or at least somewhat) is always more fun. It was something I've always wanted to do. I learned a whole lot about physically based rendering, for obvious reasons. But I also learned a lot about coding in CUDA and its in's and out's, which involved writing a lot of pure C code and writing nifty inline structs and functions for both host and device uses.<br />
<br />
Although, the renderer doesn't have fancy features, I'm quite happy with it. Despite the lack of acceleration structures, it still runs at ~20fps, and converges around 30 seconds, on my laptop. The next area of improvement would definitely be adding a kd-tree, in order to support larger scenes.<br />
<br />
Finally, as usual, I decided to make things interesting by making it interactive. Being able to easily modify the scene on the fly really makes it more fun and creates lots of interesting images. <br />
<br />
Head over to the <a href="https://github.com/nopjia/tracer">Github page</a> for a whole lot more info!Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-75019148960397237862013-05-16T01:33:00.002-04:002013-05-16T01:33:34.679-04:00WebTubeHere is a long overdue post that I finally got around to write now that school is over! Over the weekend of January 18-20th, I attended the <a href="http://2013s.pennapps.com/">Spring 2013 PennApps Hackathon</a>, the largest student-run hackathon on the east coast, organized by no other than the University of Pennsylvania. Since this was to be my last PennApps Hackathon (this being my 5th time), I decided to have fun over the weekend, hang out with people, and do something fun.<br />
<br />
I made WebTube, a fun little web app that lets you browse the internet through the comfort of an old-school CRT TV.<br />
<br />
The reception turned out much better than I had expected. I came into the hackathon only to have some fun and not expecting anything. In the end, WebTube won 3rd place overall and Audience Choice Award!<br />
<br />
Demo video: <a href="http://www.youtube.com/watch?v=8ZUCyN6yvps">http://www.youtube.com/watch?v=8ZUCyN6yvps</a><br />
Live code: <a href="http://iamnop.com/webtube/">http://iamnop.com/webtube/</a> (must enable CSS Shaders flag in Chrome)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6fm9nSfN4mwg6q4OPq0ZExnL0y-Zljarcw_WynyesuvqYyJ6RY5DtkBHnphHbzudxH51PxZDu06wBGlIu70qxpJemRoDb-egvcLdL-VbvTljAsfD4iH9nT6lzuIOh0F-bdkhVhM91jD8/s1600/webtube1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="110" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6fm9nSfN4mwg6q4OPq0ZExnL0y-Zljarcw_WynyesuvqYyJ6RY5DtkBHnphHbzudxH51PxZDu06wBGlIu70qxpJemRoDb-egvcLdL-VbvTljAsfD4iH9nT6lzuIOh0F-bdkhVhM91jD8/s200/webtube1.png" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXvdE4BcZhtdqe6vTD4FxQSBL8mTKufVxJ16R14wKPzKE8j7UGySZxzMglwnnccBijChGWCF9ThcmPqLxZX4VqGspqFqdGJwRdL3Br3vuLY1xPm1L-xskDJmsiKXT85r9v8w3TLgsZMQo/s1600/webtube2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="110" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXvdE4BcZhtdqe6vTD4FxQSBL8mTKufVxJ16R14wKPzKE8j7UGySZxzMglwnnccBijChGWCF9ThcmPqLxZX4VqGspqFqdGJwRdL3Br3vuLY1xPm1L-xskDJmsiKXT85r9v8w3TLgsZMQo/s200/webtube2.png" width="200" /></a></div>
<br />
<b>Technical Details</b><br />
<b><br /></b>
The core component of this web app is CSS Shaders, which allows access to programmable vertex and fragment shaders for HTML DOM elements. CSS Shaders are an extension to CSS Filters, which are a set of image filters available for CSS, such as grayscale, sepia, brightness/contrast, hue/saturation, etc. CSS Shaders are essentially custom filters that can be controlled through vertex and fragment shaders. This allows for a much greater freedom and very interesting CSS animations and CSS transitions. (See <a href="http://html.adobe.com/webplatform/graphics/customfilters/cssfilterlab/">CSS FilterLab</a> for live examples.) Please see related links below for more information related to CSS Shaders.<br />
<br />
With understanding of CSS Shaders, WebTube is a very simple app. It has one main DOM for the screen, which allows for different modes, including web and SSH terminal. Multiple CSS transition rules are applied to the screen using CSS Shaders. The vertex shader warps the screen to produce the curvature and the fragment shader applies TV-like effects on the screen.<br />
<br />
<b>Links</b><br />
<b><br /></b>
<a href="http://www.adobe.com/devnet/html5/articles/css-shaders.html">http://www.adobe.com/devnet/html5/articles/css-shaders.html</a><br />
<a href="http://html.adobe.com/webplatform/graphics/customfilters/cssfilterlab/">http://html.adobe.com/webplatform/graphics/customfilters/cssfilterlab/</a><br />
<a href="http://alteredqualia.com/css-shaders/article/">http://alteredqualia.com/css-shaders/article/</a><br />
<a href="https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#shading-language">https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#shading-language</a>Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-21868696823901967642012-09-20T23:21:00.000-04:002012-09-22T03:35:22.683-04:00WebGL Volumetric Renderer<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBinJFLZKKvkGnr2m7f8MG-n74TpFNbuPFlBXOL34Ug80RbL2JRpo_nDQ8p9QVs796l0J86dvW_1EY8lLONhlM2g1fPYTIXlkgjsGDWmdp_8rN0csrRJK8pCaoiJb1IN-iXWpVxxEFixw/s1600/volume-screenshot1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="161" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBinJFLZKKvkGnr2m7f8MG-n74TpFNbuPFlBXOL34Ug80RbL2JRpo_nDQ8p9QVs796l0J86dvW_1EY8lLONhlM2g1fPYTIXlkgjsGDWmdp_8rN0csrRJK8pCaoiJb1IN-iXWpVxxEFixw/s200/volume-screenshot1.png" width="200" /></a> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCih6rDYAbE9Xc8kMRgfoQpg5eqo6osWkkUW6SxuVm2SRvLn5bGZJbfuRXheJo_NM1VJI78Vi8e-JIMzBHMTmSB65HgAjlostaKZFqn2Bv_WmLGL35hHKUYOgbmLnyxw1wJM2EA6Mwt3Y/s1600/volume-screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="161" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCih6rDYAbE9Xc8kMRgfoQpg5eqo6osWkkUW6SxuVm2SRvLn5bGZJbfuRXheJo_NM1VJI78Vi8e-JIMzBHMTmSB65HgAjlostaKZFqn2Bv_WmLGL35hHKUYOgbmLnyxw1wJM2EA6Mwt3Y/s200/volume-screenshot.png" width="200" /></a></div>
<br />
Live code: <a href="http://iamnop.com/volumetric">iamnop.com/volumetric</a><br />
(Does not run Windows. Unknown bug with shader compiling.)<br />
<br />
Video: <a href="http://www.youtube.com/watch?v=VPhnwOpmUqY">http://www.youtube.com/watch?v=VPhnwOpmUqY</a><br />
<br />
GitHub: <a href="https://github.com/nopjia/WebGL-Volumetric">https://github.com/nopjia/WebGL-Volumetric</a><br />
<br />
As a small side project, I implemented volumetric ray casting in WebGL. The idea is to ray cast a 3D texture, which should be very fast since OpenGL texture lookups are highly optimized; however, this is not doable since 3D textures are not allowed in WebGL.<br />
<br />
During SIGGRAPH 2012, I met Luis Kabongo from VICOMTech, who showed me their <a href="http://demos.vicomtech.org/volren/">implementation</a> of a WebGL volume renderer, which they use for medical imaging. They made it possible by, instead of using a 3D texture, using a 2D texture atlas, which is made up of 2D texture slices. This is a very simple solution. I immediate took this idea and implemented my own version.<br />
<br />
VICOMTech's volume renderer is for simply viewing 3D datasets, so they implemented it using alpha compositing with no lighting.<br />
<br />
I took it a step further for my own renderer and implemented physically-based volume rendering. The lighting model is based on light transmittance. I introduced multiple lights into the scene and use exponential fall-off to calculate transmittance.<br />
<br />
As a result, the renderer features physically-based lighting, volumetric shadows, and support for multiple lights. The results turned out very nicely.<br />
<br />Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com9tag:blogger.com,1999:blog-1148994336372878857.post-33082487986628271182012-09-18T01:45:00.003-04:002013-07-25T12:18:47.711-04:00CodeDJ Live!Live code <a href="https://dl.dropboxusercontent.com/u/5058905/codedjlive/index.html">here</a>.<br />
(Only works on Firefox, since it uses Audio Data API.)<br />
The app is not most intuitive and has a tiny learning curve.<br />
Please refer to <a href="https://dl.dropbox.com/u/5058905/codedjlive/help.html">more info</a> section.<br />
<br />
Video: <a href="http://www.youtube.com/watch?v=bl11T112Jn0">http://www.youtube.com/watch?v=bl11T112Jn0</a><br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguElZITsrmpbCJIz_TxTRdTQGGlTiGAQj0zShp-42lnvWmYtUrWKsO79nmUc2ItjMRGcXp0DViIZ0JbtSkartLPL8W9ly7AwYyHMsEHE7U8ldmlDOyPuBXqs1fsLO-yGhyphenhyphenwfNo39lEZNg/s1600/bars.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="125" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguElZITsrmpbCJIz_TxTRdTQGGlTiGAQj0zShp-42lnvWmYtUrWKsO79nmUc2ItjMRGcXp0DViIZ0JbtSkartLPL8W9ly7AwYyHMsEHE7U8ldmlDOyPuBXqs1fsLO-yGhyphenhyphenwfNo39lEZNg/s200/bars.png" width="200" /></a> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEXbSOnPW02zFXVILrV0N_9l5XEufjpDCYiAWkOoDLYspEwe0EXwIu4-L6zttpM2bwgIXZWOeykFVwaeyiroUYo_P3s1jUHqxNCJU5hyPaNW7qgcX3FvXyEJTt7O3x_tDOpX0_9-ttzDQ/s1600/rings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="125" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEXbSOnPW02zFXVILrV0N_9l5XEufjpDCYiAWkOoDLYspEwe0EXwIu4-L6zttpM2bwgIXZWOeykFVwaeyiroUYo_P3s1jUHqxNCJU5hyPaNW7qgcX3FvXyEJTt7O3x_tDOpX0_9-ttzDQ/s200/rings.png" width="200" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVZruvNc6XCjVQMxULGfgJqTcRanAwcN9W48_AIXHcesF6LqjH4RMVrigWotiJgw8vueCAvIy3xa9c6yjfx7JyypBu04PpzAQqc54q_oq3mBePpNF8SOz_rdB3CXcc-TGSTDwhfKxhiME/s1600/radial.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="125" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVZruvNc6XCjVQMxULGfgJqTcRanAwcN9W48_AIXHcesF6LqjH4RMVrigWotiJgw8vueCAvIy3xa9c6yjfx7JyypBu04PpzAQqc54q_oq3mBePpNF8SOz_rdB3CXcc-TGSTDwhfKxhiME/s200/radial.png" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbubF-DB48wu4VnChXCrNFQJG4qJS2p447IPJeqO7prYkHmJWIVbtXG3-cKXxWTgxrK02pnGuoMFOGXj0Fpmko5abpqgfGH6GN6Du6WrxT3NKvRy5RzjGHSAXOZ5A6Ql_9cOP0dleyVaw/s1600/blocks.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="125" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbubF-DB48wu4VnChXCrNFQJG4qJS2p447IPJeqO7prYkHmJWIVbtXG3-cKXxWTgxrK02pnGuoMFOGXj0Fpmko5abpqgfGH6GN6Du6WrxT3NKvRy5RzjGHSAXOZ5A6Ql_9cOP0dleyVaw/s200/blocks.png" width="200" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
A project I did for the <a href="http://2012f.pennapps.com/">PennApps</a> 48-hour hackathon.<br />
<br />
<b>About</b><br />
CodeDJ Live! is a web-based app for programmers to code up visuals in real-time as the music plays. With this app the programmer becomes a Visualizer DJ who produces stunning visuals at a party.<br />
<br />
The app is inspired by <a href="http://www.iquilezles.org/">Iñigo
Quilez</a> and his live code demos at SIGGRAPH 2012 Real-time Live event. Similar examples can be seen <a href="http://www.youtube.com/watch?v=emjuqqyq_qc">here</a> and <a href="http://www.youtube.com/watch?v=XdhIu4-fb9c">here</a>.<br />
<br />
<b>Technical Overview</b><br />
This app is essentially a WebGL GLSL live coder hooked up to audio spectrum analyzer. The user has access to the GLSL code that is producing the visuals, which can be compiled instantly and displayed.<br />
<br />
<b>Technical Details</b><br />
<br />
Music Analyzer<br />
Audio frequency analysis is done using Mozilla's <a href="https://wiki.mozilla.org/Audio_Data_API">Audio Data API</a> and fast-Fourier transform functions, provided by [blank]'s signal processing library. The Audio Data API provides access to the framebuffer, which contains the decoded audio sample data. This data is fed into the fast-Fourier transform to extract spectrum frequency data. Frequency data has 1024 channels. This is way too many for the use of this app and needs to be reduced to a manageable and meaningful number. The higher half of the frequencies are barely noticeable, so they are ignored. The lower half are kept and averaged down to 8 channels total for the user to use.<br />
<br />
Music Access<br />
Audio Data API requires access to the audio framebuffer data, which is sensitive secured data access. A limitation to this is the "<a href="http://en.wikipedia.org/wiki/Same_origin_policy">same origin policy</a>", which means it cannot access audio data outside the same root website. This becomes a problem since users need to be able to use their own music for this app. A solution is to host the web app on a public directory on my personal Dropbox, and have users provide their music using their own Dropbox. This is done through the Dropbox javascript API. This works because now the web app and any user provided files are all within the same root website, which is dropbox.com.<br />
<br />
Music Streaming<br />
The user logs in through Dropbox API and specifies which folder to contains the music files. Only .ogg and .wav files are accepted, as determined by Mozilla Firefox. Once the user has selected a folder, no music files are downloaded or transferred. Instead, public URLs of the files are generated and stored within the app for that session. These URLs expire within 4 hours. The audio is then streamed per file as they are needed, using the URL. The app does not load more than one audio file at any time.<br />
<br />
Visuals Shader<br />
Visuals are generated using a fullscreen quad and a fragment shader. Audio frequency levels are passed into this shader as uniforms. The GLSL code generating the visuals is exposed through a large text editor, where the code can be edited and compiled in real-time to be displayed on the screen. <br />
<br />
Postprocessing Shader<br />
Finally, the visuals go through a post-processing shader which applies a series of custom effects to produce dance-club-like styles. This includes over-saturation, bloom, box-blur, and film grain. Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-77751844809239453102012-04-25T03:18:00.002-04:002014-06-08T16:18:12.480-04:00Final DeliverablesHere are the final deliverables for the CIS 565 final project.<br />
<br />
Live code:<br />
<a href="http://iamnop.com/raymarch/">http://iamnop.com/raymarch/</a>
<br />
<br />
Code<br />
<a href="https://github.com/nopjia/WebGL-RayMarch">https://github.com/nopjia/WebGL-RayMarch</a><br />
<br />
Slides<br />
<a href="https://dl.dropboxusercontent.com/u/5058905/raymarch/presentation.pdf">https://dl.dropboxusercontent.com/u/5058905/raymarch/presentation.pdf</a><br />
<br />
Report<br />
<a href="https://dl.dropboxusercontent.com/u/5058905/raymarch/report.pdf">https://dl.dropboxusercontent.com/u/5058905/raymarch/report.pdf</a><br />
<a href="http://www.seas.upenn.edu/~pjia/raymarch/report.pdf"></a>
<br />
Video (turn on captions)<br />
<a href="http://www.youtube.com/watch?v=djTVUUJvC9E">http://www.youtube.com/watch?v=djTVUUJvC9E</a>
<br />
<br />Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-90956781254481893932012-04-24T02:02:00.001-04:002012-04-24T02:27:45.336-04:00Some Nice Images<div style="text-align: left;">
Just throwing up some nice rendered screenshots. </div>
<div style="text-align: left;">
Click to see full-size (500x400).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJncpjnY0rC2J8-jDbn6vi6M77A9sGa-eBCGqTWonEG4PmnL9hX_f2uOOC97aO99tJoOK5gr6aRgO9o4QjQVYLQ9XLILjNkZTGuHgPwQb0AfUuzdDJgWkDZ5W_R8csEMS_Bn5N2A2mOj0/s1600/saved01e.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJncpjnY0rC2J8-jDbn6vi6M77A9sGa-eBCGqTWonEG4PmnL9hX_f2uOOC97aO99tJoOK5gr6aRgO9o4QjQVYLQ9XLILjNkZTGuHgPwQb0AfUuzdDJgWkDZ5W_R8csEMS_Bn5N2A2mOj0/s200/saved01e.png" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi75JqwLDFzcNarP9LEnsbRhUqZezDBNDt-eTxpG_YoKm66zDUOwMQRn2qjJASKxk8wxnSIPywQoxUdA6m-u0BYfHWAG0VML6D54DFopYhci5Ft9JEln6vE6aVD-4Tq20T8l7FoiT2FE0M/s1600/saved04e.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi75JqwLDFzcNarP9LEnsbRhUqZezDBNDt-eTxpG_YoKm66zDUOwMQRn2qjJASKxk8wxnSIPywQoxUdA6m-u0BYfHWAG0VML6D54DFopYhci5Ft9JEln6vE6aVD-4Tq20T8l7FoiT2FE0M/s200/saved04e.png" width="200" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgTrRXwc8DVh2kbj99GHukeYtDkyUabuE0ctdv8O02Vmp3OwqUEvrPumdCVs2WSOua3GHK_9v6O1jefR629gvfZsIBybPVWjzUTs1DJvSUTBtqrsVCIJSrcJmHVRPajyVGlvp-l-aBZL0/s1600/saved02e.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgTrRXwc8DVh2kbj99GHukeYtDkyUabuE0ctdv8O02Vmp3OwqUEvrPumdCVs2WSOua3GHK_9v6O1jefR629gvfZsIBybPVWjzUTs1DJvSUTBtqrsVCIJSrcJmHVRPajyVGlvp-l-aBZL0/s200/saved02e.png" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ-5tvjImmByCBlOzVhiAL7cG-SEh7lrvm9jaIKjA-hPXtcfx0f_KwBPeRUN1ggxWf97N1kTVRCwNlJdV-RNyAv04j_BU58EgkIBvnshFGo00t_S2tm0WV-G2zhrggz3rAUNULT8YAOec/s1600/saved03e.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ-5tvjImmByCBlOzVhiAL7cG-SEh7lrvm9jaIKjA-hPXtcfx0f_KwBPeRUN1ggxWf97N1kTVRCwNlJdV-RNyAv04j_BU58EgkIBvnshFGo00t_S2tm0WV-G2zhrggz3rAUNULT8YAOec/s200/saved03e.png" width="200" /></a></div>
</div>
<div style="text-align: left;">
</div>Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-41430710279828679842012-04-22T04:37:00.002-04:002012-04-22T04:37:45.277-04:00Another Experimental FeatureDecided to throw in another fun experimental feature.<br />
<br />The Displaced Bumps option displaces the distance function according to an arbitrary function (in this case a simple sin wave). It doesn't work very well with square shapes. However, it works great with round box, and it creates a very interesting shape with the knot.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgUpO5hUvMmJWoREyoPxBr5hfxcdgPLPijkpEnhdBXboeXJSzO3WoxVIm-puYQ9swBbaeumV7gAQOIuKZP4SaslQi-LON89FKRtw-l3lLI50OVfDZt2_hJ5di7-7hIB5mklo8ErJUuvts/s1600/bumpy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgUpO5hUvMmJWoREyoPxBr5hfxcdgPLPijkpEnhdBXboeXJSzO3WoxVIm-puYQ9swBbaeumV7gAQOIuKZP4SaslQi-LON89FKRtw-l3lLI50OVfDZt2_hJ5di7-7hIB5mklo8ErJUuvts/s1600/bumpy.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj64n2boQsfH3M4OCo5FUSkNUqH6ejr-3poJ21ETm-ralXIdjSPvTx587GGrzvRqiYe_gT5bYJxYZiE1dDNRVf2DFIOgk0zHOW8Hvuae-EW8v_p4tNLjYs_vwH9fcnxGHzUTIMJWMmeuUk/s1600/bumpy+knot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj64n2boQsfH3M4OCo5FUSkNUqH6ejr-3poJ21ETm-ralXIdjSPvTx587GGrzvRqiYe_gT5bYJxYZiE1dDNRVf2DFIOgk0zHOW8Hvuae-EW8v_p4tNLjYs_vwH9fcnxGHzUTIMJWMmeuUk/s1600/bumpy+knot.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-56576634566531502262012-04-22T03:56:00.001-04:002012-04-22T13:02:19.283-04:00Coding Done! (for now)Worked straight 10 hours today. I think I have reached a point where I am satisfied with the code.<br />
<br />
A huge improvement is a user interface for selecting options. To bring up the GUI, press "Shift+Q". The code is live at <a href="http://www.seas.upenn.edu/~pjia/raymarch">www.seas.upenn.edu/~pjia/raymarch</a> (since unfortunately <a href="http://iamnop.com/">iamnop.com</a> is still having issues.) If you are running this, remember to resize your browser to a smaller size for reasonable performance.<br />
<br />
Here's what it looks like now:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3fkOD4hbrIzwu8SsHiq_Urbx8wXK4yWcP_VNOHtvCyBdWbfd_Zov5UMqRoki-vEGM0jXhMU__Q1j6JIuPfgkOvAHEGh_ig744XMkkkh9aGhYNmNJ9EF0vO9_x5wNXXVCfev-UmnLrHlw/s1600/done-gui+v1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3fkOD4hbrIzwu8SsHiq_Urbx8wXK4yWcP_VNOHtvCyBdWbfd_Zov5UMqRoki-vEGM0jXhMU__Q1j6JIuPfgkOvAHEGh_ig744XMkkkh9aGhYNmNJ9EF0vO9_x5wNXXVCfev-UmnLrHlw/s1600/done-gui+v1.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXXR7oj3yu84_NUlH5juaJvYUEXLt-xV2w4Sgrmc3yc8lgIqe8THiQn9A7uXOAKRqPNQ8BwXio-LoCidRYbcR7U2znsLNvEeVaLXhLNGugeV5Z4mPKWfYOlvjH6Sa7lNwNLSa1IgEzfwE/s1600/done+v1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXXR7oj3yu84_NUlH5juaJvYUEXLt-xV2w4Sgrmc3yc8lgIqe8THiQn9A7uXOAKRqPNQ8BwXio-LoCidRYbcR7U2znsLNvEeVaLXhLNGugeV5Z4mPKWfYOlvjH6Sa7lNwNLSa1IgEzfwE/s1600/done+v1.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Aside from fixing corner cases and doing optimizations, here are the new features implemented:</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li>New GUI! (of course!)</li>
<li>Mirrored reflections.
</li>
<li>New more realistic soft shadows method, based on technique by <i>the.savage. </i></li>
<li>New fog. Not really fog anymore. It simply darkens the color relative to distance marched. Takes care of the far distances where numerical errors are large. </li>
<li>Focal blur, which is basically dithering based on distance. This is implemented last minute and doesn't produce very good results. </li>
</ul>
<div>
And of course, the project is not complete, and there are a few known bugs:</div>
<div>
<ul>
<li>Ambient Occlusion and Subsurface Scattering stops working when warping is turned on. </li>
<li>As mentioned, focal blur at this moment is an experimental and unfinished feature. To improve, I will need to take several dithered samples and average between them. However, this will hurt performance.</li>
<li>The quaternion fractal does not render quite well with all modes, since I'm trying to optimize across all types of scenes, balancing quality and performance. The current smoothing level doesn't work quite well for the fractal, so there will be breaks in the surface. It's also running at a few iterations, so it seems to leave artifacts across the scene. I'm just putting it in there as an example of a very complex shape.</li>
</ul>
</div>Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-89609345719504704312012-04-21T19:57:00.002-04:002012-04-21T19:57:29.884-04:00Distortion Issue Solved!Distortion issue is caused by the inaccuracies of the ray marching method. The distance based marching does not provide a good enough approximation of the shape.<br />
<br />
The solution is to apply a "smoothing" constant having a value between 0.0 to 1.0. This number is simply scales the distance estimated sampled at every step, such that the ray will only march a certain % of the distance. So no smoothing would be 1.0, stepping the whole distance towards the scene.<br />
<br />
This is a balance between quality and performance. Smoothing eliminates the rippling distortion effect. However, now that we're taking a non 100% of the distance sampled, we need to take more steps in order to reach the scene.<br />
<br />
The suggested smoothing level is 0.5, but I'm afraid performance would take a hit since now I'll have to take many more steps in order to render the edge details. A good number that I empirically came up with is 0.75, meaning the ray march would only march 75% of the distance closest to the scene.<br />
<br />
Below are examples:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhapqXn-eiNwd_doL71qf6MJUq37cc3akkBcMGhuHWG82jdvSq6Pskyr2orrd11-9vt-qwiEErD2Z0nir-JlwlkhycYjSS8y5fCpt54U2HqveOmoAqMlEEFgdwS4Rh1Kx0RoCBykKyvtQU/s1600/twist+smoothed.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhapqXn-eiNwd_doL71qf6MJUq37cc3akkBcMGhuHWG82jdvSq6Pskyr2orrd11-9vt-qwiEErD2Z0nir-JlwlkhycYjSS8y5fCpt54U2HqveOmoAqMlEEFgdwS4Rh1Kx0RoCBykKyvtQU/s1600/twist+smoothed.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
The twisted cube. Smoothing at 0.75. </div>
<div class="separator" style="clear: both; text-align: center;">
Some minor rippling effect still visible at lower left corner, but is much better. </div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4EPTa9uiFi1XOn1fkP55NGs-WUCUs0kBUw3zs6zpDre_A6uN-B3d3nyWh-3_-P8HHI3EHsraS4MzgIietbW7TEvUUCJnamCpqCSLliyG82qyNtU_Hqkes1Abd3zIPESyi62CSjnTPR1s/s1600/quaternion+smoothed.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4EPTa9uiFi1XOn1fkP55NGs-WUCUs0kBUw3zs6zpDre_A6uN-B3d3nyWh-3_-P8HHI3EHsraS4MzgIietbW7TEvUUCJnamCpqCSLliyG82qyNtU_Hqkes1Abd3zIPESyi62CSjnTPR1s/s1600/quaternion+smoothed.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
The Julia quaternion fractal. Smoothing 0.5.</div>
<div class="separator" style="clear: both; text-align: center;">
Now smooth everywhere compared to before where there were gaps in the surface.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com2tag:blogger.com,1999:blog-1148994336372878857.post-66938394439036370032012-04-21T00:31:00.000-04:002012-04-21T00:41:37.996-04:00Distortion IssueThe distortion issue becomes worse when trying to render increasingly complicated objects.<br />
<br />
Just as a test, I ported another shape form <i>the.savage</i>'s renderer, the Julia quaternion fractal. It was able to run at ok performance at few iterations of the fractal. However, the distortion problem becomes lot worse and the shape is barely viewable.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9rAwhhBpZdi0ulLEsgkJWBSLZKqIlLjdbfMEScb5Hy__GllYR42hG0g4MCNS9pQc89_KNw3oHew6z5sllPxQwRVNiTagys49lvqNNQ2WMIbQuDHcezmBExmeoGlbLQIK4KONGuKaHc-0/s1600/quarternion+blehh.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9rAwhhBpZdi0ulLEsgkJWBSLZKqIlLjdbfMEScb5Hy__GllYR42hG0g4MCNS9pQc89_KNw3oHew6z5sllPxQwRVNiTagys49lvqNNQ2WMIbQuDHcezmBExmeoGlbLQIK4KONGuKaHc-0/s1600/quarternion+blehh.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
5 iterations</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKBTUIyXKBO9dXv0Rwwd3LIrODQ5PUX4qPn0rIUti6KEQjfDG7KLmf1Z9J37u_pTWiggnjid-DXEw8WfvUw4eEJtscbmzGKUFlfvVRBrMwvY-Q0_grx9TvjwFUVbGcnnQ4S-oUUjy0k4I/s1600/quarternion+error.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKBTUIyXKBO9dXv0Rwwd3LIrODQ5PUX4qPn0rIUti6KEQjfDG7KLmf1Z9J37u_pTWiggnjid-DXEw8WfvUw4eEJtscbmzGKUFlfvVRBrMwvY-Q0_grx9TvjwFUVbGcnnQ4S-oUUjy0k4I/s1600/quarternion+error.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
10 iterations. Shape barely recognizable.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
At this point, I would like to shift the focus from the actual modeling of fractals back to the rendering. I have been trying to read up on fractals but the math is making it a very difficult and a slow process, and right now I still don't have a good understanding.<br />
<br />
Since now I don't have too much time left, I'd rather focus on the renderer and its performance, especially since I have just discovered there's much performance yet to be squeezed out (see last post.) I also have a few more effects that I would like to implement, such as glow, reflection, real soft shadows, and focal blur.<br />
<br />
I feel that going in this direction is much more relevant to this class than trying to construct fractals. Going forward, instead of trying to generate my own fractals, I would port existing fractal code from various resources as test target renders.Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-3609943433485044162012-04-21T00:14:00.004-04:002012-04-21T00:14:47.342-04:00Slow Progress + IssuesWorked on the code a bunch today. I'll quickly run through some of the issues.<br />
<br />
Implemented the recursive tetrahedral outlined <a href="http://blog.hvidtfeldts.net/index.php/2011/08/distance-estimated-3d-fractals-iii-folding-space/">here</a>. However, it is represented in points, and is not appropriate for this framework. So I decided to remove it. Below's a render of the fractal using the number of steps.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDoSmw3M-SvUgBo5piUFuz-r4fimxPbxc7NX-KkLySGZc_0-IYgSNGAYRuwJQBKbIU0ha8AmsbduezXC7rzj3oa7dys0zXGiU_6-68t-T1PBRcUTbx-IXC4BKyv17H4B2x5x0_J6_UKRI/s1600/tetra1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDoSmw3M-SvUgBo5piUFuz-r4fimxPbxc7NX-KkLySGZc_0-IYgSNGAYRuwJQBKbIU0ha8AmsbduezXC7rzj3oa7dys0zXGiU_6-68t-T1PBRcUTbx-IXC4BKyv17H4B2x5x0_J6_UKRI/s1600/tetra1.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Next was to reverse my last change for the branch optimization that I blogged about. I just did a few tests and realized that when I flip the camera such that it is under the ground plane and it would only render black, I noticed a FPS increase of 2-3. This is because of screen space coherence and warp termination. There is branch diversion during whether it would render or not, and when enough pixels do not need to render, there is a performance increase.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Next I ported a knot shape code from <i>the.savage</i>'s renderer from his renderer in GLSL Sandbox. Performance took a huge hit. Result below:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_fogdJ1Y9aukcz27VFGixOT7GU0r6MOn5zLhsd6GenxGfDnlpwC4Zy5KQ7hLQeYvCloKor6OyURB-F2eSeyUpfjGJgjjnJq4wcPHoF-hQbCN7LC3H0ykEdQSXTK16YCxcE41PQdHLDqc/s1600/knot+no+bounds.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_fogdJ1Y9aukcz27VFGixOT7GU0r6MOn5zLhsd6GenxGfDnlpwC4Zy5KQ7hLQeYvCloKor6OyURB-F2eSeyUpfjGJgjjnJq4wcPHoF-hQbCN7LC3H0ykEdQSXTK16YCxcE41PQdHLDqc/s1600/knot+no+bounds.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Then I realized that his renderer does something quite smart. He uses a circular bounding volume, and his renderer only renders what is inside the volume. It works for him since he only renders single floating objects in the middle of the screen. I implemented this into my own pipeline. It was a huge performance boost, over double the FPS. And if I zoom out such that the bounding volume occupies a even smaller portion of the screen, I see significant performance increase, from ~18 FPS to up to 90 FPS, again, due to coherency and warp termination. However, this technique is not too suitable for the types of images I'm trying to render since it crops only the center area of the scene. Here's a result:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAjxrlFyP18wFrRLL_kutP_GmSNRlkNLwi-InW7BNG7fVWOqTFuwMSoLGHdHa06UTZODFu4rTByF8sirGybZhNRGLkgQG8NwGdbjVKbyAaiyqtkLJCH32XgbQpaE82XUuohcf0IjWG00s/s1600/knot+bounded.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAjxrlFyP18wFrRLL_kutP_GmSNRlkNLwi-InW7BNG7fVWOqTFuwMSoLGHdHa06UTZODFu4rTByF8sirGybZhNRGLkgQG8NwGdbjVKbyAaiyqtkLJCH32XgbQpaE82XUuohcf0IjWG00s/s1600/knot+bounded.png" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I'll have to think about whether to use this technique, since it does provide a very significant performance boost.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Next, I discovered that my renderer has a huge issue in that for certain shapes when viewed from certain angles, there are banding / rippling distortion errors. I spent a long time looking at it but still cannot find the answer. I might have to go ahead without solving this issue since time is running out and I'd rather focus on other things. Here's an example:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<img alt="Inline image 6" src="https://mail.google.com/mail/u/0/?ui=2&ik=3c5f167354&view=att&th=136d2bd845bdd570&attid=0.2&disp=emb&realattid=ii_136d2bcaa86cb56d&zw&atsh=1" />
</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<br />Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-26297270879179072562012-04-19T01:56:00.002-04:002012-04-19T01:59:54.106-04:00Initial Test + Micro OptimizationImplemented Inigo Quilez's menger sponge, by following his <a href="http://www.iquilezles.org/www/articles/menger/menger.htm">tutorial</a>. This is to test if the framework can handle scenes that are getting more complex. The frame rate is still acceptable, on my puny laptop graphics card.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4kjwNwLPX2X06VNQJMh07flZYoOxz9UhAgexNHWDLa8dmgyCe2SJyb8s5QW17qc_AgKBAaToWrA0RzCyZyKPHO5HILVH9uIgUtgzMq17vpvLiNLP1HAniie1znQnc80540LPXUAsSCm0/s1600/menger.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4kjwNwLPX2X06VNQJMh07flZYoOxz9UhAgexNHWDLa8dmgyCe2SJyb8s5QW17qc_AgKBAaToWrA0RzCyZyKPHO5HILVH9uIgUtgzMq17vpvLiNLP1HAniie1znQnc80540LPXUAsSCm0/s1600/menger.png" /></a></div>
<br />
I also implemented a micro optimization that came to my mind. Before I had:<br />
<br />
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial;">
<b><span style="color: maroon; font-family: Consolas; font-size: 12pt;">if</span></b><span style="font-family: Consolas; font-size: 12pt;"> </span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">(</span><span style="font-family: Consolas; font-size: 12pt;">t</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">></span><span style="color: green; font-family: Consolas; font-size: 12pt;">0.0</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">)</span><span style="font-family: Consolas; font-size: 12pt;"> </span><span style="color: purple; font-family: Consolas; font-size: 12pt;">{</span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial;">
<span style="font-family: Consolas; font-size: 12pt;"> </span><span style="color: dimgrey; font-family: Consolas; font-size: 12pt;">// compute col</span><span style="font-family: Consolas; font-size: 12pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial;">
<span style="font-family: Consolas; font-size: 12pt;"> <o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial;">
<span style="font-family: Consolas; font-size: 12pt;"> gl_FragColor </span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">=</span><span style="font-family: Consolas; font-size: 12pt;"> vec4</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">(</span><span style="font-family: Consolas; font-size: 12pt;">col</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">,</span><span style="font-family: Consolas; font-size: 12pt;"> </span><span style="color: green; font-family: Consolas; font-size: 12pt;">1.0</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">)</span><span style="color: purple; font-family: Consolas; font-size: 12pt;">;</span><span style="font-family: Consolas; font-size: 12pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial;">
<span style="color: purple; font-family: Consolas; font-size: 12pt;">}</span><span style="font-family: Consolas; font-size: 12pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial;">
<b><span style="color: maroon; font-family: Consolas; font-size: 12pt;">else</span></b><span style="font-family: Consolas; font-size: 12pt;"> </span><span style="color: purple; font-family: Consolas; font-size: 12pt;">{</span><span style="font-family: Consolas; font-size: 12pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial;">
<span style="font-family: Consolas; font-size: 12pt;"> gl_FragColor </span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">=</span><span style="font-family: Consolas; font-size: 12pt;"> vec4</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">(</span><span style="color: green; font-family: Consolas; font-size: 12pt;">0.0</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">,</span><span style="font-family: Consolas; font-size: 12pt;"> </span><span style="color: green; font-family: Consolas; font-size: 12pt;">0.0</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">,</span><span style="font-family: Consolas; font-size: 12pt;"> </span><span style="color: green; font-family: Consolas; font-size: 12pt;">0.0</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">,</span><span style="font-family: Consolas; font-size: 12pt;"> </span><span style="color: green; font-family: Consolas; font-size: 12pt;">1.0</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">)</span><span style="color: purple; font-family: Consolas; font-size: 12pt;">;</span><span style="font-family: Consolas; font-size: 12pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial;">
<span style="color: purple; font-family: Consolas; font-size: 12pt;">}</span></div>
<br />
Instead, I use built-in functions to eliminate the branching altogether.<br />
<br />
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial;">
<span style="font-family: Consolas; font-size: 12pt;">t </span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">=</span><span style="font-family: Consolas; font-size: 12pt;"> </span><span style="color: #603000; font-family: Consolas; font-size: 12pt;">max</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">(</span><span style="font-family: Consolas; font-size: 12pt;">sign</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">(</span><span style="font-family: Consolas; font-size: 12pt;">t</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">),</span><span style="font-family: Consolas; font-size: 12pt;"> </span><span style="color: green; font-family: Consolas; font-size: 12pt;">0.0</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">)</span><span style="color: purple; font-family: Consolas; font-size: 12pt;">;</span><span style="font-family: Consolas; font-size: 12pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial;">
<span style="font-family: Consolas; font-size: 12pt;">gl_FragColor
</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">=</span><span style="font-family: Consolas; font-size: 12pt;"> vec4</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">(</span><span style="font-family: Consolas; font-size: 12pt;">t</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">*</span><span style="font-family: Consolas; font-size: 12pt;">col</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">,</span><span style="font-family: Consolas; font-size: 12pt;"> </span><span style="color: green; font-family: Consolas; font-size: 12pt;">1.0</span><span style="color: #808030; font-family: Consolas; font-size: 12pt;">)</span><span style="color: purple; font-family: Consolas; font-size: 12pt;">;</span><span style="font-family: Consolas; font-size: 12pt;"><o:p></o:p></span></div>
<br />
I'm not sure if this helps performance, might be by a difference of 1 fps at the moment.Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com2tag:blogger.com,1999:blog-1148994336372878857.post-48069919807286299022012-04-11T19:20:00.001-04:002012-04-11T19:25:19.320-04:00So Much Math!Found a great resource on rendering fractals, written by Mikael Hvidtfeldt Christensen, who is a physicist and a software developer (and apparently an expert on fractals rendering.)<br />
<br />
<a href="http://blog.hvidtfeldts.net/index.php/2011/06/distance-estimated-3d-fractals-part-i/">http://blog.hvidtfeldts.net/index.php/2011/06/distance-estimated-3d-fractals-part-i/</a>
<br />
<br />
He wrote a 7-part (so far) article on rendering fractals. His series is almost a one-stop resource for all things related to rendering fractals, covering topics from coloring and lighting, to complex math associated with generating different types of fractals, such as Julia sets and Mandelbulbs.<br />
<br />
Most of the rendering part I have already figured out from various other sources, but it is a great read nonetheless, and has given me a few more ideas on various rendering passes. The part that is most useful is the part on modeling and generating fractals. This opened up a whole new area that I am completely new to. There is a tremendous amount of math involved, and it is a rather difficult read. A lot of the math I do not understand, and I am still working on the reading and figuring it out.<br />
<br />
I only wished I had found this blog earlier!<br />
<br />
Here are some amazing images from stuff he's working on. This guy's a true expert!<br />
<a href="http://www.flickr.com/photos/syntopia/">http://www.flickr.com/photos/syntopia/</a>Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com1tag:blogger.com,1999:blog-1148994336372878857.post-63018029262260542492012-04-10T03:56:00.002-04:002012-04-10T03:58:03.083-04:00Check Out Live Code!Quite satisfied with the rendering results. Go to <a href="http://iamnop.com/raymarch/">http://iamnop.com/raymarch/</a> for some nice real-time live code! (Hint: it's animated!)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSjfgBS3bybyS-2o3rPuwj3VCsq-9S5E6TGnknHDWhdmDngyzfr4lt6J2C8Sp7qwbQy_Y2Lm9MgLnEqv-7wgdmW2tq9Mom6TN4DqIGWdvB4o5ccFCsDC5g13efE1fgPycWeeuUqSXIoJI/s1600/Untitled1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSjfgBS3bybyS-2o3rPuwj3VCsq-9S5E6TGnknHDWhdmDngyzfr4lt6J2C8Sp7qwbQy_Y2Lm9MgLnEqv-7wgdmW2tq9Mom6TN4DqIGWdvB4o5ccFCsDC5g13efE1fgPycWeeuUqSXIoJI/s1600/Untitled1.png" /></a></div>
<br />Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com4tag:blogger.com,1999:blog-1148994336372878857.post-3427542904888937152012-04-10T03:38:00.003-04:002012-04-10T03:38:42.179-04:00Observed Performance DifferenceWith the full shading stack, rendering each frame becomes much more heavy, and performance differences become greater.<br />
<br />
From observation, when viewport is mostly sky (far distances), the frame rate is about 30 fps. When the viewport is mostly ground or geometry (close distances), the frame rate jumps to about 50 fps. This is good news, since it implies that the ray marching loop is correctly optimized, where it successfully terminates when an intersection is found. I was not able to observe this difference until now.Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com2tag:blogger.com,1999:blog-1148994336372878857.post-17938454229188438272012-04-10T02:34:00.002-04:002012-04-10T02:34:52.366-04:00Combined Render PassesI have tweaked and fixed up various shading passes, and I think I am ready to move onto the modeling part of the project.<br />
<br />
Here are the components of the shading:<br />
<br />
<ol>
<li>Diffuse lighting</li>
<li>Soft shadows. Used instead of ray traced shadows. Also eliminates the need for ambient occlusion.</li>
<li>Subsurface scattering (so called). I figured it looks more like effects of depth volume rendering, not quite like subsurface scattering, but can account for some types of a similar effect.</li>
<li>Fog. Mainly used to hide numerical errors for large distances. Instead of light blue (or other fog color), can be set to black to simulate view-aligned lighting. </li>
</ol>
<br />
Here's the current output:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjITG-irkmAceHMWT4wStKUuhwRW_FU6vnq5ZAUcKaTAX9fQlrX7YYUGZsKX1LKLHg3QAOTwmxR7AjQ7veqR3iwU7g-1YabrS6egluL5J-0Xi8flWE_WMSX7-PcgdOczaW1WYTtX-xFgiI/s1600/alltgt.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjITG-irkmAceHMWT4wStKUuhwRW_FU6vnq5ZAUcKaTAX9fQlrX7YYUGZsKX1LKLHg3QAOTwmxR7AjQ7veqR3iwU7g-1YabrS6egluL5J-0Xi8flWE_WMSX7-PcgdOczaW1WYTtX-xFgiI/s1600/alltgt.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<br />Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-85842574695430841602012-04-05T18:07:00.000-04:002012-04-05T18:07:04.980-04:00Initial Subsurface ScatteringImplemented subsurface scattering based on sample code from <a href="http://www.mazapan.se/news/2010/07/15/gpu-ray-marching-with-distance-fields/">Mazapan</a>. The code again is similar to the technique for ambient occlusion. It samples distances along the marching ray. However, since it relies on negative sampled distance, it only works on signed distance fields (for example, it doesn't work with udBox).<br />
<div>
<br /></div>
<div>
Here's an initial result.<br />
<div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2diJRBEEoaPOUtgLvU5n7Txg3ACr5Y944zo9kmW9SPUn3rYaGWF0lYY6cjfcmUXIfw2mK9jHd_O_kKeJXg6aH_68QGBJONgv7rxnIfpW2PgoFa5tdhcfsrzOV4fHLiNTt0DXLIVCjjQw/s1600/sss.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2diJRBEEoaPOUtgLvU5n7Txg3ACr5Y944zo9kmW9SPUn3rYaGWF0lYY6cjfcmUXIfw2mK9jHd_O_kKeJXg6aH_68QGBJONgv7rxnIfpW2PgoFa5tdhcfsrzOV4fHLiNTt0DXLIVCjjQw/s1600/sss.png" /></a></div>
<div>
<br /></div>
</div>
</div>Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com2tag:blogger.com,1999:blog-1148994336372878857.post-40826602941303751982012-04-03T22:46:00.003-04:002012-04-03T22:46:27.919-04:00Soft ShadowsImplemented soft shadows. The technique is very similar to ambient occlusion. Instead of taking samples along the normal at the surface, it takes samples along the ray from the surface to the light. This roughly estimates the distances of the surrounding object to the ray of light, creating an effect very visually similar to soft shadows. Therefore, this is "fake" empirical soft shadows and is purely geometry based.<br />
<br />
Here are some results of just the soft shadows component. I personally think they look very nice, and I am questioning the need for the diffuse lighting component at all.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMsbQSg-md3rveCIoF-IvySYargh6diRi_HI1vv2u2P1lq0dKlUwS_9we0tGRN-XA5sFA0MRpdNJfGM4MnNrZV8mSxG3ZxasGH8LQEbiMAUOiQ-KP0Tze6bW9yLlLQ8X8Ef2NaBXh5lwE/s1600/ss1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMsbQSg-md3rveCIoF-IvySYargh6diRi_HI1vv2u2P1lq0dKlUwS_9we0tGRN-XA5sFA0MRpdNJfGM4MnNrZV8mSxG3ZxasGH8LQEbiMAUOiQ-KP0Tze6bW9yLlLQ8X8Ef2NaBXh5lwE/s1600/ss1.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMIx_tTNdzHeAqDWSvgUbOhQf6qDdE4U00gogKUImyYplPQXm6sZh4AOUWvdFK_rBJQJvfb2Anrj-0ypV0U4p6ZCshNHTqtZ53njIY_XHu57QT3WOxlC9Pru4YU0mG16eAtCQ6nyEPWQM/s1600/ss.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMIx_tTNdzHeAqDWSvgUbOhQf6qDdE4U00gogKUImyYplPQXm6sZh4AOUWvdFK_rBJQJvfb2Anrj-0ypV0U4p6ZCshNHTqtZ53njIY_XHu57QT3WOxlC9Pru4YU0mG16eAtCQ6nyEPWQM/s1600/ss.png" /></a></div>
<br />Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-46249543227369254382012-04-03T15:36:00.002-04:002012-04-03T15:50:06.793-04:00Ambient OcclusionImplemented ambient occlusion, based on method proposed by <a href="http://www.iquilezles.org/www/material/nvscene2008/rwwtt.pdf">Iñigo Quilez</a>. The method is originally based on another paper, "<a href="http://delivery.acm.org/10.1145/1190000/1185834/p153-evans.pdf?ip=130.91.56.121&acc=ACTIVE%20SERVICE&CFID=75722014&CFTOKEN=98229886&__acm__=1333476715_e39174e539efd004434c2f86991e62c6">Fast Approximations for Global Illumination on Dynamic Scenes.</a>"<br />
<br />
Here's how the method works: the ambient occlusion coefficient at each surface point is computed by taking samples of the distance field at varying distances above the point long its normal. This essentially estimates the "openness" of the region above the point. Here is a more formal mathematical description:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglCnalGCYVPGOtqAfm8aiJzMDXQWHDq_ryGFu53-EfEHS5pQJNm65_dBmhTzuSBkkvKIudWkI3aWsBWpI2tcRVKaiWv48zIt9-1cXhQzvJNDR93OAWNWbkontD-lBZ4Mk2VGHwwhHLkbc/s1600/ao+formula.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglCnalGCYVPGOtqAfm8aiJzMDXQWHDq_ryGFu53-EfEHS5pQJNm65_dBmhTzuSBkkvKIudWkI3aWsBWpI2tcRVKaiWv48zIt9-1cXhQzvJNDR93OAWNWbkontD-lBZ4Mk2VGHwwhHLkbc/s1600/ao+formula.png" /></a></div>
<br />
Here is an output of just the ambient occlusion term.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb80CDY_vYiLI0ga4DejipubvmgNrcCdzd5QS4awIJomLqY_voiO8LYrVcF4XpGfPPzIjFSKHVjsvL5384-GTfPxsZmrXprLjfRGCqTup6aqDVzCmdDapTFpl_TvobQrHxOcXdB6FqB-g/s1600/Untitled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb80CDY_vYiLI0ga4DejipubvmgNrcCdzd5QS4awIJomLqY_voiO8LYrVcF4XpGfPPzIjFSKHVjsvL5384-GTfPxsZmrXprLjfRGCqTup6aqDVzCmdDapTFpl_TvobQrHxOcXdB6FqB-g/s1600/Untitled.png" /></a></div>
<br />
Here is ambient occlusion with diffused lighting.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8xH_cED1zDKE3klMHC4u-da2mEzn1vJCb3_AosSmMfC9XKGI697f0S-ceJQ2XznYVEoGjYy5cFEDaHPau-lSFpvjLVWwejouTYpgAOh2l4ZC1Er8rodFQ4VQjC4xHO8eAslZPr4BwfLg/s1600/Untitled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8xH_cED1zDKE3klMHC4u-da2mEzn1vJCb3_AosSmMfC9XKGI697f0S-ceJQ2XznYVEoGjYy5cFEDaHPau-lSFpvjLVWwejouTYpgAOh2l4ZC1Er8rodFQ4VQjC4xHO8eAslZPr4BwfLg/s1600/Untitled.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Also, I want to point out that, with ambient occlusion implemented, there is an unintentional "skyline" effect where the ground plane ends. This could be because the ray does not intersect anything and therefore the normal is undefined at those points. However, it does provide a nice gradient visual effect, where before there were curved bands going across as a result of numerical errors. Here's a better picture of the "skyline".</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRBc9NK_p2L52Nvvrv8vWg-w5zFrPP4ToV7zpKlF44pj6jCRXqtZIJlH8jBqG0wpjC4TkVGTuQRtD7zkRyW5ntik4aSLKD2DDRxMLfaueVZKJqJUQ6egvnZJg1Ni6ylULw5gMWwE_Iu0g/s1600/Untitled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRBc9NK_p2L52Nvvrv8vWg-w5zFrPP4ToV7zpKlF44pj6jCRXqtZIJlH8jBqG0wpjC4TkVGTuQRtD7zkRyW5ntik4aSLKD2DDRxMLfaueVZKJqJUQ6egvnZJg1Ni6ylULw5gMWwE_Iu0g/s1600/Untitled.png" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com1tag:blogger.com,1999:blog-1148994336372878857.post-32191482270794786662012-04-01T21:28:00.003-04:002012-04-01T21:28:47.928-04:00Midpoint PresentationSee the slide deck for the midpoint presentation <a href="https://docs.google.com/presentation/pub?id=1lUAl7uXzPrZSx1ecNhyWf8oAstUuevIQWBJxpTcclbg&start=false&loop=false&delayms=3000">here</a>.Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-54494736370443305372012-03-28T16:18:00.001-04:002012-07-11T03:41:39.640-04:00LinksLive Code<br />
<a href="http://www.iamnop.com/raymarch/">http://www.iamnop.com/raymarch/</a> <br />
<br />
Git Repo <br />
<a href="https://github.com/prutsdomj/WebGL-RayMarch">https://github.com/nopjia/WebGL-RayMarch</a>Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-33754117324104799002012-03-28T15:37:00.002-04:002012-03-28T15:42:47.151-04:00Looking Better!Just as a test, to see if a good output image is possible.<br />
<ol>
<li>Added fog as an exponential function of ray distance.</li>
<li>Increased maximum steps to eliminate numerical error artifacts.</li>
</ol>
The output looks nice, but the performance also took a big hit. <br />
<br />
Since more steps produce better results, now I know an area of optimization is definitely in the balance of maximum step number and maximum distance. Something to look into further down the road.<br />
<br />
And here's a screenshot.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaIRHugSTio1bGQiNxh5nc4QfQ_ly4ika_-93u8Twl4ewatHwFhQQXVrnNkix1IB_ZNsHn72K_eWQ8KyQ79WsrnGULxsg14MikSAtvXtU1xMizmpFA-sPidy3rcG6Ss_jrY3RnKO-hq-c/s1600/Untitled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaIRHugSTio1bGQiNxh5nc4QfQ_ly4ika_-93u8Twl4ewatHwFhQQXVrnNkix1IB_ZNsHn72K_eWQ8KyQ79WsrnGULxsg14MikSAtvXtU1xMizmpFA-sPidy3rcG6Ss_jrY3RnKO-hq-c/s1600/Untitled.png" /></a></div>
<br />Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-62609614195994974802012-03-28T14:37:00.001-04:002012-03-28T14:37:48.505-04:00Diffuse LightingAdded basic diffuse lighting!<br />
<br />
The frame rate is still pretty good. The picture does look pretty funky at the moment though, especially around the edges and very far away when ray marching hits the maximum steps.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitX-OWjdKYBeupTZDtqZk4mZ1EW5TRyYQww4iyVQTfDonH-wCxd9wCISRnlbtNWLqpmyzILKnzBBUSC2vPQukgdQuqvJcdnDHWgTWFcJk3G-eqWwbdPrK-tgERV8qtNYVHoe_D3JrLv-0/s1600/Untitled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibNYDb4_R8q7ngFfZPitu2vmjyiNx8wfN7fQYRhtWSb3BOq4NSDdIur1bHTQvgPNERYfUjOXkcZMbZZ5Z8S03OmJLfjO_3tOw1m29Lmrebl8sf7mEITAeqTa61r5cPSmee4lZ5EodgIv0/s1600/Untitled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibNYDb4_R8q7ngFfZPitu2vmjyiNx8wfN7fQYRhtWSb3BOq4NSDdIur1bHTQvgPNERYfUjOXkcZMbZZ5Z8S03OmJLfjO_3tOw1m29Lmrebl8sf7mEITAeqTa61r5cPSmee4lZ5EodgIv0/s1600/Untitled.png" /></a></div>
<br />Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0tag:blogger.com,1999:blog-1148994336372878857.post-60856569896852029702012-03-28T13:37:00.001-04:002012-03-28T13:37:17.932-04:00Playing with Various FunctionsPlayed around with various distance functions from<br />
http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm<br />
<br />
The screenshot below uses the udRoundBox primitive and the repetition operator. The frame rate is pretty high, possibly due to the newly revised ray marching loop. This also shows that increasing the number of shapes does not affect performance at all since this is an implicitly described scene. Later on, when the distance functions become more complex the performance might take a hit.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNewKGLVfOgV6nL50xJ00HGWduN8QC3CaAaCsZkrqz6a8btNX8evAe93O-i6oV448CDOtpRGqhzt0w0HBbGSE4xlfGInPfhWwsJdeHR0oPZr9uH0mHHzLeK3PL3BOvocvyCAq6Ez9cIkE/s1600/Untitled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNewKGLVfOgV6nL50xJ00HGWduN8QC3CaAaCsZkrqz6a8btNX8evAe93O-i6oV448CDOtpRGqhzt0w0HBbGSE4xlfGInPfhWwsJdeHR0oPZr9uH0mHHzLeK3PL3BOvocvyCAq6Ez9cIkE/s1600/Untitled.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />Nop Jiarathanakulhttp://www.blogger.com/profile/04557004230445722355noreply@blogger.com0