Python ShaderData/ChannelData problem [SOLVED]
-
On 16/12/2014 at 00:43, xxxxxxxx wrote:
Hi,
this topic is also somehow related to another one by me in the C++ section of this forum:
Custom Tile Shader problem with previewsI tried to translate my test shader that you can find in the link above to Python.
Just because it makes prototyping such stuff more comfortable that you can simply reload registered Python plugins in C4D after source code changes.But unfortunately I run into a problem here too.
Any manipulations I try to make to "cd.p" are ignored.
Here is the source code:
############################################################# ## CINEMA 4D Python Tile Shader Test ## ############################################################# ## by Thomas Chen (2014) ## ############################################################# ## Py-TileShaderTest.pyp ## ############################################################# import c4d from c4d import plugins #warning Please obtain your own plugin ID from http://www.plugincafe.com PLUGIN_ID = 1000010 class TileShaderTest(plugins.ShaderData) : tiles = 1 texture = None def __init__(self) : #if a Python exception occurs during the calculation #of a pixel colorize this one in red for debugging purposes self.SetExceptionColor(c4d.Vector(1.0, 0.0, 0.0)) def Init(self, node) : #Called when a new instance of the node plugin has been allocated. node[c4d.TILESHADERTEST_TILES] = self.tiles node[c4d.TILESHADERTEST_TEXTURE] = self.texture return True def InitRender(self, sh, irs) : #Precalculate any data for rendering. self.tiles = sh[c4d.TILESHADERTEST_TILES] self.texture = sh[c4d.TILESHADERTEST_TEXTURE] if self.texture: self.texture.InitRender(irs) return 0 def FreeRender(self, sh) : #Free any resources used for the precalculated data from InitRender() if (self.texture) : self.texture.FreeRender() self.texture = None def Output(self, sh, cd) : #Called for each point of the visible surface of a shaded object. Here you should calculate and return the channel color for the point cd.p. cd.p.x = cd.p.x * self.tiles cd.p.y = cd.p.y * self.tiles col = c4d.Vector(0.0, 0.0, 0.0) if self.texture: col = self.texture.Sample(cd) return col def RegisterTileShaderTest() : return plugins.RegisterShaderPlugin(PLUGIN_ID, "Py-TileShaderTest", 0, TileShaderTest, "xtileshadertest", 0) if __name__ == '__main__': RegisterTileShaderTest()
That seams to have no effect at all:
cd.p.x = cd.p.x \* self.tiles cd.p.y = cd.p.y \* self.tiles
I also tried to hardcode different values for "tiles" and to assign different formulas and hardcoded values to "cd.p" too.
The output is always the complete texture at the whole uv area when I return:
self.texture.Sample(cd)
Any idea what I miss here?
Kind regards,
Tom -
On 16/12/2014 at 11:54, xxxxxxxx wrote:
Hello Tom,
just assign cd.p to a variable first, like:
def Output(self, sh, cd) : x = cd.p.x *1.8 y = cd.p.y *1.8 z = cd.p.z cd.p = c4d.Vector(x,y,z) col = c4d.Vector(0.0, 0.0, 0.0) if self.texture: col = self.texture.Sample(cd) return col
Best wishes
Martin -
On 16/12/2014 at 12:22, xxxxxxxx wrote:
again,
I´ve just read your c++ post more closely.
for the other issues you can set some texflags.
cd.texflag= 0
or
cd.texflag= c4d.TEX_TILEHope this helps?
Best wishes
Martin -
On 16/12/2014 at 13:41, xxxxxxxx wrote:
Hi Martin,
thank you very much for your replies!
I'll try that immediately.But just for my understanding can you explain to me why this extra step with additional variables is necessary at all to assign new values to cd.p?
That would be really nice from you .
I just can't see the logic behind it but I want to grok what I have to do and why.~~And for the other thing with ~~
~~ cd.texflag = c4d.TEX_TILE~~
~~or
~~~~ cd.texflag = 0~~
I have still tried that myself before (at least the first version) but unfortunately I can't see any effect at all. Do you also have tried that yourself and it really worked for you?Kind regards,
TomEdit:
I now implemented your tip with the extra variables and of course it works! !Smile
[URL-REMOVED]
Though I still don't understand why but nevertheless, thank you again for that valuable hint.Edit 2:
Strange, meanwhile I also had success with cd.texflag = c4d.TEX_TILE.
Maybe the refresh hadn't worked as I tried that the first time or I don't know what the problem was.
At least it works partly in a way that all the previews and the tiling behave as expected but the mirroring is prohibited completely and the mix with no mirroring internally but the option with seamless mirroring of the shader output as a whole didn't work that way.
(Like this: or this: )Only for the editor preview but not for the rendering.
But that would just be the cherry on the cake and I can deal with the current result too if no one knows the perfect solution.Know I just have to implemenrt that in my C++ version in a similar way.
But I have to check that out tomorrow.
[URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.
-
On 17/12/2014 at 03:15, xxxxxxxx wrote:
Hi Tom,
I´m glad it is working for you!
to edit 2:
sometimes you need to delete the shader and open another one to make your script changes happen
after you´ve reloaded python shader plugin.
I´ve no experiences with this, but I guess you´ve allready tried _the c4d.TEX_MIRROR flag?
_Please let me know if you found out about the cherry.
For further explanations why we need a variable, please ask the support team.Best wishes
Martin -
On 17/12/2014 at 15:56, xxxxxxxx wrote:
Hi Tom,
Although I'm not a Python expert, apparently the *= operator exists in Python, just like in C/C++. Why not try that out?
Example:
cd.p.x *= self.tiles cd.p.y *= self.tiles
BTW, there should be no reason to have to use intermediate variables. The only reason off the top of my head is type mismatch or a close equivalent. Specifying that it's a Vector() is the only notable difference with monkeytack's working code.
I hope that helps,
Joey Gaspe
SDK Support Engineer -
On 17/12/2014 at 16:28, xxxxxxxx wrote:
Hello Joey,
your example wont work.
Please give it a try.
As your are much more a programmer than me, it would be nice to understand what´s going on.Best wishes
Martin -
On 18/12/2014 at 02:47, xxxxxxxx wrote:
Hi Joey,
Martin is right that makes no difference.
And how should it as [ _ a *= b_ ] is the same as [ _ a = a * b_ ]?But I figured out that it just don't work if you try to assign the single components of the vector seperately (what isn't really necessary for my simple example here but it might be for more complex ones)
So the following works:
cd.p *= self.tiles
as well as:
cd.p = cd.p * self.tiles
But as mentioned above it doesn't work with cd.p.x , cd.p.y and cd.p.z.
And as I said, I have no idea why that is.
(But I'd still like to understand! )Kind regards,
Tom -
On 18/12/2014 at 07:18, xxxxxxxx wrote:
Hi guys,
You have a point, and it's on our side, not Python itself. I found out that this is actually a known issue in Cinema 4D's own Vector Python code, and so will be logged as a defect.
In the mean time, you'll have to use the workaround you've found, so I'll close the topic.
Thanks,
Joey Gaspe
SDK Support Engineer