7
$\begingroup$

Is there way to do "Rounded Edge Width" in Blender? It's familiar for me from Modo. Anyone know the trick?

Like Modo's Rounded Edge Width. Couple links for reference:
From the modo documentation:

The 'Rounded Edge Width' option adjusts the rendered result of surface normals at a polygons edge to blend them with adjoining polygon normals, giving the impression of a small rounded edge between the two intersecting faces. To explain it more simply it shades polygons edges at render time to look as if a small rounded bevel has been applied, to what normally would be a sharp intersection. Users can define an Edge Width to determine the amount or 'roundness' but keep in mind it is merely a shading trick and wont round the edges of the actual geometry, nor change the objects silhouette in the rendered image, so it is best to keep set the length to just a few pixels in width in the final rendered image.

emphasis mine

Video demonstrating the effect.

Rounded Edge Width

$\endgroup$
  • $\begingroup$ Welcome Sakari! Cycles or Blender Internal? $\endgroup$ – p2or Dec 16 '14 at 19:41
  • $\begingroup$ You could try using a Bevel modifier... $\endgroup$ – someonewithpc Dec 16 '14 at 19:42
  • 1
    $\begingroup$ @someonewithpc I think the OP wants to do this with disconnected intersecting faces. $\endgroup$ – gandalf3 Dec 16 '14 at 20:03
12
$\begingroup$

There's an OSL bevel Shader for Cycles that I believe was originally written by the person who built Cycles. Several people have been making adjustments to it and have been posting the results to the following thread on BlenderArtists.org http://www.blenderartists.org/forum/showthread.php?329295-Bevel-shader

OSL Code

Paste the following code into a new Text Datablock in Blender, and use it in the script node of an OSL node tree:

void rng_seed(output int rng, int seed)
{
  int chash = seed;
  if (chash == 0) chash = 1;
  rng = chash * 30391861;
}

float rng_uniform(output int rng)
{
  float res = rng / float(2137483647) * 0.5 + 0.5;
  rng *= 30391861;
  return res;
}

void to_unit_disk(float x, float y, output float x_out, output float y_out)
{
  float r, phi;
  float a = 2.0 * x - 1.0;
  float b = 2.0 * y - 1.0;

  if(a > -b) 
  { if(a > b) 
    { r = a;
      phi = M_PI_4 *(b/a);
    }
    else 
    { r = b;
      phi = M_PI_4 *(2.0 - a/b);
  } }
  else 
  { if(a < b) 
    { r = -a;
      phi = M_PI_4 *(4.0 + b/a);
    }
    else 
    { r = -b;
      if(b != 0.0) phi = M_PI_4 *(6.0 - a/b);
      else phi = 0.0;
  } }
  x_out = r * cos(phi);
  y_out = r * sin(phi);
}

void make_orthonormals(vector N, output vector a, output vector b)
{
  if(N[0] != N[1] || N[0] != N[2]) a = cross(vector(1, 1, 1), N);
  else a = cross(vector(-1, 1, 1), N);

  a = normalize(a);
  b = cross(N, a);
}

vector sample_cos_hemisphere(vector N, float randu, float randv)
{
  vector T, B;

  make_orthonormals(N, T, B);
  to_unit_disk(randu, randv, randu, randv);
  float costheta = sqrt(max(1.0 - randu * randu - randv * randv, 0.0));

  return randu * T + randv * B + costheta * N;
}

