[3Delight] Reflections

Hi All,

I have been trying out all the different surface shaders that come with 3delight, but I have not found one that actually renders reflections. Fortunately I have the book “Essential Renderman” and it has a shader for just such a task.

I typed in the reflect shader and called the filename reflect.sl


/* 
    Surface Reflection From Essential Renderman.
    Typed in from book by Atom 07-31-2011
*/
surface reflect (
    float Ka = 1;
    float Kd = 0.2;
    float Ks = 0.7;
    float Kr = 0.3;
    float roughness = 0.1;
    color specularcolor = 1;
)

{
    normal Nf = faceforward (normalize(N), I);
    vector V = -normalize(I);
    color Ct;
    
    vector R = normalize(reflect(I,Nf));
    color Cr = trace(P,R);
    Ct = Cs;
    Oi = Os;
    Ci = Oi * ( Ct * (Ka * ambient() + Kd*diffuse(Nf)) + specularcolor* (Ks*specular(Nf,V,roughness) + Kr*Cr));
}

I compiled the shader with the following command on windows, other OS will vary.

shaderdl.bat "reflect.sl"

This produced a file called reflect.sdl. I copied that compiled shader file into the shader path and then typed in the name of the shader, inside the 3Delight exporter. Now I can apply a reflection to an object.

Floor reflecting solid text.


Floor and text reflecting each other.


Here is another reflection test which also shows procedural and image based displacement. Notice there is no glossy reflection blur available in this reflection shader.

Attachments



afaik you can pass an optional “blur” argument to the trace shadeop. or use the gather() shadeop instead. I hope pyhton defined nodes will be in trunk soon so that we can start working on a node based shader editor within blender. Meanwhile i’m working on a standalone shader editor written in Qt/C++, you can check it out on my github page: https://github.com/frigge/FRG-Shader-Editor. Unfortunately you’d need to compile it yourself.
If you’re interested, let me know.
Btw. alway nice to see people showing real interest in the power of renderman. Keep it!

EDIT: Imo the most flexible way to get reflections is to use the environment() shadeop and pass “raytrace” as the filename. it also takes an optional “blur” argument (Passed as a token/value pair).

That would be awesome! will try and build now.

What do you think of the other existing graphical sl editors?

@Michael W you should wait a few minutes. I need to upload recent changes. It’s still quite buggy and the possibilities are a little limited but generating basic shaders should be possible.

I’ve tried shaderman.next, shrimp and shaderbox. They all have their pros and cons.
Shaderman.next and shrimp are very low level but that gets complicated with complex shaders.
On the other hand shaderbox is more like a material editor which can be extended via XML but the basic version is very limited and i don’t like coding nodes in XML.

The best one (combining both pros) is imo the one in Houdini. You can colapse parts of you network into new nodes and have as many node networks in node networks which makes working on complex shaders quite easy and not too cluttered.
As I like this approach the most I’ve tried to do the same with my tool and extended it so that you can easily save your colapsed network nodes (I call them container nodes).
The most low level nodes you get in my editor are the build in ones (input/output variables, loops, maths, conditions and values) and function nodes (shadeops) which you need to create yourself. From there you can combine them and build your own shader bricks which you can then reuse in any shader.
You can output your shader code by right clicking on an output node and chose “set Shader Name” and then “Create Code”

Edit: pushed recent changes

@frigge:

I am looking at the gather() function as described in the 3Delight manual. I am still unsure how I would integrate this into the above shader.

If I replace the trace() line with gather() is that all there is to it?

        float num_samples = 0;
        color hit_ci = 0;
        vector ray_dir = 0;
        gather( "illuminance",
            i_P, i_direction, i_angle, i_samples,
            "distribution", "cosine",
            "surface:Ci", hit_ci, "ray:dir", ray_dir )

How do I integrate the extra parameters into the shader?
I only have P and R available…

gather is the most low level raytracing function in RSL. With it you can get any information from sorrounding objects (thier surface shaders) you want. As you only want to get the output of the surface shaders “surface:Ci” is important, as that tells the gather construct to take the value of Ci from objects hit by the ray.

What you should be aware of is, that gather is Looping construct. So you need to give it a body just like you would give some to a for or while loop. The boy of the gather loop is executed everytime a ray hits another object. You can also give it an optional “else” part which is executed every time a ray does not hit another object.

