Jump to content

Ambient Occlusion - Whats going on?


Recommended Posts

Hi,

I have included a hip file with a few examples of shader based ambient occlusion, each of them slightly different and I was wondering if anyone could tell me what is going on in them...?

Example 1:

Nothing plugged into AO position or surface normal inputs. So it should use the global variables by the same names. Fine...

But what space are the surface position and surface normals in in this case? Camera space? Object space? World space?

Example 2:

Same as example 1 except that the AO position is using the global variables surface position transformed into object space.

Do we need to do this kind of conversion? If so what space should we be converting to? Object or world space?

Example 3:

Same as example 2 except the unaltered surface normals from the global variables are being passed into the AO surface normal input.

Why should this look any different to example 2???

Example 4:

Same as example 1 except that the object scope is set to:

* ^/obj/EXAMPLE4/torus

In my understanding this means that /obj/EXAMPLE4/torus is now not contributing to the occlusion on any object this shader is assigned to.

If you look at the result, even surfaces on the torus with normals that are facing away from the grid seem to be occluded by the grid. Is this the expected behaviour? Surely we only want areas on the torus that have normals pointing at the grid to be occluded? How can we do this? Do we need to get a dot product involved or is this somehow built into the occlusion vex node?

Can someone clear all this up for me!?

Thanks.

AO_testing_v01.hip

Link to comment
Share on other sites

Interesting, cheers for the reply. Any ideas about example 4?

Basically what I am trying to get is the effect of no self occlusion for each object the shader is applied to.

Is that possible or do I need to make unique shaders per object and change the object scope for each one?

Thanks!

Link to comment
Share on other sites

You may use renderstate("object:name", string &name) to get a currently rendered object's name. In Vops place RenderstateVop and wire it into PrintVOP with format string lilke: * ^% and use it as a scope input in occlusion. You should see no self shadowing. Note, that you can apply occlusion via light shader too, it spares some setup for multiply objects. Also Occlusion in Houdini should be multiplied x 2 to mimic b/w occlusion behavior know from other renders (could be set by Background color = 2).

Edited by symek
  • Like 2
Link to comment
Share on other sites

Cool so now got the occlusion shader working exactly as I want and have complete control over what occludes what...

Would someone be able to post an example of how to use occlusion through a light shader I have tried a quick set up and no joy.

I tried making a light shader builder and setting up the occlusion in the same way and then applying it to a light template SOP. It didn't seem to do the job.

The other thing that I have bee dying to know which absolutely must be possible is as follows:

Is there a way to have one material assigned to an object but change the way each ray sees that object? (see attached picture)

Red ball is red to eye ray, blue to refraction ray and green in reflections of other objects.

If someone has the answer I will love them forever!

post-8142-0-47180300-1368394001_thumb.jp

Link to comment
Share on other sites

Would someone be able to post an example of how to use occlusion through a light shader I have tried a quick set up and no joy.

Take a look in Global Illumination Light shader (v_gilight). It's made of occlusion() among other setups.

The other thing that I have bee dying to know which absolutely must be possible is as follows:

Is there a way to have one material assigned to an object but change the way each ray sees that object? (see attached picture)

Red ball is red to eye ray, blue to refraction ray and green in reflections of other objects.

If someone has the answer I will love them forever!

You mean like this? :)

http://max3d.pl/forum/attachment.php?attachmentid=81401&d=1313505947

First, you can count rays with Ray Bounce Level VOP and switch surface properties with that. More general mechanics in Mantra is message passing. Basically you attach a tag to a ray, and let surface know which ray is hit by. This is a good start reading: http://www.sidefx.com/docs/houdini12.5/vex/functions/gather. Same applies to trace().

  • Like 1
Link to comment
Share on other sites

Nice one Symek, that's awesome! I knew there had to be a way. Now I just need to understand it. I have just read through that page and it kinda makes sense but I would find it incredibly useful to see an example and hack it to pieces. Is there any chance you could post a really simple scene with a result like either yours or my example image?

I take it all of that vex code in the examples at the bottom of that page are possible to represent with VOP nodes?

Thanks a lot for your input on this one!

Link to comment
Share on other sites

Ok, so super fast example of two or even tree techniques. Really messy, sorry:

1. Main take: simple scene as expected.

2. Ray counting take: simple switch based on ray level value.

3. Message passing take has two meaning:

3.1 gather("send:name", name) sends a sender name to a sampled surface, which by using rayimport() compares it with hardcoded string and behaves accordingly. So communication goes from a sender to a receiver. This is used by a bigger sphere which ray-imports names of a smaller spheres to expose itself differently.

3.2 gather(..., "variable_name", variable) imports any variable exported from a sampled surface - similarly as aov, so communication is in an opposite direction. This is used in a mirror surface (in the backgound) to use an uv of a hit objects to draw a checkerboard on itself), so instead of a mirror we have a checkerboard using reflected uvs (in addition cut off by the hit Of). Pretty useless, but funny.

hope this helps,

skk.

post-744-0-57962400-1368534926_thumb.png

ray_message_passing.hipnc

  • Like 1
Link to comment
Share on other sites

Cheers Tomas, very useful to know. I have no idea how I was supposed to find that out otherwise though... is there a page in the help somewhere that gives me a list of labels that various models export or something? Or do you just have to "know"...? How do I know what other labels I have access to?

Also is there a VOP equivalent of the "rayimport" VEX function?

Cheers guys...

Link to comment
Share on other sites

there are default labels (reflect, refract, diffuse, nolimit, primary, shadow), you can view them in docs here

http://www.sidefx.com/docs/houdini12.5/vex/functions/gather#id580817

if you use those labels, mantra will know the type of the ray for setting the limits for the rays and masks, that doesn't mean that all materials have all of them set, but the most common like reflect and refract usually are

so it's up to the shader if it uses any of them or not, or completely custom ones

there is no VOP for rayimport so you have to stick with inline

but for some cases you can use VOPs like Is Shadow Ray for shadow rays or Ray Bounce Level to detect primary/secondary rays

Link to comment
Share on other sites

  • 1 year later...

Just had a quick play, before the final surfaceOutput, put down a switch node, use the raybounce as your switch controller, the original surfacemodel as input1, then your alternate surface model as input2 which will be used for the first bounce. 

 

I went on a quick hunt through the mantra surface, found how they define the diffuse component (its a physically based diffuse multiplied by colour), and fed that to my switch node. No idea if this is efficient or insane in production, but hey, works for a screenshot. :)

 

 

post-7292-0-04762900-1408628221_thumb.pn

rayswitch_pbr.hipnc

Link to comment
Share on other sites

Also, occlusion light.

 

Again, Matt Ebb worked out the guts of it, wasn't really documented anywhere. In theory its simple enough; create a light template, a light shader, stick occlusion in, done.

 

In practice, two little gotchas. The first is obvious enough, you don't use the light P, you use surface P (Ps).

 

The second is that you connect the surface normal N to lighting vector L. 'Why would you do that?' I hear no-one shout? Because otherwise it'll still take the light direction relative to the shaded point into account; like you're taking a point light render, and multiplying it by the occlusion render. By setting the lighting vector to the same as the surface normal, you're essentially cheating and saying the shading point is always pointing directly at the light. We don't want any lighting directionaliy, only occlusion.

 

Unless you _do_ want that, in which case, disconnect N from L. :)

 

post-7292-0-25308200-1408629912_thumb.pn

 

occlusion_light.hipnc

Link to comment
Share on other sites

  • 3 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...