- Home /
Rendering GL Lines - Z order manipulation
Hello,
So I'm rendering a grid in run time using GL immediate drawing functions. This grid however is drawing on top of my sprites. This is undesired and have failed so far to correct it's depth. I'd like some help. The below shows the grid drawing above the sprite.
Here's the code I use to setup the material being used for the line rendering.
static void CreateLineMaterial()
{
if (!_lineMaterial)
{
//Unity has a built-in shader that is useful for drawing
//simple colored things.
//https://docs.unity3d.com/ScriptReference/GL.html
//Shader shader = Shader.Find("Hidden/Internal-Colored");
Shader shader = Shader.Find("Custom/GridShader");
_lineMaterial = new Material(shader);
//_lineMaterial.renderQueue=1;
_lineMaterial.hideFlags = HideFlags.HideAndDontSave;
// Turn on alpha blending
_lineMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
_lineMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
// Turn backface culling off
_lineMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
// Turn off depth writes
_lineMaterial.SetInt("_ZWrite", -10);
_lineMaterial.SetInt("_ZTest", 0);
//_lineMaterial.SetInt("_ZTest", (int)UnityEngine.Rendering.CompareFunction.LessEqual);
//_lineMaterial = new Material("Shader \"Lines/Colored Blended\" {" +
// "SubShader { Pass { " +
// " Blend SrcAlpha OneMinusSrcAlpha " +
// " ZWrite Off Cull Off Fog { Mode Off } " +
// " ZTest Always " + //<------------------------------Added this
// " BindChannels {" +
// " Bind \"vertex\", vertex Bind \"color\", color }" +
// "} } }");
}
}
The GridShader.shader is almost identical to the Hidden/Internal-Colored shader. This is the code for that, below.
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/GridShader"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_SrcBlend ("SrcBlend", Int) = 5.0 // SrcAlpha
_DstBlend ("DstBlend", Int) = 10.0 // OneMinusSrcAlpha
_ZWrite ("ZWrite", Int) = 1.0 // On
_ZTest ("ZTest", Int) = 4.0//Always
_Cull ("Cull", Int) = 0.0 // Off
_ZBias ("ZBias", Float) = 0.0
}
SubShader
{
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Opaque" }
Pass
{
Blend [_SrcBlend] [_DstBlend]
ZWrite [_ZWrite]
ZTest [_ZTest]
//ZWrite On
//ZTest LEqual
Cull [_Cull]
Offset [_ZBias], [_ZBias]
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
float4 color : COLOR;
};
struct v2f {
fixed4 color : COLOR;
float4 vertex : SV_POSITION;
};
float4 _Color;
v2f vert (appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.color = v.color * _Color;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return i.color;
}
ENDCG
}
}
}
You can see it in action over here: twitter video post
If I manage to figure this out i'll post the answer here for anybody else struggling with this.
Answer by Bunny83 · Oct 26, 2019 at 11:04 PM
There are in general two solutions:
either make sure all involved materials do write into the depth buffer and the lines do perform a depth test
or make sure you draw your grid before you draw your sprites.
Note that "ZTest Always" essentially ignores the z buffer and always draws the lines. The usual ZTest mode is "LEqual"
We don't know how and where you draw your grid, nor how you draw your sprites.
Hey Bunny83,
Using script execution order within Unity I assumed the grid would be rendered before the sprite.
The sprite is using SpriteRenderer and exists on a gameobject with the script PlayerController.cs.
The actual grid rendering is executed within a script called OpenGL_GridController.cs. This is attached to the main camera, the one and only camera.
Grid$$anonymous$$anager.cs is a singleton that contains vector positions for the grid.
I've tested with LEqual and had no luck. I'm no expert when it comes to shader coding and assume with what I show here, it does indeed write to the depth buffer. if you know otherwise however, be cool if you pointed anything out to me =]
I've also tried changing the subshaders tags within GridShader.shader, "Queue"="Background", "RenderType"="Transparent".
I'm lost with this so far. How can I identify whether or not the material writes to the depth buffer?
No, the script execution order has no influence on the rendering. It only controls the execution of Update and similar callbacks. It's for the logic. Again it's still not clear how you draw your grid. Which callback do you use? Which methods do you use?
I didn't know, thanks.
The following is the actual grid drawing code.
public void OnPostRender()
{
OpenGLLogic();
}
public void OnRenderObject()
{
//OpenGLLogic();
}
private void OpenGLLogic()
{
//Will be called after all regular rendering is done.
CreateLine$$anonymous$$aterial();
//CreateCell$$anonymous$$aterial();
//Apply the line material.
_line$$anonymous$$aterial.SetPass(0);
//_gridCell$$anonymous$$aterial.SetPass(0);
GL.Push$$anonymous$$atrix();
$$anonymous$$atrix4x4 m = _targetTransform.localToWorld$$anonymous$$atrix;
GL.$$anonymous$$ult$$anonymous$$atrix(m);
if (!Grid$$anonymous$$anager._instance._setupRuntimeGridFlag)
return;
GL.Begin(GL.LINES);
RenderAxis();
RenderRuntimeGrid();
//RenderGridCells(_gridCell, Color.red);
GL.End();
GL.Pop$$anonymous$$atrix();
}
Note, OnPostRender() and OnRenderObject() both render the GL lines on top of my sprite.