Adding AO To A ShaderBuilder 'Faked' IBL ?
![3dcheapskate](https://farnsworth-prod.uc.r.appspot.com/forums/uploads/userpics/662/n0HSNEA3VB7BJ.jpg)
Ages ago I created a 'faked'* Image Based Light (IBL) in ShaderBuilder for my DS worldball. My Poser worldball used Poser's built-in Diffuse IBL, which also had Ambient Occlusion (AO). I never got AO working in the DS version (well, never really tried).
Now I want to add AO to the DS worldball. So today I opened up DS4.6 and took a look at ShaderBuilder again.
The 'Occlusion' brick (which was already available back in DS3) seems to be the one that'll do the trick. The problem, as always, is the lack of documentation - there's the old artzone wiki, (not much help), the new version of the documentation (still not much help), and the old tutorial (a great introduction, but not much help for this). And then there's always Pixar's RISpec for the real nitty-gritty behind it all, but that's too much for me!
So here's what I have (see image below) - the current DS WorldBall IBL plus an unconnected 'Occlusion' brick (the orange-highlighted one).
And here's my goal - to somehow connect that brick up to get AO working with the IBL. (I do realizethat there may be more to it, but one totally undocumented brick is plenty for starters.
But here's the problem - where can I find a definition of what those inputs/outputs mean?
And here's what I'm hoping some of you good folks will be able to do - just point me in the right direction!
*I first used that term 'faked' IBL in my reply to semicharm's comment here because I'd come to the conclusion that it was 'faked'. But now I'm not so sure.
Comments
The inputs on the Occlusion Brick can be infered from the real occlusion shaders - Strength is the strength of the effect, Max Distance is how far the shader looks for obstructions before deciding that the way is clear (lowering it not only avoids unwanted shading from distant items but speeds the render), Cone Angle is the spread of angles over which the render looks for obstructions (the default 90 makes a hemisphere, lowering the angle would restrict the range of diections checked - which would reduce render time), Axis allows you to tilt the cone (so you could restrict the range and direction of angles if you were interested in blockages in only some directions, because you knew that was where the main light was for example), Samples is a quality setting (how many rays the renderer sends out in the cone, too few and adjacent points may get different results producing noise) and Bias is the usual offset value. I'm not sure what the vector output is, the float output is the amount of occlusion so higher value is more occlusion - in the sample I inverted it and connected itt o Diffuse Strength.
Thanks Richard... but that's ShaderMixer, not ShaderBuilder.
(I couldn't create my 'faked' IBL in ShaderMixer, which is why I ended up in ShaderBuilder)
Oops, sorry.
No worries, it took me a while to realize - I was wondering why the occlusion block had changed/shrunk so much between DS4.6 (what I'm using) and DS4.8 (which I assume you're using) ... and it wasn't till I looked at your screenshot side-by-side with mine that it hit me! ;o)
... sound of tumbleweed rolling ...
(yet again)
Okay, adopting the 'suck it and see' approach...
Here's what I think I know already:
1) Inputs on the left, outputs on the right.
2) Square brackets around an input/output indicate something...
3) The colour of the circle next to the input/output indicates its type.
Guesses at what dot colours mean:
- Pale green = a point, i.e. (x,y,z)
- Dark green = a normal, i.e. (x,y,z) ... same same but different
- Orange = a color, i.e. (r,g,b)
- Red/pink = a number
- Blue = an image. Sometimes.
Guess at what the square brackets mean? Optional (for inputs). Not sure for outputs - probably indicates that they're not the main (i.e. most commonly used) outputs?
So looking at the non-square-bracketed inputs/outputs on the occlusion brick I have P, N, samples, and Result.
P will be the point on the surface - so I guess I just plug the 'Ps' (Point on Surface) brick directly into that?
N will be the surface normal at this point - so I guess I just plug the 'Ns' (Normal of Surface) brick directly into that?
samples is a number - probably 1 to 5 is a sensible start? Should probably be a user parameter.
Result is a number - I guess 0 to 1, indicating how 'occluded' the point is. Probably need to multipy this by the light intensity...
Anybody got any other educated guesswork, or is this going to be a one-man show? :D
Guesses:
maxdist - the distance from the point at which 3Delight stops looking for occluding geometry
coneangle - the width (from the normal) of the cone emanating from the point in which 3Delight looks for occluding geometry
hitmode - by analogy with other shaders, whether the base geometry/opacity encountered is used for determining if occlusion occurs or whether the surface shader on the geoemtry is evaluated to determine if it will occlude (which will be much slower, of course).
hitsides - perhaps whether it ignores surfaces with normals facing the wrong way - towards the item perhaps (which would mean light passed through them towards the point).
Those sound feasible. I tried connecting up an occlusion brick as I mentioned in my previous post - it doesn't seem to have any effect (i.e. renders look identical to the version with no occlusion brick. I tried with samples set to 3, 10 and 100.
Screenshots of failed network, variables, and a comparison of renders attached.The light code it gave me when I compiled it is this :
#ifndef DELIGHT
#define DELIGHT
#endif
/*********************************************************************/
light ONGOING_WorldBall_IBL_DS4(
string from_2 = "";
float diffiblmapblur = 0;
float Intensity = 1;
color LightColor = color( 1, 1, 1 );
float AO_samples = 3;
point from = point "shader" (0,0,0);
string shadowmap_posx = "";
string shadowmap_negx = "";
string shadowmap_posy = "";
string shadowmap_negy = "";
string shadowmap_posz = "";
string shadowmap_negz = "";
float ShadowStrength = 1.0;
float ShadowSoftness = 0.0;
float ShadowBias = 0.0;
float falloff = 0.5;
float ShadowSamples = 8;
float ShadowWidth = 1;
uniform string __category = "";
output uniform float __nonspecular = 0;
output uniform float __nondiffuse = 0;
)
{
illuminate((Ps + Ns))
{
Cl = ((Intensity*LightColor)*((from_2 != "") ? color environment(from_2, vector(ntransform("shader", Ns)), "blur", diffiblmapblur, "filter", "gaussian", "width", 1) : color( 0, 0, 0 )));
}
Cl = (Cl*occlusion(Ps, Ns, AO_samples));
}
This is driving me crazy !
When I hover over the occlusion brick it says something about returning the percentage of the hemisphere that is occluded by local geometry. So I guess that I should subtract the Result output from 1 (or 100?) before multiplying by the output of the illuminate brick. I've tried all variations I can think of and I can get the spheres and plane totally black or totally white. But nothing that looks anything like AO...
Somebody must know something about that occlusion node and how to connect it up - it should be so simple...
heeeeeeeellllllllpppppp !
Not sure...usually the lights I've been bringing in already have the occlusion code included. I don't have to plug in the brick...
Hmm... which lights are they? The only light I see that uses an occlusion brick is the DzAmbientLight*, where the Result output from the occlusion brick is plugged into the 'Ambient Occlusion' input of the 'GI Light' macro brick.
Except that that occlusion brick isn't an occlusion brick - it's an occlusion macro brick (which is, of course, different from an occlusion(surface) macro brick)... :oS
Maybe the key is that the AO is applied to CI before the illuminate?
Do I even have the vaguest idea what I'm talking about? LOL
*Now that's got me wondering - did the DzAmbientLight do what I wanted all along? I'm sure I looked at it and decided it didn't, but...
This will not work. The Cl has to be set inside the illuminate. It should be something like this:
I think you should connect the output to the input of the illuminate brick to get that (although i practically never use shader builder, so i cannot actually confirm that this works with shader builder).