So to sum up all you need to do to get normal raytraced reflections is something like this:

color reflectionColor = 0;
color hit_ci = 0;
gather(P, N, 0, 1, "surface:Ci", hit_ci)
{
    reflectionColor += hit_ci
}

which would shoot one ray in the direction of the normal and take the surface color of the object it hits and adds it to reflectionColor variable, which is pretty useless with only one ray obviously.
But if you’d make the coneangle bigger and shoot more rays:

color reflectionColor = 0;
color hit_ci = 0;
gather(P, N, 0.1, 8, "surface:Ci", hit_ci)
{
    reflectionColor += hit_ci
}

You’d get the sum of all rays. Divided by the number of rays you’d get the average => blurred reflections.

Ok, but if I replace trace() with gather() I have no value for Cr.
Do I replace Cr with reflectionColor?


/* 
    Surface Reflection From Essential Renderman.
    Typed in from book by Atom 07-31-2011
    Trying to add blurred reflections with help from frigge.
*/
surface reflect (
    float Ka = 1;
    float Kd = 0.2;
    float Ks = 0.7;
    float Kr = 0.3;
    float roughness = 0.1;
    color specularcolor = 1;
)

{
    normal Nf = faceforward (normalize(N), I);
    vector V = -normalize(I);
    color Ct;
    
    vector R = normalize(reflect(I,Nf));
    /*
    color Cr = trace(P,R);
    */
    color reflectionColor = 0;
    color hit_ci = 0;
    gather("illuminance",P, N, 0.1, 8, "surface:Ci", hit_ci);
    {
        reflectionColor += hit_ci;
    }
    
    Ct = Cs;
    Oi = Os;
    Ci = Oi * ( Ct * (Ka * ambient() + Kd*diffuse(Nf)) + specularcolor* (Ks*specular(Nf,V,roughness) + Kr*reflectionColor));
}

It does seem like gather() takes a category string which you omitted. (I am guessing with illuminance here). I have not had any success integrating your suggested code into a working shader that 3Delight will compile. It would be nice to have blurred reflections, however…

Yep. But you also need to divide reflectionColor by the number of samples. Otherwise the reflection gets brighter with every sample you add.
try this:


/* 
    Surface Reflection From Essential Renderman.
    Typed in from book by Atom 07-31-2011
    Trying to add blurred reflections with help from frigge.
*/
surface reflect (
    float Ka = 1;
    float Kd = 0.2;
    float Ks = 0.7;
    float Kr = 0.3;
    float roughness = 0.1;
    color specularcolor = 1;
    float reflection_blur = 0;
    float samples = 1;
)

{
    normal Nf = faceforward (normalize(N), I);
    vector V = -normalize(I);
    color Ct;
    
    vector R = normalize(reflect(I,Nf));
    /*
    color Cr = trace(P,R);
    */
    color reflectionColor = 0;
    color hit_ci = 0;
    gather(P, N, reflection_blur, samples, "surface:Ci", hit_ci);
    {
        reflectionColor += hit_ci;
    }

    reflectionColor /= samples > 0 ? samples : 1; /*In case you chose 0 samples, which would be bad ;) */
    
    Ct = Cs;
    Oi = Os;
    Ci = Oi * ( Ct * (Ka * ambient() + Kd*diffuse(Nf)) + specularcolor* (Ks*specular(Nf,V,roughness) + Kr*reflectionColor));
}

Hmm…I do get a compile error using your code. 3Delight seems to require a “category” as a string for the first parameter of gather().

I did mange to get this shader to produce no errors during compile, but 3delight still does not generate the required .sdl file so there is no way to test it.


/* 
    Surface Reflection From Essential Renderman.
    Typed in from book by Atom 07-31-2011
    Trying to add blurred reflections with help from frigge.
*/
surface reflect (
    float Ka = 1;
    float Kd = 0.2;
    float Ks = 0.7;
    float Kr = 0.3;
    float roughness = 0.1;
    color specularcolor = 1;
)

