炫酷的汽车展示效果 Shader+ 线条生成

一、Shader 篇 命名有改动

Shader "Car/VertexColorTransform" //顶点颜色变换

{

    Properties

    {

        _MainColor("Main Color", Color) = (1,1,1,1)

        //_CubeMap("Cube Map", CUBE) = ""{}

        _ReflectAmount("Reflect Amount", Float) = 1

        _RimColorMultiply("Rim Color Multiply", Float) = 0

        _RimPower("Rim Power", Float) = 1

        _ReflFresnelPower("Reflect Fresnel Power", Float) = 1

        _ReflFresnelOffset("Reflect Fresnel Offset", Float) = 0

        _WaveLength("Wave Length", Float) = 1

        _WaveStrenth("Wave Strenth", Float) = 1

        _WaveOffset("Wave Offset", Float) = 0

        _StartPos("Start Position", Vector) = (0,0,0,0)

        _TargetColor("Target Color", Color) = (1,1,1,1)

        _OcclusionStrength("DarkColor Strength", Float) = 1

        _OcclusionOffset("DarkColor Offset", Float) = 0

        _FinalColorAdjust("FinalColorAdjust", Float) = 1.3

    }

    SubShader

    {

        Tags { "RenderType"="Opaque" "IgnoreProjector"="True"}

        CGINCLUDE

        #pragma vertex vert

        #pragma fragment frag

        #pragma fragmentoption ARB_precision_hint_fastest

        #pragma exclude_renderers xbox360 ps3 flash d3d11_9x

        fixed4 _MainColor;

        samplerCUBE _CubeMap;

        fixed _ReflectAmount;

        half _ReflFresnelPower;

        half _ReflFresnelOffset;

        half _RimColorMultiply;

        half _RimPower;

        half _WaveLength;

        half _WaveStrenth;

        half _WaveOffset;

        float4 _StartPos;

        fixed4 _TargetColor;

        fixed _OcclusionStrength;

        float _OcclusionOffset;

        float _FinalColorAdjust;

        fixed4 _LightColor0;

       

        struct VertexInput

        {

            float4 vertex:POSITION;

            fixed3 normal:NORMAL;

        };

        struct VertexOutput

        {

            float4 pos:SV_POSITION;

            fixed4 reflectDir:TEXCOORD0;

            fixed rimMultiply:TEXCOORD2;

            fixed3 transColor:TEXCOORD3;

            float4 worldPos:TEXCOORD4;

        };

        VertexOutput vert(VertexInput v)

        {

            VertexOutput output;

            //vertex offset

            fixed pi = 3.1415926535898;

            half dist = distance(_StartPos.xyz, mul(_Object2World, v.vertex).xyz);

            half x = (_WaveOffset - dist) * _WaveLength;

            half normalOffset = (sin(x + pi*0.5) + 1) * _WaveStrenth;

            normalOffset = (x > -pi && x < pi) ? normalOffset : 0;

            float4 worldPos = mul(_Object2World, v.vertex);

            worldPos.xyz += float3(mul(_Object2World, fixed4(v.normal,0)).xyz) * normalOffset;

            output.pos = mul(UNITY_MATRIX_VP, worldPos);

            x = saturate(x*0.25+0.5);

            output.transColor = lerp(_MainColor.rgb, _TargetColor.rgb, x);

            output.worldPos = worldPos;

            //light & color

            fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);

            fixed3 normalDir = normalize(mul(_Object2World, float4(v.normal, 0)).xyz);

            output.lightColor = _LightColor0.rgb * (dot(lightDir, normalDir) * 0.5 + 0.5) + UNITY_LIGHTMODEL_AMBIENT.rgb;

            fixed3 viewDir = normalize(float3((_WorldSpaceCameraPos - mul(_Object2World, v.vertex)).xyz));

            fixed NdotV = dot(normalDir, viewDir);

            output.reflectDir.xyz = reflect(-viewDir, normalDir);

            output.reflectDir.w = _ReflectAmount * pow(1-NdotV, _ReflFresnelPower) + _ReflFresnelOffset;

            output.rimMultiply = pow(1-NdotV, _RimPower) * _RimColorMultiply;

             

            return output;

        }

        fixed4 frag(VertexOutput i):COLOR

        {

            fixed4 c = fixed4(0,0,0,1);

            fixed3 cubeColor = texCUBE(_CubeMap, i.reflectDir.xyz).rgb * i.reflectDir.w;

            c.rgb = (i.transColor.rgb + cubeColor + i.transColor.rgb * i.rimMultiply) * i.lightColor;

            //final color

            c.rgb = c.rgb * saturate((i.worldPos.y + _OcclusionOffset) * _OcclusionStrength) * _FinalColorAdjust;

            return c;

        }

        ENDCG

        Pass

        {

            Tags{"LightMode"="ForwardBase"}

            CGPROGRAM

            #define UNITY_PASS_FORWARDBASE

            #define multi_compile_fwdbase_fullshadows

            ENDCG

        }

    }

}

