[Sidefx-houdini-list] Hidden interior shader

zhang xiao zhangxiao6776 at gmail.com
Mon Jan 21 12:50:57 EST 2008


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---



More information about the Sidefx-houdini-list mailing list