creating instance of procedural texture, write it

On 08/08/2014 at 14:54, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   R13 
Platform:   Windows  ;   
Language(s) :     C++  ;

I'm creating my own render engine, wanted to benefit from Cinema4D procedural textures "like noise, ..."

so what I wanted is to "cache" this procedural texture into a pointer, so I can sample it with my own sampler

is this possible?

On 08/08/2014 at 15:32, xxxxxxxx wrote:

You can create a Description (for elements) or Dialog (commands and such) Link and store either the TextureTag, Material or Shader in that link.  If using an element added to the document, the link stored in the Description will be saved and loaded with the document.

On 08/08/2014 at 15:54, xxxxxxxx wrote:

seems good, but can I extract an output texture from that procedural texture? for example 1K resolution of that procedural surface texture?

On 09/08/2014 at 01:20, xxxxxxxx wrote:

You can sample a procedural shader with BaseShader.Sample(cd).

« shader » is your BaseShader.

from c4d.modules.render import ChannelData, InitRenderStruct  
irs = InitRenderStruct()  
init = shader.InitRender(irs)  
if init != c4d.INITRENDERRESULT_OK : return  
cd = ChannelData()  
cd.p = Vector() # The point to render  
color = shader.Sample(cd) # The output color  

On 09/08/2014 at 12:28, xxxxxxxx wrote:

I totally understand sampling, but this is kinda a bad approach ( I got my own samplers, so I just need the texture of the procedural texture)

isn't there a direct approach of just extracting the result of procedural texture without using the whole shader system?

I see in the worst case I would create an invisible plane with 1024 * 1024 polygons, assign a shader with luminance channel with the required procedural texture, then sample this, but this is an ugly slow approach :(

On 09/08/2014 at 14:26, xxxxxxxx wrote:

There is the problem (but no easy programmatic solution presented).  Sampling out an image texture from a procedural texture requires some parameters such as size.  The choice of size will affect how the texture renders because of its parameters (it gets even worse for 3D procedurals).  For the most part, procedural textures are applied at the point of render in the realm of texture space (UVW or whatever projection is in use).  One way to achieve what you want without sample per pixel is to define a scene with a rectangular polygon containing the texture, pointing directly at the camera with the simplest lighting scheme and rendering that out as an image.  No need to sample but your results will depend upon the render settings, lighting, render size vs. procedural parameters and so forth.

On 09/08/2014 at 15:00, xxxxxxxx wrote:

@Robert I thought of this too :) "similar to what I said in the previous reply", but it is kinda a huge work around "if the user has 20 different procedural textures of size 2k this may lead to a long pre-process?"

now rises 2 questions:
1- what about baking?
2- I thought that the procedural texture is just a function which takes an input point (x,y,z) "z is optional for 3d textures", and the values (x,y,z) are [0,1] , this makes sampling much easier you know what I mean

may be this is how it is done in displacement deformer?

On 10/08/2014 at 05:26, xxxxxxxx wrote:

There should be a way, in my mind, to do what you are asking..  When i was looking at using noise in a displacement recently, i was literally searching the entire API for any instance of noise - and there are a lot of instances.  It`s a bit of a maze tbh, there are various references to noise in the API as well as Modules folders but i did eventually find what i was looking for..

I think my point is, maybe try digging deeper into all of those references to noise in the API, and find out what the differences are.  Not all of them are just used for shaders..

On 10/08/2014 at 08:49, xxxxxxxx wrote:

Baking might be an option.

There are more parameters than procedurally creating a sample at some x,y in the texture space. There might be tilings in both or either the texture itself and possibly the Texture tag.  What if other shaders or material channels are being applied that may affect the procedural shader in question?

Because of these factors, not even considering lighting, shading, and other contributions to the rendering process, sampling the C4D shader as a passthrough to your render engine may be the only option.

On 10/08/2014 at 10:36, xxxxxxxx wrote:

well, it is just about "luxury" option in my rendering engine, wanted to give the artist more procedural textures which they are used to in Cinema4D, and material applying, Tiling, ... all can be done the same with a known texture instead of procedural texture "same concept"

so now I guess the only solution "possibly the fastest" is to create a template plane with its camera, and apply this texture to luminance channel and render this plane alone, any example in the SDK for rendering in the background? so I can catch the result internally

On 10/08/2014 at 11:14, xxxxxxxx wrote:

what about catching the texture preview slot!! ? I tested it in Cinema4D and it produces exactly what I want, any help here?

I want to size the texture preview slot , then catch whatever is there

On 10/08/2014 at 14:30, xxxxxxxx wrote:

You can set the Texture Preview Size in the Editor tab of the Material.  Don't see a similar option for Shaders though.  Use Material::GetPreview() to get a bitmap (BaseBitmap) of the texture preview. There is also a BaseShader::GetBitmap() (see docs).

On 10/08/2014 at 14:44, xxxxxxxx wrote:

@Robert thanks a lot!!, seems like what I need,but there is something that confuses me, what is the base class of procedural textures? (noise and others), I think it should be possible to create an instance of these procedural textures anywhere in Cinema4D "like xpresso, displacement deformer, ..."

so it would be like: //pseudo code

BaseTextureClass *MyTexture = new ....;

On 10/08/2014 at 15:12, xxxxxxxx wrote:

Not sure if it helps but this is how i create my noise shader:

//// NOISE BASE ////
BaseShader *noiseBase = BaseShader::Alloc(Xnoise);
BaseContainer *noiseData_BASE = noiseBase->GetDataInstance();
noiseData_BASE->SetLong(SLA_NOISE_NOISE, 2007); //Noise Type - DISP_TURB
noiseData_BASE->SetReal(SLA_NOISE_OCTAVES, 20);
noiseData_BASE->SetReal(SLA_NOISE_GLOBAL_SCALE, 35);
noiseData_BASE->SetReal(SLA_NOISE_LOW_CLIP, 0);
noiseData_BASE->SetReal(SLA_NOISE_HIGH_CLIP, 1);
noiseData_BASE->SetReal(SLA_NOISE_BRIGHTNESS, -0.04);
noiseData_BASE->SetReal(SLA_NOISE_CONTRAST, 0.81);
noiseData_BASE->SetLong(SLA_NOISE_SEED, (rand() % 1000));
op->InsertShader((BaseShader* )noiseBase, NULL);

And here`s how i drop it into a Fusion shader and apply to a Displace object:

//// FUSION MAP ////
BaseShader *fusion1 = BaseShader::Alloc(Xfusion);
BaseContainer *fusionData = fusion1->GetDataInstance();
fusionData->SetBool(SLA_FUSION_USE_MASK, TRUE);
fusionData->SetReal(SLA_FUSION_BLEND, 0.79);
fusionData->SetLink(SLA_FUSION_BASE_CHANNEL, noiseBase);
fusionData->SetLink(SLA_FUSION_MASK_CHANNEL, noiseMask);
fusionData->SetLink(SLA_FUSION_BLEND_CHANNEL, noiseBlend);
op->InsertShader(fusion1, NULL);
BaseObject *dP1 = BaseObject::Alloc(1018685);
BaseContainer *dispData = dP1->GetDataInstance();
dispData->SetLong(PRIM_AXIS, PRIM_AXIS_XP);
dispData->SetLink(ID_MG_SHADER_SHADER, fusion1);

On 10/08/2014 at 15:31, xxxxxxxx wrote:

@Eclectrik excellent!! , I think this is exactly what I need, thanks a lot,and this definitely helped me already