Search Unity

Fabio Policarpo - Relief Mapping with Correct Silhouettes

Discussion in 'Shaders' started by apple_motion, Oct 20, 2009.

  1. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169
    While someone saw my video test on youtube and ask me to share the code, I believe, this forum is always the best place to share.

    http://www.youtube.com/watch?v=W3aoQpECaU0

    Not all feature are implemented, like depth correction, shadow map...etc (since, I still don't understand completely :p)

    Antonio Hui




    Tips: For the relief texture, please turn off the "Generate Mip Maps" option of the Texture Importer.
     

    Attached Files:

    pottering likes this.
  2. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169
    Anyone interested on this too ??

    [ paper demo from original creator ]
    http://www.fabio.policarpo.nom.br/Demos.html



    Fabio's shader always good to learn, full of wisdom and challenge :)

    In fact, porting his shader to unity is quite easy, almost 95% unchanged from the original code. However, I still don't understand how to make the multi-layered normal maps and the workflow to prepare the textures :p

    Tips: To get the best result, when import the relief and normal maps, please disable the "Mip Maps" and set the "Filter Mode" to "Point" on Texture Importer.

    Antonio Hui

    (ps. I didn't port the shadow map part yet :p )
     

    Attached Files:

    pottering likes this.
  3. Superflat

    Superflat

    Joined:
    Mar 19, 2009
    Posts:
    354
    Surrender all your shaders and no one will get hurt.
     
  4. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,356
    Yes, this looks awesome. Even without source, I'm just interested in the approach. I'm not familiar with relief mapping beyond basic parallax stuff.
     
  5. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,435
    Ha, ha! :D Very nice shaders, I'll have to try this.

    Edit: I just gave this a spin and love it. Nice! :)
     
  6. norby

    norby

    Joined:
    Jul 10, 2006
    Posts:
    268
    Great shaders , beautiful

    Norby :)
     
  7. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,327
    I understand the first shader and think it's awesome - this is what all games are going to be using soon, no doubt. Can you provide some insight as to what's going on in the second, though, please? It looks great, regardless.
     
  8. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169
    Happy to know that everyone love these shaders. I will upload another unity port of Fabio's shader, "Relaxed Cone Stepping for Relief Mapping", that is from chapter 18 of GPUGems 3 of Nvidia's book.
    http://http.developer.nvidia.com/GPUGems3/gpugems3_ch18.html

    hi Jessy, this is the right paper to start with. In fact, I don't understand too much yet. I still study from it :)
    http://fabio.policarpo.nom.br/docs/Multilayer_ReliefMapping_I3D2006.pdf

    Also, chapter 5 of this book Advanced game development with programmable graphics hardware By Alan H. Watt, Fabio Policarpo tell the whole story too. Enjoy !


    Antonio Hui
     
    pottering likes this.
  9. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,356
    Thanks for the extra references! Can you please save this thread by truncating that URL, though?

    Code (csharp):
    1. [url=http://example.com]Site Name[/url]
     
  10. GusM

    GusM

    Joined:
    Aug 27, 2005
    Posts:
    585
    Impresive shaders, thank you so much. I guess the special textures for the second one can currently only be built with a 3DMax plugin?
     
  11. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169
    A technique to improve the small details of the original relief mapping shader...

    Comparison between the "relaxed cone stepping" (left) and original relief mapping (right) algorithm.
    Those are using the same amount of intersect searching value, 15(linear), 5(binary).


    You may enable one of them to see the difference :)
    Code (csharp):
    1. //#pragma fragment pixel_shader_normal
    2. //#pragma fragment pixel_shader_relief
    3. //#pragma fragment pixel_shader_quadcone
    4. #pragma fragment pixel_shader_relaxedcone
    Also, comment in/out the border clamp define to en/disable the border clamp.
    (small improvement, big impact ! the silhouettes is back :))
    Code (csharp):
    1. #define BORDER_CLAMP
    Code (csharp):
    1.     // border clamp
    2.     float alpha=1; 
    3. #ifdef BORDER_CLAMP
    4.     if (texcoord.x<0)alpha=0;
    5.     if (texcoord.y<0) alpha=0;
    6.     if (texcoord.x>tile) alpha=0;
    7.     if (texcoord.y>tile) alpha=0;
    8. #endif
    9.  
    I try to kept the code as close to original paper as possible. Hope that it is easy for everyone to study (include myself :p)

    The next step is find out the way to prepare the texture. If anyone knew the solution please tell us. many thanks :)

    Antonio Hui

    ps. for more detail on the algorithm, please read the following. have fun !
    http://http.developer.nvidia.com/GPUGems3/gpugems3_ch18.html
     

    Attached Files:

  12. norby

    norby

    Joined:
    Jul 10, 2006
    Posts:
    268
    Hi Antonio

    This looks fantastic.
    would it be possible to use a sequence of pictures in the slots
    to create wave animation ?
    good work

    Norby
     
  13. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,435
    This is a fascinating thread, the shaders are wonderful, but how does one go about making some of these relief maps? What tools are out there to produce them?
     
  14. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169
    Hi Norby,

    The answer is YES ! (of course, not by me :p)

    Fabio Policarpo have a better idea ! I knew he wrote a new paper (maybe on SIGGRAPH 2008) talking about how to animate the relief and normal map within the fragment shader interactively. I saw his demo in youtube sometime ago. (but forgot the link :s)

    Once I found the above paper and the sample code, for sure, I will port it to Unity ASAP too. Good Luck to myself :)

    Antonio Hui
     
  15. norby

    norby

    Joined:
    Jul 10, 2006
    Posts:
    268
    Hi Antonio

    This would be cool, i wish i could code :oops:
    can you tell me what type of light can be used
    because when i added some additional lights
    there was no difference.

    Norby
     
  16. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,356
    If you look at the shader settings, you can set up the light inside the shader. It would be a bit of work to get these shaders split into passes and compatible with Unity's lighting pipeline.
     
  17. norby

    norby

    Joined:
    Jul 10, 2006
    Posts:
    268
    thanks Daniel
    for clarifying this.

    norby
     
  18. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169
  19. WinningGuy

    WinningGuy

    Joined:
    Aug 10, 2009
    Posts:
    884
    Awesome awesome stuff.

    I couldn't get relaxed_cone_relief_mapping.shader to work. And quite frankly, I didn't really understand what to put in the available fields for the quad_depth_relief_mapping shader.

    But just seeing the Relief_correct_silhouettes shader working was pretty amazing.

    If anyone could set me straight on the stuff I didn't get right I'd appreciate it.

    Also, how are the Relief Maps created? I tried using some normal maps and they didn't work.

    Edit: Ahh... I see that you're asking the same thing about making the maps
     
  20. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169


    It is because, lack of height information. That is stored in the fourth channel - alpha. (red, green, blue channel for x,y and z component of the normal.)

    Simply, Relief Map = Normal Map + Height Map :)

    Antonio Hui
     
  21. WinningGuy

    WinningGuy

    Joined:
    Aug 10, 2009
    Posts:
    884
    Awesome. Thank you!

    You've inspired me to start reading up on shaders.
     
  22. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,356
    Those are nice images, as they make it clear that a normal map is just wrapped lighting from the X, Y and Z directions.

    I do plan on reading the papers that explain the processes, but would you be able to give a layman's explanation of what the quad depth map, and X- and Y-specific normal maps are? It seems strange to me that geometry which is behind has an effect on the image. Obviously you couldn't render it without that data being present, but I don't understand what those maps represent.
     
  23. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169

    As the paper said, for the efficiency reasons, they reorder the depth and normal components into different files.

    As see from the chart (low-left conner), the Normal Z component of each layer are computed as z = sqrt(max(0, 1-(x*x+y*y)))

    Edit: Not 100% sure at the moment, the Normal Z seem to wrong... :s

    Antonio Hui
     
  24. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,356
    Ok, so each texture consists of:

    R = information for the top of layer 1
    G = information for the bottom of layer 1
    B = information for the top of layer 2
    A = information for the bottom of layer 2

    Meaning that unless you add more textures, you can only have two layers to the mesostructure.

    Also, yeah, that regenerated Z component looks incorrect.
     
  25. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169
    Thanks Daniel !

    Also, just found that:-

    R = information for the front face of element 1
    G = information for the back face of element 1
    B = information for the front face of element 2
    A = information for the back face of element 2

    plus, element 1 2 could be not in depth order.

    I almost find the answers for how to prepare the textures, since I could made simple 2-element relief map now :)

    workflow:
    1. modo - create the depth and normal maps by en/disable the mesh and flipping the faces.
    2. shake - reorder the color and alpha channels
    3. unity3d - render by cg shader






    Have a nice weekend to all !
    Antonio Hui
     
  26. Loor

    Loor

    Joined:
    Jul 12, 2009
    Posts:
    19
    Hey there Antonio !
    I'm the one who spotted your youtube video, thank you so much for sharing the code!

    Those shaders are so good ! If I'll ever make anything useful with them I'll sure let you know
    and share it with the community here also.
    I was always wondering when there will be something like this
    and here it is! AWESOME!
     
  27. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,356
    What program are you using to composite your inputs? That looks really useful.
     
  28. melmonkey

    melmonkey

    Joined:
    Mar 31, 2009
    Posts:
    373
    That is Shake. One of the best compositors ever, IMHO. Unfortunately for us PC users, Apple bought the original developers (Nothing Real) and discontinued PC support after version 2.5, which I might add, I still have and use, and guard with my life!

    Sadly as of July this year, Apple removed Shake from the store, so you can't get it anymore.
     
  29. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169
    Yeah ! I am picky. I only use the best, our Unity is one of the best 3D engine too - easy to use and powerful ! :)


    You are welcome !

    In fact, those shaders were prepared for my submission on "Unity Summer of Code" project this year. (But Rejected :p) I am happy to know that I made something is useful to the community :) otherwise, I may just let it be hibernated forever :p
     
  30. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,356
    Why do you think your linked toruses have artifacts around the edges? Did you just have you texture settings right in Unity, or is there something wrong with your process?
     
  31. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169
    I think, that is the alpha channel issue, since currently the code only produce ON/OFF for the alpha, without any interpolation of the neighborhood pixels.

    Possible solution - apply blur and CLUT (colour look-up table) function to contract and smooth the edge of the alpha channel.
     
  32. Lasha84

    Lasha84

    Joined:
    Apr 18, 2010
    Posts:
    1
    Sorry for my bad english I write messages using
    http://translate.google.com.

    I hope my post will help bring to mind shader (finish) relaxed cone stepping.

    Look:
    http://www.gamedev.ru/code/forum/?id=131177

    And the most delicious here:
    http://www.gamedev.ru/code/forum/?id=131941

    Generator maps:
    http://slil.ru/28894016

    I hope my post will help refine the proper operation of the shader with self-shadows, Unity's lighting and the shadows of other objects.
    I am very fond of Unity and this shader relaxed cone stepping.
    I hope soon to see my wishes in life.
    I look forward to.
    GOOD LUCK APPLE MOTION!
     

    Attached Files:

  33. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169
    Thanks Lasha ! I have an archaeology related project ahead, hopefully, I will use lot of relief shaders onto the hi-res texture. Wish that I could understand and make use the code that you gave me very soon :)

    Thanks again :)
     
  34. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169
    Just ported the preprocessor of Relaxed Cone Stepping for Relief Mapping onto unity, but the result is not as good as the original.



    Since, I don't have pro-edition of unity and the original code need to do 65536 times of render to texture for a 256x256 texture ! so that, I replaced that portion of code to simple "screen capture".

    Code (csharp):
    1.     Camera.main.pixelRect = Rect(0, 0, g_ReliefSizeX, g_ReliefSizeY);  
    2.     yield WaitForEndOfFrame();
    3.     g_ResultTex.ReadPixels (Camera.main.pixelRect, 0, 0);
    4.     g_ResultTex.Apply ();
    Now. a 256x256 height map need 24 minutes to process. and 512x512 need more than few hours ! Not quite useful, because it is too slow, but I leant a lot from the porting process, especially for how to make use of unity for texture preprocessor :)

    Anyone like to try, please feel free to use, modify or adding improvement. The following is the full set of script and shaders to do the test, and the original paper will be found on here: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch18.html

    Shader for preprocessing:
    Code (csharp):
    1. Shader "ReleasedCone_Preprocessor_v001"
    2. {
    3.     Properties
    4.     {  
    5.         ReliefSampler   ("ReliefSampler", 2D) = "white" {}
    6.         ResultSampler   ("ResultSampler", 2D) = "white" {}
    7.        
    8.         g_Offset ("g_Offset", Vector) = (1,1,0,0)
    9.     }
    10.     SubShader
    11.     {
    12.         PASS
    13.         {
    14.            
    15. CGPROGRAM //--------------
    16. #pragma target 3.0
    17. #pragma vertex   vertex_shader
    18. #pragma fragment depth2relaxedcone
    19. #pragma profileoption MaxTexIndirections=129
    20.  
    21. //----------
    22.  
    23. #define g_WorldViewProj glstate.matrix.mvp
    24.  
    25. struct a2v
    26. {
    27.     float4 vertex : POSITION;
    28.     float2 texcoord : TEXCOORD0;
    29.  
    30. };
    31.  
    32. struct VS_OUTPUT
    33. {
    34.     float4 Position  : POSITION;
    35.     float2 texcoord  : TEXCOORD0;
    36.     float2 texcoord_InvY : TEXCOORD1;
    37. };
    38.  
    39. VS_OUTPUT vertex_shader(a2v IN  )
    40. {
    41.     VS_OUTPUT output;
    42.  
    43.     output.Position = mul( g_WorldViewProj, IN.vertex );
    44.     output.texcoord = IN.texcoord;
    45.     output.texcoord_InvY = IN.texcoord*float2(1,-1);
    46.    
    47.     return output;
    48. }
    49.  
    50. float4 depth2relaxedcone(   VS_OUTPUT input,
    51.                             uniform float3 g_Offset,
    52.                             uniform sampler2D ReliefSampler,
    53.                             uniform sampler2D ResultSampler ) : COLOR
    54. {
    55.     const int search_steps = 128;
    56.    
    57.     float3 p = float3(input.texcoord,0);
    58.    
    59.     float3 o = g_Offset + p;
    60.     o.z = tex2D(ReliefSampler,o.xy).w;
    61.    
    62.     float3 v = o - p;
    63.     v /= v.z;
    64.     v *= 1.0-o.z;
    65.     v /= search_steps;
    66.  
    67.     p = o;
    68.  
    69.     for( int i=0;i<search_steps;i++ )
    70.     {
    71.         float d = tex2D(ReliefSampler,p.xy).w;
    72.  
    73.         if ( d <= p.z )
    74.             p += v;
    75.     }
    76.     float d = tex2D(ReliefSampler,input.texcoord).w;
    77.    
    78.     float r = length(p.xy-input.texcoord);
    79.    
    80.     r = (p.z >= d) ? 1.0 : r / (d - p.z);
    81.  
    82.     float best_r = tex2D(ResultSampler,input.texcoord_InvY).x;
    83.     if ( r > best_r )
    84.         r = best_r;
    85.     return float4(r,r,r,r);
    86. }
    87.  
    88. ENDCG //--------------     
    89.         } // PASS      
    90.     } // SubShader
    91. } // Shader
    92.  
    Javascript for unity:

    Code (csharp):
    1. import System.IO;
    2.  
    3. private var g_ResultTex:Texture2D;
    4.  
    5. private var g_ReliefSizeX:int       = 0;
    6. private var g_ReliefSizeY:int       = 0;
    7.  
    8. private var g_OffsetX:int           = 0;
    9. private var g_OffsetY:int           = 0;
    10. private var g_SamplingGroupX:int    = 0;
    11. private var g_SamplingGroupY:int    = 0;
    12. private var g_SamplingGroupPos:int  = 0;
    13. private var g_SamplingGroupSize:int = 8;
    14.  
    15. private var g_SamplingOrder:int[] = [ 0,   36,   4,   32,   18,   54,   22,   50,
    16.                                       2,   38,   6,   34,   16,   52,   20,   48,
    17.                                       0+9, 36+9, 4+9, 32+9, 18+9, 54+9, 22+9, 50+9,
    18.                                       2+9, 38+9, 6+9, 34+9, 16+9, 52+9, 20+9, 48+9,
    19.                                       0+1, 36+1, 4+1, 32+1, 18+1, 54+1, 22+1, 50+1,
    20.                                       2+1, 38+1, 6+1, 34+1, 16+1, 52+1, 20+1, 48+1,
    21.                                       0+8, 36+8, 4+8, 32+8, 18+8, 54+8, 22+8, 50+8,
    22.                                       2+8, 38+8, 6+8, 34+8, 16+8, 52+8, 20+8, 48+8  ];
    23.                              
    24. private var g_RunMode:int       = 0;
    25. private var g_RenderMode:int    = 0;
    26.  
    27. private var Busy:boolean = false;
    28. private var Pass:int = 0;
    29. private var Progress:String;
    30. private var Export_Now:boolean = false;
    31.  
    32. var OuputFile:String = "";
    33.  
    34. var Preprocessor    :Material;
    35. var ChannelReorder  :Material;
    36.  
    37. var ExportTempFiles :boolean = false;   // for debug use only !
    38. var _export_per_frame :int = 32;
    39. var HalfSizeRender  :boolean = false;   // for debug use only !
    40.  
    41. function Start()
    42. {
    43.     //------ create output directory
    44.     System.IO.Directory.CreateDirectory("_output");
    45.     if(ExportTempFiles)
    46.     {
    47.         System.IO.Directory.CreateDirectory("_process_"+OuputFile);
    48.     }
    49.    
    50.     //------ setup preprocessor
    51.     if (!Preprocessor) return;
    52.    
    53.     renderer.material = Preprocessor;
    54.    
    55.     var g_ReliefTex = renderer.material.GetTexture( "ReliefSampler");
    56.    
    57.     if (!g_ReliefTex)
    58.     {
    59.         return;
    60.     }
    61.    
    62.     g_ReliefTex.filterMode  = FilterMode.Point;         //Bilinear
    63.     g_ReliefTex.wrapMode    = TextureWrapMode.Repeat;
    64.        
    65.     g_ReliefSizeX = g_ReliefTex.width   /((HalfSizeRender)? 2:1);
    66.     g_ReliefSizeY = g_ReliefTex.height  /((HalfSizeRender)? 2:1);
    67.    
    68.     //------ setup g_ResultTex and proxy texture.      
    69.     g_ResultTex = new Texture2D (g_ReliefSizeX, g_ReliefSizeY, TextureFormat.ARGB32, false);
    70.     g_ResultTex.filterMode = FilterMode.Point;
    71.    
    72.     var proxy = new Texture2D(1,1);
    73.     proxy.SetPixel(0,0, Color.white);
    74.     proxy.Apply();  
    75.     renderer.material.SetTexture( "ResultSampler", proxy);
    76.    
    77.     //------ for export
    78.     if (ChannelReorder)
    79.     {
    80.         ChannelReorder.SetTexture( "ReliefSampler", g_ReliefTex);
    81.         ChannelReorder.SetTexture( "ResultSampler", g_ResultTex);      
    82.     }  
    83.     //------ camera setup
    84.     Camera.main.transform.rotation = Quaternion(1,0,0,1);
    85.     Camera.main.pixelRect = Rect(0, 0, g_ReliefSizeX, g_ReliefSizeY);
    86.    
    87.     g_RunMode = 1;
    88. }
    89.  
    90. function FixedUpdate()
    91. {  
    92.     if(g_RunMode  !Busy)
    93.     {
    94.         OnFrameRender();
    95.     }
    96.     else if(Export_Now)
    97.     {
    98.         Export_Now = false;
    99.         if (ChannelReorder)
    100.         {
    101.             renderer.material = ChannelReorder;
    102.         }
    103.         Export();
    104.     }
    105. }
    106.  
    107. function OnFrameRender()
    108. {
    109.     //------ load last saved result
    110.     Busy = true;
    111.     if(Pass > 0)
    112.     {          
    113.         renderer.material.SetTexture( "ResultSampler", g_ResultTex);
    114.     }
    115.    
    116.     //------ process start
    117.     var OffsetX:int = g_SamplingGroupX*g_SamplingGroupSize
    118.                         +(g_SamplingOrder[g_SamplingGroupPos] %g_SamplingGroupSize);
    119.                        
    120.     var OffsetY:int = g_SamplingGroupY*g_SamplingGroupSize
    121.                         +(g_SamplingOrder[g_SamplingGroupPos] /g_SamplingGroupSize);
    122.  
    123.     var Offset:Vector3;
    124.     Offset.x = (OffsetX-parseInt(g_ReliefSizeX)/2)/parseFloat(g_ReliefSizeX) +0.5/g_ReliefSizeX;
    125.     Offset.y = (OffsetY-parseInt(g_ReliefSizeY)/2)/parseFloat(g_ReliefSizeY) +0.5/g_ReliefSizeY;
    126.     Offset.z = 0.0;
    127.  
    128.     g_SamplingGroupX++;
    129.    
    130.     if (g_SamplingGroupX>=g_ReliefSizeX/g_SamplingGroupSize)
    131.     {
    132.         g_SamplingGroupX=0;
    133.  
    134.         var s2:int = g_SamplingGroupSize*g_SamplingGroupSize;
    135.         var sx:int = g_ReliefSizeX/g_SamplingGroupSize;
    136.         var sy:int = g_ReliefSizeY/g_SamplingGroupSize;
    137.  
    138.         var progress1:float = 100.0*g_SamplingGroupPos/s2;
    139.         var progress2:float = 100.0/s2*(g_SamplingGroupX+g_SamplingGroupY*sx)/(sx*sy);
    140.  
    141.         Progress = "Progress: " +(progress1+progress2) +"%, ("
    142.                                     +(g_SamplingGroupPos+1)+", "
    143.                                     +(g_SamplingGroupSize*g_SamplingGroupSize)+")";
    144.        
    145.         g_SamplingGroupY++;
    146.        
    147.         if (g_SamplingGroupY>=g_ReliefSizeY/g_SamplingGroupSize)
    148.         {
    149.             g_SamplingGroupY=0;
    150.             g_SamplingGroupPos++;
    151.             if (g_SamplingGroupPos>=g_SamplingGroupSize*g_SamplingGroupSize)
    152.             {
    153.                 g_SamplingGroupPos=0;
    154.                 g_RunMode=0;
    155.                 Progress = "Progress: 100%";
    156.                
    157.                 Export_Now = true;
    158.             }
    159.         }
    160.     }
    161.     renderer.material.SetVector("g_Offset",Offset);
    162.    
    163.     //------ save lastest result to g_ResultTex.       
    164.     Camera.main.pixelRect = Rect(0, 0, g_ReliefSizeX, g_ReliefSizeY);  
    165.     yield WaitForEndOfFrame();
    166.     g_ResultTex.ReadPixels (Camera.main.pixelRect, 0, 0);
    167.     g_ResultTex.Apply ();
    168.    
    169.     if(ExportTempFiles  _export_per_frame)
    170.     {
    171.         if(Pass % _export_per_frame == _export_per_frame -1)       
    172.         {      
    173.             var f = Pass /_export_per_frame +1;        
    174.             var output =String.Format("{0}/{1}_{2:D07}.png","_process_"+OuputFile,OuputFile,f);
    175.             File.WriteAllBytes(output, g_ResultTex.EncodeToPNG());
    176.         }
    177.     }
    178.     Pass++;
    179.     Busy = false;
    180. }
    181.  
    182. function Export()
    183. {
    184.     var str     = (OuputFile == "")? "_relaxed_cone_ouput" : "_relaxed_cone_"+OuputFile;   
    185.     var output  = String.Format("{0}/result_{1}.png", "_output", str);
    186.    
    187.     yield WaitForEndOfFrame();
    188.    
    189.     g_ResultTex.ReadPixels (Camera.main.pixelRect, 0, 0);
    190.     g_ResultTex.Apply ();
    191.     File.WriteAllBytes(output, g_ResultTex.EncodeToPNG());
    192. }
    193.  
    194. function OnGUI()
    195. {
    196.     GUI.Box(Rect(0, Screen.height -g_ReliefSizeY-25, 256,24), Progress +" : " +Pass);
    197. }
    198.  
    Shader for post-processing: (reorder the color channel and create normal map)
    Code (csharp):
    1. Shader "ReleasedCone_ChannelReorder_v001"
    2. {
    3.     Properties
    4.     {
    5.         sampling    ("sampling", Float) = 256
    6.         bumpiness   ("gain", Float) = 1
    7.        
    8.         ReliefSampler   ("ReliefSampler",  2D) = "white" {}
    9.         ResultSampler   ("ResultSampler",  2D) = "white" {}
    10.     }
    11.     SubShader
    12.     {
    13.         Pass
    14.         {
    15.  
    16. CGPROGRAM //-----------
    17. #pragma target 3.0         
    18. #pragma vertex      vertex_shader
    19. #pragma fragment    pixel_shader
    20.  
    21. struct a2v
    22. {
    23.     float4 vertex       : POSITION;
    24.     float2 texcoord     : TEXCOORD0;
    25. };
    26.  
    27. struct v2f
    28. {
    29.     float4 position         : POSITION;
    30.     float2 texcoord         : TEXCOORD1;
    31.     float2 texcoord_invY    : TEXCOORD2;
    32. };
    33.  
    34. v2f vertex_shader(a2v IN)
    35. {
    36.     v2f OUT;
    37.    
    38.     OUT.position        = mul(glstate.matrix.mvp, IN.vertex);
    39.     OUT.texcoord        = IN.texcoord;
    40.     OUT.texcoord_invY   = IN.texcoord*float2(1,-1);
    41.    
    42.     return OUT;
    43. }
    44.  
    45. float3 height2normal_sobel_invY(float3x3 c)
    46. {      
    47.     float3x3 x = float3x3(   -1.0, 0.0, 1.0,
    48.                              -2.0, 0.0, 2.0,
    49.                              -1.0, 0.0, 1.0  ) *c;
    50.  
    51.     float3x3 y = float3x3(  -1.0, -2.0, -1.0,
    52.                              0.0,  0.0,  0.0,
    53.                              1.0,  2.0,  1.0 ) *c;
    54.  
    55.     float cx =   x[0][0] +x[0][2]
    56.                 +x[1][0] +x[1][2]
    57.                 +x[2][0] +x[2][2];
    58.    
    59.     float cy =   y[0][0] +y[0][1] +y[0][2]
    60.                 +y[2][0] +y[2][1] +y[2][2];
    61.                
    62.     float cz =  sqrt(1-(cx*cx+cy*cy));
    63.    
    64.     return float3(cx, cy, cz);
    65. }
    66.  
    67. float3x3 img3x3(sampler2D color_map, float2 tc, float ts, int ch)
    68. {
    69.     float   d = 1.0/ts;                                 // ts, texture sampling size
    70.     float3x3 c;    
    71.     c[0][0] = tex2D(color_map,tc + float2(-d,-d))[ch];  // ch, color channel
    72.     c[0][1] = tex2D(color_map,tc + float2( 0,-d))[ch];
    73.     c[0][2] = tex2D(color_map,tc + float2( d,-d))[ch]; 
    74.        
    75.     c[1][0] = tex2D(color_map,tc + float2(-d, 0))[ch];
    76.     c[1][1] = tex2D(color_map,tc                )[ch];
    77.     c[1][2] = tex2D(color_map,tc + float2( d, 0))[ch];
    78.        
    79.     c[2][0] = tex2D(color_map,tc + float2(-d, d))[ch];
    80.     c[2][1] = tex2D(color_map,tc + float2( 0, d))[ch];
    81.     c[2][2] = tex2D(color_map,tc + float2( d, d))[ch];
    82.    
    83.     return c;
    84. }
    85.    
    86. float4  pixel_shader(   v2f IN,
    87.                         uniform sampler2D ReliefSampler,
    88.                         uniform sampler2D ResultSampler,
    89.                         uniform float sampling,
    90.                         uniform float bumpiness ) :COLOR
    91. {  
    92.     float3x3 c = img3x3(ReliefSampler, IN.texcoord_invY, sampling, 3 ); // use alpha as height
    93.     float3 normal = height2normal_sobel_invY(c);
    94.    
    95.     normal.z = bumpiness;
    96.     normal = normalize(normal);
    97.    
    98.     float4 color;
    99.     color.xy = normal.xy + float2(0.5, 0.5);
    100.     color.z  = tex2D(ResultSampler, IN.texcoord     ).z;
    101.     color.w  = tex2D(ReliefSampler, IN.texcoord_invY).w;
    102.  
    103.     return color;  
    104. }      
    105. ENDCG //----------     
    106.  
    107.         } // Pass
    108.     } // SubShader
    109. } // Shader
    110.  
     
    pottering likes this.
  35. Battle Angel Alita

    Battle Angel Alita

    Joined:
    Mar 29, 2010
    Posts:
    44
    hint for hi-res textures
    To example for 2048 texture you can create a 512 relaxed cone map. It provide slightly quality drops, but big perfomance boost.
     
  36. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169
    Thanks for your tips.

    In fact, I found another paper, they use different method for pre-processing, it can be 10x boosted and finished the process in realtime.
    http://www.csie.ntu.edu.tw/~cyy/publications/papers/apsipa2009.pdf

    If I have time again, I will try to implement that too :)
     
  37. moska

    moska

    Joined:
    Nov 1, 2009
    Posts:
    27
    i was just trying to understand the connection between bump and normal for a parallax default shader and found this.i just hope this can be used at default.i supouse its very slow now?ill try it .why there are no textures to try with quadmap?is this somehow related with vector displcement maps like mudbox ones?unity could use these also? displacements maps could or no as they need big mesh?also found www.brunoevangelista.com on this.
    good luck and thanks
     
  38. joeythepoey

    joeythepoey

    Joined:
    Jun 18, 2010
    Posts:
    12
    So, did anyone got this working yet as a proper shader in Unity with lighting and shadows?

    I tried the relief shader example, and though it works awesomely well, it doesn't allow lights or shadows yet...:S

    Cheers,

    Joe
     
  39. Barrett

    Barrett

    Joined:
    Nov 28, 2009
    Posts:
    1
    I've spent yesterday, and most of today looking for a way to create a map which looks like the attachment.

    I've tried exporting different types of normals (Both object, tangent and world) from Maya. I've tried exporting a regular normal map (of all those three types) and adding to them via Photoshop, a displacement layer which I also rendered in Maya. This seemed to yield at least some distorted height, but nothing like the attachment does. That is probably due to smoothing issues.

    I've tried using xNormals to export a proper map, and even tried using its "Height map to cone map" tool. Which yielded poor results.

    Having tried as many solutions as I could think of, and searching this, and various other forums, I think I'll finally ask in this thread, and hope it isn't too old to be of any help.

    In Unity, I have the example using the "Relaxed_cone_relief_mapping_112" shader. I've assigned the attached image to the "relaxedcone" texture holder in a material made from the "Relaxed_cone_relief_mapping_112" shader, and applied it to a plane. The result is bloody stunning! Once you've turned off "Mip Maps" and changed some other settings, it is a fantastic result.

    But the thing is, that result is only occurring with the attached file. I find myself with two problems.

    1) I am unable to render displacement maps from Maya (Which use a black/white scheme, which is why I'm using them) that are sufficiently spread out through the ranges. The maps that I render (Even using spheres and toruses) always have a harsh change from white to black, not a nice smooth one.



    2) I am at an absolute loss as how I would go about creating a normal map like the attachment. At first I thought it looked like an object space normal map (More rainbow like, less blue), but even my object normal maps from Maya don't seem to be working.


    Help me please! :)
     

    Attached Files:

  40. apple_motion

    apple_motion

    Joined:
    Jul 2, 2009
    Posts:
    169
    Hi Barrett,

    You need a program called "gpu_reliefmap_preprocess.exe" (or write you own) to make the relaxed_cone_relief_map. The program come with the CD of a book - GPUGems 3 or you could found it in this thread too. (please scroll up to Lasha84 post. I checked that is the same file as of the CD :)

    Remark. I didn't use that exe yet, since I don't have PC at the moment. (that's why I try to port it :p)

    Good Luck !
     
  41. dongliang28

    dongliang28

    Joined:
    Oct 3, 2010
    Posts:
    161
    apple_motion:
    Hello~thank you for your great shader~i love them~
    Are you tried to use your shader in unity 3.0?
    I could only get "relaxed_cone_relief_mapping_112.shader" to work.
    I knew they had rewrite the shaderlab.
    But i don't know why some could get work and some not.
    Because your shader i start to learn Cg shader.
    What sad is i found it not enough only learning Cg,
    I am learning Cg shader with FX composer,but i could never get Cg shader to work,even i just copy the example Cg shader into it or load the Cg shader directly.
    I saw some book use VC++ to code Cg shader,i can't do as the same,because i do not know any C++......
    Should i give up it or anything else i can do to just make the example Cg shader to work?
    How do you learning Cg shader?
    Are you good at C++?
     
  42. kurylo3d

    kurylo3d

    Joined:
    Nov 7, 2009
    Posts:
    1,121
    I am dieing for a version of this shader that works with unity lighting and shadows. apple_motion , please check your private message if your interested in getting paid for some quick freelance work writing shaders.
     
    Last edited: Nov 9, 2010
  43. reissgrant

    reissgrant

    Joined:
    Aug 20, 2009
    Posts:
    726
    Here is my relief conversion for Unity 3.0. It works with shadows, but the shadows do not follow the relief contour. Silhouettes are working too.

    View attachment $Relief.unitypackage

    btw sup Orlando buddy!
     
  44. kurylo3d

    kurylo3d

    Joined:
    Nov 7, 2009
    Posts:
    1,121
    oh oh , looks like i just made a new contact :) What up! im between ucf and fullsail... by the way nice shader ... that thing is hot.. check your private messages. Im about to send you one.
     
  45. namassa

    namassa

    Joined:
    Oct 16, 2010
    Posts:
    7
    Ive got problem with using that preprocessor to get proprer relaxed cone map. How to use it? I mean should i use it on heightmap or depthmap shoud i say. And later what? I understand that i should merge it with depthmap later. Each map which i get from preprocessor is without alpha. Map from example is colored and with A channel. I even tried to use xNormals ... and still no result. I hope that i can find help here.
     
  46. 121

    121

    Joined:
    Nov 26, 2009
    Posts:
    199
    Thanks for porting the shader Antonio.

    I played around with this and made an identical rockbump_relaxedcone tga image using the gpu preprocess program.

    I could make a small tutorial if anyone is still stuck.
     
    Last edited: Dec 3, 2010
  47. moska

    moska

    Joined:
    Nov 1, 2009
    Posts:
    27
    please do it!
    thanks
    i think this is very important
     
  48. 121

    121

    Joined:
    Nov 26, 2009
    Posts:
    199
    Hi Moska,


    Open the rockbump_relaxedcone tga map in Photoshop.

    Click on Channels and you'll see the inverted Alpha Map under the RGB channels.

    Make a new tga that is the same size in pixels and drag the Alpha channel from rockbump_relaxedcone into the new image.

    Invert this image and you'll find that its a height map. This was originally made by painting over the pebble photo on a separate layer.

    Save this file and open your 3d program. I used 3ds Max. Make a plane and make the length and width segments the same as the pixels of the height map (256 x 256).

    Add a Displace modifier and load the new height map into it. Make it about 4cm high.

    Don't add any lights to the scene and just leave it default.

    Use Render to Texture to make a diffuse map.

    Open the diffuse map in Photoshop and use the Nvidia Normal Map filter to make a normal map (I set the scale to 16).

    Look at the normal maps Channels and delete the Alpha Channel if theres one.

    Invert the height map (the one you made earlier ) back to how it was (negative) and drag its 'Alpha channel' back to the normal map.

    Save the normal map as a 32 bit Targa (I think) and load it in the GPU Preprocess program.

    Choose Relaxed and hit start. As it renders, you'll notice that its black and white but the finished image will not be. When its done hit Save.

    Open the new relaxedcone image in Photoshop and increase the contrast all the way to 100.

    You should have an identical image to rockbump_relaxedcone.

    To make your own relaxed cone map from a photo or texture, open it in photoshop and add a new layer. Paint a height map using 50% opacity. Save this and use it for displacement. I tried using the height map and photo to make the normal map with the nvidia filter but the results were bad. You need to displace the image to get a good finish.

    There maybe a quicker way but this works for now.

    I've attached two jpegs of the relaxedcone maps. Ones the original.





    HTH
     

    Attached Files:

  49. moska

    moska

    Joined:
    Nov 1, 2009
    Posts:
    27
    thanks
    but not sure the gpu_reliefmap_preprocess.sln works on mac
    it opens with mono developer but its too much for a poor little artist like me
    i just found these relief shaders are much more intersting than unity paralax ones
    there was a pretty good one from Slin for 2.6.1
    but these ones here are very sofisticated
    i saw a youtube video where a single image plane was rendered as a full 3d object!
    ill have to try reissgrant one too
    lets hope all this goes forward and react to light!
     
  50. moska

    moska

    Joined:
    Nov 1, 2009
    Posts:
    27
    hi
    i notice the unity paralax shader has changed presentation and now has two slots(one for normalmap and the other for for heightmapA)like the reissgrant one.so now we dont have to put heightmap on normalmap´s alpha?
    but that A on the heightmap means alpha?
    or we put a normalmap without alpha in normalmap slot and then a normalmap with alpha eightmap on height slot or what?
    also on reissgrant shader what are that use alpha and alpha falloff for? by the way thanks for it reissgrant!i can see now it works!
     
unityunity