Unity考虑做个zbrush效果 mesh 鼠标挤压变形效果,compute shader

果然是在开玩笑。

等后面上传git代码

Unity考虑做个zbrush效果 mesh 鼠标挤压变形效果,compute shader_第1张图片


代码,用ComputeShader来运算,虽然不用遍历运算了,但是还要遍历赋值。感觉没淘到多少便宜.

using UnityEngine;

public class MeshDeformerInputByCS : MonoBehaviour
{

    float force = 1f;
    float forceOffset = 0.1f;//用于产生力的角度

    void Update()
    {
        if (Input.GetMouseButton(0))
        {
            HandleInInput();
        }

        if (Input.GetMouseButtonUp(0) )
        {
            HandleEndPression();
        }
    }

    void HandleInInput()
    {
        Ray inputRay = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        if (Physics.Raycast(inputRay, out hit))
        {
            MeshDeformerByCS deformer = hit.collider.GetComponent();
            if (deformer)
            {
                Vector3 point = hit.point;//World space
                point += hit.normal * forceOffset;//world space 用于计算受力的方向
                deformer.AddInDeformingForce(point, force);

            }
        }

    }

    void HandleEndPression()
    {
        Ray inputRay = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        if (Physics.Raycast(inputRay, out hit))
        {
            MeshDeformerByCS deformer = hit.collider.GetComponent();
            if (deformer)
            {
                deformer.ClearVertexVelocities();
            }
        }
    }
}

using UnityEngine;

struct DBuffer
{
    public Vector3 vertexPos;//作用的mesh顶点
}

[RequireComponent(typeof(MeshFilter))]
public class MeshDeformerByCS : MonoBehaviour
{
    public ComputeShader shader;
    private ComputeBuffer buffer;
    int bufferArrayLength;

    private Mesh deformingMesh;
    Vector3[] originalVertices, displacedVertices;
    Vector3[] vertexVelocities;
    new MeshCollider collider;

    public float AlphaOfVertexes = 0.5f;
    Vector3 lastPoint = Vector3.zero;
    float uniformScale = 1f;

    #region public
    public void AddInDeformingForce(Vector3 point, float force)
    {
        point = transform.InverseTransformPoint(point);
        if (lastPoint == Vector3.zero)
            lastPoint = point;

        else if (lastPoint != Vector3.zero && lastPoint != point)
        {
            lastPoint = point;
            ClearVertexVelocities();
        }

        Dispatch(force, point);
        //根据Shader返回的buffer数据更新物体信息
        DBuffer[] values = new DBuffer[bufferArrayLength];
        buffer.GetData(values);
        for (int i = 0; i < bufferArrayLength; i++)
        {
            displacedVertices[i] = values[i].vertexPos;
        }

        deformingMesh.vertices = displacedVertices;
        deformingMesh.RecalculateNormals();
        collider.sharedMesh = deformingMesh;
    }

   
    public void ReCover()
    {
        vertexVelocities = new Vector3[originalVertices.Length];
        deformingMesh.vertices = originalVertices;
        deformingMesh.RecalculateNormals();
    }

    public void ClearVertexVelocities()
    {
        vertexVelocities = new Vector3[originalVertices.Length];
    }
    #endregion

    #region unity
    void Start()
    {
        deformingMesh = transform.GetComponent().mesh;
        bufferArrayLength = deformingMesh.vertexCount;
        originalVertices = deformingMesh.vertices;
        displacedVertices = new Vector3[originalVertices.Length];
        for (int i = 0; i < originalVertices.Length; i++)
        {
            displacedVertices[i] = originalVertices[i];
        }
        vertexVelocities = new Vector3[originalVertices.Length];

        collider = GetComponent();

        CreateBuffer();
    }

    #endregion

    void CreateBuffer()
    {
        //count数组的长度(等于2个三维的积 2x2x1 * 2x2x1),40是结构体的字节长度
        buffer = new ComputeBuffer(bufferArrayLength, 12);
        DBuffer[] values = new DBuffer[bufferArrayLength];
        for (int i = 0; i < bufferArrayLength; i++)
        {
            DBuffer m = new DBuffer();
            SetStruct(ref m, displacedVertices[i]);
            values[i] = m;
        }
        // 初始化结构体并赋予buffer
        buffer.SetData(values);
    }

    void SetStruct(ref DBuffer m, Vector3 vertexPos)
    {
        m.vertexPos = vertexPos;
       
    }


    void Dispatch(float force, Vector3 pressPos)
    {
        //必须分配足够多的线程
        //int groupx = (int)Mathf.Pow(bufferArrayLength / 256, 1 / 3);
        shader.SetFloat("force", force);
        shader.SetVector("pressPos", pressPos);
        shader.SetInt("groupx", 8);
        shader.SetInt("groupy", 8);

        int kid = shader.FindKernel("CSMain");
        shader.SetBuffer(kid, "dBuffer", buffer);

        shader.Dispatch(kid, 8, 8, 8);
    }

    #region private
    #endregion

    void ReleaseBuffer()
    {
        buffer.Release();
    }
    private void OnDisable()
    {
        ReleaseBuffer();
    }
}

// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel CSMain

struct DeformBuffer
{
    float3 vertexPos;//作用的mesh顶点
};

RWStructuredBuffer dBuffer;
float force;//力
float3 pressPos;//力的作用点
uint groupx;
uint groupy;


[numthreads(8,8,8)]
void CSMain (uint3 id : SV_DispatchThreadID)
{

	int index = id.x + id.y * groupx * 8 + id.z * groupx * groupy * 8 * 8;
	
    float3 pointToVertex =  dBuffer[index].vertexPos -pressPos;
	float attenuatedForce = force / (1 +length(pointToVertex));

    float3 Velocity0 = normalize( pointToVertex) * attenuatedForce * 0.01f;
    dBuffer[index].vertexPos += Velocity0;
       
}



你可能感兴趣的:(Unity,Unity,Mesh)