Unity 贴图叠加,添加水印

原创内容,转载请标明出处

Shader "Custom/AddWatermarkShader"
{
    Properties
    {
        _MainTex("Main Texture", 2D) = "white" {}
        _WatermarkTex("Watermark Texture", 2D) = "white" {}
        _WatermarkPosition("Watermark Position", Vector) = (0, 0, 122, 34)
    }

    SubShader
    {
        Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_TexelSize;

            sampler2D _WatermarkTex;
            float4 _WatermarkTex_TexelSize;

            float4 _WatermarkPosition;

            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                //计算水印贴图相对于底图的尺寸
                float2 ratio = float2(_WatermarkTex_TexelSize.z / _MainTex_TexelSize.z, _WatermarkTex_TexelSize.w / _MainTex_TexelSize.w);

                if (i.uv.x >= _WatermarkPosition.x && i.uv.x <= _WatermarkPosition.x + ratio.x &&
                    i.uv.y >= _WatermarkPosition.y && i.uv.y <= _WatermarkPosition.y + ratio.y)
                {
                    float2 watermarkUV = (i.uv - _WatermarkPosition.xy) / float2(ratio.x, ratio.y);
                    fixed4 watermarkColor = tex2D(_WatermarkTex, watermarkUV);
                    return watermarkColor;
                }
                else
                {
                    fixed4 mainColor = tex2D(_MainTex, i.uv);
                    return mainColor;
                }
            }
            ENDCG
        }
    }
}

  

进阶:全景图上添加水印

Shader "Custom/MosaicSaveSample"
{
	Properties
	{
		_MainTex("Main Texture", 2D) = "white" {}
		_SecondTex("Second Texture", 2D) = "white" {}
		_LeftBottom("LeftBottom(原点)",vector) = (0,0,0)
		_RightBottom("RightBottom(u方向)",vector) = (0,0,0)
		_LeftTop("LeftTop(v方向)",vector) = (0,0,0)
	}
		SubShader
		{
			Tags { "RenderType" = "Opaque" }
			//翻转曲面
			//Cull front
			LOD 100

			Pass
			{
				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag			

				#include "UnityCG.cginc"

				struct appdata
				{
					float4 vertex : POSITION;
					float2 uv : TEXCOORD0;
				};

				struct v2f
				{
					float2 uv : TEXCOORD0;
					float4 vertex : SV_POSITION;
				};

				sampler2D _MainTex;
				float4 _MainTex_TexelSize;
				sampler2D _SecondTex;
				float4 _SecondTex_TexelSize;

				float3 _LeftTop;
				float3 _LeftBottom;
				float3 _RightBottom;

				//uv对应的世界坐标
				float3 FromUVCoords(float2 uv) {
					float3 dir_u = (_RightBottom - _LeftBottom) * uv.x;
					float3 dir_v = (_LeftTop - _LeftBottom) * uv.y;
					return _LeftBottom + (dir_u + dir_v);
				}

				//世界坐标对应的uv坐标
				inline float2 ToUVCoords(float3 position)
				{
					float3 dir = position - _LeftBottom;
					float u = dot(dir, normalize(_RightBottom - _LeftBottom) / length(_RightBottom - _LeftBottom));
					float v = dot(dir, normalize(_LeftTop - _LeftBottom) / length(_LeftTop - _LeftBottom));
					return float2(u, v);
				}

				//世界坐标映射到全景图上的UV坐标
				inline float2 ToRadialCoords(float3 coords)
				{
					float3 normalizedCoords = normalize(coords);
					float latitude = acos(normalizedCoords.y);
					float longitude = atan2(normalizedCoords.z, normalizedCoords.x);
					float2 sphereCoords = float2(longitude, latitude) * float2(0.5 / UNITY_PI, 1.0 / UNITY_PI);
					return float2(0.5,1.0) - sphereCoords;
				}

				//全景图上的UV坐标映射到三维坐标
				inline float3 FromRadialCoords(float2 uv)
				{
					float2 sphereCoords = float2(0.5, 1.0) - uv;

					float longitude = sphereCoords.x / (0.5 / UNITY_PI);
					float latitude = sphereCoords.y / (1.0 / UNITY_PI);

					float sinLatitude = sin(latitude);

					float3 coords;
					coords.x = sinLatitude * cos(longitude);
					coords.y = cos(latitude);
					coords.z = sinLatitude * sin(longitude);

					return coords;
				}

				//射线是否和AABB包围盒相交,可以求交点
				float3 RayIntersectAABB(float3 rayOrigin, float3 rayDirection, float3 boxMin, float3 boxMax)
				{
					float3 center = (boxMin + boxMax) * 0.5;
					float3 centerDir = normalize(center - rayOrigin);
					if (dot(rayDirection, centerDir) < 0)
					{
						return float3(0, 0, 0);//方向不同说明在背面
					}

					float3 tMin = (boxMin - rayOrigin) / rayDirection;
					float3 tMax = (boxMax - rayOrigin) / rayDirection;

					float3 realMin = min(tMin, tMax);
					float3 realMax = max(tMin, tMax);

					float tNear = max(max(realMin.x, realMin.y), realMin.z);
					float tFar = min(min(realMax.x, realMax.y), realMax.z);

					if (tNear <= tFar)
					{
						return rayOrigin + rayDirection * tNear;//交点
					}
					else
					{
						return float3(0, 0, 0);
					}
				}

				v2f vert(appdata v)
				{
					v2f o;
					o.vertex = UnityObjectToClipPos(v.vertex);
					o.uv = v.uv;
					return o;
				}
				fixed4 frag(v2f i) : SV_Target
				{
					float3 worldPos = FromRadialCoords(i.uv.xy);

					float3 rayOrigin = float3(0,0,0);
					float3 rayDirection = normalize(worldPos - rayOrigin);
					float3 boxMin = min(_LeftTop, min(_LeftBottom, _RightBottom));
					float3 boxMax = max(_LeftTop, max(_LeftBottom, _RightBottom));

					float3 intersectPoint = RayIntersectAABB(rayOrigin, rayDirection, boxMin, boxMax);
					if (intersectPoint.x==0&& intersectPoint.y == 0&& intersectPoint.z == 0)
					{
						return tex2D(_MainTex, i.uv);
					}
					else
					{
						float2 uv = ToUVCoords(intersectPoint);
						return tex2D(_SecondTex, uv);
					}
				}
				ENDCG
			}
		}
}

  

posted on 2024-03-01 11:31  Jason_c  阅读(178)  评论(0编辑  收藏  举报