Shader creating a strange bump result

On 12/03/2015 at 12:34, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   15 
Language(s) :

I'm creating a new shader and is coming out fine.
However, when I place it in the Bump channel, the result of some of its outputs comes out weird.
For example:

No matter how thin I set the lines, it always seems that the bump is quite large. And instead of creating a soft bump, it looks like a harsh displaced bevel.
Is there anything that needs to be done when outputting to the Bump channel?
My output is a simple RGB and, in the shown example, RGBs that result in a ramp of greys.

On 13/03/2015 at 08:02, xxxxxxxx wrote:

Hello Rui,

I'd like to apologize, this is not straight forward at all and it is poorly (if at all) documented.
Try the following:

Implement GetRenderInfo() and at least return SHADERINFO_BUMP_SUPPORT.

SHADERINFO ShaderData::GetRenderInfo(BaseShader* sh)

Then in your shader's Output() adjust the coordinates like so (with _rd.width/height your textures dimensions and fx and fy from cd->p.x and y ) :

Vector ShaderData::Output(BaseShader* shader, ChannelData* cd)
  Int32 texflag = cd->texflag;
    switch (GET_TEX_BUMP_SAMPLE(texflag))
      case 1: fx += (1.0/_rd.width)*0.5; if (!(texflag&TEX_TILE) && fx > 1.0) fx = 1.0; break;
      case 3: fy += (1.0/_rd.height)*0.5; if (!(texflag&TEX_TILE) && fy > 1.0) fy = 1.0; break;
      case 0: fx -= (1.0/_rd.width)*0.5; if (!(texflag&TEX_TILE) && fx < 0.0) fx = 0.0; break;
      case 2: fy -= (1.0/_rd.height)*0.5; if (!(texflag&TEX_TILE) && fy < 0.0) fy = 0.0; break;

As soon as I find the time, I will add something to the SDK docs about this.

On 13/03/2015 at 10:03, xxxxxxxx wrote:

Thank you, Andreas. But, what exactly are the texture dimensions?
Because I'm generating all my patterns procedurally.
I simply get the cd->p.x and cd->p.y values and, from those values I create ALL my patterns.
Since they are procedural, what dimensions (width / height) must I assume?

On 13/03/2015 at 10:11, xxxxxxxx wrote:

Hm? To be honest I hadn't thought of that.
The above code is from a shader sampling a bitmap.

But your shader still has some kind of resolution, hasn't it? I mean, there is some kind of "pixel equivalent" to p.x and p.y equal 1.0. That I would regard the width and height. But I might be totally wrong...

On 13/03/2015 at 10:25, xxxxxxxx wrote:

Actually, it doesn't :-)
It is absolutely resolution independent.
It simply gets the u,v coordinates from cd->p.x and cd->p.y and performs calculations in the normalized space (0 to 1) and returns a color from a gradient (according to the calculated result that is always a normalized value (between 0 and 1).
So, everything happens in procedural space (if there is such a thing).

Even the hexagonal pattern that I shown above is calculated procedurally.
The problem is that, no matter how thin I set it, it always produces that exaggerated bump. :-(

On 13/03/2015 at 10:35, xxxxxxxx wrote:

Did you try SHADERINFO_BUMP_SUPPORT without the correction? Does it make a difference?
I haven't analyzed the internal algorithms completely yet. And I probably won't have time before Monday...

On 13/03/2015 at 10:36, xxxxxxxx wrote:

I will try it. I will report the result in a few minutes.

On 13/03/2015 at 10:47, xxxxxxxx wrote:

I added that and now I do get an editor preview of the bump but nothing in the render. It completely stopped working when I apply the shader in the Bump channel.

On 13/03/2015 at 11:15, xxxxxxxx wrote:

Hi Rui,
please try to add the correction, but instead use an arbitrary small value to add and subtract instead of the value calculated from width and height and forget about the limiting for tiling.
The point is, that for the bump channel, the shader get's sampled four times, each time offset in x (+/-) and y (+/-). As you are not offsetting, it doesn't work currently. I don't know yet, how this offset should be calculated correctly. For noise shaders the delta value (amongst others) is taken into account. Perhaps you should play with this over the weekend.

On 13/03/2015 at 13:05, xxxxxxxx wrote:

Sorry for the lateness in my reply but I had to go and pick my children at school

I did like you said and it worked much better.
The problem is that I'm changing the p.x and p.y values by a constant value (in my case, .001). I tried .0001 but the Bump became too soft and it required very high values of bumpness to make it work comparatively with other native shaders.
Shouldn't I be changing those values by a variable value?
Well, since it is working now, I should not be very worried [:-)]
Thank you so much, Andreas.

On 13/03/2015 at 13:31, xxxxxxxx wrote:

You can adapt the value in way you like or feel appropriate for your shader.
As I said, for the bitmap shader this is a constant value depending on the size of the texture. For noise shader it's more complicated, but it still is a constant (for the render), which the user can fine tune to his needs (delta value, octaves, noise type and global scale are taken into account). I'm sure there are other implementations as well. And if you feel it would help to have the value variable (like for working out subtle details in certain areas) you could certainly do so as well. In the end it comes all down to render speed...

On 13/03/2015 at 13:33, xxxxxxxx wrote:

Well, adjusting the delta will not affect the render speed in my case. So, I may add that as an option. Everyone loves to have more options :-)

On 13/03/2015 at 13:35, xxxxxxxx wrote:

What I meant by render speed: It makes a difference, if such value is calculated once in InitRender() or dynamically for every sample.

On 13/03/2015 at 13:39, xxxxxxxx wrote:

Oh, I see. But it will not influence much, in my case, even if calculated for each sample. Actually, I implemented it in between this and my last answer

On 27/05/2015 at 19:48, xxxxxxxx wrote:

I know this is a somewhat older thread, but maybe 'my' method can be of use to others.
What i sometimes do in an procedural shader is use the cd->vd->pp[] vectors to determine the 4 point displacement for bump mapping.

As far as i understand, the pp[] vectors are surface hits for the adjacent screen pixels in the x and y direction (given that the traced rays can be seen as frustums projecting into world space onto objects).

Vector surfp = cd->vd->p;  
Vector dx = cd->vd->pp[0] - surfp;  
Vector dy = cd->vd->pp[1] - surfp;  
Int32 texflag = cd->texflag;  
if (GET_TEX_CHANNEL(texflag) == CHANNEL_BUMP) {  
  switch (GET_TEX_BUMP_SAMPLE(texflag)) {  
  case 0: surfp -= _delta * dx; break;  
  case 1: surfp += _delta * dx; break;  
  case 2: surfp -= _delta * dy; break;  
  case 3: surfp += _delta * dy; break;  
// use surfp instead of cd->vd->p when sampling your shadercode  
// _delta is an user adjustable value, a default value of 1.0 gives nice results.  

Personally this method gave me great results, far better than using a delta value only, but your mileage may vary.

One little note: the api docs state that cd->vd->pp[] is only valid if VOLUMEINFO_MIPSAT is set, but this doesn't seem necessary in a shaderdata plugin (setting it can only be done in a materialdata plugin?)