PDA

View Full Version : textureMap (color by speed)


JokerMartini
06-07-2012, 11:43 PM
Does anyone know how to write shaders in max?
It would be awesome to have a texture map that would color an entire object based on the supplied values and its transform speed.

the material would have 4 controls. see image.
http://forums.cgsociety.org/attachment.php?attachmentid=167932&stc=1

Would this be possible on a shader level?
Think of it as the motion blur. The slower the object is the moving the more it appears black versus the more white it appears when its moving fast, blending inbetween. Where as motionblur, blurs an object more the faster its moving and less blur the slower its moving.

Raytracer05
06-08-2012, 12:43 PM
There is already textureMap Conversion_Float_To_Color. You could try putting this into the diffuse slot of a standard material and use a float_script controller on the scalar subanim of the map to calculate the speed of your object.

BTW I haven't tried this :p

Raytracer05
06-08-2012, 01:55 PM
Just tried it and it works!
At bit crude but...(
$.material = standard()
$.material.diffuseMap = Conversion_Float_To_Color()
objSpeed = float_script()
objSpeed.addNode "node" $
objSpeed.SetExpression "(distance $.pos (at time (currentTime-1) ($.pos)))*(frameRate*0.00001)"
$.material.diffuseMap.scalar.controller = objSpeed
)
My scene was in mm so you'll have to adjust the '0.00001' so value the expression returns is between 0 and 1.

Raytracer05
06-08-2012, 02:45 PM
I was over-complicating things with the Conversion_Float_To_Color map. Just add a point3_script controller to the diffuse colour.(
$.material = standard()
objSpeed = point3_script()
objSpeed.addNode "node" $
objSpeed.SetExpression "rgb = (distance node.pos (at time (currentTime-1) (node.pos)))*(frameRate*0.00001)\n color rgb rgb rgb"
$.material.diffuse.controller = objSpeed
)

JokerMartini
06-08-2012, 05:52 PM
Dan, Nicely done. This is exactly what I was after. I ended up doing a controller script lastnight and it was way more complex than it needed to be. You've condensed and simplified it quite a bit.

Thanks.

Raytracer05
06-08-2012, 06:01 PM
Thanks, mine's very crude though, no error checking and there's nothing to stopping the rgb values being greater than 1. Hope some of it helps anyway.

PiXeL_MoNKeY
06-08-2012, 06:36 PM
NOTE: that map is a metaSL map and will only work in metaSL compatible renderers.

