Hello Guest

Author Topic: Multiple Materials in a single Collection ?  (Read 19485 times)

n0mad

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 29
    • View Profile
Multiple Materials in a single Collection ?
« on: March 01, 2012, 10:00:43 pm »
Hello,

To enable an effect on a particular sprite, I need to assign a different material (different shader in fact, but as Shaders are bound to materials ...) than the one generated by Commit().

Whenever I put a new one into the Collection material list, and I click Commit, the list is wiped and the new material kicked out. How can I keep this material on my specific sprite without it being reverted to the generated one whenever I click Commit() ? (Commit has to happen, like when I want to add a new sprite)

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: Multiple Materials in a single Collection ?
« Reply #1 on: March 02, 2012, 12:01:08 am »
You can simply change the material which the collection generates, instead of binding a new one. It should not overwrite it then.

But your request is actually more interesting than that - what is your use case for this? Is it for one sprite within the collection, and do you need the default material on the other sprites?


n0mad

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 29
    • View Profile
Re: Multiple Materials in a single Collection ?
« Reply #2 on: March 02, 2012, 01:54:29 am »
But your request is actually more interesting than that - what is your use case for this? Is it for one sprite within the collection, and do you need the default material on the other sprites?

Yes exactly : I have a big HUD sprite collection, but I want the health bar to gain from a more complicated shader (a mask shader), and I don't want all the other sprites to use this shader for performance reasons as there are many HUD elements.

If I separate the health bar, I'd lose the benefit of packing everything into one atlas. Plus, it would add a drawcall (well it would add one even if multiple materials were supported because of 2 materials, but this could start to get messy if Collections had to be separated by material).

edit : it's ok, I found a workaround :) (But I guess some users in the future will want to have more than one material per Collection anyway)
« Last Edit: March 02, 2012, 02:05:06 am by n0mad »

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: Multiple Materials in a single Collection ?
« Reply #3 on: March 02, 2012, 11:42:13 am »
This is already in our TODO, but it will be a bit later before it gets done. The priority now is to get 1.57patch1 out (there were some nasty issues which needed fixing) and after that its the tile map editor.

n0mad

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 29
    • View Profile
Re: Multiple Materials in a single Collection ?
« Reply #4 on: March 02, 2012, 01:41:46 pm »
Thanks for your reply :)

Anyway, about that masked sprite feature, here is some suggestion that could easen you the work of implementing it in your framework in less than a few hours :

For every SpriteCollection generated atlas texture, create a clone of it, but instead of copying the Alpha values, you multiply them with another Alpha gradient going from 0 to 100, in a direction that would be decided by user (left, right, up, down).
The reason for this is to enable Alphatesting on a ramping up float value, so that every pixel of said sprite that is greater than this float would be masked.
Additionally, you could also force any RGB value into white to save space on compression.

This is the most drawcall efficient solution I found around (lurking on forums, searching, etc). The only cullprit is that PowerVR hardware really slows down from AlphaTesting, but that would be the user's choice to temper his use of MaskedSprites anyway.

The Alpha gradient script could look like that (it would be run on each separate imported sprite texture, not on the whole atlas) :

Code: [Select]
//there's a bit of pseudo code to make it clearer

if (myMaskedSpriteSetting == false)
return; // if user did not check any Masked Sprite property into the Sprite Collection Builder, no MaskedSprite atlas is created

Texture2D MaskedSpriteAtlas = new Texture2D(spriteAtlas.width, spriteAtlas.height); // this is the masked sprite clone atlas I was talking about

foreach (Texture2D tex in myImportedSpritesArray) {
//assuming the Texture2D pixel array is left to right, bottom to top (cf. docs)
Color[] newTex = tex.GetPixels();
string RevealType = myRevealSettings[mySpriteIndex] (pseudocode);

for (int y = 0; y < newTex.height; y++)
for (int x = 0; x < newTex.width; x++) {
switch (RevealType) {
case "Left-To-Right" :
newTex[x+(newTex.width*y)] = new Color(1f,1f,1f, newTex[x+(newTex.width*y)].a * x/newTex.width);
case "Right-To-Left" :
newTex[x+(newTex.width*y)] = new Color(1f,1f,1f, newTex[x+(newTex.width*y)].a * (1f-x/newTex.width));
case "Bottom-To-Top" :
newTex[x+(newTex.width*y)] = new Color(1f,1f,1f, newTex[x+(newTex.width*y)].a * y/newTex.height);
case "Top-To-Bottom" :
newTex[x+(newTex.width*y)] = new Color(1f,1f,1f, newTex[x+(newTex.width*y)].a * (1f-y/newTex.height));
}
}

// Then you export this new Texture info into MaskedSpriteAtlas (I didn't put the MaskedSprite atlas creation, you get the idea, but it should be all black with white sprites, each having an alpha gradient)
// Important : all those masked sprite UVs must be the same as the original sprites, to enable the forthcoming shader
}

Here, in the end, you would have your basic SpriteCollection Atlas, but if I checked "MaskedSprite" setting for the Health Bar in this Collection, a second atlas is generated inside the data folder, containing the mask infos.

Then, finally, the last step would be to create a special shader for these masked sprites (it would be contained in the data folder aswell, right next to classic tk2d atlas material).
Starting from the already existing tk2d premul shader :

Code: [Select]
// unlit, vertex colour, premultiplied alpha blend with mask

Shader "tk2d/PremulVertexColorWithMask"
{
Properties
{
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
_MaskTex ("Base (RGB) Trans (A)", 2D) = "white" {}
_Cutoff ("Alpha cutoff", Range (0,1)) = 0.9
}

SubShader
{
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
LOD 100

ZWrite Off
Blend One OneMinusSrcAlpha
Cull Off

BindChannels
{
Bind "Vertex", vertex
Bind "TexCoord", texcoord
Bind "Color", color
}

Pass
{
Lighting Off
AlphaTest LEqual [_Cutoff]
SetTexture [_MaskTex] { combine texture }
SetTexture [_MainTex] { combine texture * primary, previous }
}
}
}

