基于Unity实现油画风格的着色器
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/oilScreen" {
//------------------------------------【属性值】------------------------------------
Properties
{
_MainTex("Base (RGB)", 2D) = "white" {}
_Distortion("_Distortion", Range(0.0, 1.0)) = 0.3
_ScreenResolution("_ScreenResolution", Vector) = (0., 0., 0., 0.)
_ResolutionValue("_ResolutionValue", Range(0.0, 5.0)) = 1.0
_Radius("_Radius", Range(0.0, 5.0)) = 2.0
}
//------------------------------------【唯一的子着色器】------------------------------------
SubShader
{
//--------------------------------唯一的通道-------------------------------
Pass
{
//设置深度测试模式:渲染所有像素.等同于关闭透明度测试(AlphaTest Off)
ZTest Always
//===========开启CG着色器语言编写模块===========
CGPROGRAM
//编译指令: 指定着色器编译目标为Shader Model 3.0
#pragma target 3.0
//编译指令:告知编译器顶点和片段着色函数的名称
#pragma vertex vert
#pragma fragment frag
//包含辅助CG头文件
#include "UnityCG.cginc"
//外部变量的声明
uniform sampler2D _MainTex;
uniform float _Distortion;
uniform float4 _ScreenResolution;
uniform float _ResolutionValue;
uniform int _Radius;
//顶点输入结构
struct vertexInput
{
float4 vertex : POSITION;//顶点位置
float4 color : COLOR;//颜色值
float2 texcoord : TEXCOORD0;//一级纹理坐标
};
//顶点输出结构
struct vertexOutput
{
half2 texcoord : TEXCOORD0;//一级纹理坐标
float4 vertex : SV_POSITION;//像素位置
fixed4 color : COLOR;//颜色值
};
//--------------------------------【顶点着色函数】-----------------------------
// 输入:顶点输入结构体
// 输出:顶点输出结构体
//---------------------------------------------------------------------------------
vertexOutput vert(vertexInput Input)
{
//【1】声明一个输出结构对象
vertexOutput Output;
//【2】填充此输出结构
//输出的顶点位置为模型视图投影矩阵乘以顶点位置,也就是将三维空间中的坐标投影到了二维窗口
Output.vertex = UnityObjectToClipPos(Input.vertex);
//输出的纹理坐标也就是输入的纹理坐标
Output.texcoord = Input.texcoord;
//输出的颜色值也就是输入的颜色值
Output.color = Input.color;
//【3】返回此输出结构对象
return Output;
}
//--------------------------------【片段着色函数】-----------------------------
// 输入:顶点输出结构体
// 输出:float4型的颜色值
//---------------------------------------------------------------------------------
float4 frag(vertexOutput Input) : COLOR
{
//【1】根据设置的分辨率比值,计算图像尺寸
float2 src_size = float2(_ResolutionValue / _ScreenResolution.x, _ResolutionValue / _ScreenResolution.y);
//【2】获取坐标值
float2 uv = Input.texcoord.xy;
//【3】根据半径,计算出n的值
float n = float((_Radius + 1) * (_Radius + 1));;
//【4】定义一些参数
float3 m0 = 0.0; float3 m1 = 0.0;
float3 s0 = 0.0; float3 s1 = 0.0;
float3 c;
//【5】按半径Radius的值,迭代计算m0和s0的值
for (int j = -_Radius; j <= 0; ++j)
{
for (int i = -_Radius; i <= 0; ++i)
{
c = tex2D(_MainTex, uv + float2(i, j) * src_size).rgb;
m0 += c;
s0 += c * c;
}
}
//【6】按半径Radius的值,迭代计算m1和s1的值
for (int j = 0; j <= _Radius; ++j)
{
for (int i = 0; i <= _Radius; ++i)
{
c = tex2D(_MainTex, uv + float2(i, j) * src_size).rgb;
m1 += c;
s1 += c * c;
}
}
//【7】定义参数,准备计算最终的颜色值
float4 finalFragColor = 0.;
float min_sigma2 = 1e+2;
//【8】根据m0和s0,第一次计算finalFragColor的值
m0 /= n;
s0 = abs(s0 / n - m0 * m0);
float sigma2 = s0.r + s0.g + s0.b;
if (sigma2 < min_sigma2)
{
min_sigma2 = sigma2;
finalFragColor = float4(m0, 1.0);
}
//【9】根据m1和s1,第二次计算finalFragColor的值
m1 /= n;
s1 = abs(s1 / n - m1 * m1);
sigma2 = s1.r + s1.g + s1.b;
if (sigma2 < min_sigma2)
{
min_sigma2 = sigma2;
finalFragColor = float4(m1, 1.0);
}
//【10】返回最终的颜色值
return finalFragColor;
}
ENDCG
}
}
}

