- Home /
GPU Instancing and sorting problem
I have a project with tons of cubes (same meshes, standart cubes) in frame. Purpose of this project is to visualize data from server (from data.txt for now). From two sides meshes looks good as expected, but other two sides looks messed up, when I rotate the camera. I guess it is sorting problem, maybe even something wrong with blending.
I tried a lot of things:
-manipulating far and near clip planes
-combined meshes and then draw through drawmeshnow
-tried a lot of blend modes and culling modes
-tried anti-aliasing
I don't try writing my own sorting or working with depth buffer somehow, I just don't know where to start. I can't use occlusion culling, because it's procedural cubes. Anyone knows how to fix those artifacts? Please, give me a hint. Sorry for my terrible english
Video https://www.youtube.com/watch?v=-rg0iorJ59M
Test project https://drive.google.com/file/d/0ByatJvaR7W02a3Rna1lOSmxUcmc/view?usp=sharing
Code:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
public class BunchOfCubes : MonoBehaviour
{
public Mesh mesh; // mesh to draw (cube in this case)
public Material mat; //material to draw gpu instanced cubes
// public Vector2 size; // not used
// public Color color;
List<Matrix4x4> listMatrices;
public MatrixConteiner[] matConteiner; // container for matrices
// private List<Vector4> colors; // I used colors instead of texture ramp before. Same result.
private List<float> rampVals; //values for texture ramp
private List<MaterialPropertyBlock> blocks; // property blocks
void Start()
{
Generate();
}
public void Generate()
{
// mesh = GameObject.CreatePrimitive(PrimitiveType.Cube).GetComponent<MeshFilter>().mesh;
listMatrices = new List<Matrix4x4>();
//Props = new MaterialPropertyBlock();
// colors = new List<Vector4>();
rampVals = new List<float>();
blocks = new List<MaterialPropertyBlock>();
// for (int x = 0; x <= size.x; x++)
// {
// for (int y = 0; y < size.y; y++)
// {
// float rand = Random.Range(1f, 255f);
// Color col = Color.Lerp(Color.blue, Color.red, rand / 255f);
// // col = Color.red;
// colors.Add(col);
// listMatrices.Add(Matrix4x4.TRS(new Vector3(x, rand / 2, y), Quaternion.identity, new Vector3(1f, rand, 1f)));
// }
// }
float[,] data = DataReader.Inst.GetData();
for (int x = 0; x < data.GetLength(0); x++)
{
for (int y = 0; y < data.GetLength(1); y++)
{
// float scaleY = Random.Range(1f, 255f);
float scaleY = data[x,y];
// Color col = Color.Lerp(mat.GetColor("_Color0"), color, scaleY / 255f);
// colors.Add(col);
float rampVal = scaleY / 255f;
rampVals.Add(rampVal);
listMatrices.Add(Matrix4x4.TRS(new Vector3(x, scaleY / 2, y), Quaternion.identity, new Vector3(1f, scaleY, 1f)));
}
}
// simply split matrices and material blocks in chuncks of 1000
int len = listMatrices.Count / 1000;
if (listMatrices.Count % 1000 == 0)
matConteiner = new MatrixConteiner[len];
else
matConteiner = new MatrixConteiner[len + 1];
int q = 0;
for (int i = 0; i < listMatrices.Count; i++)
{
if ((float)(i) % 1000 == 0)
{
MaterialPropertyBlock prop = new MaterialPropertyBlock();
Matrix4x4[] mats;
int count = 0;
if (listMatrices.Count - i >= 1000) count = 1000;
else count = listMatrices.Count - i;
mats = new Matrix4x4[count];
mats = listMatrices.GetRange(i, count).ToArray();
matConteiner[q] = new MatrixConteiner(i, mats, count);
//prop.SetVectorArray("_Color", colors.GetRange(i, count));
prop.SetFloatArray("_RampVal", rampVals.GetRange(i, count));
blocks.Add(prop);
// matConteiner[i].matrix = mats;
// matConteiner[i].i = i;
// matConteiner[i].count = count;
q++;
}
}
//Props.SetVectorArray("_Color", colors);
//Initialize camera
Camera.main.GetComponent<GameCamera>().Init(new Vector3(data.GetLength(0) / 2, 0, data.GetLength(1) / 2));
}
void LateUpdate ()
{
for (int i = 0; i < matConteiner.Length; i++)
{
Graphics.DrawMeshInstanced(mesh, 0, mat, matConteiner[i].matrix, matConteiner[i].count, blocks[i], ShadowCastingMode.Off, false, 0);
}
}
public class MatrixConteiner
{
public int i;
public Matrix4x4[] matrix;
public int count;
public MatrixConteiner(int _i, Matrix4x4[] _matrix, int _count)
{
i = _i;
matrix = _matrix;
count = _count;
}
}
}
Shader Shader "Custom/TextureRamp" { Properties { _Ramp("Texture ramp", 2D) = "white" {} } SubShader { //Tags { "RenderType"="Opaque" "Queue" = "Geometry" } //"UNITY_MAX_INSTANCE_COUNT"="150" // LOD 100 Tags { "RenderType"="Opaque" "IgnoreProjector"="True" }
Pass
{
Cull Off
Blend One Zero
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// #pragma target 3.0
#pragma multi_compile_instancing
#include "UnityCG.cginc"
struct appdata
{
half4 vertex : POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
half4 vertex : SV_POSITION;
float4 col : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
uniform sampler2D _Ramp;
UNITY_INSTANCING_CBUFFER_START (Props)
UNITY_DEFINE_INSTANCED_PROP (fixed, _RampVal)
UNITY_INSTANCING_CBUFFER_END
v2f vert (appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID (v);
UNITY_TRANSFER_INSTANCE_ID (v, o);
o.vertex = UnityObjectToClipPos (v.vertex);
// o.vertex = v.vertex;
o.col = tex2Dlod(_Ramp, float4(0, UNITY_ACCESS_INSTANCED_PROP(_RampVal), 0, 0));
//o.col = UNITY_ACCESS_INSTANCED_PROP (_Color); //lerp(_Color0, UNITY_ACCESS_INSTANCED_PROP (_Color), v.vertex.y + 0.5);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// fixed4 col = _Color0;
// UNITY_SETUP_INSTANCE_ID (i);
return i.col;
//return UNITY_ACCESS_INSTANCED_PROP (_Color);
}
ENDCG
}
}
}
I tried to use 3 different cameras with different depth and far/near clip planes, but it doesn't work too. Any hint why this happening and how to solve it? Some ideas? Anyone?
I don't know how helpful that might be, but I remember that I had the same looking issue with my procedural terrain generator and surprisingly it was a problem with generation, everything else was fine. If I find some more time I'll take a look at that, but here is hint.
Thanks for reply, ThisGuyThatsHere! Of course. BunchOfCubes script above spawn cubes "procedurally". I'm not actually making procedural geometry now, just spawn a bunch of same meshes through Draw$$anonymous$$eshInstanced. So it's not broken normals or vertices or bad spacing between cubes, as far as I can tell. It's just regular unity primitive cubes, that instantiates on GPU. I also tried combining cubes in chunks using Combine$$anonymous$$eshes method, that they have about 65k vertices in each mesh and then spawn through Draw$$anonymous$$eshNow - nothing changed. I starting to think that this artifacts appears because of big different in height, color and big density of cubes and it's not possible to solve. But I hope it's somehow possible : )
Does your light have shadowing enabled? I could see the shadow buffer getting very confused by that geometry.
Thanks for reply. No lighting in scene, no lightmaps, no lighting calculation in shader, cubes instantiated with shadow casting mode turned off and with receive shadows flag set to false. Shader just returns the color of texture ramp.
Okay, next thing to look at would be the shader. I don't see anything about z-testing in there. Try adding that and see if it helps.