Sample shader with modified ChannelData
-
On 28/04/2015 at 09:27, xxxxxxxx wrote:
User Information:
Cinema 4D Version:
Platform:
Language(s) :---------
I want to sample a shader in my shader but with different UV coordinates than the ones requested
for my shader. Modifying ChannelData::p doesn't change anything (strangely) (and also the SDK says it's
read-only).Any idea how to do it?
ThanksUpdate: Nevermind, the problem is the Noise shader. Everything else seems to work fine. I am only
wondering why it won't work for the Noise shader (even if I change it to UV space) -
On 29/04/2015 at 08:55, xxxxxxxx wrote:
Hello,
if you could share the code you use to sample the shader we might be able to find out what is going wrong.
Best wishes,
Sebastian -
On 29/04/2015 at 10:12, xxxxxxxx wrote:
Hi Sebastian,
I've doctored this code since the actual codebase is much larger and more complex. But
basically it mimics what a certain code branch will do:virtual Vector Output(BaseShader* shader, ChannelData* cd) { if (!shader || !cd) return Vector(1.0, 0, 0); BaseContainer* bc = shader->GetDataInstace(); if (!bc) return Vector(1.0, 1.0, 0); BaseShader* subShader = static_cast<BaseShader*>( bc->GetLink(MYSHADER_SUBSHADER, shader->GetDocument(), Xbase)); if (!subShader) return Vector(0.0, 1.0, 0); static const Int32 stepu = 1.0 / 6; static const Int32 stepv = 1.0 / 6; Float u = fmod(Abs(cd->p.x), 1); Float v = fmod(Abs(cd->p.y), 1); // This function calculates the stepped value of *x* based on // the specified *step*. auto steppit = [](const Float x, const Float step) -> Float { if (Abs(step - 1.0) <= EPSILON) return 0.0; Float r = (x - fmod(x, step)) / (1.0 - step); // Rounding errors could lead r to exceed 1.0 *sligthly*, // but we really need to make sure it does not, otherwise we // will start sampling the other end of the shader again. if (r > 1.0) r = 1.0; else if (r < 0.0) r = 0.0; return r; }; u = steppit(i, stepu); v = steppit(i, stepv); ChannelData data = *cd; data.p = Vector(u, v, 0); return subShader->Sample(&data); }
Of course, InitRender() and FreeRender() are called on the subShader.
Thanks,
Niklas -
On 30/04/2015 at 08:31, xxxxxxxx wrote:
I am currently facing a much more important problem.
I only know at the time ShaderData::Output() is called what sub-shader I need to sample. So once
I figured it out, I will call InitRender() on it. But unfortunately that leads me to a deadlock.What happens is the following:
1. I figure out a shader that I need to sample from my shader , I create an AutoLocker
2. I create a clone of the shader that I want to sample and insert it as a shader into my shader
3. I use the copy of the InitRenderStruct from InitRender() and initialize its member vd with the
VolumeData from the ChannelData.
4. I call subShader- >InitRender() with the new InitRenderStruct, but this call never exits
5. I unlock the AutoLockerI found this case happening when subShader is a Layer shader. I thought it would be dangerous
to initialize a shader from Output(), but is it impossible?Thanks a lot in advance,
Niklas -
On 04/05/2015 at 07:17, xxxxxxxx wrote:
I've moved the initialization to my InitRender() method and now it all works fine (except for the Noise
Shader which still ignores the U/V data I pass). It's been much more effort to actually figure out the
shader's that will be needed rather than initializing them on-demand as I could deduce it from the
ChannelData that was passed to Output(). -
On 04/05/2015 at 07:38, xxxxxxxx wrote:
@Niklas, you can get the correct Noise for whatever UV coordinate you want with a hack, noise shader got a Bitmap view that you can get with a size "1k for example" , and then hit the pixel that you want from the UV coordinate
-
On 11/05/2015 at 02:04, xxxxxxxx wrote:
Hello,
sampling a shader I prefer to use a fully setup ChannelData object like this:
ChannelData channelData; channelData.off = 0; channelData.scale = 0; channelData.t = 0; channelData.texflag = TEX_TILE; channelData.p.x = u; channelData.p.y = (1.0-v); channelData.p.z = w; channelData.d = Vector(1,1,1); channelData.n = Vector(0,1,0); channelData.vd = NULL; Vector res = shader->Sample(&channelData);
best wishes,
Sebastian -
On 11/05/2015 at 04:55, xxxxxxxx wrote:
Thank you Sebastian, I'll give it a try!