Jump to content

Car Shader


priel

Recommended Posts

Just saw Cars from Pixar, really amazing work on the car shaders!

...so...

..how about a nice car shader, with all the goodies such as candy specks, clear laquer on top etc.. I figure since all the other render engines always p1mp their car shaders, why not mantra :P

Peter.

Link to comment
Share on other sites

  • Replies 50
  • Created
  • Last Reply

Top Posters In This Topic

  • 1 month later...

Hi, I am trying to create my own car shader. Still work in progress.

I've posted my progress of making the car shader in my blog.

Anyone interested, feel free to check it out.. and if is possible,

please pin-point my mistake and help me to refine my shader.

[link]My blog

Car-paint WIP

post-1266-1160300178_thumb.jpg

Link to comment
Share on other sites

Hi, I am trying to create my own car shader. Still work in progress.

I've posted my progress of making the car shader in my blog.

Anyone interested, feel free to check it out.. and if is possible,

please pin-point my mistake and help me to refine my shader.

[link]My blog

Car-paint WIP

post-1266-1160300178_thumb.jpg

Good progress :)

I assume that the goal here is metallic paint like the Cars poster. The solid colour paints would be quite different and probably a bit simpler.

I'd suggest a couple of things:

  • I don't know if you've downloaded images and sketches and code examples of recreating metallic paints but if you haven't, go and do that. The actual equations in some papers might sometimes be too dense but they often point out what the effect is they're trying to achieve - and often they're things you haven't thought of. Generally the model for metallic paint is:
    - A metal base - with diffuse reflection and a tinted blinn specular
    - A coating of laquer issuing clear reflections - with a fresnel rolloff on intensity
    - Flecks of suspended metallic "mirrors" in the lacquer.
  • Personally I vote for a little more artist control with really good defaults and some good presets so thats just something to keep in mind when exposing controls.
  • Watch the naming of your Parameters - I see you have "Edge Colour" in there when you really mean Reflection colour, right? It would be easy to thing that you have a rolloff in your base colour instead. I don't know why you've set this to purple here - is it just a test?
  • Metals like this usually have two speculars - one wider, softer specular - probably blinn - multipied by the base color (as metals are; see Renderman Companion) and one crisp colourless one for the laquer coating. The raytraced/reflection-mapped reflection can often take care of this if you're lighting this with imaged based lighting (IBL) or in a fullly CG environment, but there is no harm in supporting a tight glossy or phong specular() too for those key lights.
  • Some car paints are treated to have this pearlized look in which the base color of the paint seems to change with viewing direction. This I find that you can get away with Mixing two base colours based on viewing direction (using the Edge Falloff VOP). Most of the time you can make these colors exactly the same, but sometimes you may want to slightly change the Base Colour (Edge) to emulate the pearlized metallic effect. You can also fake a bit of retro-reflectivity (issuing brighter reflections in the viewer direction) by using the same base colour on the edge as you do for the centre except for being just a little darker.
  • I'd definitely add support for EnvironmentMapping since most of the time you'll end up putting the car in an environment using an HDR light probe. One hint here is that the reflectlight() VEX function can accept more arguments that what are exposed in VOPs - and there is a very useful "environment" variadic argument you can add. You'll have to make a copy of the Reflected Light VOP and modifiy it and distribute it with your VOPnet OTL. Look here: http://www.sidefx.com/docs/content/vex/gui...ing_rayopts.xml
  • How do you intend to support the little metal flakes suspended in the laquer? There are some methods out there; only a few of which are particularly good at being able to sustain a good look at various ranges to the car. If you see a car across the street with this metallic finish, the metal flakes are invisible. Standing right next to it you see them clearly. How you make this both efficient and antialias/filter down correctly is a big thing.
  • I'd also considering adding support for some low-amplitude, low-frequency bump noise just to make the reflection directions imperfect. The intensity of the bump could be multiplied against a point-attribute too which you could set up so that bumping is most intense on the broader flatter areas of the car and less intense on ridges and edges where the metal is more reinforced and less likely to be warped.
  • I'd do tests with a more valid model (like the front section of a car) in a high-resolution HDR environment. This will make everything seem more familiar and be easier to judge. If you need help finding some test models and HDR, just write in here and someone must have some good resources to share.

