- Home /
Changing draw order of meshes in Graphics.DrawMesh()
Hi! I'm working on a game where we need to be able to draw things with 3D lines, and I've come across a road block. I'm using the Graphics.DrawMesh() function to draw each line to the screen (each line is its own procedurally generated mesh). However, I can't figure out what the best way is to modify the order in which they draw.
Here's the Draw method for a drawing:
public void Draw()
{
for (int i = 0; i < _lineMeshes.Count; i++)
{
Graphics.DrawMesh(_lineMeshes[i], transform.localToWorldMatrix, _lineMaterials[i], 0);
}
}
My first instinct was to reverse the order of the For loop, but that didn't change anything. Changing the Z position of the meshes didn't change anything, either. The issue is, every mesh that is created later is drawn later to the screen. Here's an image showing the problem:
"1" was the first mesh created, "2" second, and so on. I'd like this order to be reversed.
The shader on the lines is as follows (not sure if it helps, but maybe it's part of the problem):
Shader "Custom/LineShader"
{
Properties
{
_Color ("Main Color", Color) = (0,0,0,1)
}
SubShader {
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
Color [_Color]
Lighting Off
Cull Off
}
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
Color [_Color]
Lighting Off
Cull Off
}
}
FallBack "VertexLit"
}
Any help is appreciated! Thanks in advance
Answer by supernat · Mar 27, 2014 at 04:59 PM
The shader helps. You turned ZWrite off in the shader. If you leave z write on and change the Z value of the mesh (assuming you are looking down the Z axis), that will allow the Z value to control the order. I'm guessing DrawMesh() probably just queues the meshes up into a buffer and is not guaranteed to keep the order that you call DrawMesh in, which is unfortunate.
EDIT: Hmmm...I should clarify a couple of things. Z Write has Zero to do with the Z axis (can I call you Zorro just for fun?). Z Write is the Z Depth in the final view-projection matrix, i.e. after after everything has been transformed into the screen space, it's the Z Depth into the screen. So you could draw your numbers along the Y axis, along the X axis, and then the Y and X values would control the depth. Just wanted to clarify.
Another thought came to me. You could use the Sorting Layers and Sorting Order to order the draw calls. You can assume the default sorting layer and would only need to set the sorting order for each mesh, but I don't know the API for that off hand, and it's not listed in the Unity reference.
The other thing I thought of is that you may want the numbers to draw on top of everything else in the world, hence is why you set the Z write off. In that case, if you can't control the order in which the numbers are drawn using sorting layers, you must leave ZWrite on, and you need to render the numbers on a separate layer and with a separate camera, similar to how we would do UI. The second camera would clear the depth buffer then draw the meshes in that layer. There are several unity answers on how to render UI to a second camera if you're interested.
Thanks for the input! I'll try to work with what you've told me to fix the issue... Basically, the idea is that the player draws his own character which is used in-game, so we need the lines to draw on top of each other, but also be present in 3d space and be obscured by other objects. Thanks! :)
You'll want to think through that then. It sounds like you definitely want ZWrite on, but that means everything in the scene will need to be ordered in the Z axis (if that's what you use) and you'll want to use only 1 camera in that case. You can probably just decrement the Z value each time the user clicks and releases the mouse so that each draw is closer. It'll need to be really small amounts though so that their models can run around in the environment without leaving gaps big enough for other objects to slip through. But not too small, because then your Z resolution will cause Z fighting. To avoid that, make sure you set the near clip plane on the camera as far away as you can and the far clip plane as close as you can.
Thanks again :) we ended up going with a solution that changes the z position very slightly with every line. I wish we could have gotten a solution that would have just reversed the default behavior, but this will work for what we need it to (hopefully!).
Well the thing is, if you want to turn ZWrite off, you pretty much only have 1 choice. Everything you draw with ZWrite off must be sorted and drawn in order (I'm sure we could figure a way to get that to work but surprised Draw$$anonymous$$esh didn't). The problem then is you can't just draw anything else in the environment unless it too is sorted or unless you are okay with the stuff you draw always being on top. It sounds like you made the logically correct choice because you want your drawings to move around in the environment and be occluded by other objects. It sounds like a cool game/application, good luck with it!