Posts Tagged alpha

Masking textures using shaders NGUI

If you follow this blog, you know that I am having some problems with Unity3d and NGUI. Mostly it’s because I was so familiar with Flash/AS3 that I am feeling kinda lost. But I am getting better at this 2D in a 3D world thing. One of the thing that I miss the most is masks. In Flash they are very easy to use and with them you can do a plethora of effects and animations. Now with bitmap based technologies, it is not such a simple task to implement a mask.

Clipping

NGUI Panels have the option of being clipped panels, which means that only a rectangle of the panel will be shown. This is great for some cases, like when you need your masked region to be a rectangle, but for most masking cases it won’t work. Also, it doesn’t allow nested clipping which is a bummer.

Using another camera

Also, this guy created a shader that allows you to do similar masking as in Flash. It looks good, and it does the desired effect, but there is one drawback, for every mask, you need a new camera… That makes it very hard to manage in a large project or if you have multiple masks. I would use clipping more than this technique because it is easier to deal with.

Transparency shader

Now, this is the technique I devised that allows you to have multiple textures masked at the same time each with their own masks. This is really good if you load images (thumbnails) from a server and need them to be masked.

To do it we need to create a new shader. We start that by taking the Unlit – Transparent Colored shader and we will add two lines of code to it. First we will give it another texture for input. Secondly, we will take the output of the shader, use its rgb colors, but use the alpha of the new input texture we added.  Here is the code :

Shader "Unlit/Transparent Colored with mask" {
  Properties {
    _MainTex ("Base (RGB), Alpha (A)", 2D) = "white" {}
    _AlphaTex ("Yeahyeah", 2D) = "white" {}
  }
 
  SubShader{
    LOD 100
 
    Tags{
      "Queue" = "Transparent"
      "IgnoreProjector" = "True"
      "RenderType" = "Transparent"
    }
 
    Pass {
      Cull Off
      Lighting Off
      ZWrite Off
      Fog { Mode Off }
      Offset -1, -1
      ColorMask RGB
      AlphaTest Greater .01
      Blend SrcAlpha OneMinusSrcAlpha
      ColorMaterial AmbientAndDiffuse
 
      SetTexture [_MainTex] {
        Combine Texture * Primary
      }
 
      SetTexture [_AlphaTex] {
        Combine previous, texture
      }
    }
  }
}

So that is the shader, but now we have to use it. This is actually what I found to be the most difficult part because there is a lot of documentation about how to make shaders, but not how to use them. So in the next chunk of code, we will create a texture in NGUI, give it a shader. After that we will feed the shader the textures it need to calculate the mask.

_newTexture = NGUITools.AddWidget<UITexture>(gameObject);
_newTexture.pivot = UIWidget.Pivot.TopLeft;
_newTexture.material = new Material(Shader.Find("Unlit/Transparent Colored with mask"));
_newTexture.mainTexture = myTexture2D;
_newTexture.MakePixelPerfect();
 
//now we give the shader the textures
 
_newTexture.material.SetTexture(<wbr />"_MainTex", testRed);
_newTexture.material.SetTexture(<wbr />"_AlphaTex", testAlpha);

In this testRed is the image we want to mask and testAlpha is the alpha channel we want our previous image to use.

So here you have it, I will add pictures later to illustrate it better, but for now that’s how it is. Note that with this technique you can’t really animate or nest the masks, but you can have a lot of them at the same time.

UPDATE : If you are using a version of NGUI that is higher than 2.64, you should probably use this shader instead.

, , , , , , , ,

3 Comments


BlendMode.LAYER; A must when changing the alpha property of a DisplayObject containing other DisplayObjects

I don’t know if you ever tweened a MovieClip’s alpha while this MovieClip contained multiple assets, but I kinda do this all the time (fade in ,fade out being the easiest transition for almost everything). The default way Flash handles this is by changing the alpha of every assets in the containing MovieClip (or Sprite). Sometimes it doesn’t matter but most of the time that’s not the behavior you would like it to have. When you have shapes or bitmaps that overlap or hide other graphical assets you will see what is under it when changing the alpha instead of actually changing the alpha of the container as if it was a whole.

Well I don’t know if it’s clear but I have an example below that should clarify that. Anyway, I have stumbled upon the solution to this while browsing through the help files for BlendMode. If you set the blendMode of your containing DisplayObject to BlendMode.LAYER Flash will consider this DisplayObject as only one layer and will change the alpha the way you normally think it would.

Here is the example that will illustrate my point better. The left Sprite is the reference object, the middle Sprite has no blendMode on and the right Sprite has a blendMode of BlendMode.LAYER. Mostly look at the colors while tweening and the overlapping regions of the green and blue ellipses.

I really wish I had found this earlier and I hope this will help others that were in my situation.

Cet article en Français

, , , ,

18 Comments


Converting a RGB color and Alpha to ARGB in ActionScript 3

So I was using the color picker component that comes with the Flash IDE. When the user selects a color, the color picker fire a ColorPickerEvent.CHANGE event and from that event you can access the new color that was chosen. The format of this color is a uint; when working with colors I am more used to the hexadecimal format.  From the event you can also access to the hexadecimal value, but as a String which is not that useful if you want to do operation on the color.

The color you get from the color picker component is in the RGB format, so no transparency. If you want to add an alpha channel to that color (converting it to ARGB), let’s say to use the setPixel32 method of the BitmapData class  and produce Bitmap with transparency, you’re going to have to modify the uint you can do so using this simple function (AS3):

1
2
3
4
5
6
7
private function returnARGB(rgb:uint, newAlpha:uint):uint{
  //newAlpha has to be in the 0 to 255 range
  var argb:uint = 0;
  argb += (newAlpha<<24);
  argb += (rgb);
  return argb;
}

What this function does is that it bit shift the value of the Alpha you input and adds it to the original RGB color making it ARGB. You see, RGB format uses 8 bits for each color for each pixel (so 24 bits for each pixel), when you add transparency, the alpha channel takes up another 8 bits for each pixels (making it 32 bits for each pixel thus the 32 in setPixel32). That also explains why newAlpha has to be from 0 to 255, because 255 is the highest number you can store in 8 bits. The Blue color takes the bits from 1 to 8, the Green color takes the bits from 9 to 16, Red from 17 to 24 and finally Alpha from 25 to 32. This is why we bit shift alpha from 24 bits (newAlpha<<24);

I don’t use the color picker component often, but there seem to be missing the end of the sentence here.

, , , , , , ,

8 Comments