5
$\begingroup$

I would like to have a script node that would output a boolean depending of if two objects are intersecting or not.

The goals is to use it in a mix shader and to hide / show my object depending of the intersection (kind of a mask).

enter image description here

The available inputs of my script node should be two objects ("active" object and "mask" object); and the output should be a boolean (0 or 1) for the FAC of a mix shader.

After having read this, I think it is possible, but don't know Blender scripting good enough yet to achieve it.

Can anyone help ?

Thanks !

$\endgroup$
6
  • $\begingroup$ Does this actually need to be a script node or could it be achieved with other means - such as Dynamic Paint? $\endgroup$ Commented Apr 9, 2018 at 22:29
  • $\begingroup$ Hi Rich, I don't know about Dynamic Paint. I added an image to improve my question. What do you think ? $\endgroup$
    – gordie
    Commented Apr 10, 2018 at 8:39
  • $\begingroup$ Knowing that I would like to be able to "switch" the material of the inside voxels too, not only the "surface" of the pile. $\endgroup$
    – gordie
    Commented Apr 10, 2018 at 8:40
  • $\begingroup$ Do you intend for the whole object (cube) to switch as soon as any of it intersected with the ‘mask’ or would only the intersecting bit be affected? $\endgroup$ Commented Apr 10, 2018 at 11:50
  • 1
    $\begingroup$ it's better to this with python and hide the geometry if it intersects with another object... specially because there are too many voxels, doing this in OSL is not a good ideia. $\endgroup$
    – Secrop
    Commented Apr 10, 2018 at 13:36

2 Answers 2

3
$\begingroup$

I've been working on something that goes somewhere towards answering your problem.. don't take it too seriously, I'm only getting used to some of the quirks of OSL in Blender/Cycles: some of these conditionals may look unnecessary, but for example, if I don't use the 'hit' local variable, it won't work, even though I don't need to.

#include "stdosl.h"

shader Dipper(
    string Container = "",
    output int IsInside = 0
)

{      
    if  ( raytype("refraction") != 1 ) IsInside = 0;
    else{

        int ray_depth;
        getattribute("path:ray_depth", ray_depth);

        if  ( ray_depth % 2  != 0){

            string source_name;
            int hit;
            hit = trace (P,I);
            getmessage ("trace", "geom:name", source_name);

            if (hit==1){
                if (source_name == Container ){ 
                    IsInside =1;
                }
            }
        }
    }   
}

Example Render

You enter the name of your container object in the 'Container' input,(unquoted).

Nodes

I'm also pretty sure you could make the logic of this shader fail, without too much effort.

$\endgroup$
8
  • $\begingroup$ Awesome !!! I'll try that. Just to be sure : OSL does not work on GPU ? $\endgroup$
    – gordie
    Commented Apr 12, 2018 at 19:51
  • $\begingroup$ @gordie .. at the moment, you are not offered the option of OSL if you select GPU as your rendering device in Blender. $\endgroup$
    – Robin Betts
    Commented Apr 12, 2018 at 22:06
  • 1
    $\begingroup$ You could adapt this old script of mine. It works with materialsIDs, so you get a better control of what objects work as a mask and what objects should be rendered as normal. blenderartists.org/forum/… $\endgroup$
    – Secrop
    Commented Apr 13, 2018 at 6:16
  • $\begingroup$ Seems nice too. Also, what I wanted to achieve is to "toggle" the material change (eg. when the origin of the mesh is inside the "domain"); not to have a transition. Would it be possible ? $\endgroup$
    – gordie
    Commented Apr 13, 2018 at 7:20
  • 1
    $\begingroup$ @Robin Betts, the script is old.. from a time I was still exploring OSL. just posted here to show that you can also probe materialsIDs, when tracing. For the full list of attributes you can retrieve from the message system, check the osl_services.cpp: git.blender.org/gitweb/gitweb.cgi/cycles.git/blob/HEAD:/src/… $\endgroup$
    – Secrop
    Commented Apr 13, 2018 at 11:14
0
$\begingroup$

It's my first experience with OSL, so I can't say if this code has no bugs, but at first look it works as it should. I used source from Secrop's comment and adapted just as he advised.

surface Mask(
    closure color Surface = 0,
    output closure color Closure = 0
) {
    float visible = 0.0;
    float myMaterialIndex = 0.0;
    float hitMaterialIndex = 0.0;
    vector VectorTrace = vector(0.0, 0.0, 0.0);
    int Hit = 0;

    getattribute("material:index", myMaterialIndex);
    if(backfacing()) {
        VectorTrace -= I;
    } else {
        VectorTrace += I;
    }

    int DoTrace = trace(P, VectorTrace);

    if(DoTrace) {
        int HitTrace = getmessage("trace", "hit", Hit);

        if(Hit != 0) {
            HitTrace = getmessage("trace", "material:index", hitMaterialIndex);
        }

        visible = myMaterialIndex == hitMaterialIndex;
    }
    if(visible != 0) {
        Closure = Surface;
    } else {
        Closure = transparent();
    }
}

The setup consists of setting equal pass index for both objects materials and plugging script's node right before last node.

Masked object material

Result

Be aware that any objects, placed behind one with according material index, will block view at your masked object. It sounds obvious, but not really, when it comes to transparent objects too, even those that doesn't contain typical shader output but only volume output.


Ye, it doesn't return boolean, as author wanted, but at least it solves that tricky problem, when you forced to use multiple render layers and compositor...)

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .