UI-AlphaMask buildin rp 正交相机测试

This commit is contained in:
StarBeats 2025-10-10 20:13:16 +08:00
parent 45c479df00
commit 290a6a6529
10 changed files with 575 additions and 1 deletions

View File

@ -0,0 +1,199 @@
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
[ExecuteInEditMode]
[RequireComponent(typeof(Image))]
public class UIImageAlphaMask : MonoBehaviour
{
private Image m_MaskImage;
private Canvas m_Canvas;
private RectTransform m_RectTransform;
private Image[] m_TargetImageList;
private Material m_Material;
private Material Material
{
get
{
if (m_Material == null)
{
m_Material = new Material(Shader.Find("Hidden/UI/AlphaMask"));
}
return m_Material;
}
}
private Image MaskImage
{
get
{
if (m_MaskImage == null)
{
m_MaskImage = GetComponent<Image>();
}
return m_MaskImage;
}
}
private RectTransform SelfRect
{
get
{
if (m_RectTransform == null)
{
m_RectTransform = GetComponent<RectTransform>();
}
return m_RectTransform;
}
}
private Canvas RootCanvas
{
get
{
if (m_Canvas == null)
{
var canvas = GetComponentInParent<Canvas>();
if (canvas != null)
{
if (canvas.rootCanvas != null)
{
m_Canvas = canvas.rootCanvas;
}
else
{
m_Canvas = canvas;
}
}
}
return m_Canvas;
}
}
private void SetMaterial(Image[] imageList, Material material)
{
if (imageList == null)
{
return;
}
for (int i = 0; i < imageList.Length; i++)
{
var image = imageList[i];
image.material = material;
}
}
private void Update()
{
if (!IsValid())
{
return;
}
if (m_TargetImageList == null || m_TargetImageList.Length <= 0)
{
m_TargetImageList = GetComponentsInChildren<Image>(true);
m_TargetImageList = m_TargetImageList.Where(o => o.transform != this.transform).ToArray();
SetMaterial(m_TargetImageList, Material);
}
SetProperties();
}
private bool IsValid()
{
if (RootCanvas == null)
{
return false;
}
if (RootCanvas.renderMode == RenderMode.ScreenSpaceOverlay)
{
return false;
}
if (MaskImage.sprite == null)
{
return false;
}
return true;
}
private void SetProperties()
{
var camera = GetCamera();
if (camera == null)
{
return;
}
var matrix = CalculateMatrix(camera);
Material.SetTexture("_MaskTex", MaskImage.sprite.texture);
Material.SetMatrix("_MaskMatrix", matrix);
}
private Camera GetCamera()
{
return RootCanvas.worldCamera;
}
private Matrix4x4 CalculateMatrix(Camera camera)
{
var rect = CalcurateViewportRect(camera);
Matrix4x4 result = Matrix4x4.identity;
var halfSize = rect.size * 0.5f;
result = Matrix4x4.Ortho(
rect.center.x - halfSize.x,
rect.center.x + halfSize.x,
rect.center.y - halfSize.y,
rect.center.y + halfSize.y,
camera.nearClipPlane,
camera.farClipPlane
);
result = Matrix4x4.TRS(Vector3.one * 0.5f, Quaternion.identity, Vector3.one * 0.5f) * GL.GetGPUProjectionMatrix(result, false) * camera.worldToCameraMatrix;
return result;
}
private Rect CalcurateViewportRect(Camera camera)
{
var corners = new Vector3[4];
SelfRect.GetWorldCorners(corners);
var p1 = RectTransformUtility.WorldToScreenPoint(camera, corners[1]);
var p3 = RectTransformUtility.WorldToScreenPoint(camera, corners[3]);
var x = p1.x - (Screen.width * 0.5f);
var y = p3.y - (Screen.height * 0.5f);
var width = p3.x - p1.x;
var height = p1.y - p3.y;
x /= (Screen.width * 0.5f);
width /= (Screen.width * 0.5f);
y /= (Screen.height * 0.5f);
height /= (Screen.height * 0.5f);
var size = camera.orthographicSize;
var aspect = Screen.width / (float)Screen.height;
x *= size * aspect;
width *= size * aspect;
y *= size;
height *= size;
var rect = new Rect()
{
x = x,
width = width,
y = y,
height = height
};
return rect;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d8fd4dba1064bc642874d75100ae59fa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -40,7 +40,7 @@ MonoBehaviour:
m_MainLightShadowmapResolution: 2048
m_AdditionalLightsRenderingMode: 2
m_AdditionalLightsPerObjectLimit: 4
m_AdditionalLightShadowsSupported: 0
m_AdditionalLightShadowsSupported: 1
m_AdditionalLightsShadowmapResolution: 2048
m_AdditionalLightsShadowResolutionTierLow: 256
m_AdditionalLightsShadowResolutionTierMedium: 512

8
Assets/Shaders.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 20aee86cb7a762843aa7fd2e76903f53
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,119 @@
Shader "Hidden/UI/AlphaMask"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
_StencilComp ("Stencil Comparison", Float) = 8
_Stencil ("Stencil ID", Float) = 0
_StencilOp ("Stencil Operation", Float) = 0
_StencilWriteMask ("Stencil Write Mask", Float) = 255
_StencilReadMask ("Stencil Read Mask", Float) = 255
_ColorMask ("Color Mask", Float) = 15
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask [_ColorMask]
Pass
{
Name "Default"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#include "UnityCG.cginc"
#include "UnityUI.cginc"
#pragma multi_compile __ UNITY_UI_ALPHACLIP
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
float4 worldPosition : TEXCOORD1;
float2 maskUv : TEXCOORD2;
UNITY_VERTEX_OUTPUT_STEREO
};
fixed4 _Color;
fixed4 _TextureSampleAdd;
float4 _ClipRect;
float4x4 _MaskMatrix;
v2f vert(appdata_t IN)
{
v2f OUT;
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.worldPosition = IN.vertex;
float4 wp = mul(unity_ObjectToWorld, IN.vertex);
OUT.vertex = mul(UNITY_MATRIX_VP, wp);
OUT.maskUv = mul(_MaskMatrix, wp).xy;
OUT.texcoord = IN.texcoord;
OUT.color = IN.color * _Color;
return OUT;
}
sampler2D _MainTex;
sampler2D _MaskTex;
fixed4 frag(v2f IN) : SV_Target
{
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
half4 mask = tex2D(_MaskTex, IN.maskUv);
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
color.a *= mask.a;
#ifdef UNITY_UI_ALPHACLIP
clip (color.a - 0.001);
#endif
return color;
}
ENDCG
}
}
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 5c547192ffda6db41ab2c9d23f79b171
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

View File

@ -0,0 +1,114 @@
fileFormatVersion: 2
guid: a3178569a950efc42a31ec01a5756b01
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
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
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
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: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,114 @@
fileFormatVersion: 2
guid: 2c0de1bad5aed9d4fa2e54bdf034e619
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
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
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
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: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant: