To start on this project I have started with understanding how
to get information from one shader to other. This is called shader
to shader messenging. This allows us to collect information from
one shader and pass this on to another shader. Using "output
varying float" allows for whatever float information to be
parsed out. In these shaders we use a number of different functions
to get the information we need. Starting with the suface shader
of the object we want or don't want to reflect, we have to look
at a number of things that this shader must do: (these points
are reiterated on Malcom Kesson's website)
1. Use the RSL attribute() function to get the name of the object
to which the shader has been applied.
2. Decide if the shader has been hit by a gather ray that originated
from the the emitting shader.
3. If the shader has been hit by a gather ray, assign a value
to a special variable that will be gathered by the shader that
emitted the ray.
4. if hit by any other gather rays that have been emitted from
other shaders or objects (i.e. camera, lights, specular...) colorize
the surface in the normal way.
Once we have this information we are able to move on to the emitting
shader. And again, there are a number of things that the shader
must be able to do: ( once again, these points are reiterated
on Malcom Kesson's website)
1. Use the RSL gather() function to emit the rays.
2. Name therays so that they can be identified by the object shader
3. For every gather ray that strikes a surface check to see if
we have been able to gather the special variable known only to
the shader above
4. If we've gathered the variable as a result of a ray hit simply
ignore the hit - effectively ignoring the surface that was struck.
Essentially with all of this we are able to get a shader that
will ignore the object that the first shader is applied to as
long as the name is equal to the name we have set within the shader
to match() against. In these images, the first set of spheres
are named at the object level to "reflect". The second,
the sphere to the right is set to "no_reflect" and the
left set still to reflect. no_reflect is what the shader is matching
to which in turn "tells" the emitting shader not to
reflect the object.
object name = reflect for both right and left spheres
= no_reflect for right sphere reflect for left sphere
Since this is a WIP (Work In Progress), I will be attempting
to get the object to cast a reflection and not be visible to the
camera. Also I will be work on using "maxdist" within
gather() to collect object distances which in turn can be used
to change reflectivity among other things.
click here for
the object shader code
click here for the
emitter shader code
By using a clever idea of having a surface shader that "senses"
which emitted ray (i.e. camera, specular...) we are able to disclude
the idea of having a shader that gathers information from one
shader to figure out if it should or should not reflect the object.
With using an If test within the shader we are able to tell the
object to be or not to be visible depending on the ray which strikes
the object. With this in hand I was able to get to a point, using
Malcolm's shader as a base, to get the idea of seen by the camera
and not reflecting and vise versa. By controlling the opacity
(Oi) over time I was able to get the effect of the unreflected
and unseen object slow appearing. Below shows a still image and
an animation of this shader.
Moving on to the distance verses reflectivity, This idea seemed
to be simple but became difficult to solve. By employing a smoothstep()
based on the length(I) and plugging these values in for the Oi,
I was able to get a reflection that becomes fully opaque as the
object moves away from a relective surface. This is also more
believeable when I take the color trace(P, I) and mix it with
the surface color or Cs. the trace is allowing for the information
from the surrounding environment to be included in the Ci of the
reflection. If this isn't used then you get a situation where
the ray from the mirror surface is ignored and black is used in
place of the environment color. This movie shows visually what
is happening as the object moves away from the mirrored surface.
Adjusting the smoothstep() minimum and maximum values will make
the ojbect "appear" quicker or slower.
With this working, it seemed logical that if you take the inverse
of smoothstep that you would get the inverse of the visual, disappear
as the object moves away from the mirrored surface. But this is
where I ran into a problem. It seemed that when you took the inverse
that the trace() was only tracing to the inside of the top part
of the surface and in this case I was only returning black on
the mix. Working with James Van Allen, we were able to discern
that if we do an If test stating that we only want to deal with
any face point foward or, n == nf. Any other face is ignored or
the Oi is set to 0. By using this idea we are able to only calculate
the Ci for the reflection with the front of the object and allow
the trace() to trace out to the environment. This took a while
to get our heads around, but it seemed to be a good solution.
Below is a movie that shows this in action.
The next step in this process would be to incorporate the two
shaders into one and give the artist the ability to choose which
invisibility they would like the object to produce. I would like
to take this to another level and see if there is a way of controlling
other things within the scene (i.e. displacement, color change...).
Eventhough this is a straight forward project, there seems to
be some underlying ideas for this that could be explored.
click here for the visibility
click here for the visibility