How to make an OSL that detects the distance of objects? See example.

I want this texture, show circles instead of straight in the direction of vector (image).


#include "stdosl.h"#include "node_fresnel.h"
#include "oslutil.h"


shader G_approximation(
    color ColorIn = color(1.0,1.0,1.0),
    color ColorHit = color(0.0 , 0.0 , 0.0 ),
    closure color closureIn = color(1.0,1.0,1.0) * emission() ,
    float maxDistance = 25.0 ,
    vector test = vector (0.0 , 0.0 , 0.0),
    output color CoulOut = color(1.0,0.0,0.0) , 
    output closure color closureOut = closureIn
    )
{
    {
    	      
    // Trace Ray  for approximation
    float Dist = 1.0 ;
    float mixage = 1.0 ;
       
    int DoTrace = trace (P, test, "maxdist" , maxDistance ) ;
  	
    if ( DoTrace) {
        int HitTrace = getmessage ("trace", "hitdist" ,  Dist ) ;
        mixage = clamp ( (Dist / maxDistance) , 0.0 , 1.0 ) ;
        CoulOut = mix  ( ColorHit , ColorIn , mixage ) ;


       } else {
	   // else, return black
        CoulOut = ColorIn;
       
        
      }
   }
}

I intend to make a different “texture” to the grass at the base of trees and the rest of the lawn. As in this image:
http://download.ultradownloads.com.br/wallpaper/68037_Papel-de-Parede-Dia-Ensolarado-no-Parque_1680x1050.jpg

Maybe derivating from ambient occlusion can do the trick ? Here’s an OSL shader for AO : http://vadrouillegraphique.blogspot.fr/2012/12/simple-osl-ambient-occlusion.html

Thanks KWD, but this texture is slow and does not work exactly how I want (you can not control with colorramp and does not allow select 100% other material)

raytracing from within OSL is rather slow, so wouldn’t it be a better idea to simply create a shader that calculates the distance to a given point and combine (add) several of them (one for each tree) to drive a mix shader?


// warning untested
shader distance(
  point Pos=P,
  point ObjectPosition,
  float MaxDistance,

  output float Dist=0,
){
  float d = distance(Pos, ObjectPosition);
  if(d < MaxDist){
    Dist = 1-d/MaxDist;
  }
}

varkenvarken, I liked the idea, but how can I put the coordinates of each of the 20,000 hair particles in my scene? I’m newbie at this.

@mano-wii: I am not quite sure what you mean. From the image that you linked to (the one with the trees) I guessed that you wanted a circular area around each tree. With a couple of trees that’s doable, but creating a circular area around each blade of grass clearly isn’t.
if you do want to create a circular area with different particles (say shorter and brown grass around the trees and longer and greener grass further away) the way to go would be creating vertex groups on the plane (which will need some subdividing to allow for some detail). One vertex group would have some weight in areas around the tree, the other would be more or less its inverse. These vertex groups could then be used to drive the dendity of two particle systems. (there are numerous tutorials on that and the manual is also helpful: http://wiki.blender.org/index.php/Doc:2.6/Manual/Modeling/Meshes/Vertex_Groups/Weight_Paint)

but of course I might be completely misunderstanding what you really want :slight_smile:

@varkenvarken, that’s not I want. Each of the 20,000 particles are rendered as trees. (This texture would only be seen in around 100 of them). I’ll show a picture.

It was not exactly this picture but it serves to show what I’m talking about.


i see, that’s a whole different story. you might have a look at dynamic painting which lets you change mesh properties (like vertex colors) based in interaction w. other objects and/or particles.
http://www.miikahweb.com/en/articles/blender-dynamicpaint-basics

Thanks @varkenvarken for the advice, but it seems hair particles don’t serve as a brush. I’ve tried.
I think if I put enough trace rays in OSL, would begin to look like a circle. But I don’t know how to do this.


shader G_approximation(    float maxDistance = 1.0 ,
    vector control = vector(0.0, 0.0, 0.0),
    output color V1 = color(0.0, 0.0, 0.0),
    output color V2 = color(0.0, 0.0, 0.0),
    output color V3 = color(0.0, 0.0, 0.0),
    output color V4 = color(0.0, 0.0, 0.0) 
    )
{
    	      
    // Trace Rays for approximation
    float Dist = 1.0 ;
    float mixage = 1.0 ;
           
    int DoTrace1 = trace (P, vector(0.0 , -1.0 , 1.0));
  	int DoTrace2 = trace (P, vector(0.0 , 1.0 , 1.0));
    int DoTrace3 = trace (P, vector(-1.0 , 0.0 , 1.0));
    int DoTrace4 = trace (P, vector(1.0 , 0.0 , 1.0));
      
    if  (DoTrace1) {
        int HitTrace = getmessage ("trace", "hitdist", Dist);
        V1 = clamp ((Dist/maxDistance), 0.0, 1.0);
        }
    if  (DoTrace2) {
        int HitTrace = getmessage ("trace", "hitdist", Dist);
        V2 = clamp ((Dist/maxDistance), 0.0, 1.0);
        }
    if  (DoTrace3) {
        int HitTrace = getmessage ("trace", "hitdist", Dist);
        V3 = clamp ((Dist/maxDistance), 0.0, 1.0);
        }
    if  (DoTrace4) {
        int HitTrace = getmessage ("trace", "hitdist", Dist);
        V4 = clamp ((Dist/maxDistance), 0.0, 1.0);
        }
}

@mano-wii

you could sample a number of randomly distributed rays (warning: untested code):


...
for(int n=0; n<NumberOfRays; n++){
  vector ray=noise("perlin",P,n);
  ray[2]=1; // restrict to upper half
  if(trace(P,ray)){
    getmessage("trace","hitdist",Dist);
    break;
  }
}
... do something with Dist ..


notes:

  • as shown above the rays are not uniformly distributed but in this case that does matter much,
  • the code as shown breaks the loop at the first hit encountered. that won’t give you the shortest distance. if you want that, don’t break but compare against the shortest distance sofar (but beware for 0 distance when hitting the plane itself)

Thanks @varkenvarken now worked :). I just made a small change in the “vector ray=noise(“perlin”,P,n);” for “vector ray=noise(“cell”,P,n)*2-1;” (just gets faster).
Thank smart solution.



shader G_approximation(
    float maxDist = 1.0,
    float mixDist = 1.0,
    float upper = 1.0,
    int NumberOfRays = 4,
    output color V1 = color(1.0, 1.0, 1.0) 
    )
{
    	      
// Trace Ray for approximation


    float Dist = 1.0 ;
    float mixage = 1.0 ;
               
    for(int n=0; n<NumberOfRays; n++){
        vector ray=noise("cell",P,n)*2-1;
        ray[2]=upper; // restrict to upper
        if(trace(P,ray,"maxdist",maxDist)){
            int HitTrace = getmessage("trace","hitdist",Dist);
            V1 = clamp ((Dist/mixDist), 0.0, 1.0);
        }
    }
}



@mano-wii: thanks for sharing. I am curious how well it performs (no time to check myself at the moment :slight_smile:

Good values ​​for the base of trees are: Mixdist = 2, upper = 0; NumberOfRays = 64