To get access to all metaSL nodes directly in 3ds max material editor see this (http://forums.cgsociety.org/showthread.php?p=7338989) post.

denisT
06-08-2012, 07:05 PM
I was over-complicating things with the Conversion_Float_To_Color map. Just add a point3_script controller to the diffuse colour.(
$.material = standard()
objSpeed = point3_script()
objSpeed.addNode "node" $
objSpeed.SetExpression "rgb = (distance node.pos (at time (currentTime-1) (node.pos)))*(frameRate*0.00001)\n color rgb rgb rgb"
$.material.diffuse.controller = objSpeed
)

nice idea!
but it's a bad practice to use at time context in script or expression controllers... another thing is we don't need any frame rate... we only need to specify the maximum speed and use it for speed normalization.
that's how i see it:

(
delete objects
node = sphere name:"ball" isselected:on
animate on
(
at time 15 node.position = [100,0,0]
at time 30 node.position = [500,0,0]
)

mat = standard name:"Speed Material"
ex = mat.diffuse.controller = point3_expression()
ex.addscalarconstant "MAX" 30.0
ex.addvectornode "P0" node offset:0
ex.addvectornode "P1" node offset:1
ex.setexpression "(min(length(P1-P0),MAX))/MAX*[1,1,1]"
node.mat = mat
)


we can feed the expression controller with maximum speed value using for example CA parameter (controller)...
in this case we have to use AddScalarTarget instead of AddScalarConstant.

JokerMartini
06-08-2012, 08:18 PM
Well that becomes even more condensed in code. That seems like it will work really well. The way your calculating the speed of the object with the max constraint is really interesting. I like the approach and it sure will be helpful. It's always something new that your showing/teaching me.
thanks Denis.

denisT
06-08-2012, 09:27 PM
here is the same but using Script controller and the color changes in HUE space from BLUE to RED:

(
delete objects
node = sphere name:"ball" isselected:on
animate on
(
at time 15 node.position = [100,0,0]
at time 30 node.position = [500,0,0]
)

mat = standard name:"Speed Material"
ex = mat.diffuse.controller = point3_script()
ex.addconstant "MAX" 30.0
ex.addtarget "P0" node.pos.controller offset:0
ex.addtarget "P1" node.pos.controller offset:1

scr = ""
scr += "v = (amin (distance P0 P1) MAX)/MAX\n"
scr += "c = red\n"
scr += "c.h = (1 - v)*170\n"
scr += "c as point4\n"

ex.setexpression scr
node.mat = mat
)

Raytracer05
06-08-2012, 09:39 PM
nice idea!
but it's a bad practice to use at time context in script or expression controllers... another thing is we don't need any frame rate... we only need to specify the maximum speed and use it for speed normalization.
that's how i see it:

(
delete objects
node = sphere name:"ball" isselected:on
animate on
(
at time 15 node.position = [100,0,0]
at time 30 node.position = [500,0,0]
)

mat = standard name:"Speed Material"
ex = mat.diffuse.controller = point3_expression()
ex.addscalarconstant "MAX" 30.0
ex.addvectornode "P0" node offset:0
ex.addvectornode "P1" node offset:1
ex.setexpression "(min(length(P1-P0),MAX))/MAX*[1,1,1]"
node.mat = mat
)


we can feed the expression controller with maximum speed value using for example CA parameter (controller)...
in this case we have to use AddScalarTarget instead of AddScalarConstant.
Yes thanks Denis, that's very informative and a much more elegant solution for getting the node's speed using addVectorNode.

You're right about not needing frame rate, I thought it might be useful for calculating the speed in real units like meters or inches per second.

Also, why is it bad practice to use 'at time' inside a controller's expression?

Raytracer05
06-08-2012, 09:51 PM
NOTE: that map is a metaSL map and will only work in metaSL compatible renderers.

To get access to all metaSL nodes directly in 3ds max material editor see this (http://forums.cgsociety.org/showthread.php?p=7338989) post.Thanks for pointing that out, I guess that's why it would only render in MR.

I was a bit uneasy about using the map but I'd had the idea of a float_script and got it into my head that I needed a map that would accept a float value and turn it into a colour.

JokerMartini
06-08-2012, 10:07 PM
this is very cool. It seems like a super useful script.
It would be cool to put this on a vertex color level so then a user could run this on verts being changed on a morpher and render to texture out a blend map for texture controlling.
Not sure if that is possible but just a thought. It would be more dynamic.

denisT
06-08-2012, 10:08 PM
Also, why is it bad practice to use 'at time' inside a controller's expression?
to get any value of specific controller at specific time the system has to evaluate this controller...
using at time context you send whole system in specified time... so for the scripted controller it looks like:
# start evaluating at time A
# get all params used in the expression at time A
# jump at time B
# get all params used in the expression at time B
# return at time A
# evaluate

if you are using the time offset system for your parameters it works this way:
# start evaluating at time A
# get all params used in the expression at time A
# get all params used in the expression at time B
# evaluate

i think that the time offset system was specially designed to do all calculations before evaluation...

JokerMartini
06-08-2012, 10:11 PM
This would be super useful for people blending between materials based on movement. Just tie it to a blend material.
Could possibly through in a few more lines of code to make it so the blend from black to white only happens once and it stays white then.

denisT
06-08-2012, 10:29 PM
to get any value of specific controller at specific time the system has to evaluate this controller... using at time context you send whole system in specified time...
...
i think that the time offset system was specially designed to do all calculations before evaluation...

here is a sample that kinda illustrates the difference:

delete objects

for k=1 to 4 do biped.createNew (units.decodevalue "2m") 0 [0,0,0]
nodes = for k=1 to 100 collect objects[k]

t1 = timestamp()
for t=1 to 100 do at time t for node in nodes do node.transform
format "v1 > time:%\n" (timestamp() - t1)

t1 = timestamp()
for node in nodes do for t=1 to 100 do at time t node.transform
format "v2 > time:%\n" (timestamp() - t1)


in V1 you are not shifting the system back and forth (actually forth and back :)) in time, and it works faster than V2 where we return back in time for every node...
believe me for really animated scenes the difference is big.

JokerMartini
06-08-2012, 10:35 PM
That is crazy how much difference there is. I wouldn't expect it to be that drastic of a difference.

denisT
06-09-2012, 12:50 AM
That is crazy how much difference there is. I wouldn't expect it to be that drastic of a difference.
that's crazy how two looking the same scripts work different. ;)

JokerMartini
06-09-2012, 02:28 AM
What would be a good solution for a script controller? The property that I'm trying to map doesn't allow for me to put a point3 script on it?
Only a script expression?

For this setup I can use the "create Variable" and pick a node in the scene which that is the node getting speed tested. Base on its speed change if its static it would return a value of 0 and say for example its moving at a speed of 20 then it returns a value of 1.0 and then blends anything in between.
Since we can't use at time t? whats the solution for this?

Raytracer05
06-11-2012, 09:12 AM
here is a sample that kinda illustrates the difference:

delete objects

for k=1 to 4 do biped.createNew (units.decodevalue "2m") 0 [0,0,0]
nodes = for k=1 to 100 collect objects[k]

t1 = timestamp()
for t=1 to 100 do at time t for node in nodes do node.transform
format "v1 > time:%\n" (timestamp() - t1)

t1 = timestamp()
for node in nodes do for t=1 to 100 do at time t node.transform
format "v2 > time:%\n" (timestamp() - t1)


in V1 you are not shifting the system back and forth (actually forth and back :)) in time, and it works faster than V2 where we return back in time for every node...
believe me for really animated scenes the difference is big.Well there is a very big difference in this small scene.

Thanks for posting this, I read it over the weekend but without access to Max I couldn't test it.

Raytracer05
06-11-2012, 09:27 AM
this is very cool. It seems like a super useful script.
It would be cool to put this on a vertex color level so then a user could run this on verts being changed on a morpher and render to texture out a blend map for texture controlling.
Not sure if that is possible but just a thought. It would be more dynamic.This would be super useful for people blending between materials based on movement. Just tie it to a blend material.
Could possibly through in a few more lines of code to make it so the blend from black to white only happens once and it stays white then.I was thinking the same. Maybe extending the blend material, that way it could be quite flexible and take two colours or maps to blend between. Although scripted materials can be a PITA as they have to be installed on any pc that is going to open your scene including render nodes.

CGTalk Moderation
06-11-2012, 09:27 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.