Link to comment
Share on other sites

Good progress :)

I assume that the goal here is metallic paint like the Cars poster. The solid colour paints would be quite different and probably a bit simpler.

I'd suggest a couple of things:

  • I don't know if you've downloaded images and sketches and code examples of recreating metallic paints but if you haven't, go and do that. The actual equations in some papers might sometimes be too dense but they often point out what the effect is they're trying to achieve - and often they're things you haven't thought of. Generally the model for metallic paint is:
    - A metal base - with diffuse reflection and a tinted blinn specular
    - A coating of laquer issuing clear reflections - with a fresnel rolloff on intensity
    - Flecks of suspended metallic "mirrors" in the lacquer.
  • Personally I vote for a little more artist control with really good defaults and some good presets so thats just something to keep in mind when exposing controls.
  • Watch the naming of your Parameters - I see you have "Edge Colour" in there when you really mean Reflection colour, right? It would be easy to thing that you have a rolloff in your base colour instead. I don't know why you've set this to purple here - is it just a test?
  • Metals like this usually have two speculars - one wider, softer specular - probably blinn - multipied by the base color (as metals are; see Renderman Companion) and one crisp colourless one for the laquer coating. The raytraced/reflection-mapped reflection can often take care of this if you're lighting this with imaged based lighting (IBL) or in a fullly CG environment, but there is no harm in supporting a tight glossy or phong specular() too for those key lights.
  • Some car paints are treated to have this pearlized look in which the base color of the paint seems to change with viewing direction. This I find that you can get away with Mixing two base colours based on viewing direction (using the Edge Falloff VOP). Most of the time you can make these colors exactly the same, but sometimes you may want to slightly change the Base Colour (Edge) to emulate the pearlized metallic effect. You can also fake a bit of retro-reflectivity (issuing brighter reflections in the viewer direction) by using the same base colour on the edge as you do for the centre except for being just a little darker.
  • I'd definitely add support for EnvironmentMapping since most of the time you'll end up putting the car in an environment using an HDR light probe. One hint here is that the reflectlight() VEX function can accept more arguments that what are exposed in VOPs - and there is a very useful "environment" variadic argument you can add. You'll have to make a copy of the Reflected Light VOP and modifiy it and distribute it with your VOPnet OTL. Look here: <a href="http://www.sidefx.com/docs/content/vex/gui...ing_rayopts.xml" target="_blank">http://www.sidefx.com/docs/content/vex/gui...ing_rayopts.xml</a>
  • How do you intend to support the little metal flakes suspended in the laquer? There are some methods out there; only a few of which are particularly good at being able to sustain a good look at various ranges to the car. If you see a car across the street with this metallic finish, the metal flakes are invisible. Standing right next to it you see them clearly. How you make this both efficient and antialias/filter down correctly is a big thing.
  • I'd also considering adding support for some low-amplitude, low-frequency bump noise just to make the reflection directions imperfect. The intensity of the bump could be multiplied against a point-attribute too which you could set up so that bumping is most intense on the broader flatter areas of the car and less intense on ridges and edges where the metal is more reinforced and less likely to be warped.
  • I'd do tests with a more valid model (like the front section of a car) in a high-resolution HDR environment. This will make everything seem more familiar and be easier to judge. If you need help finding some test models and HDR, just write in here and someone must have some good resources to share.

First of all, thanks jason for his long written guide. very cool!

To jason reply, "Watch the naming of your Parameters - I see you have "Edge Colour" in there when you really mean Reflection colour, right? It would be easy to thing that you have a rolloff in your base colour instead. I don't know why you've set this to purple here - is it just a test?"

