Есть две части этого.
Сначала вам нужно перейти на рендеринг треугольников вместо точек, и дать шейдеру вершины всех треугольников, из которых состоят ваши кубы.
Измените MeshInfo
, чтобы создатьбуфер вершин 36 * количество вершин в сетке.Это потому, что вам нужно сделать 12 треугольников для каждой вершины (2 треугольника для каждой из 6 сторон куба).Для каждой из 36 вершин вам нужно изменить ее положение, чтобы переместить ее из центра куба в один из его углов:
private void meshInfo()
{
float cubeHalfWidth = 0.01f; // determines how big the cube is.
num4vertex = 36 * meshdata.vertices;
Vector3[] newVertics = new Vector3[num4vertex];
for (int i = 0; i < meshdata.vertices; ++i)
{
Vector3 curVertex = meshdata.vertices[i];
// find corner positions
Vector3 bottomBackLeftCorner = new Vector3(curVertex.x - cubeHalfWidth, curVertex.y - cubeHalfWidth, curVertex.z - cubeHalfWidth);
Vector3 bottomFrontLeftCorner = new Vector3(curVertex.x - cubeHalfWidth, curVertex.y - cubeHalfWidth, curVertex.z + cubeHalfWidth_;
Vector3 bottomFrontRightCorner = new Vector3(curVertex.x + cubeHalfWidth, curVertex.y - cubeHalfWidth, curVertex.z + cubeHalfWidth);
Vector3 bottomBackRightCorner = new Vector3(curVertex.x + cubeHalfWidth, curVertex.y - cubeHalfWidth, curVertex.z - cubeHalfWidth);
Vector3 topBackLeftCorner = new Vector3(curVertex.x - cubeHalfWidth, curVertex.y + cubeHalfWidth, curVertex.z - cubeHalfWidth);
Vector3 topFrontLeftCorner = new Vector3(curVertex.x - cubeHalfWidth, curVertex.y + cubeHalfWidth, curVertex.z + cubeHalfWidth);
Vector3 topFrontRightCorner = new Vector3(curVertex.x + cubeHalfWidth, curVertex.y + cubeHalfWidth, curVertex.z + cubeHalfWidth);
Vector3 topBackRightCorner = new Vector3(curVertex.x + cubeHalfWidth, curVertex.y + cubeHalfWidth, curVertex.z - cubeHalfWidth)};
// create triangles, clockwise looking at visible side
int o=i*36;
// back Face
newVertics[o++] = bottomBackLeftCorner;
newVertics[o++] = topBackLeftCorner;
newVertics[o++] = topBackRightCorner;
newVertics[o++] = topBackRightCorner;
newVertics[o++] = bottomBackRightCorner;
newVertics[o++] = bottomBackLeftCorner;
// bottom Face
newVertics[o++] = bottomFrontRightCorner;
newVertics[o++] = bottomFrontLeftCorner;
newVertics[o++] = bottomBackLeftCorner;
newVertics[o++] = bottomBackLeftCorner;
newVertics[o++] = bottomBackRightCorner;
newVertics[o++] = bottomFrontRightCorner;
// front Face
newVertics[o++] = bottomFrontRightCorner;
newVertics[o++] = topFrontRightCorner;
newVertics[o++] = topFrontLeftCorner;
newVertics[o++] = topFrontLeftCorner;
newVertics[o++] = bottomFrontLeftCorner;
newVertics[o++] = bottomFrontRightCorner;
// top Face
newVertics[o++] = topBackRightCorner;
newVertics[o++] = topBackLeftCorner;
newVertics[o++] = topFrontLeftCorner;
newVertics[o++] = topFrontLeftCorner;
newVertics[o++] = topFrontRightCorner;
newVertics[o++] = topBackRightCorner;
// left Face
newVertics[o++] = bottomFrontLeftCorner;
newVertics[o++] = topFrontLeftCorner;
newVertics[o++] = topBackLeftCorner;
newVertics[o++] = topBackLeftCorner;
newVertics[o++] = bottomBackLeftCorner;
newVertics[o++] = bottomFrontLeftCorner;
// right Face
newVertics[o++] = bottomBackRightCorner;
newVertics[o++] = topBackRightCorner;
newVertics[o++] = topFrontRightCorner;
newVertics[o++] = topFrontRightCorner;
newVertics[o++] = bottomFrontRightCorner;
newVertics[o] = bottomBackRightCorner;
}
vertexbuffer = new ComputeBuffer(num4vertex, Marshal.SizeOf(newVertics.GetType().GetElementType()));
vertexbuffer.SetData(newVertics);
}
Вам также необходимо изменить MeshTopology
на Triangles
:
Graphics.DrawProceduralNow(MeshTopology.Triangles, num4vertex, num4pos);
Вторая часть заставляет кубы двигаться.Это более простой шаг.
В шейдере добавьте параметр float _moveCubeT
к шейдеру и сделайте рывок из некоторой начальной позиции в положение, которое вы уже основали на параметре _moveCubeT
:
Shader "Unlit/cshader4"
{
Properties
{
_moveCubeT ("MoveCubeT", Float) = 0
_MainTex ("Texture", 2D) = "white" {}
}
CGINCLUDE
#define time _Time.y
float3 Rotx(in float3 p,in float a){
float c,s; float3 q = p;
c = cos(a); s = sin(a);
q.y = c * p.y - s * q.z;
q.z = s * p.y + c * q.z;
return q;
}
float random(float id){
return frac(sin(id)*678.342231);
}
ENDCG
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass{
CGPROGRAM
#pragma target 5.0
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
StructuredBuffer<float3> vertexbuffer;
StructuredBuffer<float3> posbuffer;
float _moveCubeT;
struct vertIN{
uint vID : SV_VertexID;
uint ins : SV_InstanceID;
};
struct vertOUT{
float4 pos : SV_POSITION;
};
vertOUT vert(vertIN i){
vertOUT o = (vertOUT)0;
float3 startingpos = float3(0,0,0); //set starting pos for each cube here
float4 position = float4(vertexbuffer[i.vID],1);
position.xyz = Rotx(position.xyz,time*(1+random(i.ins)));
position.xyz += posbuffer[i.ins];
position.xyz = lerp(startingpos, position.xyz, _moveCubeT); // lerp based on time
o.pos = UnityObjectToClipPos(position);
return o;
}
fixed4 frag(vertOUT ou):SV_Target{
return 1;
}
ENDCG
}
}
}
Затем вернитесь в свой код C # и установите _moveCubeT
число с плавающей точкой в соответствии с тем, где кубы находятся в пути:
private void BufferSet()
{
// Move cubes for 2 seconds and pause for 8 seconds, repeat.
float t = Mathf.Clamp( (Time.time % 10f) / 2f, 0f, 1f);
cshader.SetBuffer(kernel, "posbuffer", posbuffer);
mat.SetBuffer("posbuffer", posbuffer);
mat.SetBuffer("vertexbuffer", vertexbuffer);
mat.SetFloat("_moveCubeT", t);
}
В целом, это предназначено, чтобы дать вам полностью неосвещенный, нетекстурированныйбелые кубики, которые перемещаются туда, где вершины находятся в сетке.Если вы хотите осветить, текстурировать или раскрасить эти кубики, нужно будет внести некоторые изменения, но это больше подходит для другого вопроса.
Я никогда не использовал DrawProceduralNow
, поэтому могут быть некоторые недостающие фрагменты.но это следует считать хотя бы частичным ответом.