[Sidefx-houdini-list] Hidden interior shader

Andy Nicholas andy at andynicholas.com
Mon Jan 21 13:04:12 EST 2008


Hi Zhang,
Thanks for the suggestion. Yep, I'm using metaballs where I can, but some
of the geometry has to be made up of plain ol polygons. I need to be able
to render metaballs intersecting with geometry but without needing to
worry about what happens inside.

I'd try a cookie SOP but it's not always the most reliable. Besides, a
shader would seem to be a more elegant solution. Maybe writing a shader
for Mental Ray would be a better way to go, but that would be a major
pipeline change at the moment and I can't help feeling that there must be
some way of doing this in Mantra.

Cheers

Andy



> how about use implicit surface generated by metaball for example, you
> don't
> need to worry about the boundary detection in this case.
>
> On Jan 20, 2008 12:39 PM, Andy Nicholas <andy at andynicholas.com> wrote:
>
>> Hi guys,
>>
>> First off, apologies for such a long and involved post, but this has
>> been
>> driving me nuts for a couple of days now.
>>
>> I'm trying to figure out how to create a shader to render numerous
>> transparent objects made of liquid so that I don't have to worry when
>> surfaces intersect each other. I.e. that the shader automatically
>> ignores
>> interior surfaces and only renders the first and last faces (which are
>> the
>> ones that represent the boundary between air and water). So, for
>> example,
>> if
>> you have a small sphere that sits totally enclosed within a larger
>> sphere,
>> then you won't see the smaller sphere at all. It's kind of like a
>> boolean
>> union operation, but using a shader to achieve the effect.
>>
>>
>> Ideally, I'd like to be able to query the ray history to figure out
>> whether
>> I should render the current surface or not, but as far as I know that's
>> not
>> possible in VEX? Alternatively, if I could store some sort of user data
>> in
>> the current state that shaders further down the line could access, it
>> would
>> have the same effect. But again, I don't know if that's possible.
>>
>>
>> So, having given up on that, I opted for an approach that executes a
>> series
>> of raycasts after an eye ray hits the surface. Basically it fires a
>> sequential line of rays (using rayhittest()) until it exits the liquid,
>> which it figures out by keeping a counter of how many times it has
>> entered
>> and exited a surface (based on checking the normal). When it finally
>> exits,
>> it calls trace() that will, in theory, give me the final color of
>> whatever
>> is behind the surface. I could then combine this with the result of
>> shading
>> the front and back faces.
>>
>> The problem is that trace() doesn't seem to give me anything meaningful.
>> In
>> fact it appears to call the shader again and return a negative result
>> for
>> the first rayhittest() intersection test. Is there some catch or gotcha
>> with
>> using trace() inside a surface shader that I don't know about?
>>
>> Anyway, in case it helps, the VEX code is pasted in below (with comments
>> that explain what's going on). There's no refraction or reflection built
>> in
>> yet, as I wanted to get the basics working before I took it to the next
>> stage.
>>
>> Any ideas, suggestions (or even RTFM's) are gratefully received.
>>
>> Thanks a lot :-)
>>
>> Andy
>>
>>
>>
>> - - - -
>>
>> I've just got this code inside a VEX Inline Code operator with P and I
>> being
>> supplied to it from a Global Variables node. The outputs to the VEX
>> Inline
>> Code are just called "out_col" (Vector), "out_opacity" (Vector), and
>> "out_alpha" (float) and are plugged straight into the output variables.
>> I've
>> set the output color to various things along the way for debug purposes.
>>
>>
>>
>> //Set some defaults
>> $out_col={0,0,0};
>> $out_opacity={1,1,1};
>> $out_alpha=1;
>>
>> vector $phit={0,0,0};
>> vector $nhit={0,0,0};
>> vector $curpos={0,0,0};
>> vector $raydist=$I;
>> float $maxdist=1000;
>>
>> //We need to give rayhittest a maximum length as well as direction to
>> ray
>> cast
>> $raydist = $maxdist * normalize($raydist);
>>
>>
>> float $dist=0.0;
>> float $dotp=0.0;
>>
>> //We have just hit the first surface so we set this to -1.
>> //When it gets to zero again, we know we have just left the opposing
>> surface
>> int $surfcount=-1;
>>
>> //Keep a count to make sure we do not infinitely loop
>> int $count=0;
>>
>> $curpos=$P;
>>
>> while($surfcount!=0 && $count<50)
>> {
>>    $dist = rayhittest($curpos,$raydist,$phit,$nhit,0.0001);
>>
>>    if($dist<0.0)
>>    {
>>        //Nothing intersected
>>        $out_col={1,0,0};
>>        break;
>>    }
>>    else
>>    {
>>        //Check if we have just entered or exited a surface
>>        $dotp = dot($I,$nhit);
>>
>>        if($dotp>0.0)
>>        {
>>            //We have just exited a surface
>>            $surfcount = $surfcount+1;
>>            $out_col={0,0,1};
>>        }
>>        else
>>        {
>>            //We have just entered a surface
>>            $surfcount = $surfcount-1;
>>            $out_col={0,1,0};
>>        }
>>    }
>>    $count = $count+1;
>>
>>    //Set the new intersection position to be the new ray cast position
>>    $curpos = $phit;
>> }
>>
>> if($surfcount==0)
>> {
>>    //This is the final ray trace when we have exited the final surface
>>    //It always returns red from the "Nothing intersected" block above
>>    trace($out_col, $out_opacity, $out_alpha, $phit, $I, 0.0001, 1);
>>
>> /*
>>    //Note: if you replace the single trace() call above with the
>> following
>> code:
>>    //you can see that the position it's ray casting from is correct.
>>
>>    //Returns if there's anything beyond where we've just exited the
>> surface
>>    $dist = rayhittest($curpos,$raydist,$phit,$nhit,0.0001);
>>    if($dist<0.0)
>>    {
>>        //Nope, nothing
>>        $out_col={1,1,0};
>>    }
>>    else
>>    {
>>        //Yep, we've just hit another surface
>>        $out_col={0,1,1};
>>    }
>> */
>> }
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> _______________________________________________
>> Sidefx-houdini-list mailing list
>> Sidefx-houdini-list at sidefx.com
>> https://lists.sidefx.com:443/mailman/listinfo/sidefx-houdini-list<https://lists.sidefx.com/mailman/listinfo/sidefx-houdini-list>
>>
>
>
>
> --
> ---Beijing 2008---
> _______________________________________________
> Sidefx-houdini-list mailing list
> Sidefx-houdini-list at sidefx.com
> https://lists.sidefx.com:443/mailman/listinfo/sidefx-houdini-list
>





More information about the Sidefx-houdini-list mailing list