Time to revive this topic since I’m once again trying to convert my stuff for mental ray. Basicly the mental ray part would be pretty easy at least for noise and wood. However all three questions I had in the first post are still unanswered.
How do I handle the UVW coodinate rollout options?
Sure the 3dsmaxshaders.mi defines such shaders as max_base_UVGenerator, max_UVCoordinate and max_base_XYZGenerator. However how I’m supposed to use them?
This also goes for the output rollout options.
What I want is lets say Autodesks MENTAL RAY shader of maxs noise. That would explain everything to me. It would also explain how to evaluate submaps and stuff a lot better than existing mental ray shaders, since max doesn’t send them to mr as miColors if I’m reading the mi files correctly.
So does anybody have their hands on source code of the mental ray versions any of the maxs orignal procedurals like Noise, Checker, Marble, Cellular etc. etc.?
Hi
the source code of original mental ray shader find you here: ftp://ftp.mentalimages.com/data/pub/shaders/ This library have include the Source code of turbolenz, wave, polka, checker etc…
mfg
hot chip
The problems I’m having aren’t on mental rays side but between max and mental ray.
I already have my shader converted to mr:
The problem is how to handle UVW and Output stuff. Also I’d like to know exactly how should I port submaps over.
Unfortunately this is totally undocumented.
In both cases, the max guys decided to implement these as subshaders, passed as shader parameters. Basically, you call these with mi_call_shader_x from within your shader.
I’m not 100% sure it can be implemented the same way as for the built in shaders in a custom shader, because the built in one uses a lot of semaphoring behind the scenes sending various package of info along with rays in a very complicated way, and that information isn’t public, as far as I know (you’d have to ask Autodesk to open that up). It may just automatically work anyway, but I havn’t actually tried that myself personally. If so, you would get both your UVGenerator and your Output rollout as submaps, which you then execute with mi_call_shader_x(), and the former will return your UV, the latter will modify the color you pass into it.
However, the UV and XYZ Generators are also available as a normal mental ray shader that returns the UV, so those can be used (although you would need to implement a ::TranslateParameters on your shader to copy the values over).
No, that part is actually documented.
And what you need to do depends on how you need to use it; if you only want to call a submaps default implementation with the current state, simply having it as a normal color parameter is the best way.
I.e. you don’t NEED
- a color
- a boolean for if it is on
- a ‘shader’ style paramter pointing to the map
…rather, you only need - a color, which is connected either to the fixed value, or the subshader
However, sometimes you want to do “magic things” before calling the shader (like modifying the state, the texture coordinates, etc, like your “distorsion” shader seems to do).
Then indeed you DO need to modify the coordinates prior to calling the subshader (basically write to state->tex_list[n]). If so, you need the shader passed as an actual parameter of type “shader”, and then explicitly call the shader with mi_call_shader_x after modifying the appropriate state members.
/Z
Hi Jerry,
if you use the automatic mr translation in your Max plugin to call the mental ray shader you are now writing, Max should automatically handle all of the other rollouts in your plugin (UV stuff, output, etc). So you shouldn’t need to worry about the Max specific stuff, you just need to port the textures to a mental ray shader.
Dave
Okey, I guess I’ll just try to port it and see what happens. I’m having some problems with submaps since I have to use different methods than mental ray shaders usually do.
In *.mi I have shader declaration:
color "color1",
color "color2",
color texture "colormap1",
color texture "colormap2",
boolean "colmapon1",
boolean "colmapon2",
In the C++ struct
miColor color1;
miColor color2;
miTag colormap1; // color texture
miTag colormap2; // color texture
miBoolean colmapon1;
miBoolean colmapon2;
And the evaluation
miColor* c0;
if (*mi_eval_boolean(¶ms->colmapon1)) {
c0 = mi_eval_color(¶ms->colormap1);
if (!c0) mi_eval_color(¶ms->color1);
} else {
c0 = mi_eval_color(¶ms->color1);
}
miColor* c1;
if (*mi_eval_boolean(¶ms->colmapon2)) {
c1 = mi_eval_color(¶ms->colormap2);
if (!c1) mi_eval_color(¶ms->color2);
} else {
c1 = mi_eval_color(¶ms->color2);
}
However this doesn’t work and it always returns black when maps are enabled. Looks like mi_eval_color cannot be used to evaluate miTags. So how then should I evaluate them? I tried mi_call_shader() and mi_lookup_color_texture() but both crash when rendering.
Let Max do the work… Don’t call the submaps from your shader, let Max pass them to the shader as ‘shader connections’.
Take a look at the two-sided shader in the SDK (howto/mentalray/mrSampleShaders), and you can see how the submaps get passed to the shader.
Dave
Ah okey, so in the mental ray shader I only have single miColor as input parameter and max evaluates the color, checkbox and map to see what color it gives the map? Yeah that works in this case.
However I have some cases where I need to modify the point where sub texture is evaluated (distorition/tile) so I need to get mi_lookup_color_texture() working, I think?
This always crashes max when used with the variables in my previous post.
mi_lookup_color_texture(c0, state, *mi_eval_tag(¶ms->colormap1), &state->point);
I’m not quite sure what I’m doing wrong here?
Oh and I also need to evaluate vector maps for the distortion direction which I dont think the automatic translation does either?
You are not allocating storage for the value.
You do
miColor *c0;
mi_lookup_color_texture(c0, …);
This will crash because c0 is a pointer, not pointing to anywhere.
Correct way is:
miColor c0;
mi_lookup_color_texture(&c0, …);
Now c0 is a variable, and you pass it’s address to mi_lookup_color_texture().
I suggest you read up a bit on pointers in C. But don’t be ashamed, I see this as probably the most common programming mistake when starting out with mental ray shaders. Our coding samples (like sources of the base library) doesn’t really help because it tries to be “clever” and use pointer variables like this:
miColor *c0 = mi_eval_color(&…);
This will evaluate the color, and copy the address of the result to the pointer variable c0.
…which while this works and actually saves a small memory copy of 16 bytes, it’s a tad dangerous because c0 will really point straight into your parameter structure… AND… this code leads people to think they can treat colors as pointers. A safer way is
miColor c0 = *mi_eval_color(&…);
This will evaluate the color and copy the resulting value to the color variable c0. Much safer, and you can now modify the value of c0 without risks of mangling your original parameter structure.
/Z
About the vector maps, can’t you just pass the color from your plugin to your shader and do the vector conversion there? (I’m assuming you’re using a texmap in Max to control the vectors).
For the mi_lookup_color_texture() problem, have you taken a look at the displace_texture code at http://www.writingshaders.com/ ? Maybe you could see if that works, and then adapt it to your needs.
Dave
That’s exactly what I wanted to say :applause:
I’m glad that someone who knows what they’re talking about has joined the conversation! Getting Max shaders up and running in mental ray seems to be one of the worst documented things in the SDK.
Dave
Okey now things are starting to clear up! Great! I’ve gotta try those as soon as I get home.
Yeah I’ve always hated pointers and those nasty little things don’t seem to like me either.
Thanks for all your efforts! If I somehow manage to complete this task I’ll release the source code which should make it easier for other people to convert existing max maps to mental ray.