5

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 !

gordie
  • 2,510
  • 3
  • 25
  • 47
  • Does this actually need to be a script node or could it be achieved with other means - such as Dynamic Paint? – Rich Sedman Apr 09 '18 at 22:29
  • Hi Rich, I don't know about Dynamic Paint. I added an image to improve my question. What do you think ? – gordie Apr 10 '18 at 08:39
  • Knowing that I would like to be able to "switch" the material of the inside voxels too, not only the "surface" of the pile. – gordie Apr 10 '18 at 08:40
  • 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? – Rich Sedman Apr 10 '18 at 11:50
  • The whole object. – gordie Apr 10 '18 at 12:41
  • 1
    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. – Secrop Apr 10 '18 at 13:36

2 Answers2

3

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.

Robin Betts
  • 76,260
  • 8
  • 77
  • 190
  • Awesome !!! I'll try that. Just to be sure : OSL does not work on GPU ? – gordie Apr 12 '18 at 19:51
  • @gordie .. at the moment, you are not offered the option of OSL if you select GPU as your rendering device in Blender. – Robin Betts Apr 12 '18 at 22:06
  • 1
    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. https://blenderartists.org/forum/showthread.php?329326-Multiple-transmissive-objects-as-just-one-surface&highlight= – Secrop Apr 13 '18 at 06:16
  • 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 ? – gordie Apr 13 '18 at 07:20
  • @Secrop - thanks for your ref, tider and more knowledgeable than mine; material IDs are the way to go. (I didn't even know you could retrieve them). One line has me stumped: {exteriorSurf=(myMaterialIndex==hitMaterialIndex)+hitFace;} e.g. if myMaterialIndex != hitMaterialIndex and hitFace is True, (hit face was backfacing), then exteriorSurf evaluates to 1? So enclosed unlike materials are made transparent? Maybe I've got the returns of {getmessage ("trace","backfacing" , var)} wrong. Where can you find the complete set of values that can be returned by {getmessage ("trace", "..." , var)}? – Robin Betts Apr 13 '18 at 09:24
  • @gordie If you want to flip the entire material of an object when its origin is enclosed, maybe an approach like this one is better: https://blender.stackexchange.com/questions/105789/update-values-of-objects-for-python-script/105897#105897 – Robin Betts Apr 13 '18 at 09:32
  • @gordie, I still think python is the best option (i.e. Robin's sugestion), as tracing rays is an expensive task. – Secrop Apr 13 '18 at 11:14
  • 1
    @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: https://git.blender.org/gitweb/gitweb.cgi/cycles.git/blob/HEAD:/src/kernel/osl/osl_services.cpp – Secrop Apr 13 '18 at 11:14
0

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

Duarte Farrajota Ramos
  • 59,425
  • 39
  • 130
  • 187
DIES
  • 123
  • 4