项目需要一个可以任意大小的包围盒,有shader可以直接实现,但是注意是任意大小, 这个shader一旦进行缩放就会有拉伸, 尝试过算上缩放值,可是由于UV的不规则性,,一直无法达到满意的效果,
先把那个shader效果和代码贴出来 ,有大佬给改一下的话就感激不尽了,
正常不缩放和缩放后的效果图如下, 没有会被拉伸.
shader代码如下
Shader "JaffHan/Wireframe" {
Properties
{
_Color("Color",Color)=(1.0,1.0,1.0,0.0)
_EdgeColor("Edge Color",Color)=(0.0,0.6,1.0,1.0)
_Width("Width",Range(0,1))=0.02
}
SubShader {
Tags {
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
}
Blend SrcAlpha OneMinusSrcAlpha
LOD 200
Cull Front
zWrite off
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
struct a2v {
half4 uv : TEXCOORD0 ;
half4 vertex : POSITION ;
};
struct v2f{
half4 pos : SV_POSITION ;
half4 uv : TEXCOORD0 ;
};
fixed4 _Color;
fixed4 _EdgeColor;
float _Width;
v2f vert(a2v v)
{
v2f o;
o.uv = v.uv;
o.pos=UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag(v2f i) : COLOR
{
fixed4 col;
float lx = step(_Width, i.uv.x);
float ly = step(_Width, i.uv.y);
float hx = step(i.uv.x, 1.0 - _Width);
float hy = step(i.uv.y, 1.0 - _Width);
col = lerp(_EdgeColor, _Color, lx*ly*hx*hy);
return col;
}
ENDCG
}
Blend SrcAlpha OneMinusSrcAlpha
LOD 200
Cull Back
zWrite off
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
struct a2v {
half4 uv : TEXCOORD0 ;
half4 vertex : POSITION ;
};
struct v2f{
half4 pos : SV_POSITION ;
half4 uv : TEXCOORD0 ;
};
fixed4 _Color;
fixed4 _EdgeColor;
float _Width;
v2f vert(a2v v)
{
v2f o;
o.uv = v.uv;
o.pos=UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag(v2f i) : COLOR
{
fixed4 col;
float lx = step(_Width, i.uv.x);
float ly = step(_Width, i.uv.y);
float hx = step(i.uv.x, 1.0 - _Width);
float hy = step(i.uv.y, 1.0 - _Width);
col = lerp(_EdgeColor, _Color, lx*ly*hx*hy);
return col;
}
ENDCG
}
}
FallBack "Diffuse"
}
由于不会改shader 写不出让自己满意的着色器,就只能用笨方法直接编网格了...留下了没有技术的泪水.
大致思路如下,先找出最大的范围,即立方体八个顶点的坐标,如下图
然后计算每个面的内四角, 由于都是直角,宽度公开出来,根据宽度算就好了,.逻辑很简单,不一一赘述,如下图是一个面的和多个面的
uv是没算的 有点懒,直接贴代码了.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WD : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
CreateBounds(gameObject);
}
public MeshRenderer CreateBounds(GameObject target)
{
List<Vector3> points = new List<Vector3>();
MeshFilter[] renders = target.GetComponentsInChildren<MeshFilter>();
foreach (MeshFilter VARIABLE in renders)
{
for (int i = 0; i < VARIABLE.mesh.vertices.Length; i++)
{
Vector3 localScale = VARIABLE.transform.localScale;
var mesh = VARIABLE.mesh;
Vector3 realPos = new Vector3(mesh.vertices[i].x * localScale.x,
mesh.vertices[i].y * localScale.y,
mesh.vertices[i].z * localScale.z);
Vector3 pos = realPos + VARIABLE.transform.position;
if (!points.Contains(pos)) points.Add(pos);
}
}
//找出xyz最大最小值
Vector3 temp;
Vector3 max = Vector3.one * float.MinValue;
Vector3 min = Vector3.one * float.MaxValue;
for (int i = 0; i < points.Count; i++)
{
temp = points[i];
if (max.x < temp.x) max.x = temp.x;
if (max.y < temp.y) max.y = temp.y;
if (max.z < temp.z) max.z = temp.z;
if (min.x > temp.x) min.x = temp.x;
if (min.y > temp.y) min.y = temp.y;
if (min.z > temp.z) min.z = temp.z;
}
//稍微大一点 不闪面
min -= (Vector3.one * 0.01f);
max += (Vector3.one * 0.01f);
var _boxGizmos = GameObject.CreatePrimitive(PrimitiveType.Cube);
MeshRenderer render = _boxGizmos.GetComponent<MeshRenderer>();
// render.material = BoxSelectUtils.GetWireframeMat();
// render.shadowCastingMode = ShadowCastingMode.Off;
_boxGizmos.transform.position = (max + min) / 2;
_boxGizmos.transform.localScale = max - min;
_boxGizmos.transform.parent = target.transform;
_boxGizmos.GetComponent<Collider>().isTrigger = true;
CreateVectices(_boxGizmos.gameObject);
render.enabled = false;
CreateBoxLine();
return render;
}
private List<Transform> vecticesTrans = new List<Transform>();
private void CreateVectices(GameObject _boxGizmos)
{
var mesh = _boxGizmos.GetComponent<MeshFilter>().mesh;
List<string> temp = new List<string>();
for (int i = 0; i < mesh.vertexCount; i++)
{
Vector3 realpos = new Vector3(
mesh.vertices[i].x * _boxGizmos.transform.localScale.x,
mesh.vertices[i].y * _boxGizmos.transform.localScale.y,
mesh.vertices[i].z * _boxGizmos.transform.localScale.z);
string te = realpos.ToString("F4");
if (!temp.Contains(te))
{
temp.Add(te);
GameObject g = new GameObject(i.ToString());
g.transform.position = realpos + _boxGizmos.transform.position;
// g.transform.SetParent(_boxGizmos.transform);
vecticesTrans.Add(g.transform);
}
}
}
public float width = 0.1f;
void CreateBoxLine()
{
var points = new List<Vector3>();
foreach (var VARIABLE in vecticesTrans)
{
points.Add(VARIABLE.position);
}
points.Add(new Vector3(points[1].x + width, points[1].y + width, points[1].z));
points.Add(new Vector3(points[0].x - width, points[0].y + width, points[0].z));
points.Add(new Vector3(points[2].x - width, points[2].y - width, points[2].z));
points.Add(new Vector3(points[3].x + width, points[3].y - width, points[3].z));
points.Add(new Vector3(points[1].x, points[1].y + width, points[1].z- width));
points.Add(new Vector3(points[7].x, points[7].y + width, points[7].z+ width));
points.Add(new Vector3(points[3].x, points[3].y - width, points[3].z- width));
points.Add(new Vector3(points[5].x, points[5].y - width, points[5].z+ width));
points.Add(new Vector3(points[7].x+width, points[7].y + width, points[7].z));
points.Add(new Vector3(points[6].x-width, points[6].y + width, points[6].z));
points.Add(new Vector3(points[5].x+width, points[5].y - width, points[5].z));
points.Add(new Vector3(points[4].x-width, points[4].y - width, points[4].z));
points.Add(new Vector3(points[6].x, points[6].y + width, points[6].z+width));
points.Add(new Vector3(points[0].x, points[0].y + width, points[0].z-width));
points.Add(new Vector3(points[4].x, points[4].y - width, points[4].z+width));
points.Add(new Vector3(points[2].x, points[2].y - width, points[2].z-width));
points.Add(new Vector3(points[3].x+width, points[3].y, points[3].z-width));
points.Add(new Vector3(points[2].x-width, points[2].y, points[2].z-width));
points.Add(new Vector3(points[5].x+width, points[5].y, points[5].z+width));
points.Add(new Vector3(points[4].x-width, points[4].y, points[4].z+width));
points.Add(new Vector3(points[0].x - width, points[0].y , points[0].z- width));
points.Add(new Vector3(points[6].x - width, points[6].y , points[6].z+ width));
points.Add(new Vector3(points[1].x + width, points[1].y , points[1].z- width));
points.Add(new Vector3(points[7].x + width, points[7].y , points[7].z+ width));
//测试各个顶点
for (int i = 8; i < points.Count; i++)
{
GameObject g = new GameObject(i.ToString());
g.transform.position = points[i];
}
List<Vector3> vertices = new List<Vector3>();
List<Vector2> uvs = new List<Vector2>();
List<int> triangles = new List<int>();
Mesh mesh = new Mesh();
vertices = points;
#region 第一个面
triangles.Add(0);
triangles.Add(9);
triangles.Add(1);
triangles.Add(1);
triangles.Add(9);
triangles.Add(8);
triangles.Add(0);
triangles.Add(2);
triangles.Add(9);
triangles.Add(2);
triangles.Add(10);
triangles.Add(9);
triangles.Add(2);
triangles.Add(3);
triangles.Add(10);
triangles.Add(10);
triangles.Add(3);
triangles.Add(11);
triangles.Add(1);
triangles.Add(8);
triangles.Add(11);
triangles.Add(1);
triangles.Add(11);
triangles.Add(3);
#endregion
#region 第二个面
triangles.Add(1);
triangles.Add(12);
triangles.Add(7);
triangles.Add(7);
triangles.Add(12);
triangles.Add(13);
triangles.Add(1);
triangles.Add(3);
triangles.Add(12);
triangles.Add(12);
triangles.Add(3);
triangles.Add(14);
triangles.Add(3);
triangles.Add(5);
triangles.Add(14);
triangles.Add(14);
triangles.Add(5);
triangles.Add(15);
triangles.Add(13);
triangles.Add(5);
triangles.Add(7);
triangles.Add(13);
triangles.Add(15);
triangles.Add(5);
#endregion
#region 第三个面
triangles.Add(7);
triangles.Add(16);
triangles.Add(6);
triangles.Add(16);
triangles.Add(17);
triangles.Add(6);
triangles.Add(7);
triangles.Add(5);
triangles.Add(18);
triangles.Add(7);
triangles.Add(18);
triangles.Add(16);
triangles.Add(5);
triangles.Add(19);
triangles.Add(18);
triangles.Add(5);
triangles.Add(4);
triangles.Add(19);
triangles.Add(17);
triangles.Add(4);
triangles.Add(6);
triangles.Add(17);
triangles.Add(19);
triangles.Add(4);
#endregion
#region 第四个面
triangles.Add(6);
triangles.Add(20);
triangles.Add(0);
triangles.Add(20);
triangles.Add(21);
triangles.Add(0);
triangles.Add(6);
triangles.Add(4);
triangles.Add(22);
triangles.Add(6);
triangles.Add(22);
triangles.Add(20);
triangles.Add(4);
triangles.Add(2);
triangles.Add(23);
triangles.Add(4);
triangles.Add(23);
triangles.Add(22);
triangles.Add(21);
triangles.Add(23);
triangles.Add(2);
triangles.Add(21);
triangles.Add(2);
triangles.Add(0);
#endregion
#region 上面
triangles.Add(5);
triangles.Add(3);
triangles.Add(24);
triangles.Add(5);
triangles.Add(24);
triangles.Add(26);
triangles.Add(3);
triangles.Add(2);
triangles.Add(25);
triangles.Add(3);
triangles.Add(25);
triangles.Add(24);
triangles.Add(2);
triangles.Add(4);
triangles.Add(27);
triangles.Add(2);
triangles.Add(27);
triangles.Add(25);
triangles.Add(5);
triangles.Add(27);
triangles.Add(4);
triangles.Add(5);
triangles.Add(26);
triangles.Add(27);
#endregion
#region 底面
triangles.Add(0);
triangles.Add(1);
triangles.Add(30);
triangles.Add(0);
triangles.Add(30);
triangles.Add(28);
triangles.Add(6);
triangles.Add(28);
triangles.Add(29);
triangles.Add(6);
triangles.Add(0);
triangles.Add(28);
triangles.Add(6);
triangles.Add(29);
triangles.Add(31);
triangles.Add(6);
triangles.Add(31);
triangles.Add(7);
triangles.Add(1);
triangles.Add(7);
triangles.Add(31);
triangles.Add(1);
triangles.Add(31);
triangles.Add(30);
#endregion
mesh.vertices = vertices.ToArray();
mesh.triangles = triangles.ToArray();
gameObject.GetComponent<MeshFilter>().mesh = mesh;
}
// private void Update()
// {
// if (vecticesTrans.Count==8)
// {
// CreateBoxLine();
// }
// }
}
补充一点, 代码获取MeshFilter的顶点的时候,要保证模型的可读写属性不然会报错