您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

393 行
17 KiB

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,
};
}
}
}