New Surfaces Materials?



  • On 14/04/2013 at 13:15, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   13 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    Hi,

    One of the areas that is not covered very well, or very often, is creating custom shaders.
    I've been wondering how to create my own shaders like the ones in the materials->surfaces list of shaders.

    -Are those shaders all based on math formulas? Or bitmap images?

    -There is an SDK shader exampled called "Mandelbrot" that seems like it might be what I need. But it's very simple and only has two attributes. And I'm not sure it has enough information in it to create the kind of result I want.

    I'd like to create a shader similar to pavement shader. But with a different pattern.

    -ScottA



  • On 15/04/2013 at 01:46, xxxxxxxx wrote:

    i am a bit confused by your question. do you just want to write a simple shader or are you 
    after that special shader type which is actually a material and provides its own projection like 
    the shaders you can find under materials/surfaces ?

    for the first option i have no experience, as they are a cpp only plugin type called MaterialData
    and are actually materials and not shaders. generally speaking a shader is an object which 
    returns a vector(color) for a given vector(uvw-data)(and some more informations all stored
    in the channeldata for that sample). the respective method is Output().

    so it depends on your implementation. you could write your own bitmapshader which converts
    the given channeldata into pixel coordinates of an attached bitmap and then returns that color 
    vector. but the common shader just feeds the channeldata into some formulas and returns the 
    result as a vector. as a really stupid example you could take the sinus of the U/V/W coordinates 
    and return the result as the color vector.



  • On 15/04/2013 at 04:38, xxxxxxxx wrote:

    There are two types of shader you can write - the channel shaders (like Checkerboard or Rust) and volume shaders (like Danel or Cheen). Volume shaders are a lot harder to write (IMO) but channel shaders are straightforward enough once you get the hang of how it's done.

    Take a look at the bitmap distortion shader in the SDK example, it's very simple. From that basic skeleton you can produce other shaders but AFAIK these are all based on some kind of mathematical alteration of the surface properties - that is, they don't use bitmaps. They may have a bitmap input as one of their parameters but there's no hidden bitmap under the hood.

    If you want a better Mandelbrot then as long as you know how to write a fractal mandelbrot generator you can make this into a shader. There are lots of web pages around that show how to do that.

    I'd suggest trying to get a working channel shader first that does something simple like multiplying the surface colour with a colour of the user's choice. If you can get that up and running you can do something more advanced. But the SDK examples are the way to start.

    Steve



  • On 15/04/2013 at 08:19, xxxxxxxx wrote:

    The problem is I don't really know.
    I would like to create my own procedural shader that looks like the pavement shader. And lets me change the gaps and shapes of the pattern.
    I'm thinking that a bitmap shader just warps the image. But it won't be able to actually change things like the gaps?

    There is an old plugin called EnhanceC4D that basically does what I'm trying to do. And it works just like the surface shaders.
    But I don't know how to make this kind of plugin.
    There's not enough information in the SDK example for me to get a good understanding of how to make this kind of plugin.

    -ScottA



  • On 15/04/2013 at 09:08, xxxxxxxx wrote:

    If you want to do something like the pavement shader, then you need to derive your plugin from ShaderData. The so-called "Volume Shader" (like Danel or Cheen) are actually Materials, not shaders. For those, you would have to derive your plugin from MaterialData.

    Do decide which submenu your shader should appear in, you have to add the name of the target menu in front of the shader's name:

    Bool RegisterMyShader(void)   
    {   
    return RegisterShaderPlugin(ID_MYSHADER, GeGetDefaultFilename(DEFAULTFILENAME_SHADER_SURFACES) + GeLoadString(IDS_MYSHADER), 0, MyShader::Alloc, "xmyshader", 0);   
    }   
    


  • On 15/04/2013 at 09:29, xxxxxxxx wrote:

    Hi Frank,

    I know how to create the basic plugin framework.  And how to add the shader to the material.
    The part I don't understand is the creation of the actual shapes and gaps of the shader.

    I'm guessing that the code I will need to write goes in: Output(BaseShader *chn, ChannelData *cd){}?

    I know that ChannelData is a class(a struct) that has a bunch of functions in it (p,n,d,t,etc..)
    But I don't understand how these things are used to create a specific pattern. With gaps than can be changed.

    The construction of the the pattern and gaps is what I don't know how to do.

    -ScottA



  • On 16/04/2013 at 00:32, xxxxxxxx wrote:

    Ah, ok.

    Well, the member cd->p gives you the position of the rendered ray in UV space, and cd->vd->p gives you the position in world space. You can use those coordinates to sample an algorithm that creates the patterns for you. Easiest example: Use p as the position to sample a Turbulence() and return the result in Output(). You'll end up with a noise shader.

    cd->d is the MIP delta. That gives you the amount of the UV space that is covered by the current ray. You can use this value (carefully clamped to avoid overly sensitive reactions) to control the level of detail of your shader (e.g. use it to drive the octaves of a noise you are using).



  • On 16/04/2013 at 07:35, xxxxxxxx wrote:

    Ok thanks.

    I guess what I need then is an explanation of what's going on inside of the Turbulence() function.
    I guess I'll need to write my own algorithm in order to get a specific desired result. But where do I find this information?

    What I need is some sort of a guide like the Formula Effector has in the help files.
    I wonder if there is such a shader formula database somewhere?

    -ScottA

    -Edit:
    Actually. The more I look at the pavement shader. The more it looks like a bitmap image being blended with a black image to change the size of the gaps.
    And the way the seed option changes the pattern. It almost looks like they are changing the UV's. Or possibly sampling only a small section of the entire bitmap?

    @Maxon.
    Is it possible to get more information about how to write this kind of shader?

    -ScottA



  • On 17/04/2013 at 00:36, xxxxxxxx wrote:

    Hi Scott,

    If you need algorithms to see how to write procedural shaders, there are books like "Texturing and Modeling: A Procedural Approach" (a little dated now).
    There are also lot of useful resources on the web.
    Algorithms are generals and APIs for writing shaders provide more or less the same information.



  • On 17/04/2013 at 08:32, xxxxxxxx wrote:

    Hi Yannick,

    The problem is there are so many different types of shaders. And I don't even know what kind of shader the pavement shader is.

    Is it a bitmap shader?
    Is it a formula shader?
    Are the gaps created with blending in a black color?
    Are the gaps created with a formula?
    Is it a bitmap shader that is tiled (the seed value) with a formula?
    Is it a bitmap shader that is tiled (the seed value) with the UV values?

    I've looked around for tutorials. But most of them seem to talk about making shaders like lambert, fresnels, etc..
    I THINK what I want is a bitmap shader. But that's the problem. I don't really know.
    It's hard to go looking for tutorials on this until I know what it is I'm looking for.

    All I know at this point is that what I'm after is what the pavement shader does.
    Now I need to know some of the specifics about how it's created before I can proceed.
    Things like how the shader being created and changed with the seed value.
    I can't even begin to look for tutorials until I at least know these basic things.

    -ScottA



  • On 17/04/2013 at 09:15, xxxxxxxx wrote:

    Hi Scott,

    all procedural shaders are made from algorithms. Look at this pseudocode, with it you can create a
    shader withn horizontal areas having different widths. You just need to compute the color at the
    current UV/World position. With pseudo, I mean this code is untested and should only show you
    a possible approach.

    Black has the width of the MYSHADER_WIDTH1 parameter while the white has the width of 
    the MYSHADER_WIDTH2 parameter.

    Vector MyShader::Output(BaseShader* host, ChannelData* cd) {
        Vector& p = cd->p;
        BaseContainer* bc = host->GetDataInstance();
        Real width1 = bc->GetReal(MYSHADER_WIDTH1)
        Real width2 = bc->GetReal(MYSHADER_WIDTH2)
      
        Real offset = p.x % (width1 + width2);
        if (offset <= width1) return Vector(1);
        else return Vector(2);
    }
    

    You can combine the same approach in the vertical direction (using p.y). The width2 can be seen
    as the gaps in your pavement.

    -Niklas



  • On 17/04/2013 at 09:33, xxxxxxxx wrote:

    hi,

    at least in python there are no bitmap shaders and formula shader classes. i used the term 
    bitmap shader in reference to the native c4d shader type Xbitmap which simply samples a 
    bitmap by converting the UV coordinates into pixel coordinates at that point.

    for creating a tile shader, it is pretty simple. the main problem often is how to do such things
    in a performant way (something i am really bad at), but generally you could do it this way,
    in some sort of pseudo code.

    if (sample.u <= gap.x or sample.u >= 1 - gap.x or
        sample.v <= gap.y or sample.v >= 1 - gap.y) :
        return black
    else:
        return white
    

    so you just hard code it, the result would be white rectangle, with a black border of the size 
    gap. all inputs are always 0-1 based. you do not have to implement tiling for your shader
    specifically, enabling tiling in the material tag will simply alter the channeldata (the uvw 
    coordinates being passed) to your Output() method.

    if you want to implement tiling within you shader internally you have to hardcode it into
    your method. for the gap example you would have not only to check if sample is within
    gap or 1-gap, but also within gap*0.5 and 1-gap*0.5, when the user sets the scale to
    50%.

    edit : hm, sometimes there pop postings out of nowehere for me, haven't seen nikklas
    posting before, which makes my posting kind of pointless.



  • On 17/04/2013 at 10:08, xxxxxxxx wrote:

    Thanks guys,

    But those are not organic looking shapes like the pavement shader is.
    The pavement shader looks more a like a bitmap to me because of how organic looking the shapes are.

    I'm not saying you're wrong about it being formula based.
    But I'm a bit confused because I've seen that there is a way to blend bitmaps and create organic shapes and gaps like how the pavement shader looks.
    But then I also don't know if a bitmap type shader can be tiled like the pavement shader does.
    So I'm left wondering. What's really going on in there?
    Is it really all being done with a formula?

    If it is formula based. Then the next step I need to figure out is how to make them look organic looking like the pavement shader. And how to add colors to it. Instead of simple black and white lines.
    That's a very, very big leap to make. And I just want to be sure that's the correct direction to go in. And I'm not heading towards another dead end.

    I think I heard once that the shaders are under some kind of copyrite protection. And Maxon can't share them.
    But if I could just see the code for that one shader. Just that one single shader. Or something that is similar that uses the same technique that isn't under an NDA. It would go a long way to pointing in the right direction on what I need to do.

    I just need that little boost of information to get me started.

    -ScottA



  • On 17/04/2013 at 10:20, xxxxxxxx wrote:

    Could you just show an example of the pavement shader? I mean, they're really almost all formula
    based. Even Noise is generated by a formula, and there are ways to generate dirt (see the
    Brick shader for instance), etc. Of course, it could be possible that some shader combines a bitmap
    and a formular (eg. using the bitmap to produce dirt) but no programmer would ever think of
    hardcoding it into the shader since it would be easy to let the user choose a bitmap. Or, which makes
    even more sense, just skip the bitmap part since there is the Layer and Fusion shader allowing you
    to blend different shaders.

    -Niklas



  • 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



  • 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.



  • 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



  • 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



  • 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



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

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


Log in to reply