tag:blogger.com,1999:blog-12313427304828192752024-03-13T19:47:03.789-07:00mentalmillThis blog focuses on mental mill, MetaSL, shading, 3d computer graphics and much more. Come by to see interesting shaders, effects, ideas and more.Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.comBlogger23125tag:blogger.com,1999:blog-1231342730482819275.post-57292235937509797382011-11-02T11:23:00.000-07:002011-11-02T11:23:12.926-07:00Sneak Peak mental mill 1.2Today I want to talk a little bit about mental mill 1.2 - there are a couple of new features in the next version of mental mill that many of you will appreciate, since we heard requests for them over and over again. So we took the time to implement some of these.<br />
<br />
<br />
<b><span style="font-size: large;">New node types</span></b><br />
There will be new node types in mental mill that can be recognized by their orange color. They are called "scene elements". There are several subtypes of scene elements. Even though all of them are equally important for the new workflow, the one you will be using most of the time is camera node. <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm20KdKbahgEk6mLsOmdv_Mpra5FwdFdESrO0f5B-YNCyquYot8kvBnwK2jeg5O_qVSBdomBW4k6v4NIHDSdlPd4VSZFGBkHCaxxmRfvr4kR2TF_7paW9X5likcelcfSNFacffe2EQqFuW/s1600/new_1.2_camera_node.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm20KdKbahgEk6mLsOmdv_Mpra5FwdFdESrO0f5B-YNCyquYot8kvBnwK2jeg5O_qVSBdomBW4k6v4NIHDSdlPd4VSZFGBkHCaxxmRfvr4kR2TF_7paW9X5likcelcfSNFacffe2EQqFuW/s320/new_1.2_camera_node.png" width="238" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A camera node inside mental mill displaying an entire scene built out of mutiple geometry using multiple shaders. All shaders are built with mental mill</td></tr>
</tbody></table><br />
<b>Camera node </b><br />
The camera node merges all your scene geometry into one view where you can render it using the realtime preview, mental ray or iray. You can also manipulate your scene: You can also select and move your lights and your geometry simply by clicking and dragging with the mouse.<br />
A camera node may have its own environment attached to it. You may have any number of camera nodes in your workspace, each having its own environment shader attached.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQuhZIRMm39xKE3GcwClyESWqegwa-fZWtG5pNepW3xa0ZH1rPkxqfX1Xev9TA8voLl680SCE2w3CLbuDVsJOLr-OY3Y8lcLwWNLT8cklApaiflWvAMFKV2V8DRTt4Zzs-JVzMkP1SlJKk/s1600/new_1.2_camera_node_w_env.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQuhZIRMm39xKE3GcwClyESWqegwa-fZWtG5pNepW3xa0ZH1rPkxqfX1Xev9TA8voLl680SCE2w3CLbuDVsJOLr-OY3Y8lcLwWNLT8cklApaiflWvAMFKV2V8DRTt4Zzs-JVzMkP1SlJKk/s320/new_1.2_camera_node_w_env.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A camera node with an environment shader attached. Each camera node may have its own environment shader which makes it practical for comparing multiple environment images.</td></tr>
</tbody></table><br />
<br />
<b>Geometry nodes</b><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJzNObWJzK6eFSqBVT62JzMZYO-5nwrAh8AYLlWI_A04Ojpnw5hxV7jeXTB0hbjhVknPM5x1gt6ezFPMQcTiWk7bQQHmYUfpYX955dcF1iMeqV0iPMl0xBmPms3xKonZXPQ6hNdlv5ORUe/s1600/new_1.2_geometry_nodes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div>For your scene to actually show some geometry, you need to create geometry nodes. There are two types: A geometry node that defines the type of geometry: There exists procedural shapes like the torus, sphere, plane and so on. <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJzNObWJzK6eFSqBVT62JzMZYO-5nwrAh8AYLlWI_A04Ojpnw5hxV7jeXTB0hbjhVknPM5x1gt6ezFPMQcTiWk7bQQHmYUfpYX955dcF1iMeqV0iPMl0xBmPms3xKonZXPQ6hNdlv5ORUe/s1600/new_1.2_geometry_nodes.png" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJzNObWJzK6eFSqBVT62JzMZYO-5nwrAh8AYLlWI_A04Ojpnw5hxV7jeXTB0hbjhVknPM5x1gt6ezFPMQcTiWk7bQQHmYUfpYX955dcF1iMeqV0iPMl0xBmPms3xKonZXPQ6hNdlv5ORUe/s320/new_1.2_geometry_nodes.png" width="236" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Various Geometry source nodes: Box, Terrain, .obj-file, Torus</td></tr>
</tbody></table><br />
The other geometry node actually defines the object in the scene. It must be fed by one of the aforementioned geometry nodes. Additionally it requires a shader connected to its 'material definition' input port. As soon as you have those set up, you have defined your geometry and it will be shown in the camera node.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9WijoaGm6Pznaa7M1IYsAunf5inW_uIaNWuEq0YbqnezUs_5R2KaV8PQJOMZhtRPkuKleoN3cfaR-rt1eSCJcxrSvt2FlVB-xbq3OkTN3AajyHmXV-ZF6nn0yTarm1pOGpIjULos6Co5v/s1600/new_1.2_full_attached_scene_element.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="275" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9WijoaGm6Pznaa7M1IYsAunf5inW_uIaNWuEq0YbqnezUs_5R2KaV8PQJOMZhtRPkuKleoN3cfaR-rt1eSCJcxrSvt2FlVB-xbq3OkTN3AajyHmXV-ZF6nn0yTarm1pOGpIjULos6Co5v/s320/new_1.2_full_attached_scene_element.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Scene element being fed by a Texture_lookup_2d and a Geometry source node</td></tr>
</tbody></table><br />
<br />
<b>Light nodes</b><br />
You can create lights like any other scene elemnts using the context menu and creating a light. They use the same node types as geometry nodes, however, there are special ones that define the properties of the light source. Also, the scene element node that the light geometry is connected to also requires a light shader.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2zkzVLzC0bMySJMDYtmvExRFnfeWm1f-IaVcnKzrv_gvVievqHG8nA49GU8N_HSJlX9qh3HNGMfubL6rBK3n8qO6F04vB8Ag21CilzEB_w0jGvpdQAbgOVOPZjfTFIz_u6ITJ4jCzLSJ1/s1600/new_1.2_point_light.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="230" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2zkzVLzC0bMySJMDYtmvExRFnfeWm1f-IaVcnKzrv_gvVievqHG8nA49GU8N_HSJlX9qh3HNGMfubL6rBK3n8qO6F04vB8Ag21CilzEB_w0jGvpdQAbgOVOPZjfTFIz_u6ITJ4jCzLSJ1/s320/new_1.2_point_light.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Scene Element being fed by a Light source node and a point light shader</td></tr>
</tbody></table><br />
You don't need to worry about wiring these scene elements manually - mental mill creates them automatically for you when you create them using the context menu.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiecbLoDsDHJfIs_Qllsow0Lx8qrvB6iEozQzcJE2_BM_HLHesF-nxjvIR4gut3l4ZVXtoeJOCne81Fx9QMZT15JUIC67GmajwlKIExg8zGavsB3TnGKdzkxjQUSNsE40_8eITvho-avX3c/s1600/new_1.2_context_menu.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiecbLoDsDHJfIs_Qllsow0Lx8qrvB6iEozQzcJE2_BM_HLHesF-nxjvIR4gut3l4ZVXtoeJOCne81Fx9QMZT15JUIC67GmajwlKIExg8zGavsB3TnGKdzkxjQUSNsE40_8eITvho-avX3c/s320/new_1.2_context_menu.png" width="320" /></a></div><br />
<br />
Here is an example of a complete workspace in mental mill 1.2<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwBnQz4S930vs4OoQOFX4Wt6h0nppqMHaSkDkiAEqlQvk6JL8MTk4alS1IotPG0ZQ-w2Ig2EnwoHjDMot-GpAbMxAUFGyhdPDR8eqM1DUki64-mcDwLz4dm_NTz0xkd9AVRZd71JpkDJPC/s1600/new_1.2_workspace_example.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwBnQz4S930vs4OoQOFX4Wt6h0nppqMHaSkDkiAEqlQvk6JL8MTk4alS1IotPG0ZQ-w2Ig2EnwoHjDMot-GpAbMxAUFGyhdPDR8eqM1DUki64-mcDwLz4dm_NTz0xkd9AVRZd71JpkDJPC/s320/new_1.2_workspace_example.jpg" width="320" /></a></div>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com2tag:blogger.com,1999:blog-1231342730482819275.post-67445546522769673102011-08-31T09:18:00.000-07:002011-08-31T09:18:02.086-07:00MetaSL based texturing tutorial with 3ds MaxZoltan has created a very nice and elaborate tutorial about MetaSL based texturing in 3ds Max. Take a look and give it a try. During the series of articles, you will learn how to create this:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://www.zspline.net/blog/wp-content/gallery/tutorial_metaslbasedtexturing/advexample46.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="257" src="http://www.zspline.net/blog/wp-content/gallery/tutorial_metaslbasedtexturing/advexample46.jpg" width="320" /></a></div><br />
<br />
"This series of articles are about a texturing workflow and the related set of shader nodes called MUSH (<strong>M</strong>etaSL <strong>U</strong>tility <strong>Sh</strong>aders). They allow the artist to texture up a mesh in high definition while keeping the artistic freedom to experiment and tweak the visuals in a simple way. These solutions are targeted mainly at game asset creators but might be useful to anyone who could live with the limitations of the methods."<br />
- Zoltan<br />
<br />
<a href="http://www.zspline.net/blog/metasl-based-texturing-part-i/">Part I: Overview</a><br />
<a href="http://www.zspline.net/blog/metasl-based-texturing-part-ii/">Part II: A basic example</a><br />
<a href="http://www.zspline.net/blog/metasl-based-texturing-part-iii/">Part III: Baking</a><br />
<a href="http://www.zspline.net/blog/metasl-based-texturing-part-iv/">Part IV: Displacement</a><br />
<a href="http://www.zspline.net/blog/metasl-based-texturing-part-v/">Part V: An advanced example</a><br />
<a href="http://www.zspline.net/blog/metasl-based-texturing-part-vi/">Part VI: Tips and tricks</a><br />
<a href="http://www.zspline.net/blog/metasl-based-texturing-part-vii/">Part VII: Known issues</a><br />
<a href="http://www.zspline.net/blog/metasl-based-texturing-part-viii/">Part VIII: Node reference</a><br />
<br />
If you like Zoltans work, also check out this article here:<br />
<a href="http://www.zspline.net/blog/deposit-shader-in-mentalmill/">http://www.zspline.net/blog/deposit-shader-in-mentalmill/</a>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-84359167860768920602011-08-12T08:43:00.000-07:002011-08-12T08:43:53.673-07:00Water shader study Here is a study of a water shader that I created a little while ago. The shader is based on a simple idea of using a black and white height map and a normal map that defines the heightmap where the water will be and how the normals are oriented. <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/jljzKDyeH8o?feature=player_embedded' frameborder='0'></iframe></div><br />
Download the project file <a href="http://forum.mentalimages.com/showthread.php?8636-Water-shader-study-in-mental-mill">here</a>.<br />
<br />
<br />
See the screenshot of the shader network inside the Phenomenon. Many parts could be wrapped into Phenomena themselves, but I leave that to the users as a practice. <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTPbtv4-UdhDzVHRWjY2oHdXw2ICBlyi0x9C4OdmVhDJbbT2FMNzyJ5PMPU9nezIK1A1BwaUFcn8URH3HMLFOk-ou3iVbys0094RJuCK89M1jHgSLJambapgbPaZAX478RqAdBIZYyFMbb/s1600/Water_shader_explained.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTPbtv4-UdhDzVHRWjY2oHdXw2ICBlyi0x9C4OdmVhDJbbT2FMNzyJ5PMPU9nezIK1A1BwaUFcn8URH3HMLFOk-ou3iVbys0094RJuCK89M1jHgSLJambapgbPaZAX478RqAdBIZYyFMbb/s400/Water_shader_explained.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This is a preview of the water shader network inside the Phenomenon. I broke up the network into sections (though some functionalities overlap, but I tried to give it a rough structure. See the (Note that in the image one node does not belong to any section. This is because it does nothing, and I removed it from the final .xmsl that you can download from the mental mill blog)</td><td class="tr-caption" style="text-align: center;"><br />
</td></tr>
</tbody></table><span style="font-size: large;"><b>How the effect is created (a rough overview)</b></span><br />
<br />
Two different procedural perlin noises are combined to a float2 that is biased around 0 so that the values vary between -1 and 1. These values are used for<br />
<ul><li>texture coordinate distortion (for the fake-refraction texture lookup)</li>
<li>caustic generation</li>
<li>water normal generation</li>
</ul>A height map and a normal map that are both derived from the same source are used. The height map is used to calculate the water-falloff and the normal map provides the normal of the shape that 'contains' the water which is used for the diffuse shading.<br />
The height information is used to create the falloff of the water (when it fades to the water color). Caustics are generated by using a special shader that is fed by the procedural float2 value.<br />
<br />
All effects are finally combined and composited: Reflection, (fake) refraction, water color, caustics to generate the final look of the surface.<br />
<br />
<span style="font-size: large;"><b>What to improve</b></span><br />
The next things that would be interesting to do is, to find a way to replace the procedural waves with some cheaper normal textures that would save a massive number of instructions. However, this would raise the question how the caustics are generated, since this is done in a special shader.<br />
<br />
<br />
Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-6744488918804650762011-08-04T05:01:00.000-07:002011-08-04T05:01:55.403-07:00New debuggers for debugging within mental millI have created a set of Phenomena that assist you in debugging Colors and float2 as well as float parameters. The float debugger is basically the same as built into mental mill, but you are encouraged to open the Phenomenon and study what's inside there. The details are all described in the entry on the forum. Feel free to disassemble the Phenomenon and pull it apart, enhance it or create your own flavors.<br />
Especially the color debugger has been enhanced and has more options than the built-in color debugger. It is more readable than the color encoding of the built-in debugger. <br />
<br />
Here is the location where you can also download the mental mill 1.1 project file:<br />
<a href="https://service.gmx.net/de/cgi/derefer?TYPE=3&DEST=http%3A%2F%2Fforum.mentalimages.com%2Fshowthread.php%3F8616-Debugging-colors-floats-and-float2s" style="text-decoration: underline;" target="_blank">http://forum.mentalimages.com/showthread.php?8616-Debugging-colors-floats-and-float2s</a> <br />
<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuxO0_a1_smTe0voypjX3JsxXfiNuQ8MRnlUnh_lDFXEkLLQ1xC6Ba-4yBN8rSwYjJSu7gJW3WSFvTKAygSy9vFPaQ5CnSaC1iShG9Cv0z6igcNQlqB3L6cLHwiB3FbQWu2LNZwJZdTm-B/s1600/debug_phen_color.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuxO0_a1_smTe0voypjX3JsxXfiNuQ8MRnlUnh_lDFXEkLLQ1xC6Ba-4yBN8rSwYjJSu7gJW3WSFvTKAygSy9vFPaQ5CnSaC1iShG9Cv0z6igcNQlqB3L6cLHwiB3FbQWu2LNZwJZdTm-B/s320/debug_phen_color.png" width="210" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><b>Color debugger:</b> Shows when colors are above or below a given limit in red and blue. Components can be turned on and off and the behavior for the color overlay can be toggled: Either ALL components must exceed in order to show a color overlay or it is enough that ANY component exceeds in order to show a red/blue overlay. The other outputs of the debugger Phenomenon show a compressed view of the colors and the luminance.</td><td class="tr-caption" style="text-align: center;"><br />
</td><td class="tr-caption" style="text-align: center;"><br />
</td></tr>
</tbody></table><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnSphC4-ua6IIfvu7Z1cdOm301jfEZDMQi29GtxkiWvnRqWdg72K08eiU90mTmaiXutxgdHggpMDWhHGSs47a2GwCFww2_8CEAemi5f4kOZNS2wpSiTYukyQ22sg8nO-xWXwwdMUSuYx33/s1600/debug_phen_float.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnSphC4-ua6IIfvu7Z1cdOm301jfEZDMQi29GtxkiWvnRqWdg72K08eiU90mTmaiXutxgdHggpMDWhHGSs47a2GwCFww2_8CEAemi5f4kOZNS2wpSiTYukyQ22sg8nO-xWXwwdMUSuYx33/s320/debug_phen_float.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><b>Float debugger:</b> Works basically like the built-in preview window debugger, but shows colored overlays instead of just clamping or repeating the values.</td></tr>
</tbody></table><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfVyS0QW2WDR_lhzShcf0wJsbjLGI781xj0vYVsj0nspcLb87TSLC4ZsJ6olOraE3k2Lw7go50dBOiUNzpzDCe9jjKpI1OP4CSj8W4Eb3V7P8h8tU6uCvaswcxgq8EUDA_PrhCZB4D6hbB/s1600/debug_phen_float2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfVyS0QW2WDR_lhzShcf0wJsbjLGI781xj0vYVsj0nspcLb87TSLC4ZsJ6olOraE3k2Lw7go50dBOiUNzpzDCe9jjKpI1OP4CSj8W4Eb3V7P8h8tU6uCvaswcxgq8EUDA_PrhCZB4D6hbB/s320/debug_phen_float2.png" width="233" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><b>float2 debugger:</b> debugs float2 parameters and shows a colored overlay where values go beyong or below the min/max range. Additionally it outputs the length as a float value.</td></tr>
</tbody></table>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-464313938447137532011-05-23T04:19:00.000-07:002011-05-23T04:19:28.965-07:004K animationAs mentioned in my older blog entries, IQ of the Spanish demo group RGBA is one of my CG heroes. I know hardly any people who can combine mathematical understanding and arts in a more beautiful way. This prod here is quite old, but I just knew the still-image (a 4K executable). Here is also an animation where you can see procedural graphics at the highest level in a beautiful fly-over.<br />
<br />
<a href="http://www.youtube.com/watch?v=XAWPCmVC5jA">http://www.youtube.com/watch?v=XAWPCmVC5jA</a>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-77632205045646360602011-05-17T08:36:00.000-07:002011-05-17T09:00:57.948-07:00<span class="Apple-style-span" style="font-size: large;"><b>1. Idea and Motivation for today's blog entry</b></span><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTs-kUvdv2P5kuTbJNmlYDb5_CfwBi7QpCIRZYq9mZlNcUC1AmHqeTv0bAecPeltU7CifHbcMw99S7duzOVjfIVuVk1TOYOCjlfhHU3PaNcQG7zdW2bp4SOLIydlMYP0zL_VvUbS4qJBS0/s1600/shader_variations_2.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="93" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTs-kUvdv2P5kuTbJNmlYDb5_CfwBi7QpCIRZYq9mZlNcUC1AmHqeTv0bAecPeltU7CifHbcMw99S7duzOVjfIVuVk1TOYOCjlfhHU3PaNcQG7zdW2bp4SOLIydlMYP0zL_VvUbS4qJBS0/s400/shader_variations_2.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Preview of the CgFX shader in Softimage</td></tr>
</tbody></table>Recently I started playing with ICE in Softimage, which is a wonderfull node based tool for creating your own deformers, particle simulations and much more. The workflow reminds me a lot of mental mill (and I have always been a huge fan of node based editing systems) so it was not hard to get some results pretty soon.<br />
<br />
As I was playing around, I couldn't help thinking about creating a shader in mental mill that implements a neat effect that takes advantage of ICE in Softimage. This tutorial won't be about ICE, though I will roughly explain a few details and I intend to post the project that I created along with the modified shader.<br />
<br />
<a href="http://forum.mentalimages.com/showthread.php?8387-Next-shader-example-for-using-mental-mill-and-Softimage">You can find the data to complete this tutorial here</a><br />
<i>In the zip file you can find the mental mill project as well as the softimage project. Read "Readme.txt" for a more detailed description</i><br />
<br />
<b>1.1 Preparation:</b><br />
First you need to create folders and set up default paths so that you won't end up with absolute path names in your work. This will save you lots of time later on. Absolute path names are the root of all evil as soon as you start moving your files between multiple machines...<br />
<br />
<ul><li>Under <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">C:\users\username\Autodesk\Softimage_2010\Application\ </span>create a folder called <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">"CgFX"</span> and another folder called "<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">fxtextures"</span>. These will be needed for storing your exported shader and your textures.</li>
</ul><ul><li>Copy the textures that you will be using in this tuorial under <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">C:\users\username\Autodesk\Softimage_2010\Application\fxtextures</span>so that Softimage will be able to load them automatically</li>
</ul><ul><li>Make sure that the texture path is added to mental mill's texture paths. To add a mental mill texture path, go to "<i>Edit > Preferences > Path</i>". Under <i>Texture</i> click <i>Edit</i> and add the path to your textures. This has the effect, that mental mill won't store absolute file paths when you select a texture from that directory.</li>
</ul><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4nfqUBFRd39WrNkpQMOsP9-YC1OZgFpGZgEonaoDJL4hoZuizPeTkGx27aZn3zHbfOuosDTOZ0l_oUGJw0mTcM-K02wcP_4c5kjDpjS2858NNUqT09G4kBbUYu1CW_dPQ_NumRjF_kaN5/s1600/adding_a_texture_path.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="258" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4nfqUBFRd39WrNkpQMOsP9-YC1OZgFpGZgEonaoDJL4hoZuizPeTkGx27aZn3zHbfOuosDTOZ0l_oUGJw0mTcM-K02wcP_4c5kjDpjS2858NNUqT09G4kBbUYu1CW_dPQ_NumRjF_kaN5/s320/adding_a_texture_path.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Adding a texture path in mental mill</td></tr>
</tbody></table><br />
<br />
<b><span class="Apple-style-span" style="font-size: large;">2. Implementation Softimage</span></b><br />
Let's start in Softimage where I implemented an effect that attracts geometry to other geometry. So how does it work?<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh2XKVVSVc1aNgb9f9VlpFhLOkyIjqdhM7nG8HyZK9HfhuqWscRBiCi7lMrqKVuT1deE808bxnprRI2-t3Uvtv8VuAM-f14xuMMrFRNQ4g16wGXa6oxHBWmf6lb8bIxiLolf2Z2zwhx-No/s1600/attraction_effect_softimage.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh2XKVVSVc1aNgb9f9VlpFhLOkyIjqdhM7nG8HyZK9HfhuqWscRBiCi7lMrqKVuT1deE808bxnprRI2-t3Uvtv8VuAM-f14xuMMrFRNQ4g16wGXa6oxHBWmf6lb8bIxiLolf2Z2zwhx-No/s320/attraction_effect_softimage.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The "magnetic skin" effect in Softimage</td></tr>
</tbody></table>I got a piece of geometry that I want to deform and another geometry that I will refer to as "attractor" since it will attract the other geometry as it is moved closer to the target geometry that has the ice effect applied.<br />
<br />
<b><span class="Apple-style-span" style="font-size: large;">2.1 ICE Deformer</span></b><br />
In my ICE tree I search for the nearest points on the attractor and I calculate the average value, so that I know to which position the point is attracted to.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoP68RSTautiIwu4a81aeKXNNOnHOaGKLRxbg931HFxgYkE_PZDqOeX6Piv-L4YSBzPf0yy09ZNddHh51iNgX8SgpXPf9VHhc__i764jKKw1YE9p-mYpxvAoHMJ8h0wS_JXUKeOFUlOa5L/s1600/attraction+effect+sketch.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoP68RSTautiIwu4a81aeKXNNOnHOaGKLRxbg931HFxgYkE_PZDqOeX6Piv-L4YSBzPf0yy09ZNddHh51iNgX8SgpXPf9VHhc__i764jKKw1YE9p-mYpxvAoHMJ8h0wS_JXUKeOFUlOa5L/s1600/attraction+effect+sketch.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">B is calculated as average position of the 'N' nearest points to point A.<br />
As the distance between A and B gets smaller, A will be 'warped' more and more towards B </td></tr>
</tbody></table><br />
The distance of the source point to the averaged target position is calculated. I was implementing a falloff using the square distance, which can be expressed as <i>1/(distance^2)</i>.<br />
The shorter the distance, the more the point will be attracted as the result of that calculation gets bigger. I made sure that the result of that calculation does not exceed the range between 0 and 1 by using a clamp node. This allowed me to calculate the final position by lerping between the original position value and the averaged value that I calculated on the attractor.<br />
<br />
<b><span class="Apple-style-span" style="font-size: large;">2.2 ICE weight map</span></b><br />
The next "challenge" if you like to say so was to write the values that had been calculated into a Colors at vertices map. The data from that map can then be sent over to the shader.<br />
<br />
So first I created a Colors at Vertices Property (<i>Model > Property > Color At Vertices Map</i>) into which I wanted to write the data calculated by the<br />
However, it is not possible to set data that needs to be processed 'per sample' from an output that was calculated per point.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglaYfJvolbvIW6sHLrZGTHEZLYm-gz4Co5PklSCbJs5rc4VPL7B9ZwMJYyggATVexI-b8CBImS7FPLijJsgEJewFVLJL-NeOBrJ03FFUL0pGikoYrvDqdHh6yNiMwzPZJdRCpkePn_wqo2/s1600/sample_point_mismatch.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="140" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglaYfJvolbvIW6sHLrZGTHEZLYm-gz4Co5PklSCbJs5rc4VPL7B9ZwMJYyggATVexI-b8CBImS7FPLijJsgEJewFVLJL-NeOBrJ03FFUL0pGikoYrvDqdHh6yNiMwzPZJdRCpkePn_wqo2/s400/sample_point_mismatch.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">When manipulating point-based data, it can't be written into sample based maps.<br />
The workaround is to stor the data in a temprary set data node and writing it into the<br />
Color At Vertices map (see image below)</td></tr>
</tbody></table><br />
To circumvent that problem I took a look around and I found the explanation in the <a href="http://xsibase.com/">XSIBase forum</a> that I still visit regularly. The answer is to write the data in some temporary variables using the <i>Set Data</i> node.<br />
<br />
Then, when writing into the Vertex Color map (which is sample based) the data can be retrieved using Get -> <i>self.nodelocation</i> and retrieving the data that we set which is then written into the Vertex Color.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikNbbsTCL_HHdJrMA4Q4CXZQc3FkzhO2nmq1vUebxZwFUEHMpzT3MwzA2epVrQX6XohCCBCi5owTyxZnfCHJa4-y1Y6C-mWXJbFbiRKdkksiZtfAiehvGctxqCo_SBQN_0O4H_erHMcdIv/s1600/setting_CAV_map.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="96" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikNbbsTCL_HHdJrMA4Q4CXZQc3FkzhO2nmq1vUebxZwFUEHMpzT3MwzA2epVrQX6XohCCBCi5owTyxZnfCHJa4-y1Y6C-mWXJbFbiRKdkksiZtfAiehvGctxqCo_SBQN_0O4H_erHMcdIv/s400/setting_CAV_map.png" width="400" /></a></div><br />
<br />
Now when switching to constant display, you can see the 'weight' as a grayscale being interpolated between the vertices. So much for the work that needs to be done in XSI. Next we will take a closer look at the actual shader that we will create in mental mill.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgsLWTvvuJ1QgIS3IYrQtzb47yV9FtrOhmLDEsZGiFxif5MoIbfju4q4M7GG-19YWSlupoIN9rlEo27ElZymLLAtgxGev_GGQrHr59c_RrITxcsme396RpEEQtF8OE5KUFjgcB5SbI3pvN/s1600/display_CAV.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgsLWTvvuJ1QgIS3IYrQtzb47yV9FtrOhmLDEsZGiFxif5MoIbfju4q4M7GG-19YWSlupoIN9rlEo27ElZymLLAtgxGev_GGQrHr59c_RrITxcsme396RpEEQtF8OE5KUFjgcB5SbI3pvN/s320/display_CAV.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Inspecting the Vertex Color Map in Softimage. The more the points are<br />
attracted, the brighter they appear in the map</td></tr>
</tbody></table><br />
<br />
<br />
<b><span class="Apple-style-span" style="font-size: large;">3. mental mill shader implementation</span></b><br />
The goal of this tutorial is to get an understanding of how to use Softimage ICE and shaders that were built in mental mill. For the sake of simplicity I reduce the size of the mental mill project to use just as few nodes as necessary.<br />
The idea for the effect is that the original transforms (or simply blends) into another surface as the attractor moves closer and closer. This transition effect is controlled by the grayscale map that we generated in our ICE tree above.<br />
<br />
<b>3.1 The mental mill network for the Phenomenon "Break_D_Ice"</b><br />
We want to blend between two materials. In order to give that impression, we will mix two bump maps as well as two diffuse texture maps and feed them into an illumination node. I used an <i>Illumination_phong</i> node (<b>D</b>) here.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOcVitGXbPU5KmD5jFTOS8O2m6rOmEt4bfDAsn2oTlo5TmUiZqT6mABIPVeljNXlEb7A3gCGh-rGcEar2HuwRj6eOrYLjebXRMrIXKMhivvCeHYIrsbcZY8ak0wRGVN7GRFGuGXERPpHcC/s1600/mill_network_simplified.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="608" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOcVitGXbPU5KmD5jFTOS8O2m6rOmEt4bfDAsn2oTlo5TmUiZqT6mABIPVeljNXlEb7A3gCGh-rGcEar2HuwRj6eOrYLjebXRMrIXKMhivvCeHYIrsbcZY8ak0wRGVN7GRFGuGXERPpHcC/s640/mill_network_simplified.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The mental mill shader network: Note, that I renamed the Texture lookup nodes for more clarity.</td></tr>
</tbody></table><br />
<b>3.2 Working around the Color At Vertices map in mental mill</b><br />
Right now we just got one problem to solve: Mental mill does not know about any Color At Vertices Map, so we need to create a stand-in shader node. (We will replace it manually after we have exported the shader and loaded in in Softimage). For the stand-in I created a texture_lookup_2d node (<b>G</b>). I loaded a texture with spherical transition from white to black which allows me to preview the transitions in mental mill.<br />
<br />
<b>3.3 It's a matter of blend: Mixing textures</b><br />
I used the result of the stand-in texture lookup node to blend the diffuse map textures (<b>A</b>) and (<b>H</b>). Note that I am multiplying (<b>B</b>) the two diffuse textures (<b>A</b>) and (<b>H</b>) before mixing, so the asphalt texture is modulated with the cracks.<br />
Then the textures are mixed (<b>C</b>) and fed into the Illumination Phong node for both diffuse and specular texture. The result of the Illumination Phong node is fed to the result output of the Phenomenon.<br />
<i><b>Note: </b>Typically you would have separate textures for the specular color, I just try to keep the example small...</i><br />
<br />
The same kind of blending is done with the normal maps. mental mill 1.1 ships with a couple of utility Phenomena so that you don't need to create the most basic utilities on your own. I used the Dual bump mixer here (<b>E</b>). Again, the bump mix is controlled by the stand-in texture lookup node. Since the 'Bump Mix' parameter of the Dual Bump Mixer takes a float value, it's converted from a color to a float.<br />
<br />
<b>3.4 The interface parameters to control the effect</b><br />
It's always a good practice to reduce the amount of interface parameters to a minimum. This has several reasons:<br />
The less parameters you have, the easier it is to tweak the shader.<br />
Parameters that are not exposed can be made constants by the shader compiler which can reduce instruction count of the shader.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB69ykqN3Zcd8aSCSxp4DP5Rqh3yY14tsWB_QTVWHEr2EorN3GSBxzTCqnIiDrFzuT8viE-M8DrltyURpTX0M5rrUkfQhJjnjVIfoYG91LOfovXrGI8WhMINcT7DB7y0mqtObVl3xWw-WC/s1600/interface_parameters.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB69ykqN3Zcd8aSCSxp4DP5Rqh3yY14tsWB_QTVWHEr2EorN3GSBxzTCqnIiDrFzuT8viE-M8DrltyURpTX0M5rrUkfQhJjnjVIfoYG91LOfovXrGI8WhMINcT7DB7y0mqtObVl3xWw-WC/s1600/interface_parameters.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Interface parameters of the Phenomenon</td></tr>
</tbody></table><br />
You can see in the screenshots which parameters I chose to expose. Feel free to expose the parameters that you consider relevant.<br />
<br />
<b>3.5 Exporting the shader for Softimage</b><br />
Finally, select your Phenomenon that you created and export it for Softimage under "<i>File > Export..."</i> and then select <i>Autodesk Softimage (CgFX)</i> from the dropdown menu. The location where you save the file is important. In newer Softimage versions (I used 2010) you need to store the shader files in a dedicated directory from which they will be loaded automatically upon startup. <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">C:\users\username\Autodesk\Softimage_2010\Application\CgFX</span>. (I had to create the CgFX folder manually, it was not present.)<br />
Give the shader a meaningful name, I chose to name it <i>Ice_breaker</i> which will be then stored as <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Ice_breaker.cgfx</span>.<br />
<br />
<div style="font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">There are other places that you can store your shader in. Check "<i>Loading Existing Effects Files in the Preset Manager</i>" of your Softimage Manual.</div><br />
<br />
<span class="Apple-style-span" style="font-size: large;"><b>4. Loading the shader in Softimage</b></span><br />
Next we will load the shader in Softimage. The realtime shader framework has changed in the recent version of Softimage. In older versions of Softimage you were able to load shaders using dedicated HLSL and CgFX nodes.<br />
In the new version all you need is to store the shader in a dedicated directory from whichthe shader will be loaded.<br />
<br />
<b>4.1 loading the shader</b><br />
<br />
<div style="font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">(Re)Start Softimage and open the Render Tree. If you stored the shader in the right directory, you can find your shader under the <i>Realtime > CgFX</i> category in the Render Tree. </div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEii3z0RLgWCV0eWzRJNF2xKH4qETRr2sYD7Obk8SecAoF417EBOyTDgpNGQJRlCOSCUnYxa896Pir7NJatHFrHBoPufO11Mq73y_Mhb1O05_VeHI8D_zzz9iyV_wmjy-SDsqVxLsv5SNoMF/s1600/shader_in_rendertree_shaderlist.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEii3z0RLgWCV0eWzRJNF2xKH4qETRr2sYD7Obk8SecAoF417EBOyTDgpNGQJRlCOSCUnYxa896Pir7NJatHFrHBoPufO11Mq73y_Mhb1O05_VeHI8D_zzz9iyV_wmjy-SDsqVxLsv5SNoMF/s320/shader_in_rendertree_shaderlist.png" width="269" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Realtime shaders in mental mill</td></tr>
</tbody></table><div style="font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Just drag and drop the shader from there to workspace and it is ready to be used: The image clips are automatically created and connected to your shader. If you set up your texture paths correctly as described under "preparation", then the images will be found automatically and the shader will display correctly.</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRF7Q61rPSv8RU1LKVU9eh-OzsZA2oSpsSYzTpWn2PzKf3uxGbuklRUeZheXtPIHf1G-4GFiZcrQF-7sN8DHvHSDI-mICDA1sQbup_YDBd9T18ONR2HL06wk2kajrwroT1EU_6huOFJkHs/s1600/shader_in_rendertee_workspace.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="165" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRF7Q61rPSv8RU1LKVU9eh-OzsZA2oSpsSYzTpWn2PzKf3uxGbuklRUeZheXtPIHf1G-4GFiZcrQF-7sN8DHvHSDI-mICDA1sQbup_YDBd9T18ONR2HL06wk2kajrwroT1EU_6huOFJkHs/s400/shader_in_rendertee_workspace.png" width="400" /></a></div><div style="font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="font-weight: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><b>4.2 How to feed a Color At Vertices map to the shader</b></div><br />
The next step is about hand-massaging the shadercode, so that we can feed the Color At Vertices Map that our ICE tree is generating to the exported mental mill shader. For that we need to edit the shader a little bit. To edit a shader in Softimage, right click the shader instance in the Render Tree or in the shader list and choose "<i>Edit Shader</i>" from the context menu. This will open the shader code editor.<br />
<br />
<b>4.2.1 Understanding Realtime Shaders: A quick overview</b><br />
<i>For the next step, you need to understand the structure of an exported MetaSL shader, so I will give a rough outline how realtime shaders work:</i><br />
<br />
A realtime shader takes a number of data that can be defined either per vertex or globally per frame. Per vertex data is fed to the shader via a vertex stream. The per-vertex data is first passed to the <i>vertex shader</i> which may transform the data (transforming the vertex positions by viewing matrices, etc...). Other data might be passed through to the fragment shader without modifying it, for example UV coordinates.<br />
<br />
In your shader code that mental mill is exporting for you, you don't have to worry about these things: mental mill takes care to set up all necessary vertex stream variables. Once the vertex streams are set up correctly, the right data that you want to process is automatically passed to the shader. Examples for per vertex data are:<br />
<ul><li>Texture coordinates</li>
<li>Vertex Position</li>
<li>Normal</li>
</ul>When you export a shader for Softimage, 4 different texture spaces are supported. As you just learned, texture coordinates are passed as vertex streams. In our example we just require the first texture space. This leaves 3 vertex streams that we can 'hijack' (or abuse) to feed our own vertex stream data to the shader.<br />
Softimage has a convenient interface that lets you assign any vertex data from Softimage to the vertex stream variables of a shader.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVsnVOzGsSn4IDuY4bgvwv8lXM-xBo4AG8i0zQpRXWt6sriD3A5b3Z_wI483vQko5u9pRCmQeM4qsIRg9N2yvKsJQtJsiPZGmyvcNQy9rt6WI42Rwr_t4FfWO5CxERswWy8Eb6V9R1alKg/s1600/assignable_vertex_streams.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="235" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVsnVOzGsSn4IDuY4bgvwv8lXM-xBo4AG8i0zQpRXWt6sriD3A5b3Z_wI483vQko5u9pRCmQeM4qsIRg9N2yvKsJQtJsiPZGmyvcNQy9rt6WI42Rwr_t4FfWO5CxERswWy8Eb6V9R1alKg/s320/assignable_vertex_streams.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Assigning data from Softimage to stream-variables of the CgFX Shader</td></tr>
</tbody></table><br />
This is what we need to do to get this working:<br />
<ul><li>In the shader code we will locate the texture lookup function of the stand-in node that was simulating the Color At Vertices Map. The variable that holds the result of the texture lookup of the stand-in node will be overwritten with the value that comes from the vertex stream variable that we 'hijacked'. That way you obtain the <i>real</i> value from the vertex stream data that the Ice Tree in Softimage is computing.</li>
</ul>While that may sound like one daunting step it just requires a trivial change to the shader. Nevertheless I want you to understand what we are doing exactly and why we are doing this, so let me me explain:<br />
<br />
When a mental mill shader is exported, all shader nodes are converted to functions in the exported shader code that will be called in the correct order to carry out all necessary tasks. In step 3.2 we created a stand-in texture lookup node that was acting as a holdout for our Color At Vertices map.<br />
<br />
<b>4.2.2 Editing the mental mill shader to use texture space slot for passthrough</b><br />
As we just said: We want to use a texture space to pass the Color At Vertices information from Softimage to the shader. Lets take a look at the vertex shader that you exported from mental mill:<br />
<br />
You can see, that the Vert2Frag structure holds an array of 4 vertex streams (in the image below on the left, colored in orange).<br />
In the vertex shader this stream array is passed to the state-structure variable state.tex_coord, colored in green. We need to remember where this stream data is stored. The first array element stream will hold the texture coordinates that we will be using for the texture lookups. The second one will hold the Color at Vertices Data.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2gAwwXyhN-gFXkiLe66vgsCxxHImxKjO_tT7RE8mHVf1Ak4shJeBoYNEsG-DsH6gCpz7EOu5_FVsEiFKB0bh1M0DJ2DKDXTZ2xdmT4m7unm7YmAtT_xB9C0cJHjVowkrdwBZ4Q3WOiyBz/s1600/vert2_frag_struct_code.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2gAwwXyhN-gFXkiLe66vgsCxxHImxKjO_tT7RE8mHVf1Ak4shJeBoYNEsG-DsH6gCpz7EOu5_FVsEiFKB0bh1M0DJ2DKDXTZ2xdmT4m7unm7YmAtT_xB9C0cJHjVowkrdwBZ4Q3WOiyBz/s1600/vert2_frag_struct_code.png" /></a></div><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><b><i><br />
</i></b><br />
Now we need to find the Texture lookup and replace it with the variable that holds the result of the texture lookup with the vertex stream value.<br />
<br />
<ul><li>Look for the main-function of the phenomenon that you exported from mental mill. In my case, the Phenomenon was called "Break_D_ice", so the function is called "Break_D_ice_main".</li>
</ul>The stand-in texture lookup node was renamed to "Weightmap". Inside the "Break_D_ice_main" function you need to find the function call which is a combination of the Nodename in mental mill and some additional strings to avoid name collisions. In my case it was called "Break_D_Ice_Texture_lookup_main(...)". Above the variable that will hold the result, "<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">float4 msl_Weightmap_result</span>" is declared.<br />
<br />
<br />
<ul><li>Comment out the texture lookup function.</li>
<li>Whe<span class="Apple-style-span" style="font-family: inherit;"><span class="Apple-style-span" style="font-family: inherit;">n "floa</span>t4 msl_Weightmap_result" is</span><span class="Apple-style-span" style="font-family: inherit;"> declared, assign it the texture stream variable:</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">float4 msl_Weightmap_result = float4(state.tex_coord[1].xyz, 1);</span></li>
</ul><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAag5z75u_L3Igp8qLME5bX789m6klfzSliTapiZF6BDdSXO2SA0MeurI3GY0WszzekJfrVuxMf2-KSrI9OVPdLT-kxxPggSjP3R7Rh5W_amwveE2qsKR5C4A9X6C21hEpq1Bd7o30JcB-/s1600/replacing_the_texturelookup_w_CAVMap.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAag5z75u_L3Igp8qLME5bX789m6klfzSliTapiZF6BDdSXO2SA0MeurI3GY0WszzekJfrVuxMf2-KSrI9OVPdLT-kxxPggSjP3R7Rh5W_amwveE2qsKR5C4A9X6C21hEpq1Bd7o30JcB-/s400/replacing_the_texturelookup_w_CAVMap.png" width="400" /></a></div><br />
In the Shader Code editor of Softimage click "Validate" to check your shader for errors. The shader should validate and you are ready to Apply it.<br />
<br />
If you set up everything correctly, make sure that your viewport is set to "OpenGL" preview. Below you can see some examples. I tried to vary the effect a little bit more. you can make your mental mill example much more sophisticated by extending this example. So feel free to do so!<br />
<br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhR5uED7ouGW3-KsJgi6qPymrKNDwFrqKIhaxtqL8nSbqW0AX0p9jZyG-KFSLZVcbrZAyJRSvMMzqPgs10gM4hsgSkSdKFVImGWHyEHY-M3mWwyBBZx_QbzFoAjU5hYghhAQ4rC8FhaUuIx/s1600/shader_variations.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="141" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhR5uED7ouGW3-KsJgi6qPymrKNDwFrqKIhaxtqL8nSbqW0AX0p9jZyG-KFSLZVcbrZAyJRSvMMzqPgs10gM4hsgSkSdKFVImGWHyEHY-M3mWwyBBZx_QbzFoAjU5hYghhAQ4rC8FhaUuIx/s400/shader_variations.jpg" width="400" /></a></div><br />
<span class="Apple-style-span" style="font-size: x-large;"><b>5 Conclusion</b></span><br />
In this tutorial you learned some techniques that allow you to customize and hand tweak your shader code. It's important to understand that by knowing a little bit of Cg (or HLSL) you can start customizing your shader code so that it fits on top of almost any engine.<br />
<br />
Also remember the way that data is passed to a shader. You saw, that in Softimage you can assign almost any data to a vertex stream. Knowing that, this allows you to add certain features by hand if you are familiar with your favorite DCC tool and CgFx/HLSL.<br />
<br />
Here you can see a video clip how to export the shader from mental mill and load it in Softimage:<br />
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/E3biGBm2mkM?feature=player_embedded' frameborder='0'></iframe></div><br />
<br />
<b>Further reading:</b><br />
<br />
<a href="http://http.developer.nvidia.com/CgTutorial/cg_tutorial_chapter02.html">The CG Tutorial</a><br />
This book that is available online gives you a better idea of how the CG language works and you can learn more about the structure of a cg shader.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com2tag:blogger.com,1999:blog-1231342730482819275.post-27548918009864642092011-04-29T02:56:00.000-07:002011-04-29T02:56:12.805-07:00Node navigation and resizing secretsToday I will talk about some unspoken secrets about navigating and resizing nodes in mental mill 1.1. The nodes in mental mill can be navigated and resized in a much more sophisticated way than most users might think, so I will share those secrets with you today!<br />
<br />
<strong>Hiding input and output parameters</strong><br />
Hold down the shift-key and resize the top or the bottom of your node. This will conceal the input or ouput parameter section of a node.<br />
<br />
<strong>Scrolling within a node that is partly concealed</strong><br />
When a node has been changed so that either parts of the input- or output parameter section are not visible, a light gray scroll bar appears on the side. For input parameters, the scroll bar will appear on the right side, output parameters can be scrolled on the right side.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9RUSci-1yt6tjFM3YTt8KnF1hDRSCtDVLKUH8K7owcTNsmuabJmAYVwZ58781vWjGN8HHaPLsTlQtouC8FX9o_eoodWpoqY1KH-Fb5zjdk65s6JD81fgEo4L5Eluyr1FT06KS26hFaXb7/s1600/Node_resizing_input_parameters.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="230" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9RUSci-1yt6tjFM3YTt8KnF1hDRSCtDVLKUH8K7owcTNsmuabJmAYVwZ58781vWjGN8HHaPLsTlQtouC8FX9o_eoodWpoqY1KH-Fb5zjdk65s6JD81fgEo4L5Eluyr1FT06KS26hFaXb7/s400/Node_resizing_input_parameters.png" width="400" /></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/AVvXsEiBgK7Uaamyz9P8akv0n11_jh4VlWkNvn6T0cfbQskHTFVfuQQmHNTJVGAatEWCqkSAxKXMDY8e2JF3-rxYGNE4K5g0wbKV3CUh2ibCSdr1X03Y1Y79uv_UQIX2Ijtd0OJ2XqiOxB1DL4hU/s1600/Node_resizing_output_parameters.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBgK7Uaamyz9P8akv0n11_jh4VlWkNvn6T0cfbQskHTFVfuQQmHNTJVGAatEWCqkSAxKXMDY8e2JF3-rxYGNE4K5g0wbKV3CUh2ibCSdr1X03Y1Y79uv_UQIX2Ijtd0OJ2XqiOxB1DL4hU/s400/Node_resizing_output_parameters.png" width="400" /></a></div><strong>Collapsing a node</strong><br />
You can collapse a node all the way: Hold the shift key and drag the top or bottom border of the node so that it is entirely collapsed . This is very useful when you have nodes on your workspace that don't play an important role and that you don't want to clutter up your view. If you have got any other nodes connected, you can see that the connection wires are made semi-transparent.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFlf2xMXlafvUv_wcZh2lCZ_PYdV_geXE0ZRy7A9SrSBEFtm_KieGr4v1ttVwwjsItLrvlxMUsAy0Iq8UOVQeR-DNCNlYRt3PsJJbq9ZIt9xjX88gVZxla3Bvv50C3J5I-LsQkin4uTW37/s1600/Node_resizing_collapsed_node.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="87" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFlf2xMXlafvUv_wcZh2lCZ_PYdV_geXE0ZRy7A9SrSBEFtm_KieGr4v1ttVwwjsItLrvlxMUsAy0Iq8UOVQeR-DNCNlYRt3PsJJbq9ZIt9xjX88gVZxla3Bvv50C3J5I-LsQkin4uTW37/s200/Node_resizing_collapsed_node.png" width="200" /></a></div><br />
<strong>Scrolling a party collapsed node / Restoring a node</strong><br />
<ol><li>Double-click the Top or Bottom bar of a node to restore its default view.</li>
<li>You can use the scroll bars to scroll within an input or output parameter section that is partly concealed</li>
<li>When the node is in a semi-collapsed state, you can left-click and drag the splitter bar in the middle to hide and reveal the input parameter section.</li>
</ol><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF8toaVtc7Zj7_hSLf-L8E2aGVdVwEjdRLffTOxE8oNo0VaBCJDE1dPIXBsWpGeG6FHI4SQgFldlohYLoIQlW8or2PYgKUSmYeKifFRa75hAUUDmE7_1BflMq93Kl4eu-2SfoHmtGwvzIq/s1600/Node_resizing_scrollbars_and_restoring.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="245" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF8toaVtc7Zj7_hSLf-L8E2aGVdVwEjdRLffTOxE8oNo0VaBCJDE1dPIXBsWpGeG6FHI4SQgFldlohYLoIQlW8or2PYgKUSmYeKifFRa75hAUUDmE7_1BflMq93Kl4eu-2SfoHmtGwvzIq/s400/Node_resizing_scrollbars_and_restoring.png" width="400" /></a></div><br />
<strong>Resizing preview windows</strong><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitQNVdZrlObtGUbIhh8JIloRiLN8Vb5_ftVFCMqHIqzyRUWCkPQAIVBES9kJ_J-JuxHE0ayKCVy4DHZkvLTKk8owJzdHKPWdcxn9aYFFq40haJa1m0_FH3ij-HGbwJBWAYiZpdmVDmQsd1/s1600/Node_resizing_preview_windows.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitQNVdZrlObtGUbIhh8JIloRiLN8Vb5_ftVFCMqHIqzyRUWCkPQAIVBES9kJ_J-JuxHE0ayKCVy4DHZkvLTKk8owJzdHKPWdcxn9aYFFq40haJa1m0_FH3ij-HGbwJBWAYiZpdmVDmQsd1/s320/Node_resizing_preview_windows.png" width="317" /></a></div><ul><li>The preview windows of the output parameters of a node can be resized individually: Click and drag one of the corners of the preview window.</li>
<li>Preview windows can be opened and closed by left-clicking the name of the output parameter.</li>
</ul><div class="separator" style="clear: both; text-align: center;"></div>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-82705332442317240362011-04-01T06:06:00.000-07:002011-04-01T06:06:26.182-07:00Procedural patterns using mental mill 1d Curve Shaders<div class="separator" style="clear: both; text-align: left;"><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; line-height: 15px;"><b>Motivation</b></span></div><div class="separator" style="clear: both; text-align: left;"><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; font-size: 11px; line-height: 15px;">In the previous post I explained how you can create a ray pattern effect using basis mental mill nodes. This involved some math operations and it took a couple of nodes to make the effect work. We want to achieve the </span></div><div class="separator" style="clear: both; text-align: left;"><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; font-size: 11px; line-height: 15px;">same result in a simpler way, so next I show you how to use the curve nodes that come with mental mill curve shader pack.</span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbyQBbq3xBoevD5nzZtywOh7SCUVfYSk6xHSqSTi9NDhBXoh3OBaDjXfayIK7X2lf5OGUGa2BmPzsrw34d97ZSeYypTVvRtSUysJMRpw4eVs24cNvu2gj0hMmtuc7aNN6627OcSReUT0Nl/s1600/Shaderpack_title.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="313" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbyQBbq3xBoevD5nzZtywOh7SCUVfYSk6xHSqSTi9NDhBXoh3OBaDjXfayIK7X2lf5OGUGa2BmPzsrw34d97ZSeYypTVvRtSUysJMRpw4eVs24cNvu2gj0hMmtuc7aNN6627OcSReUT0Nl/s320/Shaderpack_title.png" width="320" /></a></div><span class="Apple-style-span"><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;"><span class="Apple-style-span" style="font-size: 11px; line-height: 15px;">This pack includes nodes that generate one dimensional curves which can be used to drive shader parameters, remap values and colors and generate textures and patterns.</span></span><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;"><span class="Apple-style-span" style="font-size: 11px; line-height: 15px;">When you use those curve nodes for the first time you might get the feeling that this whole concept is a bit abstract, so I would like to give you an idea of how versatile these shaders really are and I will show </span></span><i style="font-family: verdana, arial, helvetica, sans-serif; font-size: 11px; line-height: 15px;">one</i><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;"><span class="Apple-style-span" style="font-size: 11px; line-height: 15px;"> use case.</span></span><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /></span><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVSJG6EokTYLIoKC559Zaf57JDK9xeb71nXFJ91ugpKW3feKmBELVY4Ia3rTiesYMJP7LR6nxyOfDazE6EMmE5FqjA1Uct9d6DrDu3MLFeWox9DRjqUrVma8chnKHUwqi36_kXUVsMoj4E/s1600/curve_node_preview.png" imageanchor="1" style="clear: left; display: inline !important; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVSJG6EokTYLIoKC559Zaf57JDK9xeb71nXFJ91ugpKW3feKmBELVY4Ia3rTiesYMJP7LR6nxyOfDazE6EMmE5FqjA1Uct9d6DrDu3MLFeWox9DRjqUrVma8chnKHUwqi36_kXUVsMoj4E/s320/curve_node_preview.png" width="132" /></a><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; line-height: 15px;"><b>Curve Shapes</b></span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; line-height: 15px;"><b><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /></b><span class="Apple-style-span" style="font-size: 11px;"><span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: small; line-height: normal;"></span>Curve shaders are able to generate curves of all kinds of shapes. Basically they implement a mathematical functions of the style y=f(x) which means that for a given input value </span><b style="font-size: 11px;">X</b><span class="Apple-style-span" style="font-size: 11px;"> an output value </span><b style="font-size: 11px;">Y</b><span class="Apple-style-span" style="font-size: 11px;"> is computed. The curve shader nodes were designed that you are able to see the curves graphically by opening the "graph_out" </span><span class="Apple-style-span" style="font-size: 11px;">parameter of a curve node. </span></span><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVSJG6EokTYLIoKC559Zaf57JDK9xeb71nXFJ91ugpKW3feKmBELVY4Ia3rTiesYMJP7LR6nxyOfDazE6EMmE5FqjA1Uct9d6DrDu3MLFeWox9DRjqUrVma8chnKHUwqi36_kXUVsMoj4E/s1600/curve_node_preview.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><br />
</a><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; font-size: 11px; line-height: 15px;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; font-size: 11px; line-height: 15px;">Curves can be used to generate patterns using the "gradient_linear" and "gradient_radial" nodes.</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgxaUTSNScYJnVYwp1IFi4xOKYJuQjv6T0v6o6TmSis9CG5m5c0BK2iQVw_V62NeT7rT6_bw_CwzK7D9T4MmTBQDUdmyg4nwClbfBW0NOfQ4dxyh6PwjC82v8I38GkxdWSr4Ul2_r6yxaA/s1600/curve_shapes.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgxaUTSNScYJnVYwp1IFi4xOKYJuQjv6T0v6o6TmSis9CG5m5c0BK2iQVw_V62NeT7rT6_bw_CwzK7D9T4MmTBQDUdmyg4nwClbfBW0NOfQ4dxyh6PwjC82v8I38GkxdWSr4Ul2_r6yxaA/s400/curve_shapes.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; font-size: 11px; line-height: 15px;">Here you can see which kinds of curves you can generate</span></td></tr>
</tbody></table><div class="separator" style="clear: both; text-align: center;"><br />
</div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3_PceD_y7CJx7-ZSuLoFkYkdaJvgm5cvuCtoH0lXKjyDmBfZMFPnaNDEJYkQOSUuqHx7lRQ_Z7XpdtRkDq9uh_sMO0bRxYBkHNQfd0xJZ-7WinIdxoVpB5ksFDPmsgC8IA1SS7nSoJGSq/s1600/circular_and_radial_pattern.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="146" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3_PceD_y7CJx7-ZSuLoFkYkdaJvgm5cvuCtoH0lXKjyDmBfZMFPnaNDEJYkQOSUuqHx7lRQ_Z7XpdtRkDq9uh_sMO0bRxYBkHNQfd0xJZ-7WinIdxoVpB5ksFDPmsgC8IA1SS7nSoJGSq/s200/circular_and_radial_pattern.png" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Angular and radial gradient - the boolean<br />
switch allows to change the generation behavior</td></tr>
</tbody></table><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; line-height: 15px;"><span class="Apple-style-span" style="font-size: 11px;">Let's try that: Just attach a curve shader to the '</span><i style="font-size: 11px;">curve'</i><span class="Apple-style-span" style="font-size: 11px;"> input of the </span><i style="font-size: 11px;">gradient_radial</i><span class="Apple-style-span" style="font-size: 11px;"> node. You can change the way that the pattern is generated by enabling the boolean parameter '</span><i style="font-size: 11px;">Circular</i><span class="Apple-style-span" style="font-size: 11px;">' which will generate a circular pattern.</span><span class="Apple-style-span" style="font-size: 11px;"><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /></span><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><span class="Apple-style-span" style="font-size: 11px;">Try different curves and you see how the generated texture changes. If you want to create a fancy ray pattern, use the noise_1d curve which gives you a </span></span><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; font-size: 11px; line-height: 15px;">large number of animatable parameters to generate random looking rays.</span><br />
<div class="separator" style="clear: both; text-align: center;"><br />
</div><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; line-height: 15px;"><b>Adding variation</b><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><span class="Apple-style-span" style="font-size: 11px;">Now you know how to generate basic patterns. It gets more interesting </span><span class="Apple-style-span" style="font-size: 11px;">when you start sidechaining other gradient nodes which I will show in </span><span class="Apple-style-span" style="font-size: 11px;">the next steps:</span><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><span class="Apple-style-span" style="font-size: 11px;">The <i>gradient_radial</i> node has an input parameter '<i>offset</i>'. Create another </span><span class="Apple-style-span" style="font-size: 11px;"><i>gradient_radial</i> node, convert it to a float value and attach it to the '</span><span class="Apple-style-span" style="font-size: 11px;"><i>offset</i>' parameter of the first <i>gradient_radial</i> node: You see that it </span><span class="Apple-style-span" style="font-size: 11px;">generates a spiral now.</span><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><span class="Apple-style-span" style="font-size: 11px;"><span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: small; line-height: normal;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbFOQojvek9yROEDNB5cJOSJ-rWmQ-Fa4IXTdStKBxcS2YzpGfVJSm08Fb-uvVdsCC4WSXi1hRK-Ejdh24A1Zd7GGcUOamCG_O_m-_U1Ya_aJBCm93dbPaTXa_PnqwWWwmCsX96mYq1SX1/s1600/spiral_sidechain.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="206" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbFOQojvek9yROEDNB5cJOSJ-rWmQ-Fa4IXTdStKBxcS2YzpGfVJSm08Fb-uvVdsCC4WSXi1hRK-Ejdh24A1Zd7GGcUOamCG_O_m-_U1Ya_aJBCm93dbPaTXa_PnqwWWwmCsX96mYq1SX1/s320/spiral_sidechain.jpg" style="cursor: move;" width="320" /></a></span></span><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><span class="Apple-style-span" style="font-size: 11px;">I guess now you know where we will be going with this example: The offset is now </span><span class="Apple-style-span" style="font-size: 11px;">driven by another gradient node. So what happens if we attach another </span><span class="Apple-style-span" style="font-size: 11px;">curve generator to the second gradient node? Let's try that:</span><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /></span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; line-height: 15px;"><span class="Apple-style-span" style="font-family: 'Times New Roman'; line-height: normal;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsJ6gbpwr-fg-PQrGKVmSRiwS4eUxaUgHHIsPPbZKpdaw_RPQ4qBR8AaUFsBU5-VC4IzEkbTZqgMORWTPpKIEJErEZkVN8-IGfuFMfIi4UipKZrbGAnmgOSENiqVmAPO3IqSAK85ljfpBE/s1600/spiral_sidechain2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="167" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsJ6gbpwr-fg-PQrGKVmSRiwS4eUxaUgHHIsPPbZKpdaw_RPQ4qBR8AaUFsBU5-VC4IzEkbTZqgMORWTPpKIEJErEZkVN8-IGfuFMfIi4UipKZrbGAnmgOSENiqVmAPO3IqSAK85ljfpBE/s320/spiral_sidechain2.jpg" style="cursor: move;" width="320" /></a></span><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><span class="Apple-style-span" style="font-size: 11px;"><br />
</span></span><br />
<div class="separator" style="clear: both; text-align: center;"><br />
</div><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; line-height: 15px;"><span class="Apple-style-span" style="font-size: 11px;">You see that the offset is too strong and that it's </span><span class="Apple-style-span" style="font-size: 11px;">only offsetting in one direction because we feed only positive values to the offset. So let's change the range using a Math_float_lerp node. </span><span class="Apple-style-span" style="font-size: 11px;">(Remember: A lerp nodes interpolates incoming values that ramge from 0 </span><span class="Apple-style-span" style="font-size: 11px;">to 1 to range from 'start' to 'end' so that 0 is mapped to 'start' and 1 </span><span class="Apple-style-span" style="font-size: 11px;">is mapped to 'end'. Values outside that range are extrapolated. )</span><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><span class="Apple-style-span" style="font-size: 11px;"><span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: small; line-height: normal;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZLvOetdgDmaM9-KBrdvdjao2oKeJM8Ajpv6YiPgxCic4QAMXCxRz4YTGTGCfLX6qiKYoBALWMFl6DaO5EdiskiDInm1GBKxIG9ig_NrsnZQaEgvf8hlOx_Q8t9G81A6qAlYMlrIlmHd0G/s1600/spiral_sidechain_lerped.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZLvOetdgDmaM9-KBrdvdjao2oKeJM8Ajpv6YiPgxCic4QAMXCxRz4YTGTGCfLX6qiKYoBALWMFl6DaO5EdiskiDInm1GBKxIG9ig_NrsnZQaEgvf8hlOx_Q8t9G81A6qAlYMlrIlmHd0G/s320/spiral_sidechain_lerped.jpg" style="cursor: move;" width="320" /></a></span></span><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><span class="Apple-style-span" style="font-size: 11px;">Now the offset gives some really interesting result which we can further elaborate on by</span><span class="Apple-style-span" style="font-size: 11px;"> animating it. So lets add some animation on top:</span><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><span class="Apple-style-span" style="font-size: 11px;">Create a <i>state_animation_time</i> and send it to a <i>math_float_multiply</i> so </span><span class="Apple-style-span" style="font-size: 11px;">that you can adjust the speed of the animation. Connect the result to </span><span class="Apple-style-span" style="font-size: 11px;">the offset parameter of the second generator node.</span><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><span class="Apple-style-span" style="font-size: 11px;">Start the animation now and see, how the ray pattern is animated now.</span><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /></span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; line-height: 15px;"><span class="Apple-style-span" style="font-size: 11px;">From there you get the idea how you can create arbitrarily complex </span><span class="Apple-style-span" style="font-size: 11px;">patterns by combining several gradients that drive other gradients.</span><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /></span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; line-height: 15px;"><b>Conclusion:</b><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><span class="Apple-style-span" style="font-size: 11px;">In case you need to create fancy ray patterns for some retro-70ies effect, you now know what you need. Though I'd expect you won't need to create this kind of procedural patterns too often, you get an idea </span><span class="Apple-style-span" style="font-size: 11px;">of how you can use curve nodes to create different kinds of gradients. Driving one gradient with the result of another gradient node and adding animation on top allows you to create sophisticated effects.</span></span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; font-size: 11px; line-height: 15px;">Curve nodes allow you to create much more interesting effects and there are more use cases - I intend to show more</span><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; font-size: 11px; line-height: 15px;"> in another post.</span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif; line-height: 15px;"><br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /><span class="Apple-style-span" style="font-size: 11px;">Have fun creating your own fancy patterns and playing around with them!</span></span>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com1tag:blogger.com,1999:blog-1231342730482819275.post-83605774761954321492011-03-24T13:37:00.000-07:002011-03-24T13:40:25.460-07:00Ray pattern effect using basic mental mill shaders<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;"><span class="Apple-style-span" style="font-size: 11px; line-height: 15px;"></span></span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;">This time I assembled an example that shows how to create a kind of funky sunbeam-effect using the MetaSL shaders. I won't go too much into the details this time. I tried to make the project quite self-explaining. Just start at the top of the workspace where you can see some nodes connected. This is the basic idea of how the ray pattern is created. Further down in the workspace you can find several Phenomena that extend the ray pattern effect. Later I will show you how you can achieve the same effect much easier using the MetaSL curve shaders.</span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;">You can find the mental mill project <a href="http://forum.mentalimages.com/showthread.php?p=32642#post32642">here</a>.</span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;"><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd1IL3_z8hPvQFFCskRgOE66RFYIdm3hoqYNOfkTpIlGRgCpFDtaOX1ZBVFQI1NzIX-ff_Z7f5UuTSDTHp2BPWXtjnZ175itSv7ZJGBW8JN_ieIaC8rqQvxuGpJdUeRilxpG3rhbl0uWLH/s1600/sunbeams_network.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="291" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd1IL3_z8hPvQFFCskRgOE66RFYIdm3hoqYNOfkTpIlGRgCpFDtaOX1ZBVFQI1NzIX-ff_Z7f5UuTSDTHp2BPWXtjnZ175itSv7ZJGBW8JN_ieIaC8rqQvxuGpJdUeRilxpG3rhbl0uWLH/s400/sunbeams_network.jpg" width="400" /></a></span></div><span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;">The texture space is offset so that it ranges from -0.5 to +0.5 (<b>a</b> and <b>b</b>). The u and v components are split (<b>c</b>) and then fed into a <i>Math_float_atan2</i> (<b>d</b>) node. This returns values that range from -PI to +PI. By multiplying this with an integer (<b>e</b>) (well actually it is a float, i guess you know what I mean) and feeding it into a <i>Math_float_cos</i> node (<b>f</b>) you get a result that ranges from -1 to +1 and creates the ray pattern.</span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;">To shape the rays I used a <i>Math_float_smoothstep</i> (<b>g</b>) node. The result of the cosine-node is fed into the 'locaction' input of the <i>Math_float_smoothstep</i> node. For the input parameters 'start' and 'end' use values that are close to each other to get a crisper transition. Applicable ranges are between -1 and +1.</span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;">Finally the resulting float value is converted to a color (<b>h</b>) and fed into the mix parameter of a <i>Math_color_mix </i>node (<b>i</b>) that you can use to mix two different colors.</span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: verdana, arial, helvetica, sans-serif;">Next I will show you how to use the MetaSL curve shaders to achieve the same effect but faster and in a more versatile way.</span>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-31016570121737392212011-03-22T05:36:00.000-07:002011-03-22T05:36:06.539-07:00GDC 2011Recently we have been at the GDC in San Francisco which has been a really great show. As usual we have been showing off mental mill at the NVidia booth where we were demoing the latest version of mental mill, namely an early version of 1.2.<br />
Unfortunately my pocket camera did not work too well under the lighting conditions on the showfloor, so there are no good images to show, unfortunately. However, I got one shot of David explaining the software to an interested person.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhChxh_MIQfgSYM2E_MfRngwvGYaKSKLHgvt4orZRCYhho749fyKzCaHzYQieh7giCQRkGKKCMQm57_EPOp6dS0TN7L9D0Osw4t6mVGKpK9k-eql6-HOYCL_hSyUCxj9dbbKXr59y0WjBZs/s1600/GDC_Dave.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhChxh_MIQfgSYM2E_MfRngwvGYaKSKLHgvt4orZRCYhho749fyKzCaHzYQieh7giCQRkGKKCMQm57_EPOp6dS0TN7L9D0Osw4t6mVGKpK9k-eql6-HOYCL_hSyUCxj9dbbKXr59y0WjBZs/s320/GDC_Dave.jpg" width="320" /></a></div><br />
We gave a preview of the new features that have been added to mental mill 1.2 and it was interesting to discuss with the users and hear their feedback. For those who have not been at the GDC, here are some of the highlights that we were showing:<br />
<br />
<br />
<ul><li>scene element nodes: In version 1.2 there are new node types that describe a scene that can be previewed inside mental mill. These include the description of geometry, lights and a camera.</li>
<li>Load any number of preview objects and apply different shaders to them</li>
<li>View all geometry in one scene (which is practical if you have a model that is made out of several pieces of geometry that need different shaders)</li>
<li>Render previews with iray and mental ray directly inside the camera node on the workspace. No need to launch a separate render window.</li>
<li>Shader creation for <a href="http://www.mentalimages.com/products/iray.html">iray</a>: iray supports a subset of shaders that you can easily wire up in mental mill and render it with iray inside the camera node</li>
<li>Project manager: The project manager helps to keep an overview over the shader files and shaders used in your project which helps you to keep an overview over your shader assets.</li>
</ul><div>For our demos we were kindly provided with models by <a href="http://www.thegameassembly.com/">The Game Assembly</a> which has some talented artists that created some cool models. Thanks for their collaboration, I hope to post some images soon. </div>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-18202500659407257052011-03-21T09:28:00.000-07:002011-03-21T09:28:03.226-07:00MetaSL webpage online<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhs3BQ2tcdjFvTRTMr6O5hVNLx4rbAXMaKIZSZ0fJ3Zw32ig8NDWMUrcFbTUOmm-ON7LLXqw1x9BCR3znKNx_VtTCrqFp92HmvSgAXKDOgFpcZv6kK47ZMs_Ce3OcTNGP_N8cRg665SFkv8/s1600/vase.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhs3BQ2tcdjFvTRTMr6O5hVNLx4rbAXMaKIZSZ0fJ3Zw32ig8NDWMUrcFbTUOmm-ON7LLXqw1x9BCR3znKNx_VtTCrqFp92HmvSgAXKDOgFpcZv6kK47ZMs_Ce3OcTNGP_N8cRg665SFkv8/s1600/vase.jpg" /></a></div>Today the the website <a href="http://www.metasl.org/"><span class="Apple-style-span" style="color: orange; font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">www.metasl.org</span></a> went online. For all those mental mill users who are interested in writing their own shaders, this is a comprehensive resource that helps to quickly get an idea of how to use MetaSL.<br />
<br />
Right now the webpage is work in progress. For now you can find the first four chapters which are also available as PDF downloads for reading offline. These are draft versions of chapters and might be changed and updated.<br />
New chapters will be added in the next weeks.<br />
<br />
The chapters so far are:<br />
<br />
<br />
<ul><li><b>Chapter 1: MetaSL — Strategy and scope</b></li>
<li><b>Chapter 2: Elements of the MetaSL language</b></li>
<li><b>Chapter 3: Basic surface shaders</b></li>
<li><b>Chapter 4: Rendering state</b></li>
</ul><br />
<br />
MetaSL is a platform independent shading language that can be translated to any existing target shading language. This makes it extremely useful if you need to deploy your shader on multiple platforms. Furthermore, you need to write your shader only once, allowing you to concentrate on the algorithmic aspect of your code rather than porting it manually from one language to another.<br />
<br />
For sending feedback, you can take a look at the <a href="http://forum.mentalimages.com/forumdisplay.php?f=175">MetaSL Book open forum</a> where you can leave your message and discuss with others.Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-59146663100282014932010-12-31T06:26:00.000-08:002010-12-31T06:26:29.633-08:00Blurred environment reflectionHere is a shader that is intended for real time usage. It takes advantage of passing custom derivatives to the texture lookup function. This is quite useful to produce blurred environment lookups. This enables you to produce more realistic looking surfaces because it allows you to mimic real-world surfaces in a much better way.<br />
<br />
Since it is the 31st of December and I am about to dive into the next new year's party I will keep this post short... ;)<br />
<br />
<b>Idea:</b><br />
Create an shader for real time usage that blurs the reflection based on the incident viewing direction.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGVr86HwppYDD8uL5AegvLnxz22P8RnMRNJwAaMj-dVKNnz1K0dMZ4NZ4eEgQJUJ_0c1GG-7TS0rwVgeyr1t05RTyClq29VZ9OyF64O8LA20K8GcSmm2pnmeABq56jrssxZ6u2EgTZ3rYO/s1600/blurred_environment_1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="135" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGVr86HwppYDD8uL5AegvLnxz22P8RnMRNJwAaMj-dVKNnz1K0dMZ4NZ4eEgQJUJ_0c1GG-7TS0rwVgeyr1t05RTyClq29VZ9OyF64O8LA20K8GcSmm2pnmeABq56jrssxZ6u2EgTZ3rYO/s400/blurred_environment_1.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Different Blurs of the reflection: <br />
<ul><li style="text-align: left;">From inner to outer </li>
<li style="text-align: left;">from outer to inner </li>
<li style="text-align: left;">controlled by another texture</li>
</ul></td></tr>
</tbody></table><br />
<b>Observation:</b><br />
<br />
<ul><li>If you take a look at a blurry surface, the reflection gets crisper when you look at it from a grazing angle. I observated this in detail a couple of years ago when I was working at a post production company and we were doing a promotion video for a big steel industry company.<br />
My colleagues back then told me that I was too meticulous. Maybe I was, but when your passion is building shader graphs its the observation and implementation of these small details that give the extra punch to your shader.</li>
<li>Also, reflections appear to have less saturation which, depending on the surface is not true. However, I added a control to the shader that allows you to drive the saturation of the lookup.</li>
</ul><br />
<br />
<b>Other features:</b><br />
<br />
<ul><li>The environment blur can be inverted</li>
<li>A constant blur can be applied too</li>
<li>Amount of the incident blur can be controlled</li>
</ul><br />
<b>Tip:</b><br />
<br />
<ul><li>Use the constant blur to shift the incident blur</li>
</ul><a href="http://forum.mentalimages.com/showthread.php?p=31076#post31076"><span class="Apple-style-span" style="color: #bf9000;"><b>Find the shader code on the mental images forum</b></span></a><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-75nPoeSwI4SxWhaWDZzLKfM9GXYsf-7dSpq7VqL_KXu1_a2pHg173VQSHm4CWgxVX6JvEQQt2Jju5UZaHGYNsKOCcA8__HTLoZEXKPaSp4_VciMZRMldatKke-Cs5_sb0YYNGdBmIDRJ/s1600/blurred_environment_corrosion.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-75nPoeSwI4SxWhaWDZzLKfM9GXYsf-7dSpq7VqL_KXu1_a2pHg173VQSHm4CWgxVX6JvEQQt2Jju5UZaHGYNsKOCcA8__HTLoZEXKPaSp4_VciMZRMldatKke-Cs5_sb0YYNGdBmIDRJ/s400/blurred_environment_corrosion.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Increasing the intensity of the constant blur (controlled by a texture) can yield<br />
stunning looking corrosion effects. Also the reflection saturation has been<br />
reduced for these screenshots.</td></tr>
</tbody></table><br />
<div>Happy New Year Everyone!</div>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-37704082783710015792010-12-30T06:21:00.000-08:002010-12-30T06:21:50.779-08:00Uncharted 2 Art DirectionAs shader artist, you have to work closely with other designers, modelers, art directors all of which have a different view of their profession. When it comes to creating big game titles, I am in awe how good these groups can work together to produce these marvelous wonderlands that take us to new places that don't even exist in the real world.<br />
A friend of mine forwarded me this link that gives insight in the art direction of the game "Uncharted 2". Though I haven't played the game, the document is very interesting and can give you some insight and good inspiration. Take a look.<br />
<br />
<a href="http://cmpmedia.vo.llnwd.net/o1/vault/gdc10/slides/Pangilinan_Erick_Uncharted2ArtDirection.pdf">Art Direction in Uncharted 2</a>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-31937226188937390982010-12-14T04:32:00.000-08:002010-12-14T04:32:34.799-08:00The beauty of aliasingIt does not happen too often, but occasionally there is beauty in things that you don't want. What I am talking about is aliasing. I guess that lies in the nature of those who like playing around with visuals. I have to admit that I am one of those persons who get inspiration from things that go 'wrong', but especially in visual arts there is sometimes no real wrong or right. Some people might say 'oh, that looks great' while others will comment that this is the most useless thing that they have seen.<br />
Visuals are a bit like music, taste is also so different. So while I have been testing the shader pack that will be released today or tomorrow on the mental mill forum, I started cranking up some parameters. All of a sudden, aliasing patterns appeared and that looked quite beautiful actually.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1HH4LYuSebd-2BaF4u0eaILhXaEWQMPyJUdFk_bmtjlQ-qJHRmrE6Ued_8qQoMYTBozW6jm0jMrjfuz5tCdzT1WHdKUpjK39Z9UdqBasYpPnrix7Rw_D1IWgtf2aM6i91S9AmgQbnw0WR/s1600/aliasing_pattern.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1HH4LYuSebd-2BaF4u0eaILhXaEWQMPyJUdFk_bmtjlQ-qJHRmrE6Ued_8qQoMYTBozW6jm0jMrjfuz5tCdzT1WHdKUpjK39Z9UdqBasYpPnrix7Rw_D1IWgtf2aM6i91S9AmgQbnw0WR/s1600/aliasing_pattern.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The beauty of aliasing</td></tr>
</tbody></table><br />
And talking about visual arts. My very first blog entry featured a fractal shader. I discovered this amazing 10 minute fractal zoom that features some tech-house sound. It might not be everybody's taste. Beauty is in the eye of the beholder.<br />
<br />
<b>Fractal Zoom (HD) to 6.066 e228 (2^760) Mandelbrot - (Last Lights On)</b><br />
<a href="http://www.youtube.com/watch?v=foxD6ZQlnlU">http://www.youtube.com/watch?v=foxD6ZQlnlU</a><br />
<br />
<b>Quote from the video description:</b><br />
<br />
<i>For the record, 1 to 6e228 is like expanding a proton to 7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 times the size of the visible universe. [...]</i><br />
<i>(Proton has 1 femtometer diameter, universe has 93 billion light year diameter)</i><br />
<i>If you were actually traveling into the fractal, you would be moving faster than the speed of light.</i>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-38422416149619601422010-12-10T06:41:00.000-08:002010-12-14T02:11:43.708-08:00Web 2.0 shader<b>The idea</b><br />
Seeing all those fashionable buttons and icons on every web page, smart phone etc. I though it was about time to create a shader that can just do this for us: Generate shiny icons. So here is the result:<br />
<br />
This is probably one of the most pointless shaders that I have made so far ;) Nevertheless it was great fun to work on. If you have read my previous blog entries you will see that this shader reuses the ideas presented in these blog entries. It is a mixture between rendering a square and circles.<br />
<br />
<b>Features:</b><br />
The shader outputs the color map of the icon, a bump map and a black/white mask for the icon.<br />
A large number of input parameters give you control over the shader: Roundness of the icon, position, size, highlight intensity and highlight color, bump map intensity, just to mention a few. Just play around with it and see for yourself.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-n7uxSPyoDrcVsaDvkEzdeZaSKqrsFK8V778BPqXdKd6SLiwSWh9Lp9zWSWArk_bPsbNnG53HkS1mhkWScWJtDE8qvaHGMyb8SFKDURel-DgXD_gOrAJw-zidSyt8gJFv0-LZxYxDc3ib/s1600/web20_workspace.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-n7uxSPyoDrcVsaDvkEzdeZaSKqrsFK8V778BPqXdKd6SLiwSWh9Lp9zWSWArk_bPsbNnG53HkS1mhkWScWJtDE8qvaHGMyb8SFKDURel-DgXD_gOrAJw-zidSyt8gJFv0-LZxYxDc3ib/s400/web20_workspace.png" width="400" /></a></div><br />
<br />
<b>The MetaSL code</b><br />
If you can call yourself a mental mill owner, I recommend to step with the visual debugger though the source code and see what it happening in each step. I tried to make the code as clear as possible and it is full of comments. Nevertheless sometimes looking at the debugger and 'seeing' is far much easier than reading comments and source code.<br />
<br />
Here are some variations of the shader. I plugged the bump map into an Illumination_phong node to obtain some crisp highlights that I added on top.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8KtWmkl4KsFX37Cly2BW3go8OWx1Wlc-TXpXvRUzy635jHKRUtNk0t-88PR5KShLyX3niZO6comAPaE1q8OO6nyVZHu7Qd8dIimAL_M_aJIhNRNkZat0rczJSGvcQbV3HaeJNjLTC5R8C/s1600/web20_icon_examples.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="102" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8KtWmkl4KsFX37Cly2BW3go8OWx1Wlc-TXpXvRUzy635jHKRUtNk0t-88PR5KShLyX3niZO6comAPaE1q8OO6nyVZHu7Qd8dIimAL_M_aJIhNRNkZat0rczJSGvcQbV3HaeJNjLTC5R8C/s400/web20_icon_examples.png" width="400" /></a></div><br />
You can download the shader along with the test-icon and a mental mill project from the mental images forum:<br />
<a href="http://forum.mentalimages.com/showthread.php?t=7393">Web 2.0 Shader Source</a><br />
Feel free to modify the shader for your own needs and let me know your feedback or any questions.<br />
<br />
<b>Further improvements</b><br />
As almost everything in life, this shader can be improved by adding a few more features to it. I will leave it as it is right now. Experienced users might want to implement the ideas mentioned below:<br />
<br />
<ul><li>Make a softer transition for the bump map. The edges are quite hard which leads to aliasing artifacts. It would be better to ramp the normal gently. </li>
<li>The highlight overlay could be tweaked to look nicer. Right now a simple blend between the icon color and the highlight color is performed. Trying some other blend modes might yield a more realistic looking reflection overlay.</li>
</ul>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com2tag:blogger.com,1999:blog-1231342730482819275.post-69503891093494783272010-11-25T08:28:00.000-08:002010-11-25T08:46:02.087-08:00Displaying functions in a MetaSL shaderIn the previous blog entries I talked about the procedural generation of lines, squares and spheres. Next I want to talk about the possibility to visualize 1 dimensional functions in your shader as a plotted graph. Depending on your expertise you might <i>never ever</i> want to do that. I remember that I always wondered at school what function graphs are useful for. It wasn't until I started 3D rendering, animation and shader writing that I saw a need for creating my own functions or try to understand what a certain function looks like. Now that has changed and I check regularly the look and shape of my functions.<br />
<div>I will not discuss WHY you would want to do this. You will find out at the moment when you need it. Just make sure to remember this blog entry. </div><div><br />
<span class="Apple-style-span" style="font-size: large;">Displaying a function graph on a plane</span><br />
<br />
Sometimes it can be really useful to try to understand a function and what it does in a graphical way. I will present a simple framework for displaying your graph inside a shader.<br />
<br />
<b>Using texture coordinates as our coordinate system</b><br />
First we will start by displaying a typical function graph on a plane. As in the previous blogs I will be using <i>texture_space[0]</i> as my coordinate system. In mental mill, if you switch to the plane preview geometry object texture space 0 aligns perfectly with the quad. This means, it covers the UV coordinates which range from 0 to 1 linearly.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2rQN2GFXGW4oAAtoSphqcvYqcKZo1ecHykcpl1IdmR2tcNg_blO2s9_BooMIlt6LDtmK1IAYOOHI-GoNdnQ8okDGYq9cenreYJWo8n2mY5wOAc3n4SyzdzPkMkeKO0odf0nm206lvzJL7/s1600/tex_space_0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="346" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2rQN2GFXGW4oAAtoSphqcvYqcKZo1ecHykcpl1IdmR2tcNg_blO2s9_BooMIlt6LDtmK1IAYOOHI-GoNdnQ8okDGYq9cenreYJWo8n2mY5wOAc3n4SyzdzPkMkeKO0odf0nm206lvzJL7/s400/tex_space_0.png" width="400" /></a></div><br />
</div><div><b>Changing the range of the coordinate system</b><br />
Now that we have a suitable coordinate system at hand, we take a closer look: The UV coordinates range from 0 to 1 which might be fine in some cases, however, before we start plotting a function, we should add a function that allows us to change the range of our coordinate system. I will call the function <i>change_range</i>. It maps the interval that lies between <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">old_min and</span> <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">old_max</span><span class="Apple-style-span" style="font-family: inherit;"> so that the interval will be remapped to lie</span> between <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">new_min </span>and <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">new_max</span>.<br />
<br />
Example: If old_min and old_max are 0 and 1 and new_min and new_max is 10 and 20 a value that was 0.5 in the 'old' range will be mapped to 15 in the new range.<br />
<br />
Here is the MetaSL code for the function:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #999999;">// changes the range of a given coordinate system.</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #999999;">// Values that varied between 'old_min' and 'old_max' </span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #999999;">// will be mapped so that they vary between </span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #999999;">// 'new_min' and 'new_max'</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #999999;">float change_range(float old_min, </span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #999999;"> float old_max,</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #999999;"> float new_min,</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #999999;"> float new_max,</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #999999;"> float x)</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #999999;">{</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #999999;"> return ((x-old_min)/(old_max - old_min))*(new_max - new_min) + new_min;</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #999999;">}</span></span><br />
<div style="color: #cccccc; font-family: 'Courier New', Courier, monospace;"><br />
</div><br />
<div>If we pass the UV coordinates and choose 0 and 1 for OldMin and Oldmax we can choose any arbitrary values for NewMin and NewMax. See the following image where the coordinate space is remapped using the function mentioned above: </div></div><div><br />
</div><div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDjcGcWzb0mY4WiKz6fXOZwm-yDr0iVoHlsCfim8bePWEclPF5x0MDm5GhKoZbNmqVa4wTwk6K4EuCFDehPBk58Okdtee1EfUSGRkoebV6JY5O1O7MxKZU7IHslMwMs8_5qSru0KwA3x_A/s1600/remapped_coords.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="177" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDjcGcWzb0mY4WiKz6fXOZwm-yDr0iVoHlsCfim8bePWEclPF5x0MDm5GhKoZbNmqVa4wTwk6K4EuCFDehPBk58Okdtee1EfUSGRkoebV6JY5O1O7MxKZU7IHslMwMs8_5qSru0KwA3x_A/s320/remapped_coords.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">You can see that the shader debugger clearly shows the new<br />
range of the texture coordinates.</td></tr>
</tbody></table><b>Outputting a function graph</b><br />
Now that we have met all our prerequisites, we can start thinking about plotting our function graph. For each value on the x-axis we compute a value on the y-axis that we will output.<br />
So this task is now straight-forward: We write whatever function we want to calculate and feed the x-coordinate (of our remapped texture space) as our function argument. For example if we just take a square function it would look like this:<br />
<br />
float x_square(float x)<br />
{<br />
return x*x;<br />
}<br />
<br />
We will pass the x-coordinate to our function so that it will be processed by the function to obtain the new value. Now that we have computed the new value, how can we output a graph? In older blog posts I mentioned that inside a shader we can not ask to draw lines or polygons, because a shader is executed for a given pixel when lines and polygons are already being rasterized. So instead of asking "draw here" or "draw there" we ask: "Where are we and what information we have currently available?" and based in this information we can decide in which color we want to output that pixel/fragment that is being rasterized.<br />
So we know the current coordinates and we have also calculated the new value. How can we put that into a graph? As you know, we want to show the resulting value in the y-axis of the coordinate system. As we can not explicitely ask to draw a point at a certain position, instead we test if the value that our function returned is greater or smaller than the value of the y-coordinate of our coordinate system.<br />
If it is smaller, we assign the 'lower' color, otherwise the 'upper' color.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdEirFRYqjZFXLhXu-XzJ5TEL7R7ryy6HhX9DykY57PS-XOPEX4T3a2HbTzspcRGdeMQp-KPUAJ06WQHDP-t1tlCXIsRNleMn3sBjnEgu_NmrGOnhXSzxoZJ6XmdwdmGVqWre-fFI8tm4h/s1600/x_squared.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="245" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdEirFRYqjZFXLhXu-XzJ5TEL7R7ryy6HhX9DykY57PS-XOPEX4T3a2HbTzspcRGdeMQp-KPUAJ06WQHDP-t1tlCXIsRNleMn3sBjnEgu_NmrGOnhXSzxoZJ6XmdwdmGVqWre-fFI8tm4h/s400/x_squared.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Displaying the function y = x*x using the remapped texture coordinates<br />
as our coordinate system</td></tr>
</tbody></table>Of course you can add more functionality to your shader by adding input parameters that allow you to change other parameters of your function: In the image below, the power function is used and the user may provide different values for the pow-function.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgA0r2ABycyYnugb0uqhouovrVEnHedRIZFHtN1-Bo0t2ruiqpptFbhVsMAs6N73x3_4EnZGGDKYhHMlVlk_pPhV_6rIeuNpGZj6IlCqemWgO1t2hrRPxCnykMRS8MQx4MiiaW38Am4c3ab/s1600/pow_func.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="135" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgA0r2ABycyYnugb0uqhouovrVEnHedRIZFHtN1-Bo0t2ruiqpptFbhVsMAs6N73x3_4EnZGGDKYhHMlVlk_pPhV_6rIeuNpGZj6IlCqemWgO1t2hrRPxCnykMRS8MQx4MiiaW38Am4c3ab/s400/pow_func.png" width="400" /></a></div><br />
<b><a href="http://forum.mentalimages.com/showthread.php?p=30446#post30446">Check out the code sample here</a></b>, feel free to extend and reuse it for your own projects!<br />
<br />
<br />
<b>Related links:</b></div><div><a href="http://scene.org/file.php?file=/resources/seminars/code/bp07_seminar_iq_rgba'spastandfutureintros_xvid.avi&fileinfo">RGBA's past and future intros</a> This video is a seminar that was held during Breakpoint '07. In this video clip, IQ talks about how he and his demo group are creating their demos. It has a strong realtime aspect and I recommend watching this video especially to those users who are interested in realtime shaders and those who like the <a href="http://www.pouet.net/">demo scene</a> in general. </div><div>Check out the section at minute 14. Here you can see how function can be (ab)used to generate procedural textures. Very inspiring! (<b>Note:</b> Don't be confused: The file info says that the file 1kb only, but this will be the full video file!)</div>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-51846188120973771912010-11-15T11:46:00.000-08:002010-11-16T05:32:41.438-08:00Rendering lines and squares<b><span class="Apple-style-span" style="font-size: x-large;">How to render lines in a MetaSL shader</span></b><br />
If you haven't read the previous post, I recommend to do so as well. However, I will repeat some things: In a shader you can't ask the graphics engine to draw lines or triangles to the screen because the shader is executed already <i>during</i> that process.<br />
Instead it has access to a variety of data that is passed to the shader. This data includes texture coordinates, normals, position in space and so on.<br />
When rendering a pixel we need to determine whether we shall color the pixel because it is close to a line or whether we want to output the background color. So much for the theory. The simplest thing that we can do is to draw a straight line, let's say along the x-axis:<br />
<br />
We can determine how far the pixel is away from it and apply a smoothstep function to generate a clamped transition value that fades from 0 to 1 within that range. This allows us to set the line width using a shader parameter:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsQnNIwZPZX9WUNyPj5IGjHc6Osqw0HgAZkLtcVPbKzjtpXMima0O1XSQstp2cBMPIU4cW7Y8dCPOXyhBYdLVxAvDiJ-WSHKYl9UXK6kDi1aqD5nbLPT0oLLQLTquZwOiNydbIN7IKvZ25/s1600/line_width2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsQnNIwZPZX9WUNyPj5IGjHc6Osqw0HgAZkLtcVPbKzjtpXMima0O1XSQstp2cBMPIU4cW7Y8dCPOXyhBYdLVxAvDiJ-WSHKYl9UXK6kDi1aqD5nbLPT0oLLQLTquZwOiNydbIN7IKvZ25/s400/line_width2.png" width="400" /></a></div><br />
I will let you figure out how that shader would look, it's really trivial. So next I want to extend the line drawing so that I am able to draw lines in any arbitrary angle. To define a line, we need 2 points, <b>pt_a</b> and <b>pt_b</b>.<br />
There are plenty of explanations for calculating the distance between a point and a line, <a href="http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html">check out this link on Wolfram Mathworld</a>, for example.<br />
<br />
Using the function that calculates the distance of a point to the line, we can now draw lines with arbitrary slopes:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL7zCzv_3E9ZR_9Kjc9lqNhIiNg4JqEex9AnwYnrLd6ScIy5zkpLyb7K2BMx7VPIkkja_SX42FnGwm6C-wZ1_UjXZ_p05a7nonguZYLPT15Gq8EN4HH33tdaVKoKhFmB3YzcIUkmcStgII/s1600/simple_line.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL7zCzv_3E9ZR_9Kjc9lqNhIiNg4JqEex9AnwYnrLd6ScIy5zkpLyb7K2BMx7VPIkkja_SX42FnGwm6C-wZ1_UjXZ_p05a7nonguZYLPT15Gq8EN4HH33tdaVKoKhFmB3YzcIUkmcStgII/s400/simple_line.png" width="400" /></a></div><a href="http://forum.mentalimages.com/showthread.php?p=30265#post30265">Check out the source code for the shader here</a><br />
<br />
<span class="Apple-style-span" style="font-size: x-large;">Rendering a wire/solid square in a MetaSL shader</span><br />
Since we already covered how to calculate the distance from a line/circle, we are finally missing the squares and rectangles. Without further ado, the formula for the distance of a point from a rectangle is:<br />
<br />
<span class="Apple-style-span" style="line-height: 18px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="line-height: normal;">distance = </span>max(abs(rect_center.x - coord.x) - rect_size.x,<br style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" /> abs(rect_center.y - coord.y) - rect_size.y);</span></span><br />
<div><span class="Apple-style-span" style="line-height: 18px;"><span class="Apple-style-span" style="font-family: inherit;"><br />
</span></span></div><div><span class="Apple-style-span" style="line-height: 18px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b>float2 rect_center</b></span> - The center position of the rectangle</span></div><div><span class="Apple-style-span" style="line-height: 18px;"><b><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">float2 coord </span></b>- The coordinate to test against</span></div><div><span class="Apple-style-span" style="line-height: 18px;"><b><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">float2 rect_size </span></b>- The size of the rectangle</span></div><div><span class="Apple-style-span" style="line-height: 18px;"><br />
</span></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmyZ7uHJEX6sHLX57jkS0a4edJugGSUt_R8FJFAjD88p_CijRy39hNOcs2RSQT1KG2y1WclD7263AsM9B_PMrqWn411FPKftwMVoBcqF_rBJGUe3JnFC0Kb4yYWbH4hXFoW_PxA9V1Y1vl/s1600/distance_debugger.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmyZ7uHJEX6sHLX57jkS0a4edJugGSUt_R8FJFAjD88p_CijRy39hNOcs2RSQT1KG2y1WclD7263AsM9B_PMrqWn411FPKftwMVoBcqF_rBJGUe3JnFC0Kb4yYWbH4hXFoW_PxA9V1Y1vl/s400/distance_debugger.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The debugger in mental mill allows you to take a look at the result of the distance function.<br />
You can activate the debugger by holding down the "Ctrl" key and dragging with your mouse<br />
in one of the debug variable viewports.</td></tr>
</tbody></table><div><span class="Apple-style-span" style="line-height: 18px;"><a href="http://forum.mentalimages.com/showthread.php?p=30266#post30266">You can find the shader code for the rectangle here.</a></span></div><div><span class="Apple-style-span" style="line-height: 18px;"><br />
</span></div><div><span class="Apple-style-span" style="line-height: 18px;"><br />
</span></div>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-44292597286972565532010-11-15T04:58:00.000-08:002010-11-15T04:59:24.012-08:00Drawing shapes in mental millThis post should have been originally part of a much much longer entry, but it turned out to be way too elaborate, so I will start very small. The post today is all about drawing simple geometric shapes in mental mill, using the texture space as a coordinate sytem.<br />
<br />
"So why would I ever want to do that!?" you may ask next. This is a good and valid question. It will become more obvious when I have one of my next blog entries ready that implements a simple 2 dimensional ray marcher in a shader. For now, just assume that you would like to render simple geometric shapes such as spheres and squares.<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;">Rendering procedural 2D shapes in a shader</span><br />
In a shader you can't just say "Draw a line from A to B" - this is because a shader is executed when the triangles and lines are being rasterized, so a shader can not issue drawing calls. But the shader has access to certain information that is passed along like texture coordinates, surface normal etc.<br />
If we want a shader to draw procedural shapes, we need to change the process of generating procedural shapes. Instead of asking our program to draw something (which we can not do) we ask it instead: Is the (current) pixel that we are about to display near the line? If yes, it will receive the line color, otherwise we will use some background color.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><br />
</div>Here we will use the texture coordinates as our coordinate system. This is also perfect to inspect in mental mill on the 'plane' geometry. <a href="http://forum.mentalimages.com/showthread.php?p=30252#post30252">Check out the shader code here.</a><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPjd1uFrFxa4iPn73joJRuWSO5xxwrtqqeB41RkTmyv-xPft0tICMRfCMHF0snjMbh9R75Ph0vl4-o46xg2I7wx2MDLXDcUeWgf9yB3m4Ng_qCA1VCpHozphvuw3_BuSRccR5NDcXsX_Dt/s1600/solid_circle.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPjd1uFrFxa4iPn73joJRuWSO5xxwrtqqeB41RkTmyv-xPft0tICMRfCMHF0snjMbh9R75Ph0vl4-o46xg2I7wx2MDLXDcUeWgf9yB3m4Ng_qCA1VCpHozphvuw3_BuSRccR5NDcXsX_Dt/s400/solid_circle.png" width="400" /></a></div><br />
<br />
This shader provides some control over the size and the position of the circle.<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;">Rendering an outlined circle</span><br />
However, we can change our shader to render a circle with a line. We do this by testing how far the current point is away from the boundary of the circle. If it is within a given range, we apply a smoothstep function which outputs a value from 0 to 1 when the length varies betwen 0 and "line_width".<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4X5UfoRgBx20USJ1tO9ZgyIvjpTcAd4fRu07Qyum_ZzS4AK3gjgK3HkV3cN7HSCakAiEi9XjHXPA6OhKUrm6So8Ge5T-g_5zXi1JHcw8iLMbBl-2FVNoMPrITuEsPecRFBwC7snTj4r2o/s1600/line_circle_illustration.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="217" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4X5UfoRgBx20USJ1tO9ZgyIvjpTcAd4fRu07Qyum_ZzS4AK3gjgK3HkV3cN7HSCakAiEi9XjHXPA6OhKUrm6So8Ge5T-g_5zXi1JHcw8iLMbBl-2FVNoMPrITuEsPecRFBwC7snTj4r2o/s400/line_circle_illustration.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">The result of the shader can be seen here:</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglYkr8_fShusMzJD0avzwFbq_EErjNV_QOWYQuO-y6sTvC63hXDdr9ZjBzXhCh6-CRHFtr_W2gu3rUUW2qZOzqSn5Nfzg6zGgMJcnzouYmxR-HZoK5_Eic4-kxXpzv4L57HNsSIM6W6WO1/s1600/line_circle.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglYkr8_fShusMzJD0avzwFbq_EErjNV_QOWYQuO-y6sTvC63hXDdr9ZjBzXhCh6-CRHFtr_W2gu3rUUW2qZOzqSn5Nfzg6zGgMJcnzouYmxR-HZoK5_Eic4-kxXpzv4L57HNsSIM6W6WO1/s400/line_circle.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: left;"><a href="http://forum.mentalimages.com/showthread.php?p=30254#post30254">Check out the shader code for the outlined circle here:</a></div><div class="separator" style="clear: both; text-align: left;"><br />
</div>This is just the beginning. In the next post I will show how to render lines and squares, so stay tuned for more! Feel free to ask questions if you need more explanations. Shade safe and have a nice day! :)Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-46069184524376396742010-11-10T09:36:00.000-08:002010-11-16T05:33:35.702-08:00Get inpired, check out the KoddeShader v2.0These days one of our mental mill power users released his latest version of a versatile and powerful shader, the <i>KoddeShader</i> on the mental mill. This is already release 2.0 of Kogi's shader, so there are a couple of new features that you can check out.<br />
<div>It is always great to see how users create shaders using mental mill, export them and release their work to the public. I hope to see more great work coming! Also don't forget to check out the .pdf documentation, as it is written really carefully, containing lots and lots of illustrations.</div><div><br />
</div><div><a href="http://forum.mentalimages.com/showthread.php?p=30203">Check out the KoddeShader on the mental mill forum!</a><br />
<div><br />
</div></div>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-82262164310590426012010-11-03T08:28:00.000-07:002010-11-04T02:19:49.295-07:00Things you should never doToday I read an interesting article about the consequences of writing software over and over again. While this can have a major impact in big companies, this also affects programmers who work on their own private project. Trying to start from scratch is something that happens to all of us who are writing code, no matter if it is an entire program or a shader. But you will learn those details in the article, so check it out. <div>I hope you feel as inspired as I did and remember: Good code never gets rusty, no matter how old it is!<div><div><br /></div><div><a href="http://www.joelonsoftware.com/articles/fog0000000069.html">Things you should never do</a></div></div></div>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-23519943071574587962010-10-26T05:40:00.000-07:002010-11-04T02:13:20.956-07:00texture lookups in mental mill<div style="text-align: left;">One thing that confused me in the early beginning when I started writing shaders was this: Sometimes texture lookups that caused artifacts that looked somewhat like aliasing when previewing them in the realtime preview. Later I learned why and how that happens and how to avoid it. So I will present the problem and its solution:</div><div><br /></div><div><span class="Apple-style-span" style="font-size: large;">Cutting texture coordinates</span></div><div><span class="Apple-style-span" style="font-size: large;"><br /></span></div><div>Whenever you 'cut' texture coordinates, this creates discontinuities. In this example I take a fraction of the texture and loop it over across my preview geometry. This is accomplished by using an fmod() operation. After performing the texture lookup and previewing the shader, you can see some jaggy artifacts that are especially noticeable and disturbing when moving the geometry. In the magnified region you see that between </div><div>the tiles some dark pixels show up.</div><div><br /></div><div><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg7UvPOh-RxKA9hkEYyTCFu3giwE14jo4pDIZSMYZ4B27Fv1fxjjHB1TTOd4wDAMvu828nRdFaTEhKtnwu40vQMXxRpUYXUF8HAs26kKTi0ReCgIZ6VFSdPV93vTQGOgtp7FMoPMYDduRY/s400/mipmap_artifacts_01.png" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 297px;" border="0" alt="" id="BLOGGER_PHOTO_ID_5533102632293492690" /></div><div><span class="Apple-style-span" style="font-size: large;">Wrong Mip Map lookups</span></div><div><span class="Apple-style-span" style="font-size: large;"><br /></span></div><div>So what is going on here? You might have guessed already that the fmod() operation did something bad to our coordinates. Well, one could say so, but the operation itself is innocent. The reason for this behavior is that during rasterization the GPU tries to determine the MipMap level automatically by comparing the texture current coordinates with the values of the adjacent fragment or pixel. As long as the coordinates are continuous it can correctly determine the right MipMap level. </div><div>But when the coordinates were 'sliced', this created discontinuities. When such a discontinuity is reached, the difference between two neighboring pixels or fragments is so big, that the GPU chooses a very small MapMap which causes the artifacts in the realtime preview.</div><div><br /></div><div><span class="Apple-style-span" style="font-size: large;">Fixing incorrect lookups by using custom derivatives</span></div><div><span class="Apple-style-span" style="font-size: large;"><br /></span></div><div>How can we remedy this situation? We need the texture lookup to choose the appropriate MipMap level, even though there is a discontinuity. That is why there is an overloaded version of the tex2D texture lookup in mental mill (which also exists in the Cg language, by the way).</div><div><br /></div><div><span class="Apple-style-span">tex2D(texture2D texture, float2 coordinates, float2 coord_dx, float2 coord_dy)</span></div><div><br /></div><div>The second two arguments are the derivatives to use. First we need to know: <i>What are derivatives? </i>The derivatives indicate the changes from one pixel or fragment to the next. If the user performs a texture lookup without providing custom derivatives, the derivatives of the texture coordinates are automatically calculated and used.</div><div><br /></div><div>We just saw that this operation failed. We also know why, so let's calculate our own derivatives and pass them to the texture lookup function above.</div><div><br /></div><div><span class="Apple-style-span" style="font-size: large;">How to determine the correct derivatives</span></div><div><br /></div><div>First we need to learn about the functions that calculate derivatives for us. These are:</div><div><br /></div><div><span class="Apple-style-span">ddx()</span> and <span class="Apple-style-span">ddy()</span></div><div><br /></div><div>These are overloaded functions which take a <span class="Apple-style-span">float, float2, float3, float4</span> or <span class="Apple-style-span">Color</span>. The functions return a variable of the same type which contains the derivative. The derivative returns the difference of a variable between two fragments. <span class="Apple-style-span">ddx()</span> calculates the difference in the x-direction while <span class="Apple-style-span">ddy()</span> calculates the difference in the y-direction.</div><div><br /></div><div>The derivatives that we really want to use are the derivatives of the original texture coordinates before we sliced them up. Why is that?</div><div>We didn't change the scaling of the sliced texture coordinates. We just set a different tiling. This means that we can use the derivatives of the original texture coordinates for the texture lookup.</div><div><br /></div><div>So we can write:</div><div><br /></div><div><div><span class="Apple-tab-span" style="white-space:pre"><span class="Apple-style-span"> </span></span><span class="Apple-style-span">float2 x_deriv = ddx(texture_coordinate[0].xy);</span></div><div><span class="Apple-tab-span" style="white-space:pre"><span class="Apple-style-span"> </span></span><span class="Apple-style-span">float2 y_deriv = ddy(texture_coordinate[0].xy);</span></div><div><span class="Apple-tab-span" style="white-space:pre"><span class="Apple-style-span"> </span></span><span class="Apple-style-span">result = tex2D(tex, coord, x_deriv, y_deriv);</span></div></div><div><br /></div><div>Now, lets see how that affects the shader:</div><div><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOJDplczQlfF6_BZbfnL4eq4qQbvQHOVsyGJ2_Z3-ncdH9JaIPj7G39vGLc8grq1qbA_vDjugqwFYBh6Oea4M0DnfwosS8o_B18BeCEq3li-aBi9SYNZ8FNYAfwLndG21i6OQKhwnqicGG/s400/mipmap_artifacts_fixed.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5534600078980890066" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 400px; height: 297px; " /></div><div>As you can see now, the aliasing artifacts are gone.</div><div><br /></div><div>So whenever you see such artifacts, check if you are causing discontinuities in your texture coordinates. These are created by using the fmod operation for example, but if-else clauses that assemble texture coordinates based on a condition can cause this.</div><div> If that is the case, try to resolve these issues by using the overloaded texture lookup that uses derivatives. This is especially relevant if you intend to use your mental mill shader in a realtime application. </div><div><br /></div><div>I hope next time you run into this problem you will remember this post and quickly resolve these issues.</div><div><br /></div><div><br /></div>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-51263434269681599672010-10-20T08:43:00.000-07:002010-11-04T02:21:05.390-07:00Mandelbrot revisitted<div style="text-align: center;"><div style="text-align: left;">Recently I was updating one of the first shaders that I created with mental mill called fractal. What I love about fractals are, that a simple algorithm yields such impressive shapes with sheer endless details. Obviously I was intrigued and was inspired to write a shader that made use of them.</div><div style="text-align: center;"><br /></div><div style="text-align: left;">One thing that I like about working with mental mill is, that you can make any parameter tweakable. So if you have a formula that uses three variables, they don't necessarily have to be constants. Instead you can edit them through the mental mill GUI. Sometimes you can yield surprising results by making variables tweakable that are 'not supposed' to be tweaked.</div><div style="text-align: center;"><br /></div><div style="text-align: left;">That happened to me when I recently revisited the MetaSL code for my fractal shader. I was looking at the abort conditions in the fractal loop. There are two conditions:</div></div><div><div><div><ol><li>If the squared distance of the original point exceeds 4.0, then the point is not part of the set and is discarded.</li><li>If the iteration exceeds the maximum number of iterations the process stops. At this point it is not certain whether the point will diverge or not, however it is regarded to be part of the set.</li></ol><div><div>There is not much one can change about the second condition (and the number of iterations is already a shader parameter anyway). Making this a parameter made the abort condition tweakable with some astounding results. If you lower the value, you can see how the rendering morphs into a cartoony look. </div></div></div></div></div><div><br /></div><div><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYx4v8Sr4_1onjdQyCLF8rmEwcBaQb0qp4hDFpkCxOccTX4onAdm3vffo92NM8KbfTaTEMid5UmvG8nG7OYOo3Zt67Gdvh_ZegvsDqojDMPULGSQ1YHv_Y1JLMUDK33sEdG6UPZUkW7oeT/s320/fractal_to_cartoon.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 96px;" border="0" alt="" id="BLOGGER_PHOTO_ID_5530549180245902930" /></div><div><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;">This is quite surprising and beautiful to see. If you adjust the values carefully you can get some really great pictures. If you want to use the shader in mental mill, you can find it</span></span><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;"> </span></span><a href="http://forum.mentalimages.com/showthread.php?t=7136"><span class="Apple-style-span"><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;">here</span></span></span></a><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;">. T</span></span><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;">The shader parameters are straightforward. You can switch between the </span></span><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;">Mandelbrot </span></span><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;">and the </span></span><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;">Julia</span></span><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;"> fractal. However, if you want to view the</span></span><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;"> Mandelbrot</span></span><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;"> fractal in its original shape, you must set the shader input parameters </span></span><i><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;">start_real</span></span></i><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;"> and </span></span><i><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;">start_imaginary</span></span></i><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;"> to 0.</span></span></div><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;">Here are some other presets that I created using that shader:</span></span><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFcllT-ZyniQnuZfnWbDWNJKgbakq-D4AVJvtocJm0u8_pphFh0iKOHzucoxJJX7WY1I3TcNtqX7XlQJ4OGIW6ibw_530UZSouKxh2_NFR9rNHk0owYWKwoayPZandwVU5RXlQzGjnTxxI/s400/MetaSL_mill_render.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 195px;" border="0" alt="" id="BLOGGER_PHOTO_ID_5530551606753421026" /><div><br /></div><div>That's it for now. By the way, there is a lesser known variation of the Mandelbrot fractal: The Buddhabrot which unveils even more fascinating shapes. <a href="http://www.superliminal.com/fractals/bbrot/bbrot.htm">Check out Melinda Green's page!</a></div><div><br /></div><div><span class="Apple-style-span" style="color: rgb(0, 0, 238); -webkit-text-decorations-in-effect: underline; "><img src="http://www.superliminal.com/fractals/bbrot/minib.jpg" border="0" alt="" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 600px; height: 600px; " /></span></div><div><span class="Apple-style-span" style="color: rgb(0, 0, 238); -webkit-text-decorations-in-effect: underline; "><br /></span></div>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0tag:blogger.com,1999:blog-1231342730482819275.post-53080125359047770432010-10-20T05:26:00.001-07:002010-10-21T02:42:54.786-07:00Introduction to the mental mill blog<span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;">Welcome to the mental mill blog!</span></span><div><span class="Apple-style-span" style="line-height: 18px; font-size: medium;"><span class="Apple-style-span" style="line-height: normal;"><br /></span></span></div><div><span class="Apple-style-span" style="line-height: 18px; "><span class="Apple-style-span"><span class="Apple-style-span" style="font-size: medium;">This blog is all about mental mill®, the shader workbench for programmers and artists. So what kind of information can you expect here? On this blog you can read a lot of random information about mental mill, MetaSL and 3D computer graphics. The information will be quite versatile. I plan to post shader snippets and complete shaders for mental mill. I will also include Tips and Tricks and best practices when using the mental mill application and the typical do's and dont's.<br />In some cases I will show workarounds and other non-official tricks, that may be interesting for those of you who like to get your hands dirty.<br /><br />Since I have an artist background and I like shader writing, this will be the place where both worlds meet for new ideas to inspire your own projects. Also if I come across extraordinary work from other users, which has been published, I will link you to it.<br /><br />That's all for now, I am looking forward to writing some interesting stuff here, so check out what's coming up! Shade safe and have a nice day :D<br /></span></span></span></div>Rüdigerhttp://www.blogger.com/profile/00799158208667503805noreply@blogger.com0