New Surfaces Materials?
-
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 ?
-
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
-
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.
-
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
-
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 -
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
-
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
-
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.
-
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
-
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().