erm... My initial idea was wanted to create a streetracer cameleon paint shader based on a tutorial by danielbuck http://www.danielbuck.net/index.php?page=cameleon/cameleon

I have captured a couple of still frame from the fast and the furious dvd but those images is not hi-res enough to catch the surface detail. Right now you have seen the base color which is orange gradually falloff from the center to the edge and the purple color gradually falloff from the edge to the center. Oh yea.. i can get away with a rolloff in my base colour instead as you said, but i going to add 2 more different colors at the end to achieve the cameleon paint look. So it end up with 4 colors.(yes, it may not be technically correct but just for the sake of experimentation) I would take it away if the color blend doesn't work as i expected. Right now these two colors as u saw is a constant color, I haven't added any diffuse properties yet... because it takes time to read those code examples and documentation which i just downloaded.

And Jason, where I can download some good code examples? :)

Quote again:"Metals like this usually have two speculars - one wider, softer specular - probably blinn - multipied by the base color (as metals are; see Renderman Companion) and one crisp colourless one for the laquer coating. The raytraced/reflection-mapped reflection can often take care of this if you're lighting this with imaged based lighting (IBL) or in a fullly CG environment, but there is no harm in supporting a tight glossy or phong specular() too for those key lights."

Oh yea, Checking out renderman companion now. I guess it should be render faster by using enviroment() and reflect(), instead of using reflectlight() if I am lighting with IBL. Correct me if i am wrong. And also as u suggested in http://forums.odforce.net/index.php?showtopic=406&hl=, randomized the normal to calculate very tight specular.

This link no longer works http://www.sidefx.com/docs/content/vex/gui...ing_rayopts.xml 404 not found.

Quote:"How do you intend to support the little metal flakes suspended in the laquer? There are some methods out there; only a few of which are particularly good at being able to sustain a good look at various ranges to the car. If you see a car across the street with this metallic finish, the metal flakes are invisible. Standing right next to it you see them clearly. How you make this both efficient and antialias/filter down correctly is a big thing." "I'd also considering adding support for some low-amplitude, low-frequency bump noise just to make the reflection directions imperfect. The intensity of the bump could be multiplied against a point-attribute too which you could set up so that bumping is most intense on the broader flatter areas of the car and less intense on ridges and edges where the metal is more reinforced and less likely to be warped."

erm i am guessing that the low-amplitude and low frequency bump noise like "aanoise" to make the reflection directions imperfect can also be used for the diffuse of the flake by multiply the black n white bump map to the diffuse color. And the low frequency bump noise that u concerned is like simulates the roughness or jaggedness of surfaces on a microscopic level. The tiny details on a rough surface are what scatter the light in different directions to produce a glossy or diffuse light transmission, is like a cook-torrance model.(correct me if i am wrong). Microscopic roughness in a surfaces's structure can make a surface appear smooth while still diffusing reflected light.(statement

above referred to jeremy birn, digital lighting & rendering book) . I am going to cast reflection on those flakes too.

This image ripped from los angeles mental ray forum, the structure of car paint.

glossy_carpaint_light.jpg

And last, I m gonna setup a simple scene which constitute by a simple car model and a sky dome to do a proper test.

I would probably split out the car paint shader into different layers to speed up the render time since I am going to light it with image based lighting and also render out separate passes allow me to fix the imperfection of the shader in post.(well, is not a good solution, what to do since i just started to construct shader recently.)

Link to comment
Share on other sites

more wip. I almost redo the whole shader because this time i test render with different model and enviroment map, the result is different then the previous one.

I am working on the flakes now...... having a few problems like casting reflection on the flakes...

here is the test render. Lit with image based lighting(IBL).

post-1266-1160479081_thumb.jpgpost-1266-1160479128_thumb.jpg

