Unity Shader学习:水墨效果

偶然在网上看到9级铁甲蛹大神的水墨风格后处理觉得挺有意思,参照着实现一下,还是涉及到之前油画效果的算法,叫什么滤波暂时不清楚,应该用来处理手绘效果挺多的。

水墨风格基本原理:高斯模糊原始图像,用深度算出边缘进行描边,最后用画笔效果的滤波完成最终图像。



有需要可以用Post Proces改变颜色范围,更接近水墨的颜色。


c#部分:

//屏幕后处理基类
using UnityEngine;
using System.Collections;//非运行时也触发效果
[ExecuteInEditMode]
//屏幕后处理特效一般都需要绑定在摄像机上
[RequireComponent(typeof(Camera))]
//提供一个后处理的基类,主要功能在于直接通过Inspector面板拖入shader,生成shader对应的材质
public class PostEffectBase : MonoBehaviour
{//Inspector面板上直接拖入public Shader shader = null;private Material _material = null;public Material _Material{get{if (_material == null)_material = GenerateMaterial(shader);return _material;}}//根据shader创建用于屏幕特效的材质protected Material GenerateMaterial(Shader shader){if (shader == null)return null;//需要判断shader是否支持if (shader.isSupported == false)return null;Material material = new Material(shader);material.hideFlags = HideFlags.DontSave;if (material)return material;return null;}}
//挂在摄像机上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;[ExecuteInEditMode]
public class ChineseInkPostEffect : PostEffectBase {/// <summary>/// 降分辨率未操作/// </summary>[Range(0,5)]public int downSample = 1;/// <summary>/// 高斯模糊采样缩放系数/// </summary>[Range(0,5)]public int samplerScale = 1;/// <summary>/// 高斯模糊迭代次数/// </summary>[Range(0,10)]public int count = 1;/// <summary>/// 边缘宽度/// </summary>[Range(0.0f,10.0f)]public float edgeWidth = 3.0f;/// <summary>/// 边缘最小宽度/// </summary>[Range(0.0f,1.0f)]public float sensitive = 0.35f;/// <summary>/// 画笔滤波系数/// </summary>[Range(0,10)]public int paintFactor = 4;/// <summary>/// 噪声图/// </summary>public Texture noiseTexture;private Camera cam;private void Start(){cam = GetComponent<Camera>();//开启深度法线图cam.depthTextureMode = DepthTextureMode.DepthNormals;}private void OnRenderImage(RenderTexture source, RenderTexture destination){if (_Material){RenderTexture temp1 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);RenderTexture temp2 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);Graphics.Blit(source, temp1);for (int i = 0; i < count; i++){//高斯模糊横向纵向两次(pass0)_Material.SetVector("_offsets", new Vector4(0, samplerScale, 0, 0));Graphics.Blit(temp1, temp2, _Material, 0);_Material.SetVector("_offsets", new Vector4(samplerScale, 0, 0, 0));Graphics.Blit(temp2, temp1, _Material, 0);}//描边(pass1)_Material.SetTexture("_BlurTex", temp1);_Material.SetTexture("_NoiseTex", noiseTexture);_Material.SetFloat("_EdgeWidth", edgeWidth);_Material.SetFloat("_Sensitive", sensitive);Graphics.Blit(temp1, temp2,_Material,1);//画笔滤波(pass2)_Material.SetTexture("_PaintTex", temp2);_Material.SetInt("_PaintFactor", paintFactor);Graphics.Blit(temp2, destination, _Material, 2);RenderTexture.ReleaseTemporary(temp1);RenderTexture.ReleaseTemporary(temp2);}}
}

shader部分:

Shader "Unlit/ChineseInk"
{Properties{//原始画面_MainTex ("Texture", 2D) = "white" {}//高斯模糊画面_BlurTex("Blur",2D) = "white"{}//水墨画面_PaintTex("PaintTex",2D)="white"{}}CGINCLUDE#include "UnityCG.cginc"//深度法线图sampler2D _CameraDepthNormalsTexture;sampler2D _MainTex;sampler2D _BlurTex;sampler2D _PaintTex;sampler2D _NoiseTex;float4 _BlurTex_TexelSize;float4 _MainTex_ST;float4 _MainTex_TexelSize;float4 _PaintTex_TexelSize;float4 _offsets;float _EdgeWidth;float _Sensitive;int _PaintFactor;//取灰度float luminance(fixed3 color) {return 0.2125*color.r + 0.7154*color.g + 0.0721*color.b;}//高斯模糊部分struct v2f_blur{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;float4 uv01:TEXCOORD1;float4 uv23:TEXCOORD2;float4 uv45:TEXCOORD3;};v2f_blur vert_blur(appdata_img v){v2f_blur o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.texcoord.xy;_offsets *= _MainTex_TexelSize.xyxy;o.uv01 = v.texcoord.xyxy + _offsets.xyxy*float4(1, 1, -1, -1);o.uv23 = v.texcoord.xyxy + _offsets.xyxy*float4(1, 1, -1, -1)*2.0;o.uv45 = v.texcoord.xyxy + _offsets.xyxy*float4(1, 1, -1, -1)*3.0;return o;}float4 frag_blur(v2f_blur i) : SV_Target{float4 color = float4(0,0,0,0);color += 0.40*tex2D(_MainTex, i.uv);color += 0.15*tex2D(_MainTex, i.uv01.xy);color += 0.15*tex2D(_MainTex, i.uv01.zw);color += 0.10*tex2D(_MainTex, i.uv23.xy);color += 0.10*tex2D(_MainTex, i.uv23.zw);color += 0.05*tex2D(_MainTex, i.uv45.xy);color += 0.05*tex2D(_MainTex, i.uv45.zw);return color;}//边缘检测部分struct v2f_edge{float2 uv:TEXCOORD0;float4 vertex:SV_POSITION;};v2f_edge vert_edge(appdata_img v){v2f_edge o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.texcoord;return o;}float4 frag_edge(v2f_edge i):SV_Target{//噪声float n = tex2D(_NoiseTex,i.uv).r;float3 col0 = tex2D(_CameraDepthNormalsTexture, i.uv + _EdgeWidth * _BlurTex_TexelSize.xy*float2(1,1)).xyz;float3 col1 = tex2D(_CameraDepthNormalsTexture, i.uv + _EdgeWidth * _BlurTex_TexelSize.xy*float2(1,-1)).xyz;float3 col2 = tex2D(_CameraDepthNormalsTexture, i.uv + _EdgeWidth * _BlurTex_TexelSize.xy*float2(-1, 1)).xyz;float3 col3 = tex2D(_CameraDepthNormalsTexture, i.uv + _EdgeWidth * _BlurTex_TexelSize.xy*float2(-1,-1)).xyz;float edge = luminance(pow(col0 - col3, 2) + pow(col1 - col2, 2));edge = pow(edge, 0.2);if (edge<_Sensitive){edge = 0;}else{edge = n;}float3 color = tex2D(_BlurTex, i.uv);float3 finalColor = edge * float3(0, 0, 0) + (1 - edge)*color*(0.95+0.1*n);return float4(finalColor, 1.0);}//画笔滤波部分struct v2f_paint {float2 uv:TEXCOORD0;float4 vertex:SV_POSITION;};v2f_paint vert_paint(appdata_img v) {v2f_paint o;o.uv = v.texcoord;o.vertex = UnityObjectToClipPos(v.vertex);return o;}float4 frag_paint(v2f_paint i):SV_Target{float3 m0 = 0.0;float3 m1 = 0.0;float3 s0 = 0.0;float3 s1 = 0.0;float3 c = 0.0;int radius = _PaintFactor;int r = (radius + 1)*(radius + 1);for (int j = -radius; j <= 0; ++j){for (int k = -radius; k <= 0; ++k){c = tex2D(_PaintTex, i.uv + _PaintTex_TexelSize.xy * float2(k, j)).xyz;m0 += c;s0 += c * c;}}for (int j = 0; j <= radius; ++j){for (int k = 0; k <= radius; ++k){c = tex2D(_PaintTex, i.uv + _PaintTex_TexelSize.xy * float2(k, j)).xyz;m1 += c;s1 += c * c;}}float4 finalFragColor = 0.;float min_sigma2 = 1e+2;m0 /= r;s0 = abs(s0 / r - m0 * m0);float sigma2 = s0.r + s0.g + s0.b;if (sigma2 < min_sigma2){min_sigma2 = sigma2;finalFragColor = float4(m0, 1.0);}m1 /= r;s1 = abs(s1 / r - m1 * m1);sigma2 = s1.r + s1.g + s1.b;if (sigma2 < min_sigma2){min_sigma2 = sigma2;finalFragColor = float4(m1, 1.0);}return finalFragColor;}ENDCGSubShader{Pass{CGPROGRAM#pragma vertex vert_blur#pragma fragment frag_blurENDCG}Pass{CGPROGRAM#pragma vertex vert_edge#pragma fragment frag_edgeENDCG}Pass{CGPROGRAM#pragma vertex vert_paint#pragma fragment frag_paintENDCG}}
}

Unity Shader学习:水墨效果相关推荐

  1. Unity Shader 学习笔记(33) 全局光照(GI)、反射探针、线性空间和伽马空间、高动态范围(HDR)

    Unity Shader 学习笔记(33) 全局光照(GI).反射探针.线性空间和伽马空间.高动态范围(HDR) 参考书籍:<Unity Shader 入门精要> [<Real-Ti ...

  2. Unity Shader学习-高光反射

    Unity Shader学习-高光反射 高光反射计算公式 高光反射 = 光源的色彩和强度 * 材质的高光反射系数 * pow(max(0,视角方向 · 反射方向),_Gloss) 视角方向 = ref ...

  3. Unity Shader学习:SSAO屏幕环境光遮蔽

    Unity Shader学习:SSAO屏幕环境光遮蔽 主要思路:1.随机采样像素法线半球周围的像素,平均对比与该像素深度是否处在暗处.2.双边滤波去噪点.3.后期AO图与原图混合. 原文链接:http ...

  4. Unity Shader学习:动态模糊(shutter angle方式)

    Unity Shader学习:动态模糊 动态模糊一般有帧混合和motion vector两种,这里主要介绍motion vector的方法. Keijiro源码:https://github.com/ ...

  5. Unity Shader学习:体积光/体积阴影

    Unity Shader学习:体积光/体积阴影 在前向渲染下实现平行光的体积光影效果,需要全屏深度图,延迟渲染会更划算. 思路:通过ray marching的步进点位置计算该点是否在阴影中,采样阴影贴 ...

  6. Unity Shader学习:SSR屏幕空间反射

    Unity Shader学习:SSR屏幕空间反射 本文在前向渲染模式下实现,延迟渲染更适合SSR,这里只简单的实现下,未作更深入的优化. 思路:沿视线和法线的反射向量步进光线,判断打到物体(这里用的是 ...

  7. Unity Shader学习:Dissolve消融效果

    Unity Shader学习:Dissolve消融效果 消融效果在游戏里非常常用,这里简单的实现下,代码里用到了if分支在shader里可能会费一点,如果想直接用puppet_master大佬版本的话 ...

  8. 《Unity Shader入门精要》学习笔记第5章 开始Unity Shader学习之旅

    本文章用于帮助自己学习,因此只记录一些个人认为比较重要或者还不够熟悉的内容. 原作者:http://blog.csdn.net/candycat1992/article/ 第五章 开始Unity Sh ...

  9. Unity Shader 学习笔记(3)URP渲染管线带阴影PBR-Shader模板(ASE优化版本)

    此 Shader 已经不是最新版本,最新版本见本专栏的第四篇文章: Unity Shader 学习笔记(4) 材质面板截图: 功能实现(URP渲染管线下): PBR材质.投射和接收阴影. 代码展示: ...

最新文章

  1. 【Redis】Redis学习(三) Redis 主从模式详解
  2. Android跑马灯
  3. 第二天,终于搞定 —— 2014.10.28
  4. jsp整合mybatis案例
  5. 世界坐标系到观察坐标系的变换步骤_带你轻松认识不同坐标系下向量的“变脸”——基变换...
  6. Java 数据库连接池的技术选型都应考虑哪些要素
  7. 判断sem信号量为零_kernel.sem信号量调优
  8. JS设计模式——10.门面模式
  9. Spring+Struts集成(方案一)
  10. poj2513 Colored Sticks【欧拉迹+并查集+字典树】
  11. 川大考研复试c语言参考书目_北京航空航天大学英语笔译考研参考书目-复试分数线...
  12. 计算机毕业设计Java美发门店管理系统(源码+系统+mysql数据库+lW文档)
  13. 腾讯地图产业版WeMap 升级
  14. Tbase 源码 (九)
  15. PKI体系和数字证书
  16. [Elasticsearch] 多字段搜索 (五) - 以字段为中心的查询
  17. HTTP协议中的1xx,2xx,3xx,4xx,5xx状态码分别表示什么,列举常见错误码及含义
  18. AutoCAD基本操作
  19. python1300_相机选型器 : PYTHON 1300-NOIP1SN1300A-QDI
  20. 德艺双修才貌双全 史上16位青楼佳人 迷住宋徽宗的李师师

热门文章

  1. 云存储——everbox
  2. 计算机网络安全的一些概念以及知识点
  3. 我爱计算机:张俊林专访
  4. 图说Fourier变换
  5. 南邮计算机科学专业自我鉴定,大学毕业个人自我鉴定范文
  6. 我的电脑,虽然你很慢,但是我很爱你啊!
  7. 有空就学学的实例分割1——Tensorflow2搭建Mask R-CNN实例分割平台
  8. thinksns的部署
  9. Python各种包学习
  10. 【Carla】自定义仿真场景制作