Hi there,
I am developing an app where the user can draw lines (drawings). The lines get then converted to sprites with CCRenderTexture. The problem is that after the update 1.5.0.0 the lines aren't converted anymore (or not visible).
I read the new render pipeline, especially the part about visiting in a render texture but I could not find out the problem in my code.
Following code worked fine before the update:
CCDrawNode line;
.
.
CCSize cSize = bounding.Size + FrameSize;
rtm = new CCRenderTexture(cSize, cSize);
rtm.BeginWithClear(new CCColor4B(217/255f, 217/255f, 217/255f, 1.0f));
line.AdditionalTransform = CCAffineTransform.Translate(CCAffineTransform.Identity, -bounding.Origin.X + FrameSize * 0.5f, -bounding.Origin.Y + FrameSize * 0.5f);
line.Visit();
rtm.End();
line.AdditionalTransform = CCAffineTransform.Identity;
rtm.Texture.IsAntialiased = true;
modelSprite = new CCSprite(rtm.Texture);
modelSprite.AnchorPoint = CCPoint.AnchorMiddle;
this.AddChild(modelSprite, 2)
I have attached a screenshot with before and after the update.
Anyone an idea what could be going wrong in my code?
Best regard
Posts
Hi Muhamed,
As discussed in the article on the new renderer pipeline here, you now have the ability to specify the parent transform when visiting a node. This means you don't need to attach an additional transform to achieve the behaviour you're after. Instead you can do something like the following
Although to be honest, without knowing where you're get
bounding
andFrameSize
, the transformation does seem a little strange.I think the best thing is to just clarify what you're trying to achieve. If you just want to render a drawnode into a render texture then all you should need to do is:
Hello @RamiTabbara
Many thanks for your reply!
To clarify what I'm trying to do:
In this post I asked how to correctly save a line drawing as a Sprite and got the answer:
So that's why the transformation (proposed by @kjpou1 ). Bounding is just the boundingRect of the drawnode and framesize is just 10.0.
Now all I want to do is to save the drawnode into a texture and I tried both your examples (with and without transformation) but still get an empty sprite without the drawing inside and just the background.
I am saving the rendertexture into a sprite with:
modelSprite = new CCSprite(rtm.Texture);
Is this the correct way?
There are also multiple examples of this here:
https://github.com/mono/CocosSharp/blob/master/tests/tests/classes/tests/RenderTextureTest/RenderTextureSave.cs
https://github.com/mono/CocosSharp/blob/master/tests/tests/classes/tests/RenderTextureTest/RenderTextureTestDemo.cs#L46
https://github.com/mono/CocosSharp/blob/master/tests/tests/classes/tests/RenderTextureTest/RenderTextureTestDemo.cs#L171
Those above create an image from connected lines drawn on the background image.
Here are some more:
https://github.com/mono/CocosSharp/blob/master/tests/tests/classes/tests/LabelTestNew/LabelSystemFontRenderTexture.cs
https://github.com/mono/CocosSharp/blob/master/tests/tests/classes/tests/DrawPrimitivesTest/DrawPrimitivesTest.cs#L65
https://github.com/mono/CocosSharp/blob/master/tests/tests/classes/tests/DrawPrimitivesTest/DrawPrimitivesTest.cs#L106
https://github.com/mono/CocosSharp/blob/master/tests/tests/classes/tests/DrawPrimitivesTest/DrawPrimitivesTest.cs#L143
Hello @kjpou1 , @RamiTabbara
Thank you for the links. As I said it worked perfectly before the update. As soon as I installed the update it broke. I tried every possibility in your links but still the same problem.
I tried following (which as I said worked perfectly before the update):
I have done a minimal application that does exactly the thing I want and the problem is also there. Could you please have a quick look at it?
Many thanks!
Hey Muhamed
Thanks for the code. Instead of posting back your project I will try to explain what is going on from your example. That way if anyone wants to take a look at your project and then the mods to get it to work the way you want.
In your ModelNode constructor replaced code which is a direct drop from Render Target example :
In the section of code above you are drawing to a canvasNode
DrawNode
that is basically the size of the screen. You then want to take only that part of the image that was drawn and create a smaller image version containing only that part of the image that was drawn to theDrawNode
.We added in the last release a convenience property
BoundingRect
to allow you to get this bounding region. Hmm, maybeBoundingRegion
would have been a better name instead ofBoundingRect
. Well that is neither here nor there and anyway this allows you to obtain that region.You then need to create a render target the size of this bounding area which
BoundingRect
does for you withBoundingRect.Size
. This is then used to create the render target.Because the canvas DrawNode obtains the screen points they can be anything from 0,0 to the screens width and height. You only need that section of the canvas that has been drawn to so that is obtained from the
BoundingRect.Origin
which is the lower left corner of all the primitives that were drawn to the canvas.We will create a translation transform that will offset our drawing when we do the canvasNode.Visit() so that we will only draw that section of the node to our render target.
In your GameLayer in OnTouchesEnded you are clearing the lines before the rendering has had a chance to render to the render target. Basically direct drop from Render Target example.
The Renderer Pipeline is not an immediate render process anymore as outlined in the Renderer Pipeline overview that Rami posted. Basically it takes all these draw calls and batches them up to be processed at the end of rendering cycle. So what you were doing here is clearing the lines that you had already drawn to the line DrawNode before there was a chance to process them. Thus the reason the
line.Clear()
being moved to theOnTouchesBegan
. You may need to move this someplace else in your overall application.Hope this helps.
Hej @kjpou1
Many thanks for your help and detailed explanation again!
I see now that because of my early line.Clear() call I never saw anything not even the "wrong thing"
Is there a possibility to wait for the rendering cycle to end and then call the line.Clear() method? Is this maybe in a separate thread and possible to wait for this thread to end?
Another thing is that following is not working (It used to work before the update):
rtm.BeginWithClear(new CCColor4B(217/255f, 217/255f, 217/255f, 0.8f));
While following works without problems:
rtm.BeginWithClear(CCColor4B.Gray);
Why is that?
Muhamed
There are multiple ways to achieve this:
Do not use both here but instead pick which one you want.
For your color:
new CCColor4B(217/255f, 217/255f, 217/255f, 0.8f)
CCColor4B takes values from [0 .. 255] inclusive. What you have there is what would be used for a CCColor4F which takes float values [0 .. 1] inclusive.
@kjpou1
Thanks for your reply!
It doesn't seem to work somehow:
Neither
rtm.BeginWithClear(new CCColor4B(217, 217, 217, 204))
nor
rtm.BeginWithClear (217, 217, 217, 204);
works for me... very strange...
You may be having a problem with your BlendFunc as reported here https://github.com/mono/CocosSharp/issues/252.
There is a test here for this as well as explanation in the code.
Yes it was the BlendFunc. That solved the problem many thanks!!
Great Muhamed!!