{
    normal Nf = faceforward (normalize(N), I);
    vector V = -normalize(I);
    color Ct;
    
    vector R = normalize(reflect(I,Nf));
    /*
    color Cr = trace(P,R);
    */
    
    float occ = 0;
    uniform float numSamples = 8;
    gather( "illuminance", P, Nf, PI/2, numSamples )
    {
        /* do nothing ... */
    }
    else
    {
        occ += 1;
    }
    occ /= numSamples > 0 ? numSamples : 1;
    
    Ct = Cs;
    Oi = Os;
    Ci = Oi * ( Ct * (Ka * ambient() + Kd*diffuse(Nf)) + specularcolor* (Ks*specular(Nf,V,roughness) + Kr*occ));
}

for me it creates a .sdl file.
You have to look into the folder from which shaderdl is executed.
If you’re not sure because you compiled it from within blender, open a console, cd into the folder of your shader source file and compile it yourself with “shaderdl reflect.sl” or whatever you’ve named the file.

btw. PI/2 is quite a lot blur as it shoots rays in all directions in a hemisphere around your surface normal.

Thanks again for your help. My problem was I did not rename the shader to match the file name so it was making a .sld file overtop my previous version of reflect. Now it is correct and seems to work. I consulted the Essential Renderman book, once again, for the final shader.


/* 
    Surface Reflection From Essential Renderman.
    Typed in from book by Atom 07-31-2011
    Trying to add blurred reflections with help from frigge.
*/
surface reflect_blur (
    float Ka = 1;
    float Kd = 0.2;
    float Ks = 0.7;
    float Kr = 0.3;
    float roughness = 0.1;
    color specularcolor = 1;
)

{
    normal Nf = faceforward (normalize(N), I);
    vector V = -normalize(I);
    color Ct;
    
    /*
    vector R = normalize(reflect(I,Nf));
    color Cr = trace(P,R);
    */
    
    color Cr = 0;
    color Chit = 0;
    float samples = 8;
    
    vector R = normalize(reflect(I,Nf));
    float hits = 0;
    gather("illuminance", P, R, radians(10),samples,"surface:Ci",Chit)
    {
        Cr+=Chit;
        hits+=1;
    }
    else
    {
        Cr+= color "rgb" (0.5,0.5,0.5);
        hits += 1;
    }
    Cr = Cr/hits;
    
    Ct = Cs;
    Oi = Os;
    Ci = Oi * ( Ct * (Ka * ambient() + Kd*diffuse(Nf)) + specularcolor* (Ks*specular(Nf,V,roughness) + Kr*Cr));
}

I do seem to have lost the diffuse color of my floor, however. I am wondering if that grey color in the else should be some other value, instead of hard coded grey.

I was surprised at how quickly this rendered. Using Blender Internal I always cringe at adding glossy reflections because of the increased render time…

Attachments


One minor hint which could decrease (very little) your render time: If you alway increase “hits” by one you could also leave it out completely as it always equals “samples”.

Other than that it looks nice :wink:

I am always for optimization, so here is the revised shader. It also takes into account the diffuse color now, the spotlight edge and presents the samples and cone angles as parameters to that can be adjusted by the end user from the 3Delight exporter interface.


/* 
    Surface Reflection From Essential Renderman.
    Typed in from book by Atom 07-31-2011
    Trying to add blurred reflections with help from frigge from BlenderArtists.
*/
surface reflect_blur (
    float Ka = 1;
    float Kd = 0.2;
    float Ks = 0.7;
    float Kr = 0.3;
    float roughness = 0.1;
    float samples = 8;
    float cone_angle = 10.0;
    color specularcolor = 1;
)

{
    normal Nf = faceforward (normalize(N), I);
    vector V = -normalize(I);
    color Ct;
    color Cr = 0;
    color Chit = 0;
    
    vector R = normalize(reflect(I,Nf));
    float hits = 0;
    gather("illuminance", P, R, radians(cone_angle),samples,"surface:Ci",Chit)
    {
        Cr+=Chit;
    }
    else
    {
        Cr+= Kd*diffuse(Nf);
    }
    Cr /= samples > 0 ? samples : 1;
    
    Ct = Cs;
    Oi = Os;
    Ci = Oi * ( Ct * (Ka * ambient() + Kd*diffuse(Nf)) + specularcolor* (Ks*specular(Nf,V,roughness) + Kr*Cr));
}

Now to figure out Sky and Background…

Attachments