二、线条生成

using UnityEngine;
using DG.Tweening;
 
public class RectMesh : PrimitiveBase
{
    [SerializeField]
    private float m_Width;
    [SerializeField]
    private float m_Length;
    public enum PivotAlign { Left, Center, Right }
    public PivotAlign widthAlign = PivotAlign.Center;//宽度方向的中心点
    public PivotAlign lengthAlign = PivotAlign.Center;//长度方向的中心点
    /// <summary>
    /// 宽度
    /// </summary>
    public float width
    {
        get { return m_Width; }
        set { m_Width = value; UpdateShape(); }
    }
    /// <summary>
    /// 长度
    /// </summary>
    public float length
    {
        get { return m_Length; }
        set { m_Length = value; UpdateShape(); }
    }
    /// <summary>
    /// x方向的偏移
    /// </summary>
    public float offsetX
    {
        get { return offset.x; }
        set { offset.x = value; UpdateShape(); }
    }
    protected override void UpdateShape()
    {
        if (cacheTransform == null || meshFilter == null)
        {
            Init();
        }

        Vector3 localPos = offset;
        float w2 = m_Width * 0.5f;
        float l2 = m_Length * 0.5f;

        vertices = new Vector3[4];

        float x0, z0, x1, z1, x2, z2, x3, z3;
        x0 = z0 = x1 = z1 = x2 = z2 = x3 = z3 = 0;

        switch (widthAlign)
        {
            case PivotAlign.Center:x0 = -w2;x1 = w2;x2 = -w2;x3 = w2;break;
                case PivotAlign.Left:x0 = 0f;x1 = m_Width; x2 = 0f;x3 = m_Width;break;
            case PivotAlign.Right:x0 = -m_Width;x1 = 0f;x2 = -m_Width;x3 = 0f;break;
        }
        switch(lengthAlign)
        {
            case PivotAlign.Center:z0 = -l2;z1 = -l2;z2=l2;z3 = l2;break;
            case PivotAlign.Left:z0 = 0f;z1 = 0;z2 = m_Length;z3 = m_Length;break;
            case PivotAlign.Right:z0 = -m_Length;z1 = -m_Length;z2 = 0f;z3 = 0f;break;
        }

        vertices[0].x = localPos.x + x0;
        vertices[0].y = localPos.y;
        vertices[0].z = localPos.z + z0;

        vertices[1].x = localPos.x + x1;
        vertices[1].y = localPos.y;
        vertices[1].z = localPos.z + z1;

        vertices[2].x = localPos.x + x2;
        vertices[2].y = localPos.y;
        vertices[2].z = localPos.z + z2;

        vertices[3].x = localPos.x + x3;
        vertices[3].y = localPos.y;
        vertices[3].z = localPos.z + z3;

        UpdateMesh();
    }
    protected override void InitMesh()
    {
        if (cacheTransform == null || meshFilter == null)
        {
            Init();
        }
 
        triangles = new int[] { 0, 2, 3, 0, 3, 1 };

        uvs = new Vector2[4];
        uvs[0].x = 0; uvs[0].y = 0;
        uvs[1].x = 1; uvs[1].y = 0;
        uvs[2].x = 0; uvs[2].y = 1;
 
        normals = new Vector3[4];
        normals[0].y = normals[1].y = normals[2].y = normals[3].y = 1;
 
        UpdateShape();
    }
    public Tweener DoLength(float endValue, float duration, float delay)
    {
        return DOTween.To(() => length, x => length = x, endValue, duration).SetDelay(delay);
    }
    public Tween DoWidth(float endValue, float duration, float delay)
    {
        return DOTween.To(() => width, x => width = x, endValue, duration).SetDelay(delay);
    }
}

using UnityEngine;
     
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))][ExecuteInEditMode]
public class PrimitiveBase : MonoBehaviour 
{
    /// <summary>
    /// 偏移
    /// </summary>
    public Vector3 offset;
    protected MeshFilter meshFilter;
    public Transform cacheTransform;
    void Awake()
    {
        Init();
        InitMesh();
    }
    protected void Init()
    {
        cacheTransform = transform;
        meshFilter = GetComponent<MeshFilter>();
        meshFilter.sharedMesh = new Mesh();
    }
    protected virtual void InitMesh()
    {

    }
    protected Vector3[] vertices;
    protected int[] triangles;
    protected Vector2[] uvs;
    protected Vector3[] normals;
    protected void UpdateMesh()
    {
        if(meshFilter.sharedMesh == null)
        {
            meshFilter.sharedMesh = new Mesh();
        }
        meshFilter.sharedMesh.vertices = vertices;
        meshFilter.sharedMesh.triangles = triangles;
        meshFilter.sharedMesh.uv = uvs;
        meshFilter.sharedMesh.normals = normals;
    }
    protected virtual void UpdateShape()
    {

    }
    void OnValidate()
    {
        InitMesh();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值