组装一个立方体
通过组合和旋转6个平面风格来组成一个无缝立方体
上一节画了一个面向Z轴负方向的平面。我们可以画6个这样的平面然后通过Mesh.CombineMeshes
组合起来,也可以一口气画6个面
由于有一些面是共用边的。所以导致了重复的顶点。实际上重复顶点的情况还蛮常见的。特别是用于制造一些尖锐的边缘。所以可以分别做6个面,只是放在同一个数组里而已。但是不重复点更有趣。
private int CreateBottomFace (int[] triangles, int t, int ring) {
int v = 1;
int vMid = vertices.Length - (xSize - 1) * (zSize - 1);
t = SetQuad(triangles, t, ring - 1, vMid, 0, 1);
for (int x = 1; x < xSize - 1; x++, v++, vMid++) {
t = SetQuad(triangles, t, vMid, vMid + 1, v, v + 1);
}
t = SetQuad(triangles, t, vMid, v + 2, v, v + 1);
int vMin = ring - 2;
vMid -= xSize - 2;
int vMax = v + 2;
for (int z = 1; z < zSize - 1; z++, vMin--, vMid++, vMax++) {
t = SetQuad(triangles, t, vMin, vMid + xSize - 1, vMin + 1, vMid);
for (int x = 1; x < xSize - 1; x++, vMid++) {
t = SetQuad(
triangles, t,
vMid + xSize - 1, vMid + xSize, vMid, vMid + 1);
}
t = SetQuad(triangles, t, vMid + xSize - 1, vMax + 1, vMid, vMax);
}
int vTop = vMin - 1;
t = SetQuad(triangles, t, vTop + 1, vTop, vTop + 2, vMid);
for (int x = 1; x < xSize - 1; x++, vTop--, vMid++) {
t = SetQuad(triangles, t, vTop, vTop - 1, vMid, vMid + 1);
}
t = SetQuad(triangles, t, vTop, vTop - 1, vMid, vTop - 2);
return t;
}
这次自己来画法线吧!
private Vector3[] normals;
private void CreateVertices () {
…
vertices = new Vector3[cornerVertices + edgeVertices + faceVertices];
normals = new Vector3[vertices.Length];
…
mesh.vertices = vertices; mesh.normals = normals;
}
法线也可以用GIZMOS来可视化
private void OnDrawGizmos () {
if (vertices == null) {
return;
}
for (int i = 0; i < vertices.Length; i++) {
Gizmos.color = Color.black;
Gizmos.DrawSphere(vertices[i], 0.1f);
Gizmos.color = Color.yellow;
Gizmos.DrawRay(vertices[i], normals[i]);
}
}
怎么画圆角呢。想像一个小一点的立方体悬浮在原立方体中间。两个立方体面之间的距离就等于圆润度。
image.png
private void SetVertex (int i, int x, int y, int z) {
Vector3 inner = vertices[i] = new Vector3(x, y, z);
normals[i] = (vertices[i] - inner).normalized;
vertices[i] = inner + normals[i] * roundness;
}
拆分Mesh
怎么给它上贴图呢。包裹模式没法做到无缝。我们也可以使用重复顶点。或者可以创建6个单独的平面,但使用同一组顶点。然后给每个平面单独上贴图
private void CreateTriangles () {
int[] trianglesZ = new int[(xSize * ySize) * 12];
int[] trianglesX = new int[(ySize * zSize) * 12];
int[] trianglesY = new int[(xSize * zSize) * 12];
int ring = (xSize + zSize) * 2;
int tZ = 0, tX = 0, tY = 0, v = 0;
…
mesh.subMeshCount = 3;
mesh.SetTriangles(trianglesZ, 0);
mesh.SetTriangles(trianglesX, 1);
mesh.SetTriangles(trianglesY, 2);
}
只有2个面被渲染
现在立方体被分成3组面,而只有一组被显示出来了,因为有了3个分MESH,所以需要3个材质。
三个分mesh
三个材质
但是三个材质造成了多余的DRAWCALL。所以就看要选择重复顶点还是多个材质了。如果顶点计算特别昂贵的话就选择多个材质,如果DRAWCALL是瓶颈的话就选择重复顶点。
-----------------下面的看不懂。先不管----------
渲染一个网格
尽管 目前我们可以区分面,但我们还是没有纹理坐标。假设我们想渲染一个穿过整个立方体的网格图样来看到不同的矩形,怎么办呢。
用来覆盖矩形面片的纹理
除了把UV坐标存在MESH里,也许我们可以用一个自定义SHADER来解决怎么应用纹理。
Shader "Custom/Rounded Cube Grid" {
Properties {
_Color("Color", Color) = (1,1,1,1)
_MainTex("Albedo (RGB)", 2D) = "white" {}
_Glossiness("Smoothness", Range(0,1)) = 0.5
_Metallic("Metallic", Range(0,1)) = 0.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
#pragma target 3.0
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
void surf(Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
这是一个默认的SURFACE SHADER。重点是它定义了一个输入结构包含了主纹理的坐标。这些坐标用在surf
方法中,涉及了每一个被渲染的片段。因为我们没有这种坐标,所以我们需要用别的东西来替换uv_MainTex
。
struct Input
{
float2 cubeUV;
};
…
void surf(Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D(_MainTex, IN.cubeUV) * _Color;
o.Albedo = c.rgb;
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
由于UV是跟随每个顶点定义的,所以我们需要一个涉及逐个顶点的方法。
CGPROGRAM
#pragma surface surf Standard fullforwardshadows vertex:vert
#pragma target 3.0
sampler2D _MainTex;
struct Input
{
float2 cubeUV;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
void vert(inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input, o);
}
void surf(Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D(_MainTex, IN.cubeUV) * _Color;
o.Albedo = c.rgb;
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
网友评论