[Unity] 字符风格shader

来源:互联网 发布:网络教育课程是啥子 编辑:程序博客网 时间:2024/06/03 19:24

知乎上看到字符风格的shader,然后照着自己撸了一遍代码,微做修改,增加了控制材质的C#代码
https://zhuanlan.zhihu.com/p/30775000
先看一下我实现的效果(字符由大到小,最后字符过密产生摩尔纹),素材图片在文章末尾:
这里写图片描述

思路是这样的:
将原图分割为很多个小方块,然后取小方块左上角位置的颜色,计算灰度值。
灰度值和字符图上的字符一一对应。最终就实现了字符组成的图片。当然这种左上角取颜色的方式只适合大色块的原始图。

下面是稍作修改的shader代码,注释已经写好了。

Shader "Custom/CharacterStyleShader" {    Properties    {        _MainTex ("Texture", 2D) = "white" {}        _CharTex ("Char texture", 2D) = "white" {}        //每个字符所占的uv比例,由C#传入        _WidthPerChar("Width per char", Range(0.0, 1.0)) =  0.001        //(字符图上)一共支持几个色阶        _CharCount("Char count", int) = 16        //(字符图上)每行几个色阶        _CharCountPerRow("char per row", int) = 4    }    SubShader    {        Pass        {            CGPROGRAM            #pragma vertex vert            #pragma fragment frag            #include "UnityCG.cginc"            struct appdata            {                float4 vertex : POSITION;                float2 uv : TEXCOORD0;            };            struct v2f            {                float2 uv : TEXCOORD0;                float4 vertex : SV_POSITION;            };            v2f vert (appdata v)            {                v2f o;                o.vertex = UnityObjectToClipPos(v.vertex);                o.uv = v.uv;                return o;            }            float _WidthPerChar;            sampler2D _MainTex;            int _CharCountPerRow;            int _CharCount;            sampler2D _CharTex;            fixed4 frag (v2f i) : SV_Target            {                //找到原图上网格的起点                float2 startUv = float2(floor(i.uv.x / _WidthPerChar) * _WidthPerChar, floor(i.uv.y / _WidthPerChar) * _WidthPerChar);                //找到字符图上相对网格起点的坐标                float ratio = 1.0 / _WidthPerChar / _CharCountPerRow;                float2 oppositeUv = float2((i.uv.x - startUv.x) * ratio, (i.uv.y - startUv.y) * ratio);                //计算灰度值                fixed3 color = tex2D(_MainTex, startUv).rgb;                fixed luminosity = dot(color.rgb,fixed3(0.299,0.587,0.114));                //计算灰度阶数                int greyStep = floor(luminosity * _CharCount);                //计算字符图上对应网格起点坐标                float _ReciprocalPerRow = 1.0 / _CharCountPerRow;                float2 greyStartUv = float2(floor(greyStep / _CharCountPerRow) * _ReciprocalPerRow, (greyStep % _CharCountPerRow) * _ReciprocalPerRow);                //获取                float2 greyUv = greyStartUv + oppositeUv;                return tex2D(_CharTex, greyUv);            }            ENDCG        }    }}

控制的C#代码:

//Author: 邵志恒//E-mail: zhiheng.rick@gmail.com//参考 破晓(知乎专栏) https://zhuanlan.zhihu.com/p/30775000using System.Collections;using System.Collections.Generic;using UnityEngine;[ExecuteInEditMode]public class CharacterStyleAdjust : MonoBehaviour {    [Range(0.00001f,0.1f)]    public float withPerChar = 0.001f;      //每个字符所占uv比例    public int charCount = 16;              //色阶数     [Range(1, 16)]    public int charCountPerRow = 4;         //每行色阶数    private Renderer m_Renderer;    private Material m_Mat;    private MaterialPropertyBlock m_PropBlock;    private int m_MainTexId = Shader.PropertyToID("_MainTex");    private int m_CharTexId = Shader.PropertyToID("_CharTex");    private int m_WidthPerCharId = Shader.PropertyToID("_WidthPerChar");    private int m_CharCountId = Shader.PropertyToID("_CharCount");    private int m_CharCountPerRowId = Shader.PropertyToID("_CharCountPerRow");     void Awake() {        m_PropBlock = new MaterialPropertyBlock();        m_Renderer = this.GetComponent<MeshRenderer>();        m_Mat = m_Renderer.sharedMaterial;        Debug.Log(m_Mat.name);        UpdatePropBlock();    }    // Use this for initialization    void Start () {    }    // Update is called once per frame    void Update () {        UpdatePropBlock();    }    void UpdatePropBlock()    {        m_Renderer.GetPropertyBlock(m_PropBlock);        m_PropBlock.SetFloat(m_WidthPerCharId, withPerChar);        m_PropBlock.SetFloat(m_CharCountId, charCount);        m_PropBlock.SetFloat(m_CharCountPerRowId, charCountPerRow);        m_Renderer.SetPropertyBlock(m_PropBlock);    }}

附:
字符图片:
这里写图片描述
原始图片:
这里写图片描述

原创粉丝点击