- Home /
Need help with Shaders and material layers!
Hello Unity Answers!
This would be my first post ever, so I hope I can express my concern properly.
I am trying to find a way to optimize my current game for iOS which lags considerably only on iPhone 4 (i5 + iPad runs perfectly smooth), game running at 140fps. I am aware that using my own custom shaders and atlases would increase framerate drastically, however, I am stuck on how to get this setup and executed.
First of all let me explain the situation: I got 3 layers of materials into a single cube mesh. Each layer of material has its own texture with alpha(I understand this is not efficient but I dont know how else I could set it up). For instance, material[0] is the Border, which you might ask why I have that separated, well its because when the player selects the cube, it will change the color of the border. material[1] is the block itself, once again, I have done this because I would like to change the color of the block independently. material[2] is the face expression containing eyes,mouth, and hair. Does this layer order work or does it conflict with shaders?
From what I read this is creating 3 draw calls per block. And having about 50blocks on screen, I can see why my draw calls are so high. Having said all that, I need to find an alternative method... can anyone advice me on how to get this setup? What is a great shader with alpha for iOS? I have tried a few out there but because I have multiple layers of alpha, it is causing some kind of problem and rendering doesnt happen correctly. Sometimes it is completely black, sometimes some of the block faces are not showing. I managed to use Somian/Unlit/Transparent shader for material[0] and material[2] along with Transparent/Cutout/Diffuse for material[1] which seems to render fine, but eventually this is not optimal.
In an attempt to change it up, I have also created an atlas containing all 3 textures into 1 atlas. Now the issue is as follows: I cant add 3 layers of the same atlas with offset for each layer, how do I go about this? Do I write my own custom shader with alpha blend holding 3 textures?
I would appreciate some help here, I have been scratching my head for a whole week :/ Thanks in advance!
You could write a shader that shades only specific areas of the texture, which are UV mapped to the coordinates on your $$anonymous$$esh. Then you can simply change that value on the shader ins$$anonymous$$d of on each material seperately
I am afraid im too new with shaders to really know how to do that... is that a solution to having multiple material layers with alpha stacked up on top of each other?
This is a sample of what i am trying to achieve: http://seongs.com/Example.png
I hope you can explain further =]
Answer by whydoidoit · Aug 20, 2013 at 06:51 AM
You've got more problems than draw calls - alpha between parts of the same model will not work in Unity. This is because while objects are sorted by their depth from the camera before drawing, the individual faces of the model are not so you will always get intersecting parts where the faces are drawn in the wrong order.
The best way to do this kind of thing is to:
Make a texture atlas containing the border and face textures
Create a cube that has vertices where the border ends and the block starts
Directly set the u,v coordinates of these points in the mesh to switch colours rather than changing materials
Have the face and hair as a separate object that you position correctly infront of (or possible around) the block
Make a texture atlas for the face and hair
If you are changing simple block colours or tints consider writing your own shader that uses the vertex colours from the mesh to tint or colour whatever you need (like the faces etc). But you will need to write a shader to read that information and do something with it. (They really aren't that hard when you get uses to them, I wrote a tutorial on http://unitygems.com)
Don't be scared of changing mesh properties at run time, it's much better than changing material colours to maintain batching.
This was exactly what i was looking for.. what would I do without this community, what a life saver! So lets see if i get this right... it sounds to me that the total number of draw calls would be: 1 for block/border + 4 for faces (4 different block faces) = 5 draw calls!
Thats from an unbatched 150 draw calls down to 5 holy mother! I will check out your tutorial on shaders. Would be nice if someone could point out some nice tutorials on how to:
1) create cube with custom vertices 2) map the u,v points in mesh
Thanks again! I wish i could vote thumbs up but it doesnt let me because I am new :P
Sure so $$anonymous$$esh is documented here http://docs.unity3d.com/Documentation/ScriptReference/$$anonymous$$esh.html
You can get the procedural examples from the Asset Store https://www.assetstore.unity3d.com/#/content/5141
Would this work?
1) Create 3d cube mesh with mapped uv coordinates through blender 3d 2) Import the atlas + mesh into Unity 3) Somehow create a prefab of this cube with a plane as a child containing the face with a z-depth closer to camera (any coloring done to the mesh would only affect the texture attached to the cube, not the plane with the face) 4) Instantiate the cube prefab during runtime with a specified mesh color
Another question, how do I specify a mesh color through script during runtime?
You just need to adjust the color[] for the mesh, you basically maintain an array and then set the whole array into the mesh. Same as for uvs, tangents etc.
Answer by robertbu · Aug 20, 2013 at 05:58 AM
Writing your own shader does not solve your problem. Or rather it might make only a minor dent in your problem. The base issue is batching. For example, image you had 50 block with exactly the same material. You would have 50 draw calls, but all 50 would (likely) be batched together. If you take a look at the stats you will see then number of draw calls and the number batched. Now in your game, you change the material. You change the border when the cube is selected, and the face changes, and the look of the block changes. When you change any material property at runtime, you get a new material instance and that new instance will not batch with the original material even if all the properties are the same. So by the time something has been changed on each of the 50 blocks, the number of draw calls went from effectively one (i.e. 50 batched), to 50 separate draw calls.
More information on batching here:
http://docs.unity3d.com/Documentation/Manual/DrawCallBatching.html
One way of getting around the drawcall issue is a texture atlas and changing the UVs in the mesh. No material properties are touched at runtime. Unless you have a huge number of block looks and faces, the path of least resistance is to author all combinations and put them in a texture atlas. Say you had two borders (selected and unselected), three block looks and six faces. The would men you would have 2 3 6 = 36 possible looks. You would author all 36 and put them in a texture atlas. And depending on the state of the game, you would assign the appropriate UVs for which of those 36 is needed for a particular block.
You could simplify your problem some with a custom shader. I don't have enough shader experience to advise you on the approach to take with this shader, but you have both UV and UV2 that you can manipulate. In addition, you have vertex color you can use. So it may be possible to write a shader so that you could get away with 2 + 3 + 6 = 11 images in your atlas.
Robertbu,
Thanks for your answer. As for the selected + block body, the texture for block and border will not need to change because I would simply be manipulating the colors of the textures independently. This would mean 1 border + 1 block + 4 faces = 6 textures would be all I need in an atlas for all 50 blocks.
As for batching I am well aware of it and I am planning on doing it, I just need to know how to do this with 3-4 layers of UV mapped on top of each other with alpha (stacked).
So I guess my REAL QUESTION goes as follows:
1) Is it possible to stack 3 UV textures with alpha into the same game object like this? http://seongs.com/Example.png
2) Lets say this is possible, then I am afraid I will be running again on shader problems to get it rendered correctly. So my next question is: Does anyone know of any alpha blended shader that works for multiple stacked texture layers?
Robertbu,
Thanks for your answer. As for the selected + block body, the texture for block and border will not need to change because I would simply be manipulating the colors of the textures independently. This would mean 1 border + 1 block + 4 faces = 6 textures would be all I need in an atlas for all 50 blocks.
As for batching I am well aware of it and I am planning on doing it, I just need to know how to do this with 3-4 layers of UV mapped on top of each other with alpha (stacked).
So I guess my REAL QUESTION goes as follows:
1) Is it possible to stack 3 UV textures with alpha into the same game object like this? http://seongs.com/Example.png
2) Lets say this is possible, then I am afraid I will be running again on shader problems to get it rendered correctly. So my next question is: Does anyone know of any alpha blended shader that works for multiple stacked texture layers?
because I would simply be manipulating the colors of the textures independently
If you manipulate the colors in the material you break batching. You would have to set the vertex color in the mesh to change colors.
Thats a great point.. i read that somewhere but after so much reading.. i must have forgotten lol! mesh coloring looks like the correct way to do this. Now i need to learn how to use 3ds max sigh :/
Just to be clear about my suggestion. If you need a large or arbitrary number of faces, cube colors, or border colors, @whydoidoit's suggestion is definitely the way to go, but if you have a limited number, then a single atlas solution reduces everything to a single draw call. For example, if you have two border colors, four cube colors, and six faces, you could produce one of every combination: 2 4 6 = 48 graphics. Put them all in an atlas and write a bit of code to generate the UVs of the correct graphic based on your game state. No need to write a custom shader, and all the cubes will draw in a single draw call.
Your answer
![](https://koobas.hobune.stream/wayback/20220613112531im_/https://answers.unity.com/themes/thub/images/avi.jpg)