在材质上赋予着色器之后将材质球贴敷到游戏对象上就能够看到油画效果,需要根据需求取调节材质球上的着色器各个参数,以应对不同的需求。
基于Unity实现油画风格的着色器的更多相关文章
- 基于Unity实现像素化风格的着色器
Shader "MyShaderTest/SimplePixelationShader" { Properties { _MainTex ("Base (RGB)&quo ...
- 使用Shader Graph实现《塞尔达传说:旷野之息》风格的着色器
https://mp.weixin.qq.com/s/19Xq6wYuXP0gQJDvC9Fh0g
- Unity 渲染教程(二):着色器基础
转载:https://www.jianshu.com/p/7db167704056 这是关于渲染基础的系列教程的第二部分.这个渲染基础的系列教程的第一部分是有关矩阵的内容.在这篇文章中我们将编写我们的 ...
- Unity Shader着色器优化
https://mp.weixin.qq.com/s?__biz=MzU5MjQ1NTEwOA==&mid=2247493518&idx=1&sn=c51b92e9300bcf ...
- Unity3d之Shader编程:子着色器、通道与标签的写法 & 纹理混合
一.子着色器 Unity中的每一个着色器都包含一个subshader的列表,当Unity需要显示一个网格时,它能发现使用的着色器,并提取第一个能运行在当前用户的显示卡上的子着色器. 我们知道,子着色器 ...
- 【浅墨Unity3D Shader编程】之三 光之城堡篇:子着色器、通道与标签的写法 & 纹理混合
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://hpw123.net/a/C__/kongzhitaichengxu/2014/1117/120.html 作者:毛星云 ...
- Unity3D - 图形性能优化:优化着色器载入时间
Unity官方文档之"图形性能优化-优化着色器载入时间"的翻译,E文链接. Optimizing Shader Load Time 优化着色器载入时间 Shaders are sm ...
- [Unity] Shader(着色器)输入输出和语义
在Unity5.x后, 已经支持了基于物理的光照模型,也就是常说的次时代引擎所必须具备的功能. 如果在Properties使用2D,CG里要用sampler2D,代表使用的是2维纹理 如果在Prope ...
- Unity 内置着色器(转)
Unity包括超过40种内置的shader. 标准着色器家族 Normal Shader Family 这些着色器都是Unity基本的着色器.适用于大多数的不透明物体,如果想要物体有透明.发光效果等, ...
随机推荐
- 开发常见错误解决(6)WSE3.0未处理的WebException,未处理的Web异常,基础连接以及关闭...
开发常见错误解决(6)WSE3.0未处理的WebException,未处理的Web异常,基础连接以及关闭. 我们在调试WSE服务端服务的时候会抛出,未处理的Web异常,基础连接以及关闭的异常信息.如图 ...
- iOS自定义tabBar
在我们的项目中经常会自己自定义tabBar因为苹果自带的真的太丑了!也不满足我们的项目需求. 好 开始行动吧! 先上图看下我们最终实现的效果: 继承UItabBar自定义一个自己的tabBar .h# ...
- 一个简单的wed服务器SHTTPD(6)———— SHTTPD错误处理的实现
//start from the very beginning,and to create greatness //@author: Chuangwei Lin //@E-mail:979951191 ...
- Shell脚本(三)重定向
先上一张图: 代码如下: #!/bin/bash echo "hello world" echo `ls +` 运行结果如下: PS: 1. 如果想同时将数据重定向到文件和stdo ...
- kafka可插拔增强如何实现?
导弹拦截,精准防御. 背景 拦截器:在不修改应用程序业务逻辑的情况下,一组基于事件的可插拔的逻辑处理链: 类比springMVC的拦截器: 这些都是通过配置拦截器,插入到应用程序中,实现可插拔的修改业 ...
- Java——Java自动装箱和拆箱
一.什么是自动装箱和拆箱: 我们知道java为8种基本类型分别提供了对应的包装类型,在Java SE5之前,如果要生成一个数值为10的Integer对象,必须这样进行: Integer i=new I ...
- 扩欧(exgcd讲解)
注意本文的证明都来源于这位大大大大大大大牛 知识点.扩展欧几里得求逆元 看完下面的证明后建议联系一下这题同余方程 可以对exgcd的用途和写法有有初步了解. \(问题描述:对于三个自然数 a,b,c ...
- css3的 calc属性无效问题解决
css3的 calc:计算属性. 运算符两边需要加空格,才有效. 错误示例:.mystyle{width:calc(100%-25px)}这样是不生效的 运算符"+ - * /"左 ...
- 自动化测试po模式是什么?自动化测试po分层如何实现?-附详细源码
一.什么是PO模式 全称:page object model 简称:POM/PO PO模式最核心的思想是分层,实现松耦合!实现脚本重复使用,实现脚本易维护性! 主要分三层: 1.基础层BaseP ...
- JDBC11 封装+资源配置文件管理
封装为Utils类+程序资源文件去配置 public class Utils { static Properties p=null; static { p=new Properties(); try ...