Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    New Surfaces Materials?

    SDK Help
    0
    56
    37.9k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 17/04/2013 at 10:30, xxxxxxxx wrote:

      What do mean show an example?
      The Pavement shader comes with C4D. It's one of the built-in shaders found under "Surfaces" in any material.

      When you see it. You might see better what I mean about how much it looks like a bitmap being manipulated. Rather than a formula.
      It just doesn't look like a formula to me. But it very well could be.
      I just don't know for sure.

      -ScottA

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 17/04/2013 at 10:31, xxxxxxxx wrote:

        the pavement shader is not bitmap based, it is just a mash up of existing 
        shaders. you can easily build your own pavement shader in c4d. some 
        voronoi noise, a layer shader, a colorize shader and you are done.

        this is actually the easiest way to 'write' a custom shader. simply instantiate 
        a shader tree within you plugin instance and sample that shader(tree) in the 
        Output() method.

        check the BaseShader.Sample() method, it is kind of the counter part to the 
        Output() method. at the cost of speed of course. a shader which does that all
        in one method without instantiating other shaders will always be faster.
        but speed is not the critical point for low end plugin development imho.

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 17/04/2013 at 10:33, xxxxxxxx wrote:

          Oh, it is? Haha, really missed that! It looks pretty much like Voronoi Cells mixed with a Noise. I'm
          100% sure there is not hidden bitmap under the hood.

          Best,
          -Niklas

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 17/04/2013 at 10:46, xxxxxxxx wrote:

            OK. Well helps out a little bit.
            At least I can remove the bitmap image thing from the equation.

            But I'm still rather lost how I would go about creating my own version with a different pattern.

            -ScottA

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 17/04/2013 at 10:51, xxxxxxxx wrote:

              Well, it depends on what pattern you would like to have. A rectangular pattern would be the easiest
              (similar to the standart version of the Tile shader). You would need to go the way I described above.
              You just need some kind of algorithm to determine if you're currently at a gap or not (when keeping
              things simple). I showed you above how to check if for "horizontal lines".

              Best,
              -Niklas

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 17/04/2013 at 10:58, xxxxxxxx wrote:

                could you show an example ouput (photo or simple drawing) of what you are after ?

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  On 17/04/2013 at 11:10, xxxxxxxx wrote:

                  I don't have a specific pattern in mind. I never got close enough to even get that far with it.
                  I just wanted to know how to change the pattern.

                  At this point. I have to go back and look at what you guys have posted again. And try to figure out how turn it into something that works (changes the pattern).

                  -ScottA

                  1 Reply Last reply Reply Quote 0
                  • H
                    Helper
                    last edited by

                    On 17/04/2013 at 11:55, xxxxxxxx wrote:

                    To generate things like stone or concrete you're really looking at generating a fractal noise of some kind. That's all these procedural rock/stone shaders are - just a fractal or combination of fractals. If you have Vue, it's node-based material editor is a good example of combining fractals like this.

                    So you have to know how to produce those. There are some in Cinema, take a look at fBm or RidgedMultifractal. Otherwise you'll find lots on the net. You will want to generate a value from 0 to 1 and return a colour or bump value accordingly as others have already said.

                    1 Reply Last reply Reply Quote 0
                    • H
                      Helper
                      last edited by

                      On 17/04/2013 at 12:49, xxxxxxxx wrote:

                      Thanks Steve,

                      I hope I can get far enough to use that information.
                      Right now I'm still trying to figure out how to make even a very simple basic pattern. Like a simple checkerboard pattern. Or a series of circles.

                      -ScottA

                      1 Reply Last reply Reply Quote 0
                      • H
                        Helper
                        last edited by

                        On 17/04/2013 at 14:19, xxxxxxxx wrote:

                        i just wanted to stress book tip posted by yannick -  _Texturing and Modeling: A Procedural  _
                        Approach. this book  contains a pretty down to earth description on how to write a brick 
                        wall shader (among dozens of dozens other shader listings). one of the must have books
                        for coding simpletons like me imho 😉

                        1 Reply Last reply Reply Quote 0
                        • H
                          Helper
                          last edited by

                          On 17/04/2013 at 15:37, xxxxxxxx wrote:

                          Before I can use that kind of information. I first need to learn how to use the code in the C4D SDK.

                          As far as I can make out. The main methods I need to use are the InitRender() method & the Output() method. But I'm not even really sure if I really need the InitRender() method.
                          InitRender() seems to be for sampling. But will I need to do any sampling to create my own patterns?

                          These are the basic things I need is to know how to do with the SDK first. Before trying to do anything fancy:
                          -How to create colored lines using cd->p?
                          -How to create a colored checkerboard pattern using cd->p?
                          -How to create a colored grid of circles using cd->p?

                          I'm having a very hard time understanding how these basic things work in C4D SDK.

                          -ScottA

                          1 Reply Last reply Reply Quote 0
                          • H
                            Helper
                            last edited by

                            On 17/04/2013 at 16:12, xxxxxxxx wrote:

                            You will need to implement InitRender, for (at least) two reasons. If you need to access any data from the shader interface, do it here and store the results - otherwise you could be accessing the parameters hundreds of times whenever a render occurs. Also, if you have any shader links in your shader you absolutely must call their InitRender functions, and you do that here.

                            To get started, here's the complete listing of a simple shader I wrote to mirror-image a bitmap. It's very simple and you won't need the resource to understand it. It just lets the user choose to mirror the bitmap horizontally and/or vertically, and the only other interface element is a link for the bitmap:

                              
                            // BMFlip   
                            // bmflip.cpp   
                            // includes   
                            #include "c4d.h"   
                            #include "bmflip.h"   
                            #include "xbmflip.h"   
                            #include "c4d_symbols.h"   
                            SHADERINFO BitmapFlip::GetRenderInfo(BaseShader *sh)   
                            {   
                                 return SHADERINFO_BUMP_SUPPORT;   
                            }   
                              
                            Bool BitmapFlip::Init(GeListNode *node)   
                            {   
                                    // these are class-level variables   
                                 shader = NULL;   
                                 flipX = FALSE;   
                                 flipY = FALSE;   
                                 return TRUE;   
                            }   
                              
                            void BitmapFlip::FreeRender(BaseShader *chn)   
                            {   
                                 if(shader)   
                                      shader->FreeRender();   
                                 shader = NULL;   
                            }   
                              
                            Bool BitmapFlip::Message(GeListNode *node, LONG type, void *msgdat)   
                            {   
                                 BaseContainer *data;   
                                 data = ((BaseShader* )node)->GetDataInstance();   
                                 HandleInitialChannel(node, BMFLIPSHADER_TEXTURE, type, msgdat);   
                                 HandleShaderMessage(node, (BaseShader* )data->GetLink(BMFLIPSHADER_TEXTURE, node->GetDocument(), Xbase), type, msgdat);   
                                 return TRUE;   
                            }   
                              
                            INITRENDERRESULT BitmapFlip::InitRender(BaseShader *chn, const InitRenderStruct& irs)   
                            {   
                                 BaseContainer *data;   
                                 INITRENDERRESULT result;   
                                 data = chn->GetDataInstance();   
                                 // get gadget values   
                                 flipX = data->GetBool(BMFLIPSHADER_FLIPX);   
                                 flipY = data->GetBool(BMFLIPSHADER_FLIPY);   
                                 shader = (BaseShader* )data->GetLink(BMFLIPSHADER_TEXTURE, irs.doc, Xbase);   
                                 if(shader)   
                                 {   
                                      result = shader->InitRender(irs);   
                                      return result;   
                                 }   
                                 return INITRENDERRESULT_OK;   
                            }   
                              
                            Vector BitmapFlip::Output(BaseShader *chn, ChannelData *cd)   
                            {   
                                 Vector res, uv;   
                                 if(!shader) return Vector(0.0, 0.0, 0.0);          // return black if no bitmap present   
                                 uv = cd->p;                         // get the original UV value so we can restore it later   
                                 if(flipX)   
                                      cd->p.x = 1.0 - cd->p.x;   
                                 if(flipY)   
                                      cd->p.y = 1.0 - cd->p.y;   
                                 res = shader->Sample(cd);           // get the bitmap value at this point   
                                 cd->p = uv;                         // restore the UVs   
                                 return res;                                                  // return the colour of the bitmap at the mirrored position   
                            }   
                              
                            // register the plugin   
                            Bool RegisterBMFlip(void)   
                            {   
                                 String name;   
                                 name = "Bitmap Transform";   
                                 if(RegisterShaderPlugin(ID_BMFLIP, GeGetDefaultFilename(DEFAULTFILENAME_SHADER_EFFECTS) + String("Bitmap Transform"), 0, BitmapFlip::Alloc,"Xbmflip", 0))   
                                 {   
                                      return TRUE;   
                                 }   
                                 else   
                                 {   
                                      return FALSE;   
                                 }   
                            }   
                            

                            Hope that helps!

                            Steve

                            1 Reply Last reply Reply Quote 0
                            • H
                              Helper
                              last edited by

                              On 17/04/2013 at 16:22, xxxxxxxx wrote:

                              Originally posted by xxxxxxxx

                              How to create a colored checkerboard pattern using cd->p?

                              I haven't tried it but I imagine that for a four-square checkerboard Output() would look something like this:

                                
                              Vector MyShader::Output(BaseShader *chn, ChannelData *cd)   
                              {   
                                   Vector col;   
                                   // cd.p.x and cd.p.y range from 0 to 1   
                                   if((cd.p.x < 0.5 && cd.p.y < 0.5) || (cd.p.x >= 0.5 && cd.p.y >= 0.5))   
                                        col = Vector(0.0);     // return black for top-left and bottom-right squares   
                                   else   
                                        col = Vector(1.0);     // return white for the other two squares   
                                   return col;   
                              }   
                              

                              No idea if it works! But try it and see.

                              1 Reply Last reply Reply Quote 0
                              • H
                                Helper
                                last edited by

                                On 17/04/2013 at 16:47, xxxxxxxx wrote:

                                ^Yes. It does work.
                                Thanks Steve.

                                But I'm a bit puzzled why it works.
                                You aren't using a loop to get the positions of p.
                                I would have thought that I would have needed to use a loop in this case. To check the position (then set the color) of p.
                                That's how I normally get the colors of a bitmap for example. looping through each line of pixels.

                                But what you did.
                                Setting certain sections of the shader to black or white without using a loop. Seems strange to me. And something I'll need to understand. Because I think I'll need to use a similar technique to create other things. Like circles and more complex shapes.

                                -ScottA

                                1 Reply Last reply Reply Quote 0
                                • H
                                  Helper
                                  last edited by

                                  On 18/04/2013 at 01:00, xxxxxxxx wrote:

                                  Glad to know it works. You don't need a loop because Cinema calls Output() for each point to be rendered, setting cd->p accordingly. So you don't iterate through all the points in the UV data, you just calculate the colour to return at the point passed to Output().

                                  1 Reply Last reply Reply Quote 0
                                  • H
                                    Helper
                                    last edited by

                                    On 18/04/2013 at 07:38, xxxxxxxx wrote:

                                    OK. Thanks a lot for the help Steve.
                                    I have enough information now to start looking at formulas and trying to putting something together.
                                    But I'm a long way from controlling gaps and shapes.

                                    Once again. I must make this final plea the the Maxon team (or anyone willing).
                                    Could you please provide us with one example of a procedural shader like the pavement shader?
                                    It doesn't matter what the pattern is, or what the colors are.
                                    Something that shows us how to change the gaps, shapes, and colors of the pattern so we can use it as a guide making our own shaders.

                                    If I end up figuring it out myself. I'll share what I come up with.

                                    Thanks,
                                    -ScottA

                                    1 Reply Last reply Reply Quote 0
                                    • H
                                      Helper
                                      last edited by

                                      On 18/04/2013 at 12:29, xxxxxxxx wrote:

                                      Originally posted by xxxxxxxx

                                      Could you please provide us with one example of a procedural shader like the pavement shader?

                                        
                                      // A simple turbulence shader   
                                      Vector ExampleShader::Output(BaseShader *chn, ChannelData *cd)   
                                      {   
                                      Vector p;   
                                      if (cd->vd)   
                                          p = cd->vd->p;   
                                      else   
                                          p = cd->p;   
                                        
                                      return Vector(Turbulence(p, 3.0, TRUE));   
                                      }   
                                        
                                        
                                      // Using the turbulence value to output either red or green   
                                      Vector ExampleShader::Output(BaseShader *chn, ChannelData *cd)   
                                      {   
                                      Vector p;   
                                      if (cd->vd)   
                                          p = cd->vd->p;   
                                      else   
                                          p = cd->p;   
                                        
                                      Real threshold = 0.5; // Introduce a threshold to decide on the output color   
                                        
                                        
                                      if (Turbulence(p, 3.0, TRUE) > threshold)   
                                          return Vector(1.0, 0.0, 0.0);   
                                      else   
                                          return Vector(0.0, 1.0, 0.0);   
                                      }   
                                        
                                        
                                      // Or: Displacing the turbulence with a noise   
                                      Vector ExampleShader::Output(BaseShader *chn, ChannelData *cd)   
                                      {   
                                      Vector p;   
                                      if (cd->vd)   
                                          p = cd->vd->p;   
                                      else   
                                          p = cd->p;   
                                        
                                      Real displace_scale = 0.5;        // Introduce a scale for the displacing noise   
                                      Real displace_intensity = 0.75;   // Introduce a value to control the intensity of the displacement effect   
                                        
                                      return Vector(Turbulence(p + Noise(p * displace_scale) * displace_intensity, 3.0, TRUE));   
                                      }   
                                        
                                        
                                      // Or: a simple 2D checkerboard (without MIP mapping, rather ugly)   
                                      Vector ExampleShader::Output(BaseShader *chn, ChannelData *cd)   
                                      {   
                                      Vector p = cd->p;   
                                        
                                      p *= 0.2; // Introduce a scale to control the size of the squares   
                                        
                                      p.x -= (LONG)Floor(p.x);   
                                      p.y -= (LONG)Floor(p.y);   
                                        
                                      if ((p.x > 0.5) != (p.y > 0.5))   
                                          return Vector(1.0);   
                                      else   
                                          return Vector(0.0);   
                                      }   
                                      

                                      Of course, all the control values I have introduced in the Output() function would normally be retrieved from the shader's BaseContainer in InitRender() and then stored in private class members.

                                      You see, writing a shader is very easy. But it can also get very complex, depending on the pattern you want.

                                      Algorithms for common patterns can be easily found on the web. For example, here are some old Renderman shaders from the 80s 🙂
                                      You can open the .sl files in a text editor.

                                      http://www.cs.rit.edu/~mrp9521/cg/renderman.html
                                      http://www.renderman.org/RMR/Shaders/BMRTShaders/

                                      Cheers,
                                      Frank

                                      1 Reply Last reply Reply Quote 0
                                      • H
                                        Helper
                                        last edited by

                                        On 18/04/2013 at 12:51, xxxxxxxx wrote:

                                        Thanks Frank,

                                        I think the thing I'm going to have the toughest time figuring out is how to control gap size between shapes. That's probably what I'll really need to see an example of the most.

                                        Also.
                                        After setting up my plugin and getting the basic stuff in place. I came across another issue.
                                        If I use a vector type as a color. I get lots really horrible noises all over the object when I render it.
                                        But If I use an LVector with a value of 125 like the mandelbrot SDK example uses. It fixes that problem.
                                        Example:

                                          
                                        #define CCOUNT 125  
                                        Vector *colors;  
                                        colors = GeAllocType(Vector,CCOUNT);
                                        

                                        I'm wondering whats exactly going on with that?
                                        I'm guessing that it maybe has something to do with the amount of bits a standard vector holds?
                                        I'm also wondering what the value 125 means. And what happens if I use a higher of lower number?

                                        -ScottA

                                        1 Reply Last reply Reply Quote 0
                                        • H
                                          Helper
                                          last edited by

                                          On 18/04/2013 at 23:45, xxxxxxxx wrote:

                                          I don't know what your shader code looks like, and why you would need a Vector array with 125 elements. The Mandelbrot shader needs an array because it calculates a fixed set of colors in InitRender() that it later chooses its result color from in Output(). But that's a special thing and you probably won't need that in your shader.

                                          Vector is the correct type for a single color value, a Vector array would store lots of colors.

                                          I can only imagine you're screwing your results up by doing some stuff in the Output() that might behave strange in a multi-threaded context. Remember, Output() is called for each (sub-)pixel that each thread renders.

                                          And about the gaps, it really would just be a very simple addition to the checkerboard code I have posted. You already know where the seams between the squares are, so you could just introduce a value for gap width, add or subtract it from the position (depending on if you are closer to a lower or a higher border of a square) and fill it with another color.

                                          It is all very basic stuff, you just have to read up on it 😉

                                          Did you have a look e.g. at the Renderman brick shader on the second page I linked to in my previous posting? It shows everything you're just asking for, and it's even commented (well, a bit).

                                          1 Reply Last reply Reply Quote 0
                                          • H
                                            Helper
                                            last edited by

                                            On 19/04/2013 at 08:58, xxxxxxxx wrote:

                                            I have only had a chance to briefly look at those Renderman shaders.
                                            I had to get my basic shader plugin working first. But I'll take a close look at them today.

                                            I'm a complete newb at this shader stuff. So I copied a lot of the code in the Mandelbrot example to get me started.
                                            I think I might have gotten that noisy result because I used my color vector as a pointer.
                                            Today I removed   that color pointer code from my code. And just created a standard color vector. And now it seems to work fine without using an LVector.

                                            Your 2D checkerboard example doesn't work for me for some reason. The shader is all black.
                                            The other examples you posted work fine. But for some reason that one doesn't. And I'm trying to figure out why it isn't working correctly.

                                            -ScottA

                                            *Edit- I found where the noise problem is coming from.
                                            If I declare the vector (pointer or not) as a class member variable. Then use that vector in my Output() method. I get horrendous noise when rendering.
                                            But if I declare the vector inside of the Output() method. It renders fine.
                                            That seems pretty strange to me...😵

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post