|
|
|
|
|
|
layerPaint = paint, |
|
|
|
}; |
|
|
|
|
|
|
|
parentLayer.layers.Add(layer); |
|
|
|
parentLayer.addLayer(layer); |
|
|
|
|
|
|
|
if (paint.backdrop != null) { |
|
|
|
if (paint.backdrop is _BlurImageFilter) { |
|
|
|
var filter = (_BlurImageFilter) paint.backdrop; |
|
|
|
if (!(filter.sigmaX == 0 && filter.sigmaY == 0)) { |
|
|
|
var points = new[] {bounds.topLeft, bounds.bottomLeft, bounds.bottomRight, bounds.topRight}; |
|
|
|
state.matrix.mapPoints(points); |
|
|
|
|
|
|
|
var parentBounds = parentLayer.layerBounds; |
|
|
|
for (int i = 0; i < 4; i++) { |
|
|
|
points[i] = new Offset( |
|
|
|
(points[i].dx - parentBounds.left) / parentBounds.width, |
|
|
|
(points[i].dy - parentBounds.top) / parentBounds.height |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
var mesh = ImageMeshGenerator.imageMesh( |
|
|
|
null, |
|
|
|
points[0], points[1], points[2], points[3], |
|
|
|
bounds); |
|
|
|
var renderDraw = CanvasShader.texRT(layer, layer.layerPaint, mesh, parentLayer); |
|
|
|
layer.draws.Add(renderDraw); |
|
|
|
|
|
|
|
var blurLayer = this._createBlurLayer(layer, filter.sigmaX, filter.sigmaY, layer); |
|
|
|
var blurMesh = ImageMeshGenerator.imageMesh(null, Rect.one, bounds); |
|
|
|
layer.draws.Add(CanvasShader.texRT(layer, paint, blurMesh, blurLayer)); |
|
|
|
} |
|
|
|
} else if (paint.backdrop is _MatrixImageFilter) { |
|
|
|
var filter = (_MatrixImageFilter) paint.backdrop; |
|
|
|
if (!filter.transform.isIdentity()) { |
|
|
|
layer.filterMode = filter.filterMode; |
|
|
|
|
|
|
|
var points = new[] {bounds.topLeft, bounds.bottomLeft, bounds.bottomRight, bounds.topRight}; |
|
|
|
state.matrix.mapPoints(points); |
|
|
|
|
|
|
|
var parentBounds = parentLayer.layerBounds; |
|
|
|
for (int i = 0; i < 4; i++) { |
|
|
|
points[i] = new Offset( |
|
|
|
(points[i].dx - parentBounds.left) / parentBounds.width, |
|
|
|
(points[i].dy - parentBounds.top) / parentBounds.height |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
var matrix = Matrix3.makeTrans(-bounds.left, -bounds.top); |
|
|
|
matrix.postConcat(filter.transform); |
|
|
|
matrix.postTranslate(bounds.left, bounds.top); |
|
|
|
|
|
|
|
var mesh = ImageMeshGenerator.imageMesh( |
|
|
|
matrix, |
|
|
|
points[0], points[1], points[2], points[3], |
|
|
|
bounds); |
|
|
|
var renderDraw = CanvasShader.texRT(layer, layer.layerPaint, mesh, parentLayer); |
|
|
|
layer.draws.Add(renderDraw); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void _restore() { |
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
layer.draws.Add(new RenderScissor { |
|
|
|
layer.draws.Add(new CmdScissor { |
|
|
|
deviceScissor = scissor, |
|
|
|
}); |
|
|
|
layer.lastScissor = scissor; |
|
|
|
|
|
|
filterMode = FilterMode.Bilinear, |
|
|
|
}; |
|
|
|
|
|
|
|
parentLayer.layers.Add(maskLayer); |
|
|
|
parentLayer.addLayer(maskLayer); |
|
|
|
this._layers.Add(maskLayer); |
|
|
|
this._currentLayer = maskLayer; |
|
|
|
|
|
|
|
|
|
|
return maskLayer; |
|
|
|
} |
|
|
|
|
|
|
|
RenderLayer _createBlurLayer(RenderLayer maskLayer, float sigma, RenderLayer parentLayer) { |
|
|
|
sigma = BlurUtils.adjustSigma(sigma, out var scaleFactor, out var radius); |
|
|
|
RenderLayer _createBlurLayer(RenderLayer maskLayer, float sigmaX, float sigmaY, RenderLayer parentLayer) { |
|
|
|
sigmaX = BlurUtils.adjustSigma(sigmaX, out var scaleFactorX, out var radiusX); |
|
|
|
sigmaY = BlurUtils.adjustSigma(sigmaY, out var scaleFactorY, out var radiusY); |
|
|
|
var textureWidth = Mathf.CeilToInt((float) maskLayer.width / scaleFactor); |
|
|
|
var textureWidth = Mathf.CeilToInt((float) maskLayer.width / scaleFactorX); |
|
|
|
var textureHeight = Mathf.CeilToInt((float) maskLayer.height / scaleFactor); |
|
|
|
var textureHeight = Mathf.CeilToInt((float) maskLayer.height / scaleFactorY); |
|
|
|
if (textureHeight < 1) { |
|
|
|
textureHeight = 1; |
|
|
|
} |
|
|
|
|
|
|
filterMode = FilterMode.Bilinear, |
|
|
|
}; |
|
|
|
|
|
|
|
parentLayer.layers.Add(blurXLayer); |
|
|
|
parentLayer.addLayer(blurXLayer); |
|
|
|
|
|
|
|
var blurYLayer = new RenderLayer { |
|
|
|
rtID = Shader.PropertyToID("_rtID_" + this._layers.Count + "_" + parentLayer.layers.Count), |
|
|
|
|
|
|
filterMode = FilterMode.Bilinear, |
|
|
|
}; |
|
|
|
|
|
|
|
parentLayer.layers.Add(blurYLayer); |
|
|
|
parentLayer.addLayer(blurYLayer); |
|
|
|
var kernel = BlurUtils.get1DGaussianKernel(sigma, radius); |
|
|
|
var kernelX = BlurUtils.get1DGaussianKernel(sigmaX, radiusX); |
|
|
|
var kernelY = BlurUtils.get1DGaussianKernel(sigmaY, radiusY); |
|
|
|
radius, new Vector2(1f / textureWidth, 0), kernel)); |
|
|
|
radiusX, new Vector2(1f / textureWidth, 0), kernelX)); |
|
|
|
radius, new Vector2(0, -1f / textureHeight), kernel)); |
|
|
|
radiusY, new Vector2(0, -1f / textureHeight), kernelY)); |
|
|
|
|
|
|
|
return blurYLayer; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
var maskLayer = this._createMaskLayer(layer, maskBounds, drawAction, paint); |
|
|
|
|
|
|
|
var blurLayer = this._createBlurLayer(maskLayer, sigma, layer); |
|
|
|
var blurLayer = this._createBlurLayer(maskLayer, sigma, sigma, layer); |
|
|
|
|
|
|
|
var blurMesh = ImageMeshGenerator.imageMesh(null, Rect.one, maskBounds); |
|
|
|
if (!this._applyClip(blurMesh.bounds)) { |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
void _drawLayer(RenderLayer layer, CommandBuffer cmdBuf) { |
|
|
|
foreach (var subLayer in layer.layers) { |
|
|
|
var desc = new RenderTextureDescriptor( |
|
|
|
subLayer.width, subLayer.height, |
|
|
|
RenderTextureFormat.Default, 24) { |
|
|
|
useMipMap = false, |
|
|
|
autoGenerateMips = false, |
|
|
|
}; |
|
|
|
if (layer.rtID == 0) { |
|
|
|
cmdBuf.SetRenderTarget(this._renderTexture, |
|
|
|
RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); |
|
|
|
cmdBuf.ClearRenderTarget(true, true, UnityEngine.Color.clear); |
|
|
|
} |
|
|
|
else { |
|
|
|
cmdBuf.SetRenderTarget(layer.rtID, |
|
|
|
RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); |
|
|
|
cmdBuf.ClearRenderTarget(true, true, UnityEngine.Color.clear); |
|
|
|
} |
|
|
|
|
|
|
|
foreach (var cmdObj in layer.draws) { |
|
|
|
switch (cmdObj) { |
|
|
|
case CmdLayer cmd: |
|
|
|
var subLayer = cmd.layer; |
|
|
|
var desc = new RenderTextureDescriptor( |
|
|
|
subLayer.width, subLayer.height, |
|
|
|
RenderTextureFormat.Default, 24) { |
|
|
|
useMipMap = false, |
|
|
|
autoGenerateMips = false, |
|
|
|
}; |
|
|
|
if (QualitySettings.antiAliasing != 0) { |
|
|
|
desc.msaaSamples = QualitySettings.antiAliasing; |
|
|
|
} |
|
|
|
if (QualitySettings.antiAliasing != 0) { |
|
|
|
desc.msaaSamples = QualitySettings.antiAliasing; |
|
|
|
} |
|
|
|
cmdBuf.GetTemporaryRT(subLayer.rtID, desc, subLayer.filterMode); |
|
|
|
this._drawLayer(subLayer, cmdBuf); |
|
|
|
} |
|
|
|
|
|
|
|
if (layer.rtID == 0) { |
|
|
|
cmdBuf.SetRenderTarget(this._renderTexture, |
|
|
|
RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); |
|
|
|
cmdBuf.ClearRenderTarget(true, true, UnityEngine.Color.clear); |
|
|
|
} |
|
|
|
else { |
|
|
|
cmdBuf.SetRenderTarget(layer.rtID, |
|
|
|
RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); |
|
|
|
cmdBuf.ClearRenderTarget(true, true, UnityEngine.Color.clear); |
|
|
|
} |
|
|
|
cmdBuf.GetTemporaryRT(subLayer.rtID, desc, subLayer.filterMode); |
|
|
|
this._drawLayer(subLayer, cmdBuf); |
|
|
|
|
|
|
|
if (layer.rtID == 0) { |
|
|
|
cmdBuf.SetRenderTarget(this._renderTexture, |
|
|
|
RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); |
|
|
|
} |
|
|
|
else { |
|
|
|
cmdBuf.SetRenderTarget(layer.rtID, |
|
|
|
RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); |
|
|
|
} |
|
|
|
foreach (var cmdObj in layer.draws) { |
|
|
|
switch (cmdObj) { |
|
|
|
case RenderDraw cmd: |
|
|
|
break; |
|
|
|
case CmdDraw cmd: |
|
|
|
cmdBuf.SetGlobalTexture(RenderDraw.texId, cmd.layer.rtID); |
|
|
|
if (cmd.layer.rtID == 0) { |
|
|
|
cmdBuf.SetGlobalTexture(CmdDraw.texId, this._renderTexture); |
|
|
|
} else { |
|
|
|
cmdBuf.SetGlobalTexture(CmdDraw.texId, cmd.layer.rtID); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
D.assert(cmd.meshObj == null); |
|
|
|
|
|
|
if (mesh == null) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
D.assert(mesh.vertices.Count > 0); |
|
|
|
cmd.meshObj.SetVertices(mesh.vertices); |
|
|
|
|
|
|
if (mesh.matrix == null) { |
|
|
|
cmd.properties.SetFloatArray(RenderDraw.matId, RenderDraw.idMat3.fMat); |
|
|
|
cmd.properties.SetFloatArray(CmdDraw.matId, CmdDraw.idMat3.fMat); |
|
|
|
cmd.properties.SetFloatArray(RenderDraw.matId, mesh.matrix.fMat); |
|
|
|
cmd.properties.SetFloatArray(CmdDraw.matId, mesh.matrix.fMat); |
|
|
|
cmdBuf.DrawMesh(cmd.meshObj, RenderDraw.idMat, cmd.material, 0, cmd.pass, cmd.properties); |
|
|
|
cmdBuf.DrawMesh(cmd.meshObj, CmdDraw.idMat, cmd.material, 0, cmd.pass, cmd.properties); |
|
|
|
cmdBuf.SetGlobalTexture(RenderDraw.texId, BuiltinRenderTextureType.None); |
|
|
|
cmdBuf.SetGlobalTexture(CmdDraw.texId, BuiltinRenderTextureType.None); |
|
|
|
case RenderScissor cmd: |
|
|
|
case CmdScissor cmd: |
|
|
|
if (cmd.deviceScissor == null) { |
|
|
|
cmdBuf.DisableScissorRect(); |
|
|
|
} else { |
|
|
|
|
|
|
void _clearLayer(RenderLayer layer) { |
|
|
|
foreach (var cmdObj in layer.draws) { |
|
|
|
switch (cmdObj) { |
|
|
|
case RenderDraw cmd: |
|
|
|
case CmdDraw cmd: |
|
|
|
if (cmd.meshObjCreated) { |
|
|
|
this._meshPool.returnMesh(cmd.meshObj); |
|
|
|
cmd.meshObj = null; |
|
|
|
|
|
|
public uint lastClipGenId; |
|
|
|
public Rect lastClipBounds; |
|
|
|
public Rect lastScissor; |
|
|
|
public bool ignoreClip; |
|
|
|
public bool ignoreClip = true; |
|
|
|
|
|
|
|
Vector4? _viewport; |
|
|
|
|
|
|
|
|
|
|
this.currentState = new State(); |
|
|
|
this.states.Add(this.currentState); |
|
|
|
} |
|
|
|
|
|
|
|
public void addLayer(RenderLayer layer) { |
|
|
|
this.layers.Add(layer); |
|
|
|
this.draws.Add(new CmdLayer {layer = layer}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
internal class State { |
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
internal class RenderDraw { |
|
|
|
|
|
|
|
internal class CmdLayer { |
|
|
|
public RenderLayer layer; |
|
|
|
} |
|
|
|
|
|
|
|
internal class CmdDraw { |
|
|
|
public MeshMesh mesh; |
|
|
|
public TextBlobMesh textMesh; |
|
|
|
public int pass; |
|
|
|
|
|
|
public static readonly int matId = Shader.PropertyToID("_mat"); |
|
|
|
} |
|
|
|
|
|
|
|
internal class RenderScissor { |
|
|
|
internal class CmdScissor { |
|
|
|
public Rect deviceScissor; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
10, 11, 14, 11, 15, 14, |
|
|
|
}; |
|
|
|
|
|
|
|
public static MeshMesh imageMesh(Matrix3 matrix, |
|
|
|
Offset srcTL, Offset srcBL, Offset srcBR, Offset srcTR, |
|
|
|
Rect dst) { |
|
|
|
var vertices = new List<Vector3>(4); |
|
|
|
var uv = new List<Vector2>(4); |
|
|
|
|
|
|
|
vertices.Add(new Vector2(dst.left, dst.top)); |
|
|
|
uv.Add(new Vector2(srcTL.dx, 1.0f - srcTL.dy)); |
|
|
|
vertices.Add(new Vector2(dst.left, dst.bottom)); |
|
|
|
uv.Add(new Vector2(srcBL.dx, 1.0f - srcBL.dy)); |
|
|
|
vertices.Add(new Vector2(dst.right, dst.bottom)); |
|
|
|
uv.Add(new Vector2(srcBR.dx, 1.0f - srcBR.dy)); |
|
|
|
vertices.Add(new Vector2(dst.right, dst.top)); |
|
|
|
uv.Add(new Vector2(srcTR.dx, 1.0f - srcTR.dy)); |
|
|
|
|
|
|
|
return new MeshMesh(matrix, vertices, _imageTriangles, uv); |
|
|
|
} |
|
|
|
|
|
|
|
public static MeshMesh imageMesh(Matrix3 matrix, Rect src, Rect dst) { |
|
|
|
var vertices = new List<Vector3>(4); |
|
|
|
var uv = new List<Vector2>(4); |
|
|
|