And have this message half-way, please tell me what's the problem?post-1266-1160498448_thumb.jpg

Link to comment
Share on other sites

And have this message half-way, please tell me what's the problem?post-1266-1160498448_thumb.jpg

This message occurs so often that we begin to ignore it. I'm pretty sure it's a false message since it renders as expected anyway. It gets spit out for every object that it renders that it thinks it can't find a shader for, but renders with the shader merrily anyhow.

Just wait till you have a particle system with point instances and you get 50,000 of these messages in your render logfile! :ph34r::huh::lol:

Link to comment
Share on other sites

How's the shader coming, Jordan?

Almost there, just having an issue with the flakes. If i make each single flakes 1 by 1 pixel big, it still looks unrealistic at the size of 640x480. The maximum noise that i can get from aanoise is approx. 1by1 pixel. Do u have any idea? Should i slightly exaggerate the size of the flakes? I got nothing too show right now, the render is looks funny because of the size of the flakes.

:) any idea to generate good flakes?

Link to comment
Share on other sites

:) any idea to generate good flakes?

I've had good success using point clouds in cases like the car-paint flakes (I know; very non-procedural of me :P ) -- you can tie the search radius to the filter size estimation for antialiasing, making it pretty stable and cheap even for high frequencies (which is not at all easy to get if you plan to filter over an area of wildly varying normals procedurally).

Link to comment
Share on other sites

I've had good success using point clouds in cases like the car-paint flakes (I know; very non-procedural of me :P ) -- you can tie the search radius to the filter size estimation for antialiasing, making it pretty stable and cheap even for high frequencies (which is not at all easy to get if you plan to filter over an area of wildly varying normals procedurally).

Hi Mario, do u know where to get some documentation on how to generate point cloud? By the way, I'm going thru your SSS diaries to get some clue. :rolleyes: I must complete the shader, some more hints will be much appreciated. :)

Link to comment
Share on other sites

"I've had good success using point clouds in cases like the car-paint flakes"

Ok, guys, it looks like I am missing something here, somehing fundamental. What is actually ment by filtering here? We've got aanoise in VOPs - which is filtered by default, we've got a bunch of filtering functions in COPs, which is, as Mario assumed, will just blur the image... In Renderman there's a filterednoise(P, filtersize) function, but is there anything like that in VEX? Or does it assume we have to create a custom function, maybe import some library from the WEB and use it, when generating the noise for the surface? Or is filtering somehow related to Mantra ROP filtersize/supersample and we can control it with our shader?

I am kind of missing the main idea of the process. Can somebody shed some light on this?

Thanks.

Link to comment
Share on other sites

Hi guys,

I'm a little short on time these days, but here's some stuff that will hopefully get you started...

Hi Mario, do u know where to get some documentation on how to generate point cloud? By the way, I'm going thru your SSS diaries to get some clue. :rolleyes: I must complete the shader, some more hints will be much appreciated. :)

There were some nice usage examples in the old VEX html pages but they don't seem to have made it to the new on-line help. I would suggest starting by looking at all the pc* functions (pcopen, pcclose, pcunshaded, etc) in the on-line help. But here's a copy of the examples in the pointcloud section of the old docs:

The following functions act on point cloud textures. 
Point cloud textures may either be specified as a tiled block file (tbf) or as a 
geometry file.

A point cloud texture is simply a collection of points in space. Each point has several 
channels associated with the texture. For example, the texture might have a P channel to 
indicate the position of the point, or a temperature to indicate the temperature at the 
point.

When a geometry file is used as a source for the point cloud, each point attribute is 
available as a read-only channel.

It is also possible to create temporary read-write channels. These channels allow 
information to be stored in the point cloud and re-used by later computations. The 
information in these temporary channels is maintained while the texture is still 
referenced by any VEX function. That is, if two VEX functions reference the same texture,
any temporary channels will be shared between the two functions. If the texture is flushed 
from the texture cache, then all temporary channels will also be flushed and information 
will need to be re-computed.

