kg
6 年前
当前提交
c5d11ddb
共有 43 个文件被更改,包括 2421 次插入 和 1327 次删除
-
2Runtime/editor/rasterizer.cs
-
9Runtime/material/text_selection.cs
-
20Runtime/painting/matrix_utils.cs
-
13Runtime/ui/geometry.cs
-
40Runtime/ui/matrix.cs
-
30Runtime/ui/painting/canvas.cs
-
30Runtime/ui/painting/canvas_clip.cs
-
900Runtime/ui/painting/canvas_impl.cs
-
112Runtime/ui/painting/painting.cs
-
136Runtime/ui/painting/path.cs
-
296Runtime/ui/painting/picture.cs
-
27Runtime/ui/painting/txt/font_manager.cs
-
2Runtime/ui/painting/txt/mesh_generator.cs
-
105Tests/Editor/CanvasAndLayers.cs
-
2Tests/Editor/Widgets.cs
-
178Runtime/Resources/UIWidgets_canvas.cginc
-
9Runtime/Resources/UIWidgets_canvas.cginc.meta
-
63Runtime/Resources/UIWidgets_canvas_convexFill.shader
-
9Runtime/Resources/UIWidgets_canvas_convexfill.shader.meta
-
30Runtime/Resources/UIWidgets_canvas_fill0.shader
-
9Runtime/Resources/UIWidgets_canvas_fill0.shader.meta
-
66Runtime/Resources/UIWidgets_canvas_fill1.shader
-
9Runtime/Resources/UIWidgets_canvas_fill1.shader.meta
-
18Runtime/Resources/UIWidgets_canvas_filter.shader
-
9Runtime/Resources/UIWidgets_canvas_filter.shader.meta
-
56Runtime/Resources/UIWidgets_canvas_stencil.shader
-
9Runtime/Resources/UIWidgets_canvas_stencil.shader.meta
-
64Runtime/Resources/UIWidgets_canvas_stroke0.shader
-
9Runtime/Resources/UIWidgets_canvas_stroke0.shader.meta
-
27Runtime/Resources/UIWidgets_canvas_stroke1.shader
-
9Runtime/Resources/UIWidgets_canvas_stroke1.shader.meta
-
63Runtime/Resources/UIWidgets_canvas_tex.shader
-
9Runtime/Resources/UIWidgets_canvas_tex.shader.meta
-
393Runtime/ui/painting/canvas_shader.cs
-
11Runtime/ui/painting/canvas_shader.cs.meta
-
602Runtime/ui/painting/shader.cs
-
11Runtime/ui/painting/shader.cs.meta
-
8Tests/Resources.meta
-
3Tests/Resources/6.png
-
88Tests/Resources/6.png.meta
-
3Runtime/Resources/UIWidgets_canvas.shader.meta
-
259Runtime/Resources/UIWidgets_canvas.shader
900
Runtime/ui/painting/canvas_impl.cs
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
|
|||
float4 _viewport; |
|||
float _mat[9]; |
|||
|
|||
half4 _color; |
|||
fixed _alpha; |
|||
half4x4 _shaderMat; |
|||
sampler2D _shaderTex; |
|||
half4 _leftColor; |
|||
half4 _rightColor; |
|||
half _bias; |
|||
half _scale; |
|||
int _tileMode; // 0 = clamp, 1 = mirror, 2 = repeated |
|||
|
|||
sampler2D _tex; |
|||
int _texMode; // 0 = post alpha, 1 = pre alpha, 2 = alpha only |
|||
|
|||
half2 _mf_imgInc; // _mf stands for mask filter |
|||
int _mf_radius; |
|||
half _mf_kernel[25]; |
|||
|
|||
struct appdata_t { |
|||
float4 vertex : POSITION; |
|||
float2 tcoord : TEXCOORD0; |
|||
}; |
|||
|
|||
struct v2f { |
|||
float4 vertex : SV_POSITION; |
|||
float2 ftcoord : TEXCOORD0; |
|||
float2 fpos : TEXCOORD1; |
|||
}; |
|||
|
|||
|
|||
half shader_gradient_layout(half2 pos) { |
|||
half4 p4 = half4(pos, 0.0, 1.0); |
|||
#if defined(UIWIDGETS_LINEAR) |
|||
return mul(_shaderMat, p4).x; |
|||
#elif defined(UIWIDGETS_RADIAL) |
|||
return length(mul(_shaderMat, p4).xy); |
|||
#elif defined(UIWIDGETS_SWEEP) |
|||
half2 p2 = mul(_shaderMat, p4).xy; |
|||
half angle = atan2(-p2.y, -p2.x); |
|||
// 0.1591549430918 is 1/(2*pi), used since atan returns values [-pi, pi] |
|||
return (angle * 0.1591549430918 + 0.5 + _bias) * _scale; |
|||
#else |
|||
return 0; |
|||
#endif |
|||
} |
|||
|
|||
half4 shader_gradient_colorize(half pt) { |
|||
if (_tileMode == 0) { // clamp |
|||
if (pt <= 0.001) { |
|||
return _leftColor; |
|||
} else if (pt >= 0.999) { |
|||
return _rightColor; |
|||
} |
|||
|
|||
half2 coord = half2(pt, 0.5); |
|||
return tex2D(_shaderTex, coord); |
|||
} else if (_tileMode == 1) { // mirror |
|||
pt = pt - 1; |
|||
pt = pt - 2 * floor(pt * 0.5) - 1; |
|||
pt = abs(pt); |
|||
|
|||
half2 coord = half2(pt, 0.5); |
|||
return tex2D(_shaderTex, coord); |
|||
} else if (_tileMode == 2) { // repeated |
|||
pt = frac(pt); |
|||
|
|||
half2 coord = half2(pt, 0.5); |
|||
return tex2D(_shaderTex, coord); |
|||
} |
|||
|
|||
return half4(0, 0, 0, 0); |
|||
} |
|||
|
|||
|
|||
half2 shader_image_layout(half2 pos) { |
|||
half4 p4 = half4(pos, 0.0, 1.0); |
|||
return mul(_shaderMat, p4).xy; |
|||
} |
|||
|
|||
half4 shader_image_colorize(half2 pt) { |
|||
if (_tileMode == 0) { // clamp |
|||
pt.x = clamp(pt.x, 0.001, 0.999); |
|||
pt.y = clamp(pt.y, 0.001, 0.999); |
|||
} else if (_tileMode == 1) { // mirror |
|||
pt.x = pt.x - 1; |
|||
pt.x = pt.x - 2 * floor(pt.x * 0.5) - 1; |
|||
pt.x = abs(pt.x); |
|||
pt.y = pt.y - 1; |
|||
pt.y = pt.y - 2 * floor(pt.y * 0.5) - 1; |
|||
pt.y = abs(pt.y); |
|||
} else if (_tileMode == 2) { // repeated |
|||
pt.x = frac(pt.x); |
|||
pt.y = frac(pt.y); |
|||
} |
|||
|
|||
return tex2D(_shaderTex, pt); |
|||
} |
|||
|
|||
half4 prealpha(half4 color) { |
|||
return half4(color.x * color.w, color.y * color.w, color.z * color.w, color.w); |
|||
} |
|||
|
|||
half4 shader_color (v2f i) { |
|||
half4 c; |
|||
|
|||
#if defined(UIWIDGETS_COLOR) |
|||
c = _color; |
|||
#elif defined(UIWIDGETS_IMAGE) |
|||
half2 pt = shader_image_layout(i.fpos); |
|||
c = shader_image_colorize(pt); |
|||
#else |
|||
half pt = shader_gradient_layout(i.fpos); |
|||
c = shader_gradient_colorize(pt); |
|||
#endif |
|||
|
|||
c.w *= _alpha; |
|||
return c; |
|||
} |
|||
|
|||
|
|||
v2f vert (appdata_t v) { |
|||
v2f o; |
|||
o.ftcoord = v.tcoord; |
|||
o.fpos = v.vertex; |
|||
|
|||
float3x3 mat = float3x3(_mat[0], _mat[1], _mat[2], _mat[3], _mat[4], _mat[5], 0, 0, 1); |
|||
|
|||
half2 p = mul(mat, half3(v.vertex.xy, 1.0)).xy - _viewport.xy; |
|||
|
|||
#if UNITY_UV_STARTS_AT_TOP |
|||
o.vertex = float4(2.0 * p.x / _viewport.z - 1.0, 2.0 * p.y / _viewport.w - 1.0, 0, 1); |
|||
#else |
|||
o.vertex = float4(2.0 * p.x / _viewport.z - 1.0, 1.0 - 2.0 * p.y / _viewport.w, 0, 1); |
|||
#endif |
|||
|
|||
return o; |
|||
} |
|||
|
|||
fixed4 frag (v2f i) : SV_Target { |
|||
return prealpha(shader_color(i)); |
|||
} |
|||
|
|||
fixed4 frag_stencil (v2f i) : SV_Target { |
|||
return half4(0, 0, 0, 0); |
|||
} |
|||
|
|||
fixed4 frag_tex (v2f i) : SV_Target { |
|||
half4 tintColor = shader_color(i); |
|||
|
|||
half4 color = tex2D(_tex, i.ftcoord); |
|||
if (_texMode == 0) { // post alpha |
|||
color = color * tintColor; |
|||
color = prealpha(color); |
|||
} else if (_texMode == 1) { // pre alpha |
|||
color = color * tintColor; |
|||
color = half4(color.x * tintColor.w, color.y * tintColor.w, color.z * tintColor.w, color.w); |
|||
} else if (_texMode == 2) { // alpha only |
|||
color = half4(1, 1, 1, color.w) * tintColor; |
|||
color = prealpha(color); |
|||
} |
|||
|
|||
return color; |
|||
} |
|||
|
|||
fixed4 frag_mf (v2f i) : SV_Target { |
|||
half4 color = half4(0, 0, 0, 0); |
|||
|
|||
float2 coord = i.ftcoord - _mf_radius * _mf_imgInc; |
|||
int width = _mf_radius * 2 + 1; |
|||
for (int i = 0; i < width; i++) { |
|||
color += tex2D(_tex, coord) * _mf_kernel[i]; |
|||
coord += _mf_imgInc; |
|||
} |
|||
|
|||
return color; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6565922d18a5e4ee29fa183d2600eccc |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_convexFill" |
|||
{ |
|||
Properties { |
|||
_SrcBlend("_SrcBlend", Int) = 1 // One |
|||
_DstBlend("_DstBlend", Int) = 10 // OneMinusSrcAlpha |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
Blend [_SrcBlend] [_DstBlend] |
|||
|
|||
Stencil { |
|||
Ref 128 |
|||
Comp Equal |
|||
} |
|||
|
|||
Pass { // 0, color |
|||
CGPROGRAM |
|||
#define UIWIDGETS_COLOR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 1, linear |
|||
CGPROGRAM |
|||
#define UIWIDGETS_LINEAR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 2, radial |
|||
CGPROGRAM |
|||
#define UIWIDGETS_RADIAL |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 3, sweep |
|||
CGPROGRAM |
|||
#define UIWIDGETS_SWEEP |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 4, image |
|||
CGPROGRAM |
|||
#define UIWIDGETS_IMAGE |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: da4e74e0b377e41699f5c3ed2c7c69e4 |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_fill0" |
|||
{ |
|||
Properties { |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
|
|||
Cull Off |
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 128 |
|||
CompFront Equal |
|||
CompBack Equal |
|||
ReadMask 128 |
|||
WriteMask 127 |
|||
PassFront IncrWrap |
|||
PassBack DecrWrap |
|||
} |
|||
|
|||
Pass { |
|||
CGPROGRAM |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e75e9debfc1ad4e1687365932de72aa0 |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_fill1" |
|||
{ |
|||
Properties { |
|||
_SrcBlend("_SrcBlend", Int) = 1 // One |
|||
_DstBlend("_DstBlend", Int) = 10 // OneMinusSrcAlpha |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
Blend [_SrcBlend] [_DstBlend] |
|||
|
|||
Stencil { |
|||
Ref 0 |
|||
Comp NotEqual |
|||
ReadMask 127 |
|||
WriteMask 127 |
|||
Pass Zero |
|||
} |
|||
|
|||
Pass { // 0, color |
|||
CGPROGRAM |
|||
#define UIWIDGETS_COLOR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 1, linear |
|||
CGPROGRAM |
|||
#define UIWIDGETS_LINEAR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 2, radial |
|||
CGPROGRAM |
|||
#define UIWIDGETS_RADIAL |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 3, sweep |
|||
CGPROGRAM |
|||
#define UIWIDGETS_SWEEP |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 4, image |
|||
CGPROGRAM |
|||
#define UIWIDGETS_IMAGE |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 7dbfb4eecc7a84ddc90c53891aa77e0b |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_filter" |
|||
{ |
|||
Properties { |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
|
|||
Pass { // 0, mask filter |
|||
CGPROGRAM |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_mf |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 756de2a3eb91745ba853728245a033d9 |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_stencil" |
|||
{ |
|||
Properties { |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
|
|||
Pass { // 0, stencil clear |
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Pass Replace |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 1, stencil intersect 0 |
|||
Cull Off |
|||
ColorMask 0 |
|||
Stencil { |
|||
WriteMask 127 |
|||
PassFront IncrWrap |
|||
PassBack DecrWrap |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 2, stencil intersect 1 |
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Comp Less |
|||
Pass Replace |
|||
Fail Zero |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b4673a8cf87214fdb8643b32e0ec3316 |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_stroke0" |
|||
{ |
|||
Properties { |
|||
_SrcBlend("_SrcBlend", Int) = 1 // One |
|||
_DstBlend("_DstBlend", Int) = 10 // OneMinusSrcAlpha |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
Blend [_SrcBlend] [_DstBlend] |
|||
|
|||
Stencil { |
|||
Ref 128 |
|||
Comp Equal |
|||
Pass IncrSat |
|||
} |
|||
|
|||
Pass { // 0, color |
|||
CGPROGRAM |
|||
#define UIWIDGETS_COLOR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 1, linear |
|||
CGPROGRAM |
|||
#define UIWIDGETS_LINEAR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 2, radial |
|||
CGPROGRAM |
|||
#define UIWIDGETS_RADIAL |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 3, sweep |
|||
CGPROGRAM |
|||
#define UIWIDGETS_SWEEP |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 4, image |
|||
CGPROGRAM |
|||
#define UIWIDGETS_IMAGE |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 7e33032771e1e46a6b5eda923148503f |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_stroke1" |
|||
{ |
|||
Properties { |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
|
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 0 |
|||
Comp NotEqual |
|||
ReadMask 127 |
|||
WriteMask 127 |
|||
Pass Zero |
|||
} |
|||
|
|||
Pass { |
|||
CGPROGRAM |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: ee8a29ca6a09f4510bbf6e3b70922edc |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "UIWidgets/canvas_tex" |
|||
{ |
|||
Properties { |
|||
_SrcBlend("_SrcBlend", Int) = 1 // One |
|||
_DstBlend("_DstBlend", Int) = 10 // OneMinusSrcAlpha |
|||
} |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
Blend [_SrcBlend] [_DstBlend] |
|||
|
|||
Stencil { |
|||
Ref 128 |
|||
Comp Equal |
|||
} |
|||
|
|||
Pass { // 0, color |
|||
CGPROGRAM |
|||
#define UIWIDGETS_COLOR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_tex |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 1, linear |
|||
CGPROGRAM |
|||
#define UIWIDGETS_LINEAR |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_tex |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 2, radial |
|||
CGPROGRAM |
|||
#define UIWIDGETS_RADIAL |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_tex |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 3, sweep |
|||
CGPROGRAM |
|||
#define UIWIDGETS_SWEEP |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_tex |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 4, image |
|||
CGPROGRAM |
|||
#define UIWIDGETS_IMAGE |
|||
#include "UIWidgets_canvas.cginc" |
|||
#pragma vertex vert |
|||
#pragma fragment frag_tex |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1702a648d08de40d9aacd9bbab1188b3 |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using Unity.UIWidgets.painting; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
class MaterialByBlendMode { |
|||
static readonly int _srcBlend = Shader.PropertyToID("_SrcBlend"); |
|||
static readonly int _dstBlend = Shader.PropertyToID("_DstBlend"); |
|||
|
|||
public MaterialByBlendMode(Shader shader) { |
|||
this._shader = shader; |
|||
} |
|||
|
|||
readonly Shader _shader; |
|||
readonly Material[] _materials = new Material[30]; |
|||
|
|||
public Material getMaterial(BlendMode op) { |
|||
var mat = this._materials[(int) op]; |
|||
if (mat) { |
|||
return mat; |
|||
} |
|||
|
|||
mat = new Material(this._shader) {hideFlags = HideFlags.HideAndDontSave}; |
|||
this._materials[(int) op] = mat; |
|||
|
|||
if (op == BlendMode.srcOver) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.One); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); |
|||
} else if (op == BlendMode.srcIn) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.DstAlpha); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
} else if (op == BlendMode.srcOut) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusDstAlpha); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
} else if (op == BlendMode.srcATop) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.DstAlpha); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); |
|||
} else if (op == BlendMode.dstOver) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusDstAlpha); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.One); |
|||
} else if (op == BlendMode.dstIn) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.SrcAlpha); |
|||
} else if (op == BlendMode.dstOut) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); |
|||
} else if (op == BlendMode.dstATop) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusDstAlpha); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.SrcAlpha); |
|||
} else if (op == BlendMode.plus) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.One); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.One); |
|||
} else if (op == BlendMode.src) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.One); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
} else if (op == BlendMode.dst) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.One); |
|||
} else if (op == BlendMode.xor) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusDstAlpha); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); |
|||
} else if (op == BlendMode.clear) { |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.Zero); |
|||
} else { |
|||
Debug.LogWarning("Not supported BlendMode: " + op + ". Defaults to srcOver"); |
|||
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.One); |
|||
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); |
|||
} |
|||
|
|||
return mat; |
|||
} |
|||
} |
|||
|
|||
static class CanvasShader { |
|||
static readonly MaterialByBlendMode _convexFillMat; |
|||
static readonly Material _fill0Mat; |
|||
static readonly MaterialByBlendMode _fill1Mat; |
|||
static readonly MaterialByBlendMode _stroke0Mat; |
|||
static readonly Material _stroke1Mat; |
|||
static readonly MaterialByBlendMode _texMat; |
|||
static readonly Material _stencilMat; |
|||
static readonly Material _filterMat; |
|||
|
|||
static CanvasShader() { |
|||
var convexFillShader = Shader.Find("UIWidgets/canvas_convexFill"); |
|||
if (convexFillShader == null) { |
|||
throw new Exception("UIWidgets/canvas_convexFill not found"); |
|||
} |
|||
var fill0Shader = Shader.Find("UIWidgets/canvas_fill0"); |
|||
if (fill0Shader == null) { |
|||
throw new Exception("UIWidgets/canvas_fill0 not found"); |
|||
} |
|||
var fill1Shader = Shader.Find("UIWidgets/canvas_fill1"); |
|||
if (fill1Shader == null) { |
|||
throw new Exception("UIWidgets/canvas_fill1 not found"); |
|||
} |
|||
var stroke0Shader = Shader.Find("UIWidgets/canvas_stroke0"); |
|||
if (stroke0Shader == null) { |
|||
throw new Exception("UIWidgets/canvas_stroke0 not found"); |
|||
} |
|||
var stroke1Shader = Shader.Find("UIWidgets/canvas_stroke1"); |
|||
if (stroke1Shader == null) { |
|||
throw new Exception("UIWidgets/canvas_stroke1 not found"); |
|||
} |
|||
var texShader = Shader.Find("UIWidgets/canvas_tex"); |
|||
if (texShader == null) { |
|||
throw new Exception("UIWidgets/canvas_tex not found"); |
|||
} |
|||
var stencilShader = Shader.Find("UIWidgets/canvas_stencil"); |
|||
if (stencilShader == null) { |
|||
throw new Exception("UIWidgets/canvas_stencil not found"); |
|||
} |
|||
var filterShader = Shader.Find("UIWidgets/canvas_filter"); |
|||
if (filterShader == null) { |
|||
throw new Exception("UIWidgets/canvas_filter not found"); |
|||
} |
|||
|
|||
_convexFillMat = new MaterialByBlendMode(convexFillShader); |
|||
_fill0Mat = new Material(fill0Shader) {hideFlags = HideFlags.HideAndDontSave}; |
|||
_fill1Mat = new MaterialByBlendMode(fill1Shader); |
|||
_stroke0Mat = new MaterialByBlendMode(stroke0Shader); |
|||
_stroke1Mat = new Material(stroke1Shader) {hideFlags = HideFlags.HideAndDontSave}; |
|||
_texMat = new MaterialByBlendMode(texShader); |
|||
_stencilMat = new Material(stencilShader) {hideFlags = HideFlags.HideAndDontSave}; |
|||
_filterMat = new Material(filterShader) {hideFlags = HideFlags.HideAndDontSave}; |
|||
} |
|||
|
|||
static Vector4 _colorToVector4(Color c) { |
|||
return new Vector4( |
|||
c.red / 255f, |
|||
c.green / 255f, |
|||
c.blue / 255f, |
|||
c.alpha / 255f |
|||
); |
|||
} |
|||
|
|||
static void _getShaderPassAndProps(Vector4 viewport, Matrix3 ctm, Paint paint, float alpha, |
|||
out int pass, out MaterialPropertyBlock props) { |
|||
props = new MaterialPropertyBlock(); |
|||
props.SetVector("_viewport", viewport); |
|||
props.SetFloat("_alpha", alpha); |
|||
|
|||
switch (paint.shader) { |
|||
case null: |
|||
pass = 0; |
|||
props.SetVector("_color", _colorToVector4(paint.color)); |
|||
return; |
|||
case _LinearGradient linear: |
|||
pass = 1; |
|||
props.SetMatrix("_shaderMat", linear.getGradientMat(ctm).toMatrix4x4()); |
|||
props.SetTexture("_shaderTex", linear.gradientTex.texture); |
|||
props.SetVector("_leftColor", _colorToVector4(linear.leftColor)); |
|||
props.SetVector("_rightColor", _colorToVector4(linear.rightColor)); |
|||
props.SetInt("_tileMode", (int) linear.tileMode); |
|||
return; |
|||
case _RadialGradient radial: |
|||
pass = 2; |
|||
props.SetMatrix("_shaderMat", radial.getGradientMat(ctm).toMatrix4x4()); |
|||
props.SetTexture("_shaderTex", radial.gradientTex.texture); |
|||
props.SetVector("_leftColor", _colorToVector4(radial.leftColor)); |
|||
props.SetVector("_rightColor", _colorToVector4(radial.rightColor)); |
|||
props.SetInt("_tileMode", (int) radial.tileMode); |
|||
return; |
|||
case _SweepGradient sweep: |
|||
pass = 3; |
|||
props.SetMatrix("_shaderMat", sweep.getGradientMat(ctm).toMatrix4x4()); |
|||
props.SetTexture("_shaderTex", sweep.gradientTex.texture); |
|||
props.SetVector("_leftColor", _colorToVector4(sweep.leftColor)); |
|||
props.SetVector("_rightColor", _colorToVector4(sweep.rightColor)); |
|||
props.SetInt("_tileMode", (int) sweep.tileMode); |
|||
props.SetFloat("_bias", (float) sweep.bias); |
|||
props.SetFloat("_scale", (float) sweep.scale); |
|||
return; |
|||
case ImageShader image: |
|||
pass = 4; |
|||
props.SetMatrix("_shaderMat", image.getShaderMat(ctm).toMatrix4x4()); |
|||
props.SetTexture("_shaderTex", image.image.texture); |
|||
props.SetInt("_tileMode", (int) image.tileMode); |
|||
return; |
|||
default: |
|||
throw new Exception("Unknown paint.shader: " + paint.shader); |
|||
} |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw convexFill(CommandBufferCanvas.RenderLayer layer, Paint paint, |
|||
MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix; |
|||
|
|||
var mat = _convexFillMat.getMaterial(paint.blendMode); |
|||
_getShaderPassAndProps(viewport, ctm, paint, 1.0f, out var pass, out var props); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw fill0(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
var mat = _fill0Mat; |
|||
|
|||
var pass = 0; |
|||
var props = new MaterialPropertyBlock(); |
|||
props.SetVector("_viewport", viewport); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw fill1(CommandBufferCanvas.RenderLayer layer, Paint paint, |
|||
MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix; |
|||
|
|||
var mat = _fill1Mat.getMaterial(paint.blendMode); |
|||
_getShaderPassAndProps(viewport, ctm, paint, 1.0f, out var pass, out var props); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh.boundsMesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw stroke0(CommandBufferCanvas.RenderLayer layer, Paint paint, |
|||
float alpha, MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix; |
|||
|
|||
var mat = _stroke0Mat.getMaterial(paint.blendMode); |
|||
_getShaderPassAndProps(viewport, ctm, paint, alpha, out var pass, out var props); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw stroke1(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
var mat = _stroke1Mat; |
|||
|
|||
var pass = 0; |
|||
var props = new MaterialPropertyBlock(); |
|||
props.SetVector("_viewport", viewport); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw stencilClear( |
|||
CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
var mat = _stencilMat; |
|||
|
|||
var pass = 0; |
|||
var props = new MaterialPropertyBlock(); |
|||
props.SetVector("_viewport", viewport); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw stencil0(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
var mat = _stencilMat; |
|||
|
|||
var pass = 1; |
|||
var props = new MaterialPropertyBlock(); |
|||
props.SetVector("_viewport", viewport); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw stencil1(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) { |
|||
Vector4 viewport = layer.viewport; |
|||
var mat = _stencilMat; |
|||
|
|||
var pass = 2; |
|||
var props = new MaterialPropertyBlock(); |
|||
props.SetVector("_viewport", viewport); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw tex(CommandBufferCanvas.RenderLayer layer, Paint paint, |
|||
MeshMesh mesh, Image image) { |
|||
Vector4 viewport = layer.viewport; |
|||
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix; |
|||
|
|||
var mat = _texMat.getMaterial(paint.blendMode); |
|||
_getShaderPassAndProps(viewport, ctm, paint, 1.0f, out var pass, out var props); |
|||
props.SetTexture("_tex", image.texture); |
|||
props.SetInt("_texMode", image.texture is RenderTexture ? 1 : 0); // pre alpha if RT else post alpha
|
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
image = image, // keep a reference to avoid GC.
|
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw texRT(CommandBufferCanvas.RenderLayer layer, Paint paint, |
|||
MeshMesh mesh, CommandBufferCanvas.RenderLayer renderLayer) { |
|||
Vector4 viewport = layer.viewport; |
|||
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix; |
|||
|
|||
|
|||
var mat = _texMat.getMaterial(paint.blendMode); |
|||
_getShaderPassAndProps(viewport, ctm, paint, 1.0f, out var pass, out var props); |
|||
props.SetInt("_texMode", 1); // pre alpha
|
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
layer = renderLayer, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw texAlpha(CommandBufferCanvas.RenderLayer layer, Paint paint, |
|||
MeshMesh mesh, Texture tex) { |
|||
Vector4 viewport = layer.viewport; |
|||
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix; |
|||
|
|||
var mat = _texMat.getMaterial(paint.blendMode); |
|||
_getShaderPassAndProps(viewport, ctm, paint, 1.0f, out var pass, out var props); |
|||
props.SetTexture("_tex", tex); |
|||
props.SetInt("_texMode", 2); // alpha only
|
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
}; |
|||
} |
|||
|
|||
public static CommandBufferCanvas.RenderDraw maskFilter(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh, |
|||
CommandBufferCanvas.RenderLayer renderLayer, float radius, Vector2 imgInc, float[] kernel) { |
|||
Vector4 viewport = layer.viewport; |
|||
var mat = _filterMat; |
|||
|
|||
var pass = 0; |
|||
var props = new MaterialPropertyBlock(); |
|||
props.SetVector("_viewport", viewport); |
|||
|
|||
props.SetFloat("_mf_radius", radius); |
|||
props.SetVector("_mf_imgInc", imgInc); |
|||
props.SetFloatArray("_mf_kernel", kernel); |
|||
|
|||
return new CommandBufferCanvas.RenderDraw { |
|||
mesh = mesh, |
|||
pass = pass, |
|||
material = mat, |
|||
properties = props, |
|||
layer = renderLayer, |
|||
}; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6c897b209ded34c03ac522c5f76ae23d |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public enum TileMode : int { |
|||
clamp = 0, |
|||
mirror = 1, |
|||
repeated = 2, |
|||
} |
|||
|
|||
public abstract class PaintShader { |
|||
} |
|||
|
|||
|
|||
public class Gradient : PaintShader { |
|||
|
|||
public static Gradient linear( |
|||
Offset start, Offset end, List<Color> colors, |
|||
List<double> colorStops = null, TileMode tileMode = TileMode.clamp, |
|||
Matrix3 matrix = null) { |
|||
D.assert(PaintingUtils._offsetIsValid(start)); |
|||
D.assert(PaintingUtils._offsetIsValid(end)); |
|||
D.assert(colors != null && colors.Count >= 2); |
|||
|
|||
_validateColorStops(ref colors, ref colorStops); |
|||
|
|||
return new _LinearGradient(start, end, colors, colorStops, tileMode, matrix); |
|||
} |
|||
|
|||
public static Gradient radial( |
|||
Offset center, double radius, List<Color> colors, |
|||
List<double> colorStops = null, TileMode tileMode = TileMode.clamp, |
|||
Matrix3 matrix = null) { |
|||
D.assert(PaintingUtils._offsetIsValid(center)); |
|||
D.assert(colors != null && colors.Count >= 2); |
|||
|
|||
_validateColorStops(ref colors, ref colorStops); |
|||
|
|||
return new _RadialGradient(center, radius, colors, colorStops, tileMode, matrix); |
|||
} |
|||
|
|||
public static Gradient sweep( |
|||
Offset center, List<Color> colors, |
|||
List<double> colorStops = null, TileMode tileMode = TileMode.clamp, |
|||
double startAngle = 0.0, double endAngle = Math.PI * 2, |
|||
Matrix3 matrix = null) { |
|||
D.assert(PaintingUtils._offsetIsValid(center)); |
|||
D.assert(colors != null && colors.Count >= 2); |
|||
D.assert(startAngle < endAngle); |
|||
|
|||
_validateColorStops(ref colors, ref colorStops); |
|||
|
|||
return new _SweepGradient(center, colors, colorStops, tileMode, startAngle, endAngle, matrix); |
|||
} |
|||
|
|||
static void _validateColorStops(ref List<Color> colors, ref List<double> colorStops) { |
|||
if (colorStops == null) { |
|||
colors = new List<Color>(colors); |
|||
|
|||
colorStops = new List<double>(colors.Count); |
|||
colorStops.Add(0); |
|||
var stepCount = colors.Count - 1; |
|||
var step = 1.0 / stepCount; |
|||
for (int i = 1; i < stepCount; i++) { |
|||
colorStops.Add(colorStops[i - 1] + step); |
|||
} |
|||
colorStops.Add(1); |
|||
|
|||
return; |
|||
} |
|||
|
|||
if (colors.Count != colorStops.Count) { |
|||
throw new ArgumentException("\"colors\" and \"colorStops\" arguments must have equal length."); |
|||
} |
|||
|
|||
var dummyFirst = colorStops[0] != 0; |
|||
var dummyLast = colorStops[colorStops.Count - 1] != 1; |
|||
var count = colors.Count + (dummyFirst ? 1 : 0) + (dummyFirst ? 1 : 0); |
|||
|
|||
var newColors = new List<Color>(count); |
|||
if (dummyFirst) { |
|||
newColors.Add(colors[0]); |
|||
} |
|||
for (int i = 0; i < colors.Count; i++) { |
|||
newColors.Add(colors[i]); |
|||
} |
|||
if (dummyLast) { |
|||
newColors.Add(colors[colors.Count - 1]); |
|||
} |
|||
|
|||
var newColorStops = new List<double>(count); |
|||
if (dummyFirst) { |
|||
newColorStops.Add(0.0); |
|||
} |
|||
var prevStop = 0.0; |
|||
for (int i = 0; i < colorStops.Count; i++) { |
|||
var stop = Math.Max(Math.Min(colorStops[i], 1.0), prevStop); |
|||
newColorStops.Add(stop); |
|||
prevStop = stop; |
|||
} |
|||
if (dummyLast) { |
|||
newColorStops.Add(1.0); |
|||
} |
|||
|
|||
colors = newColors; |
|||
colorStops = newColorStops; |
|||
} |
|||
|
|||
static readonly GradientBitmapCache _cache = new GradientBitmapCache(); |
|||
|
|||
internal static Image makeTexturedColorizer(List<Color> colors, List<double> positions) { |
|||
int count = colors.Count; |
|||
D.assert(count >= 2); |
|||
|
|||
bool bottomHardStop = ScalarUtils.ScalarNearlyEqual((float) positions[0], (float) positions[1]); |
|||
bool topHardStop = ScalarUtils.ScalarNearlyEqual((float) positions[count - 2], (float) positions[count - 1]); |
|||
|
|||
int offset = 0; |
|||
if (bottomHardStop) { |
|||
offset += 1; |
|||
count--; |
|||
} |
|||
if (topHardStop) { |
|||
count--; |
|||
} |
|||
|
|||
if (offset != 0 || count != colors.Count) { |
|||
colors = colors.GetRange(offset, count); |
|||
positions = positions.GetRange(offset, count); |
|||
} |
|||
|
|||
return _cache.getGradient(colors, positions); |
|||
} |
|||
} |
|||
|
|||
class GradientBitmapCache : IDisposable { |
|||
public GradientBitmapCache(int maxEntries = 32, int resolution = 256) { |
|||
this.maxEntries = maxEntries; |
|||
this.resolution = resolution; |
|||
this._entryCount = 0; |
|||
this._head = this._tail = null; |
|||
|
|||
D.assert(this.validate); |
|||
} |
|||
|
|||
public readonly int maxEntries; |
|||
public readonly int resolution; |
|||
|
|||
int _entryCount; |
|||
_Entry _head; |
|||
_Entry _tail; |
|||
|
|||
public Image getGradient(List<Color> colors, List<double> positions) { |
|||
var key = new _Key(colors, positions); |
|||
|
|||
if (!this.find(key, out var image)) { |
|||
image = this.fillGradient(colors, positions); |
|||
this.add(key, image); |
|||
} |
|||
|
|||
return image; |
|||
} |
|||
|
|||
public void Dispose() { |
|||
D.assert(this.validate); |
|||
|
|||
// just remove the references, Image will dispose by themselves.
|
|||
this._entryCount = 0; |
|||
this._head = this._tail = null; |
|||
} |
|||
|
|||
_Entry release(_Entry entry) { |
|||
if (entry.prev != null) { |
|||
D.assert(this._head != entry); |
|||
entry.prev.next = entry.next; |
|||
} else { |
|||
D.assert(this._head == entry); |
|||
this._head = entry.next; |
|||
} |
|||
|
|||
if (entry.next != null) { |
|||
D.assert(this._tail != entry); |
|||
entry.next.prev = entry.prev; |
|||
} else { |
|||
D.assert(this._tail == entry); |
|||
this._tail = entry.prev; |
|||
} |
|||
|
|||
return entry; |
|||
} |
|||
|
|||
void attachToHead(_Entry entry) { |
|||
entry.prev = null; |
|||
entry.next = this._head; |
|||
if (this._head != null) { |
|||
this._head.prev = entry; |
|||
} else { |
|||
this._tail = entry; |
|||
} |
|||
this._head = entry; |
|||
} |
|||
|
|||
bool find(_Key key, out Image image) { |
|||
D.assert(this.validate); |
|||
|
|||
var entry = this._head; |
|||
while (entry != null) { |
|||
if (entry.key == key) { |
|||
image = entry.image; |
|||
|
|||
// move to the head of our list, so we purge it last
|
|||
this.release(entry); |
|||
this.attachToHead(entry); |
|||
D.assert(this.validate); |
|||
return true; |
|||
} |
|||
entry = entry.next; |
|||
} |
|||
|
|||
D.assert(this.validate); |
|||
image = null; |
|||
return false; |
|||
} |
|||
|
|||
void add(_Key key, Image image) { |
|||
if (this._entryCount == this.maxEntries) { |
|||
D.assert(this._tail != null); |
|||
this.release(this._tail); |
|||
this._entryCount--; |
|||
} |
|||
|
|||
var entry = new _Entry {key = key, image = image}; |
|||
this.attachToHead(entry); |
|||
this._entryCount++; |
|||
} |
|||
|
|||
Image fillGradient(List<Color> colors, List<double> positions) { |
|||
Texture2D tex = new Texture2D(this.resolution, 1, TextureFormat.RGBA32, false); |
|||
tex.hideFlags = HideFlags.HideAndDontSave; |
|||
|
|||
var bytes = new byte[this.resolution * 4]; |
|||
|
|||
int count = colors.Count; |
|||
int prevIndex = 0; |
|||
for (int i = 1; i < count; i++) { |
|||
// Historically, stops have been mapped to [0, 256], with 256 then nudged to the next
|
|||
// smaller value, then truncate for the texture index. This seems to produce the best
|
|||
// results for some common distributions, so we preserve the behavior.
|
|||
int nextIndex = (int) Mathf.Min((float) positions[i] * this.resolution, this.resolution - 1); |
|||
|
|||
if (nextIndex > prevIndex) { |
|||
var c0 = colors[i - 1]; |
|||
var c1 = colors[i]; |
|||
|
|||
var step = 1.0f / (nextIndex - prevIndex); |
|||
var t = 0.0; |
|||
|
|||
for (int curIndex = prevIndex; curIndex <= nextIndex; ++curIndex) { |
|||
var c = Color.lerp(c0, c1, t); |
|||
|
|||
var baseIndex = curIndex << 2; |
|||
bytes[baseIndex] = (byte) c.red; |
|||
bytes[baseIndex + 1] = (byte) c.green; |
|||
bytes[baseIndex + 2] = (byte) c.blue; |
|||
bytes[baseIndex + 3] = (byte) c.alpha; |
|||
|
|||
t += step; |
|||
} |
|||
} |
|||
|
|||
prevIndex = nextIndex; |
|||
} |
|||
|
|||
D.assert(prevIndex == this.resolution - 1); |
|||
|
|||
tex.LoadRawTextureData(bytes); |
|||
tex.Apply(); |
|||
return new Image(tex); |
|||
} |
|||
|
|||
bool validate() { |
|||
D.assert(this._entryCount >= 0 && this._entryCount <= this.maxEntries); |
|||
|
|||
if (this._entryCount > 0) { |
|||
D.assert(null == this._head.prev); |
|||
D.assert(null == this._tail.next); |
|||
|
|||
if (this._entryCount == 1) { |
|||
D.assert(this._head == this._tail); |
|||
} else { |
|||
D.assert(this._head != this._tail); |
|||
} |
|||
|
|||
var entry = this._head; |
|||
int count = 0; |
|||
while (entry != null) { |
|||
count += 1; |
|||
entry = entry.next; |
|||
} |
|||
D.assert(count == this._entryCount); |
|||
|
|||
entry = this._tail; |
|||
while (entry != null) { |
|||
count -= 1; |
|||
entry = entry.prev; |
|||
} |
|||
D.assert(0 == count); |
|||
} else { |
|||
D.assert(null == this._head); |
|||
D.assert(null == this._tail); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
class _Entry { |
|||
public _Entry prev; |
|||
public _Entry next; |
|||
|
|||
public _Key key; |
|||
public Image image; |
|||
} |
|||
|
|||
class _Key : IEquatable<_Key> { |
|||
public _Key(List<Color> colors, List<double> positions) { |
|||
D.assert(colors != null); |
|||
D.assert(positions != null); |
|||
D.assert(colors.Count == positions.Count); |
|||
|
|||
this.colors = colors; |
|||
this.positions = positions; |
|||
this._hashCode = _getHashCode(this.colors) ^ _getHashCode(this.positions); |
|||
; |
|||
} |
|||
|
|||
public readonly List<Color> colors; |
|||
|
|||
public readonly List<double> positions; |
|||
|
|||
readonly int _hashCode; |
|||
|
|||
public bool Equals(_Key other) { |
|||
if (ReferenceEquals(null, other)) { |
|||
return false; |
|||
} |
|||
if (ReferenceEquals(this, other)) { |
|||
return true; |
|||
} |
|||
return _listEquals(this.colors, other.colors) && |
|||
_listEquals(this.positions, other.positions); |
|||
} |
|||
|
|||
public override bool Equals(object obj) { |
|||
if (ReferenceEquals(null, obj)) { |
|||
return false; |
|||
} |
|||
if (ReferenceEquals(this, obj)) { |
|||
return true; |
|||
} |
|||
if (obj.GetType() != this.GetType()) { |
|||
return false; |
|||
} |
|||
return this.Equals((_Key) obj); |
|||
} |
|||
|
|||
public override int GetHashCode() { |
|||
return this._hashCode; |
|||
} |
|||
|
|||
public static bool operator ==(_Key left, _Key right) { |
|||
return Equals(left, right); |
|||
} |
|||
|
|||
public static bool operator !=(_Key left, _Key right) { |
|||
return !Equals(left, right); |
|||
} |
|||
|
|||
static int _getHashCode<T>(List<T> list) { |
|||
unchecked { |
|||
var hashCode = 0; |
|||
foreach (var item in list) { |
|||
hashCode = (hashCode * 397) ^ item.GetHashCode(); |
|||
} |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
static bool _listEquals<T>(List<T> left, List<T> right) { |
|||
if (left.Count != right.Count) { |
|||
return false; |
|||
} |
|||
|
|||
for (int i = 0; i < left.Count; i++) { |
|||
if (!left[i].Equals(right[i])) { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
class _LinearGradient : Gradient { |
|||
public _LinearGradient( |
|||
Offset start, Offset end, List<Color> colors, |
|||
List<double> colorStops, TileMode tileMode, |
|||
Matrix3 matrix = null) { |
|||
this.start = start; |
|||
this.end = end; |
|||
this.colors = colors; |
|||
this.colorStops = colorStops; |
|||
this.tileMode = tileMode; |
|||
this.matrix = matrix; |
|||
this.ptsToUnit = ptsToUnitMatrix(start, end); |
|||
this.gradientTex = makeTexturedColorizer(colors, colorStops); |
|||
} |
|||
|
|||
public readonly Offset start; |
|||
public readonly Offset end; |
|||
public readonly List<Color> colors; |
|||
public readonly List<double> colorStops; |
|||
public readonly TileMode tileMode; |
|||
public readonly Matrix3 matrix; |
|||
public readonly Matrix3 ptsToUnit; |
|||
public readonly Image gradientTex; |
|||
|
|||
public Color leftColor { |
|||
get { return this.colors[0]; } |
|||
} |
|||
|
|||
public Color rightColor { |
|||
get { return this.colors[this.colors.Count - 1]; } |
|||
} |
|||
|
|||
public Matrix3 getGradientMat(Matrix3 ctm) { |
|||
var mat = Matrix3.I(); |
|||
ctm.invert(mat); // just use I() if not invertible.
|
|||
|
|||
if (this.matrix != null) { |
|||
mat.postConcat(this.matrix); |
|||
} |
|||
mat.postConcat(this.ptsToUnit); |
|||
return mat; |
|||
} |
|||
|
|||
static Matrix3 ptsToUnitMatrix(Offset start, Offset end) { |
|||
var vec = end - start; |
|||
var mag = vec.distance; |
|||
var inv = mag != 0 ? 1 / mag : 0; |
|||
vec = vec.scale(inv); |
|||
|
|||
var matrix = Matrix3.I(); |
|||
matrix.setSinCos((float) -vec.dy, (float) vec.dx, (float) start.dx, (float) start.dy); |
|||
matrix.postTranslate((float) -start.dx, (float) -start.dy); |
|||
matrix.postScale((float) inv, (float) inv); |
|||
return matrix; |
|||
} |
|||
} |
|||
|
|||
class _RadialGradient : Gradient { |
|||
public _RadialGradient( |
|||
Offset center, double radius, List<Color> colors, |
|||
List<double> colorStops = null, TileMode tileMode = TileMode.clamp, |
|||
Matrix3 matrix = null |
|||
) { |
|||
this.center = center; |
|||
this.radius = radius; |
|||
this.colors = colors; |
|||
this.colorStops = colorStops; |
|||
this.tileMode = tileMode; |
|||
this.matrix = matrix; |
|||
this.ptsToUnit = radToUnitMatrix(center, radius); |
|||
this.gradientTex = makeTexturedColorizer(colors, colorStops); |
|||
} |
|||
|
|||
public readonly Offset center; |
|||
public readonly double radius; |
|||
public readonly List<Color> colors; |
|||
public readonly List<double> colorStops; |
|||
public readonly TileMode tileMode; |
|||
public readonly Matrix3 matrix; |
|||
public readonly Matrix3 ptsToUnit; |
|||
public readonly Image gradientTex; |
|||
|
|||
public Color leftColor { |
|||
get { return this.colors[0]; } |
|||
} |
|||
|
|||
public Color rightColor { |
|||
get { return this.colors[this.colors.Count - 1]; } |
|||
} |
|||
|
|||
public Matrix3 getGradientMat(Matrix3 ctm) { |
|||
var mat = Matrix3.I(); |
|||
ctm.invert(mat); // just use I() if not invertible.
|
|||
|
|||
if (this.matrix != null) { |
|||
mat.postConcat(this.matrix); |
|||
} |
|||
mat.postConcat(this.ptsToUnit); |
|||
return mat; |
|||
} |
|||
|
|||
static Matrix3 radToUnitMatrix(Offset center, double radius) { |
|||
var inv = radius != 0 ? 1 / radius : 0; |
|||
|
|||
var matrix = Matrix3.I(); |
|||
matrix.setTranslate((float) -center.dx, (float) -center.dy); |
|||
matrix.postScale((float) inv, (float) inv); |
|||
return matrix; |
|||
} |
|||
} |
|||
|
|||
class _SweepGradient : Gradient { |
|||
|
|||
public _SweepGradient( |
|||
Offset center, List<Color> colors, |
|||
List<double> colorStops = null, TileMode tileMode = TileMode.clamp, |
|||
double startAngle = 0.0, double endAngle = Math.PI * 2, |
|||
Matrix3 matrix = null |
|||
) { |
|||
this.center = center; |
|||
this.colors = colors; |
|||
this.colorStops = colorStops; |
|||
this.tileMode = tileMode; |
|||
this.startAngle = startAngle; |
|||
this.endAngle = endAngle; |
|||
this.matrix = matrix; |
|||
|
|||
var t0 = startAngle / (Math.PI * 2f); |
|||
var t1 = endAngle / (Math.PI * 2f); |
|||
this.bias = -t0; |
|||
this.scale = 1f / (t1 - t0); |
|||
|
|||
var ptsToUnit = Matrix3.I(); |
|||
ptsToUnit.setTranslate((float) -center.dx, (float) -center.dy); |
|||
this.ptsToUnit = ptsToUnit; |
|||
|
|||
this.gradientTex = makeTexturedColorizer(colors, colorStops); |
|||
} |
|||
|
|||
public readonly Offset center; |
|||
public readonly List<Color> colors; |
|||
public readonly List<double> colorStops; |
|||
public readonly TileMode tileMode; |
|||
public readonly double startAngle; |
|||
public readonly double endAngle; |
|||
public readonly Matrix3 matrix; |
|||
public readonly Matrix3 ptsToUnit; |
|||
public readonly Image gradientTex; |
|||
public readonly double bias; |
|||
public readonly double scale; |
|||
|
|||
public Color leftColor { |
|||
get { return this.colors[0]; } |
|||
} |
|||
|
|||
public Color rightColor { |
|||
get { return this.colors[this.colors.Count - 1]; } |
|||
} |
|||
|
|||
public Matrix3 getGradientMat(Matrix3 ctm) { |
|||
var mat = Matrix3.I(); |
|||
ctm.invert(mat); // just use I() if not invertible.
|
|||
|
|||
if (this.matrix != null) { |
|||
mat.postConcat(this.matrix); |
|||
} |
|||
mat.postConcat(this.ptsToUnit); |
|||
return mat; |
|||
} |
|||
} |
|||
|
|||
public class ImageShader : PaintShader { |
|||
public ImageShader(Image image, |
|||
TileMode tileMode = TileMode.clamp, Matrix3 matrix = null) { |
|||
this.image = image; |
|||
this.tileMode = tileMode; |
|||
this.matrix = matrix; |
|||
} |
|||
|
|||
public readonly Image image; |
|||
public readonly TileMode tileMode; |
|||
public readonly Matrix3 matrix; |
|||
|
|||
public Matrix3 getShaderMat(Matrix3 ctm) { |
|||
var mat = Matrix3.I(); |
|||
ctm.invert(mat); // just use I() if not invertible.
|
|||
|
|||
if (this.matrix != null) { |
|||
mat.postConcat(this.matrix); |
|||
} |
|||
|
|||
mat.postScale(1f / this.image.width, 1f / this.image.height); |
|||
return mat; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 740926ff13f534c8d8ec44b0b017ff61 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: a4bf4806dd96141b189111637bb1f450 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: d8fa175306ac44f8ea120cf256fd21d9 |
|||
TextureImporter: |
|||
fileIDToRecycleName: {} |
|||
externalObjects: {} |
|||
serializedVersion: 7 |
|||
mipmaps: |
|||
mipMapMode: 0 |
|||
enableMipMap: 1 |
|||
sRGBTexture: 1 |
|||
linearTexture: 0 |
|||
fadeOut: 0 |
|||
borderMipMap: 0 |
|||
mipMapsPreserveCoverage: 0 |
|||
alphaTestReferenceValue: 0.5 |
|||
mipMapFadeDistanceStart: 1 |
|||
mipMapFadeDistanceEnd: 3 |
|||
bumpmap: |
|||
convertToNormalMap: 0 |
|||
externalNormalMap: 0 |
|||
heightScale: 0.25 |
|||
normalMapFilter: 0 |
|||
isReadable: 0 |
|||
streamingMipmaps: 0 |
|||
streamingMipmapsPriority: 0 |
|||
grayScaleToAlpha: 0 |
|||
generateCubemap: 6 |
|||
cubemapConvolution: 0 |
|||
seamlessCubemap: 0 |
|||
textureFormat: 1 |
|||
maxTextureSize: 2048 |
|||
textureSettings: |
|||
serializedVersion: 2 |
|||
filterMode: -1 |
|||
aniso: -1 |
|||
mipBias: -100 |
|||
wrapU: -1 |
|||
wrapV: -1 |
|||
wrapW: -1 |
|||
nPOTScale: 1 |
|||
lightmap: 0 |
|||
compressionQuality: 50 |
|||
spriteMode: 0 |
|||
spriteExtrude: 1 |
|||
spriteMeshType: 1 |
|||
alignment: 0 |
|||
spritePivot: {x: 0.5, y: 0.5} |
|||
spritePixelsToUnits: 100 |
|||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} |
|||
spriteGenerateFallbackPhysicsShape: 1 |
|||
alphaUsage: 1 |
|||
alphaIsTransparency: 0 |
|||
spriteTessellationDetail: -1 |
|||
textureType: 0 |
|||
textureShape: 1 |
|||
singleChannelComponent: 0 |
|||
maxTextureSizeSet: 0 |
|||
compressionQualitySet: 0 |
|||
textureFormatSet: 0 |
|||
platformSettings: |
|||
- serializedVersion: 2 |
|||
buildTarget: DefaultTexturePlatform |
|||
maxTextureSize: 2048 |
|||
resizeAlgorithm: 0 |
|||
textureFormat: -1 |
|||
textureCompression: 1 |
|||
compressionQuality: 50 |
|||
crunchedCompression: 0 |
|||
allowsAlphaSplitting: 0 |
|||
overridden: 0 |
|||
androidETC2FallbackOverride: 0 |
|||
spriteSheet: |
|||
serializedVersion: 2 |
|||
sprites: [] |
|||
outline: [] |
|||
physicsShape: [] |
|||
bones: [] |
|||
spriteID: |
|||
vertices: [] |
|||
indices: |
|||
edges: [] |
|||
weights: [] |
|||
spritePackingTag: |
|||
pSDRemoveMatte: 0 |
|||
pSDShowRemoveMatteOption: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: baf507ab371c4f4c9eb9ce70a004ba0d |
|||
timeCreated: 1543832597 |
|
|||
Shader "UIWidgets/canvas" |
|||
{ |
|||
Properties { |
|||
_SrcBlend("_SrcBlend", Int) = 1 // One |
|||
_DstBlend("_DstBlend", Int) = 10 // OneMinusSrcAlpha |
|||
} |
|||
|
|||
CGINCLUDE |
|||
float4 _viewport; |
|||
float4x4 _paintMat; |
|||
half4 _innerCol; |
|||
half4 _outerCol; |
|||
float2 _extent; |
|||
float _radius; |
|||
float _feather; |
|||
sampler2D _tex; |
|||
|
|||
half2 _mf_imgInc; // _mf stands for mask filter |
|||
int _mf_radius; |
|||
half _mf_kernel[25]; |
|||
|
|||
struct appdata_t { |
|||
float4 vertex : POSITION; |
|||
float2 tcoord : TEXCOORD0; |
|||
}; |
|||
|
|||
struct v2f { |
|||
float4 vertex : SV_POSITION; |
|||
float2 ftcoord : TEXCOORD0; |
|||
float2 fpos : TEXCOORD1; |
|||
}; |
|||
|
|||
float sdroundrect (float2 pt, float2 ext, float rad) { |
|||
float2 ext2 = ext - float2(rad, rad); |
|||
float2 d = abs(pt) - ext2; |
|||
return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - rad; |
|||
} |
|||
|
|||
#pragma vertex vert |
|||
v2f vert (appdata_t v) { |
|||
v2f o; |
|||
o.ftcoord = v.tcoord; |
|||
o.fpos = v.vertex; |
|||
|
|||
float x = v.vertex.x - _viewport.x; |
|||
float y = v.vertex.y - _viewport.y; |
|||
|
|||
#if UNITY_UV_STARTS_AT_TOP |
|||
o.vertex = float4(2.0 * x / _viewport.z - 1.0, 2.0 * y / _viewport.w - 1.0, 0, 1); |
|||
#else |
|||
o.vertex = float4(2.0 * x / _viewport.z - 1.0, 1.0 - 2.0 * y / _viewport.w, 0, 1); |
|||
#endif |
|||
|
|||
return o; |
|||
} |
|||
|
|||
fixed4 frag (v2f i) : SV_Target { |
|||
float2 pt = (mul(_paintMat, float3(i.fpos, 1.0))).xy; |
|||
float d = clamp((sdroundrect(pt, _extent, _radius) + _feather * 0.5) / _feather, 0.0, 1.0); |
|||
half4 color = lerp(_innerCol, _outerCol, d); |
|||
return color; |
|||
} |
|||
|
|||
fixed4 frag_stencil (v2f i) : SV_Target { |
|||
return half4(0, 0, 0, 0); |
|||
} |
|||
|
|||
fixed4 frag_tex (v2f i) : SV_Target { |
|||
half4 color = tex2D(_tex, i.ftcoord); |
|||
color = color * _innerCol; // tint color |
|||
color = half4(color.xyz * color.w, color.w); |
|||
return color; |
|||
} |
|||
|
|||
fixed4 frag_texrt (v2f i) : SV_Target { |
|||
half4 color = tex2D(_tex, i.ftcoord); |
|||
color = color * _innerCol; // tint color |
|||
color = half4(color.xyz * _innerCol.w, color.w); |
|||
return color; |
|||
} |
|||
|
|||
fixed4 frag_texfont (v2f i) : SV_Target { |
|||
half4 color = tex2D(_tex, i.ftcoord); |
|||
color = half4(1, 1, 1, color.w) * _innerCol; // tint color |
|||
color = half4(color.xyz * color.w, color.w); |
|||
return color; |
|||
} |
|||
|
|||
fixed4 frag_mf (v2f i) : SV_Target { |
|||
half4 color = half4(0, 0, 0, 0); |
|||
|
|||
float2 coord = i.ftcoord - _mf_radius * _mf_imgInc; |
|||
int width = _mf_radius * 2 + 1; |
|||
for (int i = 0; i < width; i++) { |
|||
color += tex2D(_tex, coord) * _mf_kernel[i]; |
|||
coord += _mf_imgInc; |
|||
} |
|||
|
|||
color = color * _innerCol; // tint color |
|||
color = half4(color.xyz * _innerCol.w, color.w); |
|||
return color; |
|||
} |
|||
|
|||
ENDCG |
|||
|
|||
SubShader { |
|||
ZTest Always |
|||
ZWrite Off |
|||
Blend [_SrcBlend] [_DstBlend] |
|||
|
|||
Pass { // 0, fill pass 0 |
|||
Cull Off |
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 128 |
|||
CompFront Equal |
|||
CompBack Equal |
|||
ReadMask 128 |
|||
WriteMask 127 |
|||
PassFront IncrWrap |
|||
PassBack DecrWrap |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 1, fill pass 1 |
|||
Stencil { |
|||
Ref 0 |
|||
Comp NotEqual |
|||
ReadMask 127 |
|||
WriteMask 127 |
|||
Pass Zero |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 2, convex fill |
|||
Stencil { |
|||
Ref 128 |
|||
Comp Equal |
|||
} |
|||
CGPROGRAM |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 3, stroke pass 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Comp Equal |
|||
Pass IncrSat |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 4, stroke pass 1 |
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 0 |
|||
Comp NotEqual |
|||
ReadMask 127 |
|||
WriteMask 127 |
|||
Pass Zero |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 5, texture pass 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Comp Equal |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_tex |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 6, render texture pass 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Comp Equal |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_texrt |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 7, stencil clear |
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Pass Replace |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 8, stencil intersect 0 |
|||
Cull Off |
|||
ColorMask 0 |
|||
Stencil { |
|||
WriteMask 127 |
|||
PassFront IncrWrap |
|||
PassBack DecrWrap |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 9, stencil intersect 1 |
|||
ColorMask 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Comp Less |
|||
Pass Replace |
|||
Fail Zero |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_stencil |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 10, font texture pass 0 |
|||
Stencil { |
|||
Ref 128 |
|||
Comp Equal |
|||
} |
|||
|
|||
CGPROGRAM |
|||
#pragma fragment frag_texfont |
|||
ENDCG |
|||
} |
|||
|
|||
Pass { // 11, mask filter |
|||
CGPROGRAM |
|||
#pragma fragment frag_mf |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue