一日一Shader·笔刷【SS_15_0】

前几天有人问我,看能不能实现笔刷效果。于是花了点时间研究了一下,找到了一个最简单的方案。

原理很简单,核心方法就是使用Graphics.Blit,将图传入shader中,叠加上detial,再保存该结果为RT,下次加入detial时将该结果迭代。

我实现了大部分功能,还有一些细节可以根据需要进行修改。比如笔刷的力度、边缘过渡、颜色渐变等。

如果还有其它的shader制作需求也可以留言,我会酌情实现。

代码:

using UnityEngine;

public class SS_15 : MonoBehaviour
{
    RenderTexture temp;
    public RenderTexture render;
    public Material mat;//处理叠加
    public Material targetMat;//将叠加的图片传入另一个材质中
    public int size=8;
    public float length=10;//10是plane的size
    [HideInInspector]
    public Vector2 pos;//传入0-size的值
    public float speed = 0.5f;
    float unit = 0;
    public RenderTexture Temp
    {
        get
        {
            if (temp == null)
            {
                temp = new RenderTexture(render);
            }
            return temp;
        }

        set
        {
            temp = value;
        }
    }
    void Start()
    {        
        Graphics.Blit((Texture2D)mat.GetTexture("_MainTex"),render);
        unit = length / size;
        Draw();
    }
    [ContextMenu("Draw")]
    public void Draw()
    {
        transform.position = new Vector3((pos.x+0.5f)* unit, 0,(pos.y + 0.5f )* unit);
        mat.SetFloat("_PosX", pos.x/size);
        mat.SetFloat("_PosY", pos.y/ size);
        Graphics.Blit(render, Temp, mat);//将当前图片传入mat中进行处理,结果放入temp
        Graphics.Blit(Temp, render);//将temp再传回render
        //targetMat.SetTexture("_Mask",render);//将遮罩图传入目标材质中
    }
    private void Update()
    {
        if (Input.GetKey(KeyCode.W))
        {
            pos.y+= speed;
            Draw();
        }
        if (Input.GetKey(KeyCode.S))
        {
            pos.y-= speed;
            Draw();
        }
        if (Input.GetKey(KeyCode.A))
        {
            pos.x-= speed;
            Draw();
        }
        if (Input.GetKey(KeyCode.D))
        {
            pos.x+= speed;
            Draw();
        }
    }
}
Shader "Unlit/SS_15_0"
{
    Properties
    {	
		_MainTex ("Texture", 2D) = "white" {}//不可略,否则 Graphics.Blit无法赋值
		_Detail ("Detail", 2D) = "white" {}
		_PosX("PosX",float)=0
		_PosY("PosY",float)=0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
				float2 uv1 : TEXCOORD1;
            };

            struct v2f
            {
				float2 uv : TEXCOORD0;
				float2 uv1 : TEXCOORD1;
                float4 vertex : SV_POSITION;
            };
			sampler2D _MainTex;
			fixed4 _MainTex_ST;
			sampler2D _Detail;
			fixed4 _Detail_ST;
			fixed _PosX;
			fixed _PosY;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);//不可略,因为每次RT赋值时uv都需要重置
				o.uv1 = TRANSFORM_TEX(v.uv1, _Detail);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {  
				fixed4 col=tex2D(_MainTex,i.uv);
				fixed2 _uv=fixed2(i.uv1.x-_PosX*_Detail_ST.x,i.uv1.y-_PosY*_Detail_ST.y);	//		_Detail_ST可以获取Tiling值	
				fixed4 col1=tex2D(_Detail,_uv);
                return col1*col;
            }
            ENDCG
        }
    }
}

返回目录:https://blog.csdn.net/yzy1987523/article/details/106676451

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值