Given a query point in space, the VEX functions provided allow the user to find the 
closest points and operate on them.

An example of how a point cloud texture might be used is in a simple occlusion map 
caching shader. 


surface store_occlusion() { 
   int handle; 
   vector qP, qN; 
   vector pp, nn; 
   vector occ; 
   float sum; 

   qP = wo_space(P); // Transform into object space 
   qN = wo_nspace(N); 
   handle = pcopen(map, "P", qP, "N", qN, .5, 50); 

   // Iterate over all of the points which don't have an "occlusion" 
   // value stored. 
   while (pcunshaded(handle, "occlusion")) { 
      pcimport(handle, "P", pp); // Find the point's P value 
      pcimport(handle, "N", nn); // Find the point's N value 
      pp = ow_space(pp); 
      nn = normalize(frontface(ow_nspace(nn), I)); 
      // Compute occlusion at the map point 
      occ = occlusion(pp, nn, "background", {1,1,1}); 
      // Store the occlusion value in the map. 
      pxexport(handle, "occlusion", occ); 
   } 
   Cf = 0; 
   sum = 0; 
   while (pciterate(handle)) { 
      pcimport(handle, "occlusion", occ); 
      Cf += occ; 
      sum++; 
   } 
   Cf += 1/sum; 
}

Another example, might be a simple image re-construction filter. This filter takes a 
point cloud and filters the points to re-construct an image:

cop recon(string map=""; float z=0) { 
   int handle; 
   vector pp, clr; 
   pp = set(X, Y, z); 
   handle = pcopen(map, "P", pp, .1, 10); 
   clr = pcfilter(handle, "Cd"); 
   assign(R, G, B, clr); 
}

Hope that helps a bit.

Ok, guys, it looks like I am missing something here, somehing fundamental. What is actually ment by filtering here? We've got aanoise in VOPs - which is filtered by default, we've got a bunch of filtering functions in COPs, which is, as Mario assumed, will just blur the image... <snip>

I am kind of missing the main idea of the process. Can somebody shed some light on this?

In this context, "filtering" is used to denote the process of choosing a "representative" value for a whole group or set of values. In many cases, a good enough representative value could simply be the average (a.k.a: a "box" filter).

When shading a point on a surface, P is the coordinate of one corner of a quadrilateral. This corner is a point and so has no area, but the quad itself (of which P is a vertex) *does* have an area -- it's a "chunk" of the surface, not just a dimensionless point.

Within the area of the quad being shaded, your procedural texture's output (like noise) may vary anywhere from very little to a great deal, depending on the frequency of the noise and/or the size of the quad. If if *does* happen to vary a great deal, then you're faced with having to choose a single representative value for that whole mess of noise values in the quad (remember your shader can only output a *single* color for the whole quad). Mantra (and PRMan) can give you an estimate of the area being shaded (the area of the quad) via the area() function -- e.g: area(P) returns an estimate of the area being shaded at P. Filtering (or averaging if you like) the values of the procedural texture over the whole area is generally left up to the shader writer.

I'm pretty sure this is all explained in much greater detail in the "Advanced Renderman" book. Have a look there.

I don't recall a "filterednoise()" function in RSL, but I haven't really kept up since version 12. In any case, the aanoise VOP (not a VEX function) is a fractal noise (not plain Perlin) and has an implicit filter size of 1. You could easily add a filter_size parameter with a small bit of coding, but before getting into all that, what is it exactly that you're trying to filter here? -- or rather: what aspect of the shader is aliasing/flickering?

