Unity打包图集还是有一些坑的,至于图集SpriteAtlas是什么请参考我之前写的文章:【Sprite Atlas】Unity新图集系统SpriteAtlas超详细使用教程_spriteatlas 使用-CSDN博客
问题:
今天碰到的问题是,shader绘制的时候,因为打包图集后,MainTexture是图集的图片,所以shader渲染就错误了。
非图集是这样显示的,正常的一个地块。
打包完图集后,发现这个MainTexture是整个图集的图片
导致显示就错乱了,如下图。
正常的显示是这样的。
问题所在:
原因就是打包图集后传入给shader的uv变了,本来只有图片的时候,uv就是0-1的本地uv值,现在素材换成一张更大的图了,导致uv采样就出现了问题。
解决方法:
将图片本身的uv信息传给shader,做一个计算转换即可。
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.Sprites;
using UnityEngine;
public class StaticGroundObject : GroundObject
{
public GameObject notCellObjectShow;
private SpriteRenderer spriteRenderer;
private const string _UVRangeName = "_UVRange";
protected override void OnStart()
{
base.OnStart();
SetSortingOrder();
spriteRenderer = GetComponentInChildren<SpriteRenderer>();
UpdateSpriteRenderer();
}
protected override void OnEnable()
{
base.OnEnable();
}
//修改也要
void UpdateSpriteRenderer()
{
if (spriteRenderer != null)
{
Sprite sprite = spriteRenderer.sprite;
Vector2 texelSize = sprite.texture.texelSize;
Rect rect = sprite.textureRect;
Vector4 uvRemap = new(
rect.x * texelSize.x,
rect.y * texelSize.y,
rect.width * texelSize.x,
rect.height * texelSize.y
);
// 将UV值传递给材质
Material material = spriteRenderer.material;
if (material != null)
{
// 确保shader中有对应的属性
if (material.HasProperty(_UVRangeName))
{
material.SetVector(_UVRangeName, uvRemap);
Debug.Log("UV值已成功写入shader");
}
else
{
Debug.LogError("shader缺少必要的属性,请确保shader中定义了_UV1和_UV2属性");
}
}
else
{
Debug.LogError("renderer的材质为空");
}
}
}
public override void SetNotCellObjectShow(GameObject notCellObjectShow)
{
base.SetNotCellObjectShow(notCellObjectShow);
this.notCellObjectShow = notCellObjectShow;
}
protected override void CheckRandomPrefabs(bool isShow)
{
if (notCellObjectShow != null)
{
//上面没有东西,而且没有混合到其他格子上
if (ParentGround == null && isShow)
{
notCellObjectShow.SetActive(true);
}
else
{
notCellObjectShow.SetActive(false);
}
}
}
private void SetSortingOrder()
{
var ground = GetComponentsInChildren<SpriteRenderer>(true)[0];
var groundName = ground.name;
var lastIndex = groundName.LastIndexOf('_');
var secondLastIndex = groundName.LastIndexOf('_', lastIndex - 1);
int.TryParse(groundName.Substring(secondLastIndex + 1, lastIndex - secondLastIndex - 1), out int result);
ground.sortingOrder -= result;
}
protected override void SetBlendMaskValue(Texture2D newBlendMask, int newRotateMaskValue, Texture2D mainBlendTex,
Texture2D blendMaskChamfer, Dictionary<int, float> _offsetList)
{
// base.SetBlendMaskValue(newBlendMask, newRotateMaskValue, mainBlendTex, blendMaskChamfer, offsetList);
//获得要渲染的对象
if (mainBlends.Count == 0)
{
mainBlends = GetComponentsInChildren<Renderer>().ToList();
}
if (mainBlends.Count == 0)
{
Debug.LogError("mainBlends.Count==0");
return;
}
//设置遮罩贴图
this.blendMask = newBlendMask;
this.rotateMaskValue = newRotateMaskValue;
this.mainBlendTex = mainBlendTex;
this.blendMaskChamfer = blendMaskChamfer;
//设置偏移值
this.blendOffsetTargetList = _offsetList;
UpdateMaterial();
UpdateSpriteRenderer();
}
protected override void SetBlendOffsetList(Dictionary<int, float> _offsetList)
{
// base.SetBlendOffsetList(_offsetList);
blendOffsetTargetList = _offsetList;
UpdateMaterial();
UpdateSpriteRenderer();
}
}
public class MaterialCacheTool
{
public static Dictionary<string, Material> materialCache = new Dictionary<string, Material>();
public static Material CheckMaterial(string materialKey, Renderer defaultRenderer, Action<Material> onInit)
{
Material checkMaterial = null;
if (materialCache.ContainsKey(materialKey))
{
checkMaterial = materialCache[materialKey];
}
else
{
var material = new Material(defaultRenderer.sharedMaterial);
material.name = materialKey;
onInit?.Invoke(material);
materialCache.Add(materialKey, material);
checkMaterial = material;
}
return checkMaterial;
}
}
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Shader/GroundObjectV3_Code"
{
Properties
{
[NoScaleOffset]_MaskMap("MaskMap", 2D) = "white" {}
[NoScaleOffset]_MainTex("MainTex", 2D) = "white" {}
[NoScaleOffset]_Chamfer("Chamfer", 2D) = "black" {}
_RotateMask("RotateMask",Range(0, 360)) = 0
_OffsetUp("OffsetUp", Range(0, 1)) = 0
_OffsetDown("OffsetDown", Range(0, 1)) = 0
_OffsetLeft("OffsetLeft", Range(0, 1)) = 0
_OffsetRight("OffsetRight", Range(0, 1)) = 0
_OffsetUpLeft("OffsetUpLeft", Range(0, 1)) = 0
_OffsetUpRight("OffsetUpRight", Range(0, 1)) = 0
_OffsetDownLeft("OffsetDownLeft", Range(0, 1)) = 0
_OffsetDownRight("OffsetDownRight", Range(0, 1)) = 0
//相反
_IsInversion("IsInversion", Float) = 0
[NoScaleOffset]_BlendMaskMap("BlendMaskMap", 2D) = "black" {}
[NoScaleOffset]_BlendMainTex("BlendMainTex", 2D) = "white" {}
[NoScaleOffset]_BlendChamfer("_BlendChamfer", 2D) = "black" {}
_BlendOffsetUp("BlendOffsetUp", Range(0, 1)) = 0
_BlendOffsetDown("BlendOffsetDown", Range(0, 1)) = 0
_BlendOffsetLeft("BlendOffsetLeft", Range(0, 1)) = 0
_BlendOffsetRight("BlendOffsetRight", Range(0, 1)) = 0
_BlendOffsetUpLeft("BlendOffsetUpLeft", Range(0, 1)) = 0
_BlendOffsetUpRight("BlendOffsetUpRight", Range(0, 1)) = 0
_BlendOffsetDownLeft("BlendOffsetDownLeft", Range(0, 1)) = 0
_BlendOffsetDownRight("BlendOffsetDownRight", Range(0, 1)) = 0
[HideInInspector]_QueueOffset("_QueueOffset", Float) = 0
[HideInInspector]_QueueControl("_QueueControl", Float) = -1
[HideInInspector][NoScaleOffset]unity_Lightmaps("unity_Lightmaps", 2DArray) = "" {}
[HideInInspector][NoScaleOffset]unity_LightmapsInd("unity_LightmapsInd", 2DArray) = "" {}
[HideInInspector][NoScaleOffset]unity_ShadowMasks("unity_ShadowMasks", 2DArray) = "" {}
_OffsetFactor("OffsetFactor", Float) = 0
_OffsetUnits("OffsetUnits", Float) = 0
[ToggleUI] _ReceiveShadows("Receive Shadows", Float) = 1.0
[ToggleUI] _CastShadows("Cast Shadows", Float) = 1.0
//阴影模糊
_ShadowBlur("ShadowBlur", Float) = 0.0
_Cull("__cull", Float) = 2.0
// 新增距离缩放因子属性
_DistanceScaleFactor("Distance Scale Factor", Range(0.1, 100.0)) = 60.0
//补充UV
_UVRange("UV Range", Vector) = (0, 0, 1, 1)
}
SubShader
{
Tags
{
"RenderPipeline"="UniversalPipeline"
"RenderType"="Opaque"
"UniversalMaterialType" = "Lit"
"Queue"="AlphaTest"
"DisableBatching"="LODFading"
"ShaderGraphShader"="true"
"ShaderGraphTargetId"="UniversalLitSubTarget"
"EnableGPUInstancing" = "true"
}
LOD 100
Pass
{
// Render State
Cull Back
ZTest LEqual
ZWrite On
Blend One Zero
AlphaToMask On
offset [_OffsetFactor] , [_OffsetUnits]
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
// #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
// #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "EgoLight.hlsl"
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
//光照计算
float4 positionOS : POSITION;
float4 normalOS : NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
// UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
float3 worldPos : TEXCOORD1;
//光照计算
float3 viewDirWS : TEXCOORD2;
float3 normalWS : TEXCOORD3;
// 新增距离变量
float distanceToCamera : TEXCOORD4;
float prevLod : TEXCOORD5; // 新增变量存储上一次的LOD
float2 uv2:TEXCOORD6;
};
sampler2D _MaskMap;
float4 _MaskMap_ST;
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _Chamfer;
float4 _Chamfer_ST;
float _RotateMask;
float _OffsetUp;
float _OffsetDown;
float _OffsetLeft;
float _OffsetRight;
float _OffsetUpLeft;
float _OffsetUpRight;
float _OffsetDownLeft;
float _OffsetDownRight;
float _IsInversion;
//混合剔除的参数
sampler2D _BlendMaskMap;
float4 _BlendMaskMap_ST;
sampler2D _BlendMainTex;
float4 _BlendMainTex_ST;
sampler2D _BlendChamfer;
float4 _BlendChamfer_ST;
float _BlendOffsetUp;
float _BlendOffsetDown;
float _BlendOffsetLeft;
float _BlendOffsetRight;
float _BlendOffsetUpLeft;
float _BlendOffsetUpRight;
float _BlendOffsetDownLeft;
float _BlendOffsetDownRight;
float4 _GlobalShadowColor;
// 新增距离缩放因子属性变量,放在HLSL代码的合适位置,这里在函数外部声明
float _DistanceScaleFactor;
float4 _UVRange;
v2f vert (appdata v)
{
v2f o;
o.uv = TRANSFORM_TEX(v.uv, _MaskMap);
float2 spriteRectPos = _UVRange.xy;
float2 spriteRectSize = _UVRange.zw;
float2 localUV = (v.uv - spriteRectPos) / spriteRectSize;
o.uv2 = localUV;
o.vertex = TransformObjectToHClip(v.vertex);//UnityObjectToClipPos //o.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
// 计算物体到摄像机的距离
o.distanceToCamera = distance(mul(unity_ObjectToWorld, v.vertex).xyz, _WorldSpaceCameraPos.xyz);
o.prevLod = 0; // 初始化
//光照计算
VertexPositionInputs positionInputs = GetVertexPositionInputs(v.positionOS.xyz);
VertexNormalInputs normalInputs = GetVertexNormalInputs(v.normalOS.xyz);
o.viewDirWS = GetCameraPositionWS() - positionInputs.positionWS;
o.normalWS = normalInputs.normalWS;
return o;
}
float2 GetMaskUV(float2 uv)
{
float2 maskUV=uv;
maskUV -= 0.5;
// 旋转 45 度(π/4 弧度)
float angle = radians(_RotateMask);
float cosAngle = cos(angle);
float sinAngle = sin(angle);
float2x2 rotationMatrix = float2x2(cosAngle, -sinAngle, sinAngle, cosAngle);
maskUV = mul(rotationMatrix, maskUV);
// 平移回原来的坐标
maskUV += 0.5;
return maskUV;
}
//全部的Offset
float GetColorMask(sampler2D colorMask, sampler2D colorChamfer,float2 uv, float _OffsetUp, float _OffsetDown, float _OffsetLeft, float _OffsetRight, float _OffsetUpLeft, float _OffsetUpRight, float _OffsetDownLeft, float _OffsetDownRight,float _lod)
{
float offsetMax = 0.5;
float2 offsets[8] = {
float2(0, -_OffsetUp * offsetMax),
float2(0, _OffsetDown * offsetMax),
float2(_OffsetLeft * offsetMax, 0),
float2(-_OffsetRight * offsetMax, 0),
float2(_OffsetUpLeft * offsetMax, -_OffsetUpLeft * offsetMax),
float2(-_OffsetUpRight * offsetMax, -_OffsetUpRight * offsetMax),
float2(_OffsetDownLeft * offsetMax, _OffsetDownLeft * offsetMax),
float2(-_OffsetDownRight * offsetMax, _OffsetDownRight * offsetMax)
};
float alpha = 0;
alpha += tex2Dlod(colorMask, float4(GetMaskUV(uv),0,_lod)).r;
// 循环采样偏移纹理
//for (int i = 0; i < 8; i++) {
// alpha += tex2Dlod(colorMask, float4(GetMaskUV(uv + offsets[i]),0,_lod)).r;
//}
alpha += tex2Dlod(colorMask, float4(GetMaskUV(uv + offsets[0]),0,_lod)).r;
alpha += tex2Dlod(colorMask, float4(GetMaskUV(uv + offsets[1]),0,_lod)).r;
alpha += tex2Dlod(colorMask, float4(GetMaskUV(uv + offsets[2]),0,_lod)).r;
alpha += tex2Dlod(colorMask, float4(GetMaskUV(uv + offsets[3]),0,_lod)).r;
alpha += tex2Dlod(colorMask, float4(GetMaskUV(uv + offsets[4]),0,_lod)).r;
alpha += tex2Dlod(colorMask, float4(GetMaskUV(uv + offsets[5]),0,_lod)).r;
alpha += tex2Dlod(colorMask, float4(GetMaskUV(uv + offsets[6]),0,_lod)).r;
alpha += tex2Dlod(colorMask, float4(GetMaskUV(uv + offsets[7]),0,_lod)).r;
// 采样倒角纹理
alpha += tex2Dlod(colorChamfer, float4(uv + float2( _OffsetLeft * offsetMax, -_OffsetUp * offsetMax),0,_lod)).r;
alpha += tex2Dlod(colorChamfer, float4(uv + float2(-_OffsetRight * offsetMax, -_OffsetUp * offsetMax),0,_lod)).r;
alpha += tex2Dlod(colorChamfer, float4(uv + float2( _OffsetLeft * offsetMax, _OffsetDown * offsetMax),0,_lod)).r;
alpha += tex2Dlod(colorChamfer, float4(uv + float2(-_OffsetRight * offsetMax, _OffsetDown * offsetMax),0,_lod)).r;
// 透明度限制在0-1之间
alpha = clamp(alpha, 0, 1);
return alpha;
}
float4 frag (v2f i) : SV_Target
{
float2 maskUV = i.uv2;
float lod = i.distanceToCamera / _DistanceScaleFactor;
lod = clamp(lod, 0, 5);
float mainAlpha = GetColorMask( _MaskMap, _Chamfer, maskUV, _OffsetUp, _OffsetDown, _OffsetLeft, _OffsetRight, _OffsetUpLeft, _OffsetUpRight, _OffsetDownLeft, _OffsetDownRight,lod);
// 计算主纹理的UV偏移
float2 mainTexUV = TRANSFORM_TEX(i.uv, _MainTex).xy;
float4 mainColor = tex2Dlod(_MainTex, float4(mainTexUV, 0, lod));//tex2D(_MainTex, TRANSFORM_TEX(i.uv, _MainTex));
mainAlpha *= mainColor.a;
float f = lerp(1.01,0.99,_IsInversion);//1.01;
//maskUV缩放变大一点点
maskUV -= 0.5;
maskUV *=lerp(1.01,0.99,_IsInversion); // 1.005;
maskUV += 0.5;
//各个边移动多一丢丢
// _BlendOffsetUp += float2(0,f);
// _BlendOffsetDown += float2(0,-f);
// _BlendOffsetLeft += float2(-f,0);
// _BlendOffsetRight += float2(f,0);
// _BlendOffsetUpLeft += float2(-f,f);
// _BlendOffsetUpRight += float2(f,f);
// _BlendOffsetDownLeft += float2(-f,-f);
// _BlendOffsetDownRight += float2(f,-f);
float blendAlpha = GetColorMask( _BlendMaskMap, _BlendChamfer, maskUV, _BlendOffsetUp, _BlendOffsetDown, _BlendOffsetLeft, _BlendOffsetRight, _BlendOffsetUpLeft, _BlendOffsetUpRight, _BlendOffsetDownLeft, _BlendOffsetDownRight,lod);
float4 blendColor = tex2Dlod(_BlendMainTex, float4(TRANSFORM_TEX(i.uv, _BlendMainTex),0,lod));
blendAlpha*=blendColor.a;
float alpha = mainAlpha - blendAlpha;
alpha = lerp(alpha,1-alpha,_IsInversion);
// 根据距离调整纹理采样的LOD
// mainColor = tex2Dlod(_MainTex, float4(TRANSFORM_TEX(i.uv, _MainTex).xy, 0, lod));
// blendColor = tex2Dlod(_BlendMainTex, float4(TRANSFORM_TEX(i.uv, _BlendMainTex).xy, 0, lod));
float _Cutoff = 0.8;
float3 color = CheckColor(i.worldPos,i.normalWS,_GlobalShadowColor,mainColor.rgb);
clip(alpha - _Cutoff);
return float4(color.rgb, alpha);
}
ENDHLSL
}
}
}