Here, changing the _Cutoff slider value would progressively reveal the given sprite depending on its alpha gradient.
And voil? :)

I hope it helps, basic GUI functionalities like this are really vital :)
« Last Edit: March 02, 2012, 01:51:39 pm by n0mad »

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: Multiple Materials in a single Collection ?
« Reply #5 on: March 02, 2012, 02:09:33 pm »
Hey just out of curiosity - if all you are doing is clipping the sprite, have you tried the clipped sprite sample I posted here? http://unikronsoftware.com/2dtoolkit/forum/index.php/topic,115.0.html

I could be wrong - I have only glanced through your code, but this should let you do the same thing, but will be a hard clip. You also don't have to pre-define the direction, you have 4 clip regions you simply modify (left, right, top, bottom). The benefit of this is you don't have to break batching - the cost of updating these is pretty much the same as updating a frame on an animated sprite.

Let me know if this is what you're after - it will be in a later version of the toolkit when it has been tested a bit more.

I have also got some ideas to do the same thing, while being able to batch the data across sprites, and to have soft clip regions as well.

unikron

n0mad

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 29
    • View Profile
Re: Multiple Materials in a single Collection ?
« Reply #6 on: March 02, 2012, 02:14:58 pm »
Ah, thanks for the link, but unfortunately I don't have access to it :/
(not enough rights)

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: Multiple Materials in a single Collection ?
« Reply #7 on: March 02, 2012, 02:18:40 pm »
Hey, that is posted in the private support forum for registered users. Please register your copy here -
http://unikronsoftware.com/2dtoolkit/forum/index.php/topic,34.0.html

n0mad

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 29
    • View Profile
Re: Multiple Materials in a single Collection ?
« Reply #8 on: March 02, 2012, 02:20:12 pm »
Oh crap, I wanted to register yesterday in order to have access to download area, but I unfortunately deleted my Unity invoice mail back ago, ignoring it would be needed for further support :/

Is there a way to find the invoice number somewhere ?

edit : Lucky me ! I found it in an old mail archive on my comp :) I'll check it, thanks
« Last Edit: March 02, 2012, 02:24:26 pm by n0mad »

n0mad

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 29
    • View Profile
Re: Multiple Materials in a single Collection ?
« Reply #9 on: March 02, 2012, 02:29:46 pm »
Yes, this is exactely what I was looking for :)
So it doesn't add any drawcall, really ?

edit : Dumb me .... I never thought about changing UV coordinates ... lol
So of course it doesn't add any drawcall ! Nice one, I take it :) Thanks

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: Multiple Materials in a single Collection ?
« Reply #10 on: March 02, 2012, 02:40:25 pm »
I will be adding a "Register your copy of 2D Toolkit" link to the main page - it isn't obvious that there is a private support section for registered customers. Could have saved you a bit of time...

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: Multiple Materials in a single Collection ?
« Reply #11 on: March 02, 2012, 02:45:21 pm »
I will still be adding support for multiple materials for a future version - there is definitely a legitimate use for this.

n0mad

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 29
    • View Profile
Re: Multiple Materials in a single Collection ?
« Reply #12 on: March 02, 2012, 02:52:27 pm »
That's great news :)

Also, the ClippedSprite script is awesome and very intuitive. Is there any chance to make an addon version so that we can keep the existing tk2dSprite objects without having to rebuild them manually ?

(or an Overriden version of tk2dSprite maybe)

edit : Importing the scripts also pop this error : "The compiler this script was imported with is not available anymore."
« Last Edit: March 02, 2012, 02:59:42 pm by n0mad »

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: Multiple Materials in a single Collection ?
« Reply #13 on: March 02, 2012, 03:29:39 pm »
I have never seen that error before!

What version of Unity are you running? I might have exported that with a beta version of 3.5 - it shouldn't affect the actual script though.

The request to convert the sprite objects from one type to another is a valid one - I've put that in my TODO. Again, no promises on when it'll get done.

n0mad

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 29
    • View Profile
Re: Multiple Materials in a single Collection ?
« Reply #14 on: March 02, 2012, 03:37:09 pm »
Using 3.5.0f5 ^^ I restarted Unity and it hasn't appeared again though (but I deleted the ClippedSprite classes too, for the reason below)

Ok, I worked on a merge from ClippedSprite class with tk2dSprite, and it works perfectly, I attach it with this post if you want to insert it as a public update.
I also merged the ClippedSpriteEditor class with tk2dSpriteEditor to have the slides in Inspector.

Logically, there wouldn't be any reason not to include this functionality into base tk2dSprite class, as you cleverly integrated a call to SetGeometry() only if the clipped values are set again. So as long as they aren't touched at runtime, this shouldn't have any overhead at all.

One question though : I integrated the SetGeometry() function inside UpdateGeometryImpl(), but I don't really know when the latter function is called. So if it is called at moments where there is not a need to recalculate those UVs, maybe the call to SetGeometry() inside it could be conditional ? What would be that condition ? (if this assumption is exact)



edit : While I'm at it, I have another unrelated question : I do generate some icons procedurally at runtime (portraits), and I would need to pack them into a general atlas at startup. Ideally I'd like to turn them into tk2dSprites. Would this be possible with 2D Toolkit to create such a Sprite Collection at runtime ?
It would be very occasional (at startup only), so performance is not a problem.
« Last Edit: March 02, 2012, 04:03:36 pm by n0mad »