这是我目前为对象emptsh
使用的脚本,该脚本使用计算着色器使点显示在BoyMesh
网格上每个顶点所在的屏幕上。
现在,我正在尝试,而不是在屏幕上为每个BoyMesh
顶点位置显示简单的点,而是从不同的位置生成立方体,然后让它们飞到每个顶点位置(每个顶点位置一个立方体) )。有什么想法吗?
using UnityEngine;
using System.Collections;
public class emptsh : MonoBehaviour
{
public BoyMesh BoyMesh;
public Mesh meshdata;
public ComputeShader cshader;
public Material mat;
private int kernel;
private int num4pos;
private ComputeBuffer posbuffer;
private int num4vertex;
private ComputeBuffer vertexbuffer;
private void meshInfo()
{
Vector3[] vertics = meshdata.vertices;
int[] triangles = meshdata.triangles;
num4vertex = triangles.Length;
Vector3[] newVertics = new Vector3[num4vertex];
for (int i = 0; i < num4vertex; ++i)
{
newVertics[i] = vertics[triangles[i]];
}
vertexbuffer = new ComputeBuffer(num4vertex, 12);
vertexbuffer.SetData(newVertics);
}
void Start()
{
meshdata = BoyMesh.Mesh;
kernel = cshader.FindKernel("CSMain");
num4pos = 1; //this determines how many appear
//num4vertex = ;
meshInfo();
//float3
posbuffer = new ComputeBuffer(num4pos, 12);
}
private void BufferSet()
{
cshader.SetBuffer(kernel, "posbuffer", posbuffer);
mat.SetBuffer("posbuffer", posbuffer);
mat.SetBuffer("vertexbuffer", vertexbuffer);
}
private void OnRenderObject()
{
BufferSet();
//1
cshader.Dispatch(kernel, 1, 1, 1);
//2
mat.SetPass(0);
//3
Graphics.DrawProceduralNow(MeshTopology.Points, num4vertex, num4pos);
}
private void OnDestroy()
{
posbuffer.Release();
vertexbuffer.Release();
}
}
然后是实际的着色器代码:
Shader "Unlit/cshader4"
{
Properties
{
_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;
struct vertIN{
uint vID : SV_VertexID;
uint ins : SV_InstanceID;
};
struct vertOUT{
float4 pos : SV_POSITION;
};
vertOUT vert(vertIN i){
vertOUT o = (vertOUT)0;
float4 position = float4(vertexbuffer[i.vID],1);
position.xyz = Rotx(position.xyz,time*(1+random(i.ins)));
position.xyz += posbuffer[i.ins];
o.pos = UnityObjectToClipPos(position);
return o;
}
fixed4 frag(vertOUT ou):SV_Target{
return 1;
}
ENDCG
}
}
}
答案 0 :(得分:1)
有两个部分。
首先,您必须更改为渲染三角形而不是点,并为着色器提供构成立方体的所有三角形的顶点。
更改您的MeshInfo
,以创建36 *网格中顶点数量的顶点缓冲区。这是因为您需要为每个顶点制作12个三角形(对于立方体的6个面中的每个侧面都使2个三角形)。对于这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
,所以可能会有一些遗漏的地方,但这应该至少被认为是部分答案。