Adam's Lair Forum

game development and casual madness
It is currently 2018/04/19, 23:14

All times are UTC + 1 hour [ DST ]




Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: 2017/09/11, 14:37 
Junior Member
Junior Member

Joined: 2017/07/20, 18:17
Posts: 27
Location: Germany
Role: Hobbyist
I have a simple problem with transparency. For getting a better performance I do some pre rendering of images to a texture once and then drawing the pre rendered texture every frame. But the transparency does not work like I want it to do.

In the pre rendering of the texture I draw a pointed square and a circle within the square. The square is solid green colored while the circle is red with a half transparent alpha channel. The circle is placed before the square on the Z axis to assure it can be seen. After pre rendering when the created texture is drawn on the screen each frame you can see that the circle has a gray color. Mixing red and blue together will result in a gray color, therefore the circle in the pre rendered texture has still its alpha channel and it will be applied when drawing the pre rendered texture. But this is not what I wanted to archieve. I want the alpha blending to happen on the pre rendering and no more after it. As a result the circle should be yellow colored. It's also important to note that the pointed square is surrounded by transparency which is intended.

Here is example to demonstrate the behaviour and to show the code I used:

Code:
  public class YourCustomRenderer : Renderer, ICmpInitializable
  {
    [DontSerialize]
    private ContentRef<Material> material;

    public override float BoundRadius { get; }

    public void OnInit(InitContext context)
    {
      var terrainTexture = new Texture(400, 400);

      // Create the render target for the texture
      var renderTarget = new RenderTarget(AAQuality.High, terrainTexture);

      // Create a simple draw device for drawing on the render target / texture
      var drawDevice = new DrawDevice();
      drawDevice.Perspective = PerspectiveMode.Flat;
      drawDevice.VisibilityMask = VisibilityFlag.AllGroups | VisibilityFlag.ScreenOverlay;
      drawDevice.RenderMode = RenderMatrix.OrthoScreen;
      drawDevice.Target = renderTarget;
      drawDevice.ViewportRect = new Rect(renderTarget.Width, renderTarget.Height);

      // Begin drawing
      drawDevice.PrepareForDrawcalls();
      var canvas = new Canvas(drawDevice);

      canvas.PushState();
      canvas.State.ColorTint = new ColorRgba(0, 256, 0);
      canvas.FillPolygon(new[] { new Vector2(200, 0), new Vector2(400, 200), new Vector2(200, 400), new Vector2(0, 200) }, 0, 0, 5);
      canvas.PopState();

      canvas.PushState();
      canvas.State.ColorTint = new ColorRgba(255, 0, 0, 128);
      canvas.FillCircle(200, 200, 4, 75);
      canvas.PopState();

      // Render to target texture
      drawDevice.Render(ClearFlag.All, ColorRgba.TransparentBlack, 10f);

      // Create the material of the texture to be used on frame rendering
      this.material = new Material(DrawTechnique.Mask, ColorRgba.White, terrainTexture).GetContentRef().As<Material>();
    }

    public override void Draw(IDrawDevice device)
    {
      var canvas = new Canvas(device);
      canvas.PushState();
      canvas.State.ColorTint = ColorRgba.White;
      canvas.State.SetMaterial(this.material);
      canvas.State.TextureCoordinateRect = new Rect(0f, 0f, 1f, 1f);
      canvas.FillRect(0, 0, 10, this.material.Res.MainTexture.Res.TexelWidth, this.material.Res.MainTexture.Res.TexelHeight);
    }
    public void OnShutdown(ShutdownContext context)
    {
    }

  }


The results in the editor can be seen here:

Image

I assume there is a simple solution to this. Any help is appreciated ^^


Top
 Profile  
 
PostPosted: 2017/09/11, 16:00 
Forum Addict
Forum Addict
User avatar

Joined: 2013/09/19, 14:31
Posts: 859
Location: Italy
Role: Hobbyist
Are you maybe using some development version? I took your code exactly as it is and it appears to be working properly..

Image

_________________
Come on Duality's Discord channel. We have cookies! :mrgreen:


Top
 Profile  
 
PostPosted: 2017/09/11, 21:12 
Junior Member
Junior Member

Joined: 2017/07/20, 18:17
Posts: 27
Location: Germany
Role: Hobbyist
Thats really strange. I downloaded the latest version of Duality to be sure, but I still see a gray colored circle. There must be something special you did so it works for you :) But I have absolutely no clue what it is. I created a new scene and created a camera by myself instead of using the camera and scene given to you by Duality at the beginning. But this should be irrelevant I think. Did you have any other idea what you may have done in another way, SirePi?


Top
 Profile  
 
PostPosted: 2017/09/11, 22:09 
Forum Addict
Forum Addict
User avatar

Joined: 2013/09/19, 14:31
Posts: 859
Location: Italy
Role: Hobbyist
Nope :troubled: nothing special on my end.. just made a new Scene, added a default Camera, copypasted your code in a new Component, and it just works..