shader node_occlusion2(
  color Effect = color(0),
  color No_Effect = color(1),
  int Mode = 0, /* 0: Concave (AO) 1:Convex (Wear) 2:Both */
  int InvertEffect = 0,
  float Distance = 0.2,
  int Samples = 1,
  output color Color = 0,
  output float Fac = 0,
  output normal outNormal = N
)
{
  int i, rng;
  float f, randu, randv, ray_t, hits = 0;
  vector ray_P, ray_R;
  normal hit_normal = N;
  float hit_dist;

  f = fmod(cellnoise(P*123456.0), 1.0);
  rng_seed(rng, int(f * 21374647));

  for(i = 0; i < Samples; i++) 
  { randu = rng_uniform(rng);
    randv = rng_uniform(rng);

    ray_P = P;
    ray_R = sample_cos_hemisphere(-N, randu, randv);
    ray_t = Distance;


    if (!Mode)
    { if(trace(ray_P, -ray_R, "maxdist", ray_t)) {
            hits += 1.0;
            int HitNormal = getmessage ("trace", "N", hit_normal);
            outNormal = outNormal + (hit_normal);
        }
    }
    else if (Mode == 1)
    { if(trace(ray_P, ray_R, "maxdist", ray_t)) {
           hits += 1.0;
           int HitNormal = getmessage ("trace", "N", hit_normal);
           outNormal = outNormal - (hit_normal);
        }
    }
    else { 
        if(trace(ray_P, -ray_R, "maxdist", ray_t)) {
            hits += 1.0;
            int HitNormal = getmessage ("trace", "N", hit_normal);
            outNormal = outNormal + (hit_normal);
        }
        if(trace(ray_P, ray_R, "maxdist", ray_t)) {
           hits += 1.0;
           int HitNormal = getmessage ("trace", "N", hit_normal);
           outNormal = outNormal - (hit_normal);
        }
    } 
  }
  Fac = 1.0 - (hits/Samples);
  if(InvertEffect) Color = mix(No_Effect, Effect, Fac);
  else Color = mix(Effect, No_Effect, Fac);
  outNormal = normalize(outNormal);
}

Here's a render of many spheres that are all separate objects. It works well in some cases but not always.

enter image description here

$\endgroup$
  • $\begingroup$ Just curious, but what makes you think that it was written by Brecht? (I assume that's who you mean). I don't see any evidence one way or another. Not that it really matters though.. $\endgroup$ – gandalf3 Dec 17 '14 at 2:44
  • $\begingroup$ That shader was posted on some other thread before this one. It was username "BAO" something or other. He said he got it from Brecht. $\endgroup$ – MarcClintDion Dec 17 '14 at 2:49
  • $\begingroup$ I find this solution to suit pretty well in my cases. There is couple different versions from bevel shader script in that forum thread. Thanks for pointing me to right direction! $\endgroup$ – Sakari Niittymaa Dec 17 '14 at 10:52
3
$\begingroup$

As @Jerryno said, you need geometry. You could try using a Bevel modifier, or the equivalent Bevel tool in Edit Mode. The modifier is however preferable, since it's easily reversible; To do this, go to the Properties panel, and in the Modifiers tab, click Add Modifier and choose Bevel.

enter image description here

Then you can tweak the settings in the modifier to give the effect you want. For instance:

enter image description here

The number of segments defines the "Smoothness" and the Profile defines in which direction the generated geometry curves. A value less than 0.25 will curve it inwards.

$\endgroup$
2
$\begingroup$

We no longer need the OSL script.

Cycles now has a dedicated node to do this.

It's found under Input-> Bevel. Just plug it into the Normal socket of the Shader.

enter image description here

$\endgroup$
  • 1
    $\begingroup$ Which version of Blender is this, please? This, (and a few other shaders referred to here), are not my install of 2.79b, $\endgroup$ – Robin Betts Jun 5 '18 at 17:52
  • 1
    $\begingroup$ The Bevel node was introduced about a year ago IIRC. Every version since then should have it. The script that I posted many years ago is not a part of any version. You have to activate OSL and load it in manually but anything OSL is painfully slow so it's a last resort. (BTW. There was a typo in this answer until yesterday) $\endgroup$ – MarcClintDion Jun 5 '18 at 23:23
  • $\begingroup$ OK, thanks, got it. it's in the official builds here. $\endgroup$ – Robin Betts Jun 6 '18 at 8:56
  • $\begingroup$ bevel shader node requires the geometry to be in the same object to work doesn't it? (Not necessarily linked, but part of the same mesh object). Possibly i've been using it wrong? $\endgroup$ – Ben May 16 at 15:27
  • $\begingroup$ You're using it right if you get these results although maybe these results are not the best way for the tools to function. I'd start a thread on BlenderArtists.org to discuss the issue. The tool author; Brecht-VL, will be change the code if there is a logical reason to do so. Be sure to post a link here if you choose to start a thread to work on this issue. Personally, I'd like the option for bevel to affect both separate and joined objects. $\endgroup$ – MarcClintDion May 25 at 18:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.