If it's the flakes, then how are the flakes generated? If aanoise is being used to generate them, then which of them is aliasing: the underlying aanoise?, or the flakes which are based on it? If the former, then aanoise is either failing to filter itself properly, or you're pushing it too hard in some way. If the latter, then your flake code is at fault. If you suspect the flake code, then how are you deriving the glints: specular reflections on random directions? If so, then how are you antialiasing them? Are you averaging over the collection of samples? Are you sure that the random sequence is always the same for a given P? Are all the bombing locations and directions always the same in the neighborhood of a given P? Are you generating proportionately more directions/locations for bigger areas than for smaller ones?... this can go on, and on, and on...

If this filtering business starts to feel a little difficult, it's because, well, it ain't easy... or at least not for me anyway.

Good luck!

Link to comment
Share on other sites

Mario, thanks for your tip. Gotta try your way soon.

Here is my attempt, getting there, but got render artifact which generated by aanoise.

If someone know how to solve this problem, I would buy you a beer. ;)

Here is the render.post-1266-1161253743_thumb.jpg

Here is my vopnet. I've tried to pipe both the global variable "P" and rest position into the "pos" input of aanoise... but i still get those little white squares. May be should i try UV Space Change? post-1266-1161254280_thumb.jpg

Link to comment
Share on other sites

I'm not sure of that, maybe I miss your conception here, but after seeing your render I would say that your aproach of rolloff/fresnel/reflections miss the point.

I would consider to use fresnel function to control reflection amount but not to control its color. If i'm not wrong your car got white edges thanks to fresnel, and in the same time reflection remains the same despite of incidende angle. I think there is nothing like that in car paint.

Maybe you should render car with different color and HDRI reflection for better proof of concept. It's hard to see light/car interaction on black ;).

As to noise/flakes/fillter issues isn't it the reason of not seeing around so many good car shaders? Accurate and effective way of sampling dotty surface is one of most challeging task in CGI. Isn't it? Hey, Mario! Isn't it a similar problem as with anisotrophic surfaces in mantra?

I will try to find my old aproach of this and post it.

cheers,

Sy.

Link to comment
Share on other sites

We've got aanoise in VOPs - which is filtered by default, we've got a bunch of filtering functions in COPs, which is, as Mario assumed, will just blur the image... In Renderman there's a filterednoise(P, filtersize) function, but is there anything like that in VEX?

Just look at the source of your VOPnet when you have an aanoise VOP. Notice how it includes voplib.h and you can recursively look at the include files for how the aanoise VOP is done.

Link to comment
Share on other sites

Here is my attempt, getting there, but got render artifact which generated by aanoise.

A couple of quick comments:

1. Those little white squares look very much like NaN's ("not a number") to me; and I really doubt that aanoise is generating them. Run the vex profiler and enable the check for NaN's with "mantra -V P"; see if it reports any.

2. If there are NaN's, then start stripping the shader layer by layer -- look for potential division-by-zero, exponentials with wild parameters, uninitialized variables, roots of negative numbers (though these may be checked internally), etc. Repeat until all NaN's are gone, but leave the profiler up because some of these may only show up at certain angles -- and if that is the case, then I would very much suspect your reflectance code (BRDF), or any other angle-dependent portion of the shader.

3. NDC? Am I seeing that right?: are you generating noise in NDC space? Why? -- this will lock the noise to the image plane... good for generating grain I guess, but maybe not what you intended (?).

I would consider to use fresnel function to control reflection amount but not to control its color.

I'm fairly certain that there *is* a color shift implicit in fresnel (related to wavelengths). The overall result is that reflections at grazing angles have the colour of the source (the thing being reflected), whereas normal reflections (along the surface normal) are tinted by the surface color. See "Computer Graphics" by Foley & van Dam -- the details are explained somewhere in there I think.

As to noise/flakes/fillter issues isn't it the reason of not seeing around so many good car shaders?

Hehehe... yes, well... still images can, and often do, look breathtakingly awesome, don't they?

Too bad that in real life the blasted camera/car has to go and ruin everything by moving... :P

I think it's no exaggeration to say that about 50% of the effort of writing shaders is spent dealing with this filtering business.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...