_________________
Come on Duality's Discord channel. We have cookies! :mrgreen:


Top
 Profile  
 
PostPosted: 2017/09/12, 10:59 
Junior Member
Junior Member

Joined: 2017/07/20, 18:17
Posts: 27
Location: Germany
Role: Hobbyist
Okay, thank you for your response. Then I have to wait for Adam returning from vacation. Hopefully he has an idea whats this about.


Top
 Profile  
 
PostPosted: 2017/09/14, 13:29 
Site Admin
Site Admin
User avatar

Joined: 2013/05/11, 22:30
Posts: 2042
Location: Germany
Role: Professional
Hey guys,

I think you may have stumbled upon an issue related to how alpha-to-coverage might be resolved differently on different GPUs / drivers / systems.

If you want alpha blending, you should set an alpha blend material. By default, a Canvas uses a material using a mask, not an alpha blendmode / DrawTechnique. Masking is intended for sharp cutouts, not smooth alpha gradients or 50% alpha overlays. Duality uses MSAA samples in alpha-to-coverage mode to smooth out the edges, and it technically works in a 50% alpha case as well, but (a) that will fail if the users machine doesn't support MSAA and (b) the results may vary based on drivers / GPUs / settings. If you're using mask, stick to sharp cutouts. If you need true alpha, use alpha. Should be something like:

Code:
canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White, null));


Now, why it's either grey or yellow, I'm not 100% sure, but my current guess would be that your two machines resolve the full-MSAA data differently into a color-only target, e.g. they might have different sampling or sample mixing techniques. In any case, just try the alpha approach and let me know if that works out :)

_________________
Blog | GitHub | Twitter (@Adams_Lair)


Top
 Profile  
 
PostPosted: 2017/09/14, 13:53 
Forum Addict
Forum Addict
User avatar

Joined: 2013/09/19, 14:31
Posts: 859
Location: Italy
Role: Hobbyist
One extra detail that I forgot to mention before, is that even after the texture is made, the yellow part remains transparent, like it actually cut a hole in the underlying square.
Image

_________________
Come on Duality's Discord channel. We have cookies! :mrgreen:


Top
 Profile  
 
PostPosted: 2017/09/14, 22:50 
Junior Member
Junior Member

Joined: 2017/07/20, 18:17
Posts: 27
Location: Germany
Role: Hobbyist
It behaves like you described also on my system, SirePi. The Logo can be seen through the square. But thanks, Adam. With you code it works perfectly now as can be seen here:

Image

Here the full code of the class now:
Code:
  public class YourCustomRenderer : Renderer, ICmpInitializable
  {
    [DontSerialize]
    private ContentRef<Material> material;

    public override float BoundRadius { get; }

    public void OnInit(InitContext context)
    {
      var terrainTexture = new Texture(400, 400);

      // Create the render target for the texture
      var renderTarget = new RenderTarget(AAQuality.High, terrainTexture);

      // Create a simple draw device for drawing on the render target / texture
      var drawDevice = new DrawDevice();
      drawDevice.Perspective = PerspectiveMode.Flat;
      drawDevice.VisibilityMask = VisibilityFlag.AllGroups | VisibilityFlag.ScreenOverlay;
      drawDevice.RenderMode = RenderMatrix.OrthoScreen;
      drawDevice.Target = renderTarget;
      drawDevice.ViewportRect = new Rect(renderTarget.Width, renderTarget.Height);

      // Begin drawing
      drawDevice.PrepareForDrawcalls();
      var canvas = new Canvas(drawDevice);

      canvas.PushState();
      canvas.State.ColorTint = new ColorRgba(0, 256, 0);
      canvas.FillPolygon(new[] { new Vector2(200, 0), new Vector2(400, 200), new Vector2(200, 400), new Vector2(0, 200) }, 0, 0, 5);
      canvas.PopState();

      canvas.PushState();
      canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White, null));
      canvas.State.ColorTint = new ColorRgba(255, 0, 0, 128);
      canvas.FillCircle(200, 200, 4, 75);
      canvas.PopState();

      // Render to target texture
      drawDevice.Render(ClearFlag.All, ColorRgba.TransparentBlack, 10f);

      // Create the material of the texture to be used on frame rendering
      this.material = new Material(DrawTechnique.Mask, ColorRgba.White, terrainTexture).GetContentRef().As<Material>();
    }

    public override void Draw(IDrawDevice device)
    {
      var canvas = new Canvas(device);
      canvas.PushState();
      canvas.State.ColorTint = ColorRgba.White;
      canvas.State.SetMaterial(this.material);
      canvas.State.TextureCoordinateRect = new Rect(0f, 0f, 1f, 1f);
      canvas.FillRect(0, 0, 10, this.material.Res.MainTexture.Res.TexelWidth, this.material.Res.MainTexture.Res.TexelHeight);
    }
    public void OnShutdown(ShutdownContext context)
    {
    }

  }


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group