Unity Shader总结(十三)——深度和法线纹理、改进的运动模糊和边缘检测及高度雾的生成

Unity描边Shader实战:从法线外扩到屏幕空间优化的完整实现 在计算机图形学中,描边(Outline)是一种基础且重要的视觉增强技术,其核心原理是通过算法识别并突出模型或场景的边缘轮廓。从实现机制上,主要分为基于几何的法线外扩、基于屏幕空间的后处理以及基于几何着色器的轮廓检测三大类。法线外扩法因其实现简单、性能可控,成为游戏开发中最常用的方案,但其在模型非均匀缩放和硬边处易出现描边不均匀的问题。通过将计算从模型空间转换到观察空间或裁剪空间,并引入法线归一化处理,可有效解决这一问题,提升描边效果的视觉一致性。在工程实践中,结合屏幕空间自适应宽度、抗锯齿优化及多Pass渲 阅读详情


深度纹理实际就是一张渲染纹理,它里面存储的像素值是一个高精度的深度值,范围是[0,1],非线性分布;

如何获取

脚本中:
深度:camera.depthTextureMode = DepthTextureMode.Depth
深度+法线:camera.depthTextureMode = DepthTextureMode.DepthNormals

深度和深度+法线:camera.depthTextureMode | = DepthTextureMode.Depth
                               camera.depthTextureMode | = DepthTextureMode.DepthNormals
采样:SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv)——绝大多数情况tex2D也可以,这里防止某些平台特殊处理;

查看

在片元着色器中用代码输出深度和法线值后如果画面全黑或全白,将摄像机的远剪裁平面调小;

运动模糊

运动模糊的另一种方法是速度映射图:利用深度纹理在片元着色器中为每个像素计算其在世界空间下的位置,计算前一帧和当前帧的位置差,生成该像素的速度。

脚本

using UnityEngine;
using System.Collections;

public class MotionBlurWithDepthTexture : PostEffectsBase {

	public Shader motionBlurShader;
	private Material motionBlurMaterial = null;

	public Material material {  
		get {
			motionBlurMaterial = CheckShaderAndCreateMaterial(motionBlurShader, motionBlurMaterial);
			return motionBlurMaterial;
		}  
	}

	private Camera myCamera;
	public Camera camera {
		get {
			if (myCamera == null) {
				myCamera = GetComponent<Camera>();
			}
			return myCamera;
		}
	}

	[Range(0.0f, 1.0f)]
	public float blurSize = 0.5f;
	//保存上一帧的视角*投影矩阵
	private Matrix4x4 previousViewProjectionMatrix;
	
	void OnEnable() {
		camera.depthTextureMode |= DepthTextureMode.Depth;

		previousViewProjectionMatrix = camera.projectionMatrix * camera.worldToCameraMatrix;
	}
	
	void OnRenderImage (RenderTexture src, RenderTexture dest) {
		if (material != null) {
			material.SetFloat("_BlurSize", blurSize);

			material.SetMatrix("_PreviousViewProjectionMatrix", previousViewProjectionMatrix);
			Matrix4x4 currentViewProjectionMatrix = camera.projectionMatrix * camera.worldToCameraMatrix;
			//当前帧的视角*投影
			Matrix4x4 currentViewProjectionInverseMatrix = currentViewProjectionMatrix.inverse;
			material.SetMatrix("_CurrentViewProjectionInverseMatrix", currentViewProjectionInverseMatrix);
			previousViewProjectionMatrix = currentViewProjectionMatrix;

			Graphics.Blit (src, dest, material);
		} else {
			Graphics.Blit(src, dest);
		}
	}
}

shader

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unity Shaders Book/Chapter 13/Motion Blur With Depth Texture" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_BlurSize ("Blur Size", Float) = 1.0
	}
	SubShader {
		CGINCLUDE
		
		#include "UnityCG.cginc"
		
		sampler2D _MainTex;
		half4 _MainTex_TexelSize;
		//unity传递的深度纹理
		sampler2D _CameraDepthTexture;
		//脚本传递的矩阵
		float4x4 _CurrentViewProjectionInverseMatrix;
		float4x4 _PreviousViewProjectionMatrix;
		half _BlurSize;
		
		struct v2f {
			float4 pos : SV_POSITION;
			half2 uv : TEXCOORD0;
			half2 uv_depth : TEXCOORD1;
		};
		
		v2f vert(appdata_img v) {
			v2f o;
			o.pos = UnityObjectToClipPos(v.vertex);
			
			o.uv = v.texcoord;
			o.uv_depth = v.texcoord;
			//平台差异化处理
			#if UNITY_UV_STARTS_AT_TOP
			if (_MainTex_TexelSize.y < 0)
				o.uv_depth.y = 1 - o.uv_depth.y;
			#endif
					 
			return o;
		}
		
		fixed4 frag(v2f i) : SV_Target {
			// 对深度纹理采样得到深度值
			float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth);
			//将深度值重新映射回NDC
			float4 H = float4(i.uv.x * 2 - 1, i.uv.y * 2 - 1, d * 2 - 1, 1);
			// 视角*投影逆矩阵变换
			float4 D = mul(_CurrentViewProjectionInverseMatrix, H);
			// 世界空间下的坐标表示
			float4 worldPos = D / D.w;
			
			// Current viewport position 
			float4 currentPos = H;
			//计算前一帧在NDC下坐标
			float4 previousPos = mul(_PreviousViewProjectionMatrix, worldPos);
			previousPos /= previousPos.w;
			
			// 计算位置差得到速度
			float2 velocity = (currentPos.xy - previousPos.xy)/2.0f;
			//利用速度值对领域像素采样,相加后取平均,利用_BlurSize控制采样距离
			float2 uv = i.uv;
			float4 c = tex2D(_MainTex, uv);
			uv += velocity * _BlurSize;
			for (int it = 1; it < 3; it++, uv += velocity * _BlurSize) {
				float4 currentColor = tex2D(_MainTex, uv);
				c += currentColor;
			}
			c /= 3;
			
			return fixed4(c.rgb, 1.0);
		}
		
		ENDCG
		
		Pass {      
			ZTest Always Cull Off ZWrite Off
			    	
			CGPROGRAM  
			
			#pragma vertex vert  
			#pragma fragment frag  
			  
			ENDCG  
		}
	} 
	FallBack Off
}

基于屏幕后处理的全局雾效

高度雾
脚本:

using UnityEngine;
using System.Collections;

public class FogWithDepthTexture : PostEffectsBase {

	public Shader fogShader;
	private Material fogMaterial = null;

	public Material material {  
		get {
			fogMaterial = CheckShaderAndCreateMaterial(fogShader, fogMaterial);
			return fogMaterial;
		}  
	}

	private Camera myCamera;
	public Camera camera {
		get {
			if (myCamera == null) {
				myCamera = GetComponent<Camera>();
			}
			return myCamera;
		}
	}

	private Transform myCameraTransform;
	public Transform cameraTransform {
		get {
			if (myCameraTransform == null) {
				myCameraTransform = camera.transform;
			}

			return myCameraTransform;
		}
	}

	//控制雾的浓度
	[Range(0.0f, 3.0f)]
	public float fogDensity = 1.0f;
	//控制雾的颜色
	public Color fogColor = Color.white;
	//雾的起始高度和终止高度
	public float fogStart = 0.0f;
	public float fogEnd = 2.0f;

	void OnEnable() {
		camera.depthTextureMode |= DepthTextureMode.Depth;
	}
	
	void OnRenderImage (RenderTexture src, RenderTexture dest) {
		if (material != null) {
			
			Matrix4x4 frustumCorners = Matrix4x4.identity;

			float fov = camera.fieldOfView;
			float near = camera.nearClipPlane;
			float aspect = camera.aspect;

			float halfHeight = near * Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad);
			Vector3 toRight = cameraTransform.right * halfHeight * aspect;
			Vector3 toTop = cameraTransform.up * halfHeight;

			Vector3 topLeft = cameraTransform.forward * near + toTop - toRight;
			float scale = topLeft.magnitude / near;

			topLeft.Normalize();
			topLeft *= scale;

			Vector3 topRight = cameraTransform.forward * near + toRight + toTop;
			topRight.Normalize();
			topRight *= scale;

			Vector3 bottomLeft = cameraTransform.forward * near - toTop - toRight;
			bottomLeft.Normalize();
			bottomLeft *= scale;

			Vector3 bottomRight = cameraTransform.forward * near + toRight - toTop;
			bottomRight.Normalize();
			bottomRight *= scale;

			frustumCorners.SetRow(0, bottomLeft);
			frustumCorners.SetRow(1, bottomRight);
			frustumCorners.SetRow(2, topRight);
			frustumCorners.SetRow(3, topLeft);

			material.SetMatrix("_FrustumCornersRay", frustumCorners);

			material.SetFloat("_FogDensity", fogDensity);
			material.SetColor("_FogColor", fogColor);
			material.SetFloat("_FogStart", fogStart);
			material.SetFloat("_FogEnd", fogEnd);

			Graphics.Blit (src, dest, material);
		} else {
			Graphics.Blit(src, dest);
		}
	}
}

shader

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unity Shaders Book/Chapter 13/Fog With Depth Texture" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_FogDensity ("Fog Density", Float) = 1.0
		_FogColor ("Fog Color", Color) = (1, 1, 1, 1)
		_FogStart ("Fog Start", Float) = 0.0
		_FogEnd ("Fog End", Float) = 1.0
	}
	SubShader {
		CGINCLUDE
		
		#include "UnityCG.cginc"
		
		float4x4 _FrustumCornersRay;
		
		sampler2D _MainTex;
		half4 _MainTex_TexelSize;
		sampler2D _CameraDepthTexture;
		half _FogDensity;
		fixed4 _FogColor;
		float _FogStart;
		float _FogEnd;
		
		struct v2f {
			float4 pos : SV_POSITION;
			half2 uv : TEXCOORD0;
			half2 uv_depth : TEXCOORD1;
			float4 interpolatedRay : TEXCOORD2;//存储插值后的像素向量
		};
		
		v2f vert(appdata_img v) {
			v2f o;
			o.pos = UnityObjectToClipPos(v.vertex);
			
			o.uv = v.texcoord;
			o.uv_depth = v.texcoord;
			
			#if UNITY_UV_STARTS_AT_TOP
			if (_MainTex_TexelSize.y < 0)
				o.uv_depth.y = 1 - o.uv_depth.y;
			#endif
			
			int index = 0;
			if (v.texcoord.x < 0.5 && v.texcoord.y < 0.5) {
				index = 0;
			} else if (v.texcoord.x > 0.5 && v.texcoord.y < 0.5) {
				index = 1;
			} else if (v.texcoord.x > 0.5 && v.texcoord.y > 0.5) {
				index = 2;
			} else {
				index = 3;
			}

			#if UNITY_UV_STARTS_AT_TOP
			if (_MainTex_TexelSize.y < 0)
				index = 3 - index;
			#endif
			
			o.interpolatedRay = _FrustumCornersRay[index];
				 	 
			return o;
		}
		
		fixed4 frag(v2f i) : SV_Target {
			float linearDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth));
			//得到该像素的世界坐标
			//linearDepth* interpolatedRay是像素相对于摄像机的偏移量,linearDepth是由深度纹理得到的线性深度值,interpolatedRay是vert输出并插值后得到的射线;
			float3 worldPos = _WorldSpaceCameraPos + linearDepth * i.interpolatedRay.xyz;
						
			float fogDensity = (_FogEnd - worldPos.y) / (_FogEnd - _FogStart); 
			fogDensity = saturate(fogDensity * _FogDensity);
			
			fixed4 finalColor = tex2D(_MainTex, i.uv);
			finalColor.rgb = lerp(finalColor.rgb, _FogColor.rgb, fogDensity);
			
			return finalColor;
		}
		
		ENDCG
		
		Pass {
			ZTest Always Cull Off ZWrite Off
			     	
			CGPROGRAM  
			
			#pragma vertex vert  
			#pragma fragment frag  
			  
			ENDCG  
		}
	} 
	FallBack Off
}

边缘检测

在深度和法线纹理上进行边缘检测,这样图像不会受到光照和纹理的影响,实现的效果更可靠;

在这里插入图片描述
robert算子本质是计算左上角和右下角的差值,因此下面的计算会取对角方向的深度或法线值,比较它们之间的差值,如果超过某个阈值,就认为它们之间存在一条边;

脚本:

using UnityEngine;
using System.Collections;

public class EdgeDetectNormalsAndDepth : PostEffectsBase {

	public Shader edgeDetectShader;
	private Material edgeDetectMaterial = null;
	public Material material {  
		get {
			edgeDetectMaterial = CheckShaderAndCreateMaterial(edgeDetectShader, edgeDetectMaterial);
			return edgeDetectMaterial;
		}  
	}

	[Range(0.0f, 1.0f)]
	public float edgesOnly = 0.0f;

	public Color edgeColor = Color.black;

	public Color backgroundColor = Color.white;
	//控制对深度+法线纹理采样时,使用的采样距离,值越大,描边越宽
	public float sampleDistance = 1.0f;
	//领域的深度或法线值相差多少时认为存在一条边,值越大,那么变化很小的地方也会形成一条边;
	public float sensitivityDepth = 1.0f;

	public float sensitivityNormals = 1.0f;
	
	void OnEnable() {
		GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals;
	}

	[ImageEffectOpaque]//不希望对透明物体产生影响
	void OnRenderImage (RenderTexture src, RenderTexture dest) {
		if (material != null) {
			material.SetFloat("_EdgeOnly", edgesOnly);
			material.SetColor("_EdgeColor", edgeColor);
			material.SetColor("_BackgroundColor", backgroundColor);
			material.SetFloat("_SampleDistance", sampleDistance);
			material.SetVector("_Sensitivity", new Vector4(sensitivityNormals, sensitivityDepth, 0.0f, 0.0f));

			Graphics.Blit(src, dest, material);
		} else {
			Graphics.Blit(src, dest);
		}
	}
}

shader

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unity Shaders Book/Chapter 13/Edge Detection Normals And Depth" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_EdgeOnly ("Edge Only", Float) = 1.0
		_EdgeColor ("Edge Color", Color) = (0, 0, 0, 1)
		_BackgroundColor ("Background Color", Color) = (1, 1, 1, 1)
		_SampleDistance ("Sample Distance", Float) = 1.0
		_Sensitivity ("Sensitivity", Vector) = (1, 1, 1, 1) //xy分别对应法线和深度检测的灵敏度,zw没有用途;
	}
	SubShader {
		CGINCLUDE
		
		#include "UnityCG.cginc"
		
		sampler2D _MainTex;
		half4 _MainTex_TexelSize;//因为需要对领域像素采样,声明_MainTex_TexelSize
		fixed _EdgeOnly;
		fixed4 _EdgeColor;
		fixed4 _BackgroundColor;
		float _SampleDistance;
		half4 _Sensitivity;
		
		sampler2D _CameraDepthNormalsTexture;
		
		struct v2f {
			float4 pos : SV_POSITION;
			half2 uv[5]: TEXCOORD0;
		};
		  
		v2f vert(appdata_img v) {
			v2f o;
			o.pos = UnityObjectToClipPos(v.vertex);
			//数组的第一个坐标存储屏幕颜色图像的采样纹理
			half2 uv = v.texcoord;
			o.uv[0] = uv;
			
			#if UNITY_UV_STARTS_AT_TOP
			if (_MainTex_TexelSize.y < 0)
				uv.y = 1 - uv.y;
			#endif
			
			o.uv[1] = uv + _MainTex_TexelSize.xy * half2(1,1) * _SampleDistance;
			o.uv[2] = uv + _MainTex_TexelSize.xy * half2(-1,-1) * _SampleDistance;
			o.uv[3] = uv + _MainTex_TexelSize.xy * half2(-1,1) * _SampleDistance;
			o.uv[4] = uv + _MainTex_TexelSize.xy * half2(1,-1) * _SampleDistance;
					 
			return o;
		}
		
		half CheckSame(half4 center, half4 sample) {
			half2 centerNormal = center.xy;
			float centerDepth = DecodeFloatRG(center.zw);
			half2 sampleNormal = sample.xy;
			float sampleDepth = DecodeFloatRG(sample.zw);
			
			// difference in normals
			// do not bother decoding normals - there's no need here
			half2 diffNormal = abs(centerNormal - sampleNormal) * _Sensitivity.x;
			int isSameNormal = (diffNormal.x + diffNormal.y) < 0.1;
			// difference in depth
			float diffDepth = abs(centerDepth - sampleDepth) * _Sensitivity.y;
			// scale the required threshold by the distance
			int isSameDepth = diffDepth < 0.1 * centerDepth;
			
			// return:
			// 1 - if normals and depth are similar enough
			// 0 - otherwise
			return isSameNormal * isSameDepth ? 1.0 : 0.0;
		}
		
		fixed4 fragRobertsCrossDepthAndNormal(v2f i) : SV_Target {
			//对深度+法线纹理采样
			half4 sample1 = tex2D(_CameraDepthNormalsTexture, i.uv[1]);
			half4 sample2 = tex2D(_CameraDepthNormalsTexture, i.uv[2]);
			half4 sample3 = tex2D(_CameraDepthNormalsTexture, i.uv[3]);
			half4 sample4 = tex2D(_CameraDepthNormalsTexture, i.uv[4]);
			
			half edge = 1.0;
			//计算对角线差值,CheckSame返回值是0或1,0就认为该两点之间存在一条边界,如果结果小于阈值,就返回1,说明差异不明显
			edge *= CheckSame(sample1, sample2);
			edge *= CheckSame(sample3, sample4);
			
			fixed4 withEdgeColor = lerp(_EdgeColor, tex2D(_MainTex, i.uv[0]), edge);
			fixed4 onlyEdgeColor = lerp(_EdgeColor, _BackgroundColor, edge);
			
			return lerp(withEdgeColor, onlyEdgeColor, _EdgeOnly);
		}
		
		ENDCG
		
		Pass { 
			ZTest Always Cull Off ZWrite Off
			
			CGPROGRAM      
			
			#pragma vertex vert  
			#pragma fragment fragRobertsCrossDepthAndNormal
			
			ENDCG  
		}
	} 
	FallBack Off
}

如果希望特定的物体描边,使用Graphics.DrawMesh或Graphics.DrawMeshNow把需要描边的物体再次渲染一遍,再使用边缘检测计算深度或法线纹理中每个像素的梯度值,如果小于某个阈值,就在shader中使用clip()将该像素剔除,从而显示出原来的物体颜色;

Unity Shader图片区域遮罩:从原理到实战的完整实现指南 在计算机图形学与游戏开发中,纹理采样与像素操作是构建丰富视觉表现的核心基础。其核心原理是通过对纹理数据进行采样与数学运算,控制每个像素的最终输出,从而实现复杂的视觉效果。这一技术的核心价值在于将内容与表现形式解耦,极大地提升了资源复用率和开发灵活性。在工程实践中,它被广泛应用于UI动态效果、场景特效融合、角色自定义等关键场景。本文聚焦于图片区域遮罩这一具体实现,深入剖析了如何通过顶点/片元着色器进行纹理混合,并详细讲解了遮罩纹理的制备、Shader参数化设计以及性能优化策略,为开发者提供了一套从概念到生产的 阅读详情

相关推荐

Unity Shader核心:顶点与片元着色器原理与实战解析

在计算机图形学中,着色器是GPU渲染管线的核心编程单元,它定义了3D模型如何转换为屏幕上的2D像素。其工作原理遵循着从顶点处理到像素着色的固定流程:顶点着色器首先处理模型的每个顶点,执行坐标变换等任务;随后光栅化生成片元,片元着色器则负责计算每个片元的最终颜色。这项技术的核心价值在于将渲染流程从固定功能管线转变为可编程管线,极大地提升了图形渲染的灵活性与表现力,是实现复杂视觉效果(如动态光照、高级材质和后期处理)的基础。在游戏开发、实时渲染和交互式应用等场景中,理解并掌握顶点着色器与片元着色器的分工与协作,

weixin_33800463的博客 444

Unity Shader 图片模糊效果实现

Unity Shader 图片模糊效果实现 shader源码如下 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/GaussianBlur" { Properties { _MainTex("Texture", 2D)...

weixin_30681615的博客 1095

Unity URP深度图重建世界坐标:全屏后处理核心技术与避坑指南

在实时渲染与游戏开发中,屏幕空间后处理技术是实现高级视觉效果的关键环节,其核心原理在于将二维屏幕像素映射回三维世界空间。这一过程依赖于深度图(Depth Texture)与逆投影变换,通过采样每个像素的深度值,结合摄像机矩阵,精确重建其在游戏世界中的三维坐标。该技术为屏幕空间环境光遮蔽(SSAO)、体积雾、边缘光等效果提供了基础数据支持,极大地增强了场景的真实感与沉浸感。在Unity URP管线中,正确实现这一流程需处理动态分辨率、图形API差异及深度纹理采样等工程细节。本文聚焦于深度图与ComputeWo

weixin_30633405的博客 346

【游戏开发实战】Unity ShaderGraph实现图片的高斯模糊效果

文章目录一、前言二、最终效果三、高斯模糊的原理四、ShaderGraph的高斯模糊实现 一、前言 之前我写了一篇文章:ShaderGraph使用教程与各种特效案例:Unity2020 有网友私信问我下面这个问题: 使用ShaderGraph如何实现高斯模糊的效果呢?今天我就来写下实现过程。 二、最终效果 Demo工程已上传到GitHub,地址:https://github.com/linxinfa/UnityShaderGraphGaussBlurDemo 三、高斯模糊的原理 对图片进行模糊处理,简单

linxinfa的专栏 1万+

Unity URP水体焦散效果实现:从原理到实战的完整指南

焦散是光线通过非均匀介质(如波动水面)折射后,在接收面上形成明暗相间光斑的光学现象。其物理原理基于斯涅尔定律,描述了光线在界面处的偏折与汇聚。在实时计算机图形学中,精确模拟这一现象对提升水体、玻璃等材质的视觉真实感至关重要。技术实现上,开发者常借助屏幕空间着色技术,通过采样深度与法线纹理,重建世界空间位置,并模拟光线追踪来高效近似焦散效果。这为游戏与交互应用提供了动态、逼真的光照交互方案。本文聚焦Unity通用渲染管线,深入剖析水体焦散的核心实现方案,涵盖从基础的预烘焙纹理投影,到基于屏幕空间深度与法线信息

weixin_30388677的博客 377

Unity低多边形Shader实战:硬边着色、阴影优化与透明排序全解析

在计算机图形学中,着色器(Shader)是控制3D模型外观与光照的核心程序。其工作原理是通过顶点和片段着色阶段,对模型的几何、纹理、法线等属性进行计算,最终输出屏幕像素颜色。对于追求特定艺术风格的游戏开发,自定义Shader技术价值巨大,它能突破引擎默认渲染的局限,实现独特的视觉表达。低多边形(Low-poly)风格便是典型应用场景,它要求用硬边着色(Flat Shading)替代平滑渐变,这直接与Unity等引擎基于顶点法线插值的默认光照模型相冲突。本文聚焦于解决由此引发的模型边缘平滑、阴影模糊及透明排序

迷彩风情 362

【Unity3D】运动模糊特效

开启混合(Blend)后,通过Alpha通道控制当前屏幕纹理与历史屏幕纹理进行混合,当有物体运动时,就会将当前位置的物体影像与历史位置的物体影像进行混合,从而实现运动模糊效果。第一个 Pass通过Alpha通道控制当前屏幕纹理与历史屏幕纹理进行混合,通过 ColorMask RGB保证融合不影响Alpha通道值;第二个Pass对当前屏幕的Alpha通道进行采样,通过 ColorMask A保证采样不影响RGB通道的值。

little_fat_sheep 2707

unity仿射变换图形矫正demo

unity仿射变换图形矫正demo,用于我的博客讲解提供示例

Unity ShaderGraph教程——进阶shader(水面、积雪,数字线框)

注意:需要用到scence color节点需要在UniversalRP-xxxQuality inspector面板将不透明texture的对勾打开。将屏幕上颜色和水面颜色混合,使场景中已经被渲染的不透明物体屏幕坐标产生一定的扭曲,跟当前颜色合成后模拟折射效果。公式:场景深度 节点深度 — 屏幕空间位置的W向量 = 半透明物体与不透明物体的相交边缘。原理:场景深度 节点深度包含透明像素,屏幕空间w向量不包含透明像素。实现效果:水面光滑程度、水下物体以及阴影扭曲效果。

羽阿呆的博客 2215

什么是以太网链路聚合

以太网链路聚合技术通过将多个物理端口捆绑成逻辑端口,可显著提升网络性能。该技术能增加总带宽(各链路带宽之和)、提高可靠性(故障秒级切换)并实现智能负载分担。主要分为手工模式和基于LACP协议的动态模式,后者能检测链路故障更可靠。配置时需确保接口参数一致、模式匹配,适用于核心交换、服务器接入等场景。华为设备通过创建Eth-Trunk接口、指定LACP模式并添加成员接口即可完成部署。这项成熟技术能以低成本解决带宽瓶颈和可靠性问题,是构建高速稳定网络的关键方案。

lai_2020的博客 675

固定时间收敛的控制器设计(基础知识)

针对控制系统的有限时间收敛和固定时间收敛给出一些常用定理。

qq_40241332的博客 1万+

Unity Shader实现运动模糊(一) : 摄像机运动产生模糊

运动模糊是个经常会用到的效果,常见的实现步骤是: 对深度纹理进行采样,取得当前片元的深度信息 根据深度信息建立当前片元的NDC空间的坐标curNDCPos 把curNDCPos乘以当前VP矩阵的逆矩阵(即View*Projection)-1,得到当前片元的世界空间坐标WorldPos 把WorldPos乘以上一帧的VP矩阵(即View*Projection),得到上一帧在裁切空间中的位置 la...

博客标题 3406

RISC-V内核移植实战:从零开始手把手实现RT-Thread上下文切换(附GD32VF103代码解析)

本文详细解析了在RISC-V架构上移植RT-Thread实时操作系统的核心步骤,重点聚焦于上下文切换机制的实现。通过对比ARM Cortex-M与RISC-V在中断处理和寄存器管理上的关键差异,并以GD32VF103开发板为例,手把手指导开发者完成libcpu抽象层适配、线程栈初始化以及三种上下文切换方式的代码编写与调试,为嵌入式开发者从ARM转向RISC-V平台提供了实战指南。

fern8的博客 740

shader结果总结

屏幕后处理效果是当前场景的主要渲染或者所有的不透明的pass渲染完成后调用后处理脚本对之前的渲染完成的基础之上再调用shader和material做整体的调整。

llllllllllgyt的博客 819

系统-等保三级-CentOS Linux 7合规基线检查 shell脚本

系统-等保三级-CentOS Linux 7合规基线检查 shell脚本

swindy博客 2409

【AI智能体】基于Coze 制作高质量PPT实战操作详解

基于Coze 制作高质量PPT实战操作详解

congge 6102

Unity深度特效开发全流程:从深度纹理获取到Shader优化实战

深度缓冲是计算机图形学中记录像素到相机距离的核心数据结构,它通过存储每个像素的深度值来实现遮挡检测和三维空间感知。其工作原理是在渲染管线中,将物体顶点变换到裁剪空间后,通过深度测试决定像素的可见性。深度信息的技术价值在于为屏幕空间特效提供了关键的几何数据,是实现景深、体积雾、边缘光等高级视觉效果的基础。在游戏开发与实时渲染的应用场景中,深度纹理的获取、解码与空间重建是高频技术难点。本文聚焦Unity引擎,针对深度纹理的精度处理、世界空间位置重建以及特效Shader编写中的常见问题,提供系统性的解决方案与性能

weixin_34341117的博客 358

基于YOLOv13+CBAM注意力机制

本教程详细介绍了CBAM注意力机制的原理及其在YOLOv13中的集成方法。CBAM通过通道注意力和空间注意力两个模块,动态调整特征权重以增强模型性能。通道模块利用池化操作和共享MLP生成通道权重,空间模块则通过池化和卷积生成空间权重。教程提供了在YOLOv13中实现CBAM的具体步骤,包括模块代码定义、模型配置修改等关键环节,帮助开发者在目标检测任务中提升模型表现。

FJN110的博客 305

URP管线Shader开发全解析:从基础结构到高级效果实现

在实时渲染领域,着色器(Shader)是决定图形表现的核心技术组件,它定义了物体表面如何与光线交互,从而生成最终的像素颜色。其工作原理基于图形渲染管线,通过顶点着色器和片段着色器对几何数据进行变换与计算。在Unity引擎的通用渲染管线(URP)架构下,Shader的编写范式发生了显著转变,需要遵循模块化、声明式的数据流规则,并与管线配置深度集成,这为开发者带来了更高的定制化能力与性能优化空间。这种技术价值体现在能够高效实现诸如体积雾、UI模糊等复杂的屏幕空间后处理效果,以及风格化的地表渲染,广泛应用于游戏开

weixin_33804582的博客 342

⭐️VMwareWorkstation17.0虚拟机安装搭建Windows 7虚拟机(完整图文详细步骤含配置VMware Tools教程)

本教程为大家提供了从安装VMware Workstation 17.0开始,到在虚拟机上成功搭建Windows 7专业版系统的完整步骤。我们详细介绍了准备阶段所需的软件和硬件要求,以及在VMware中配置和安装Windows 7系统的每一步操作。此外,我们还特别提到了如何在虚拟机上配置VMware Tools,以便更好地与宿主机进行交互。 通过本教程的学习,读者不仅能够掌握在VMware Workstation 17.0上安装Windows 7虚拟机的技能,还能了解到如何配置虚拟机的硬件以及安装VMwar

Python老吕的博客 2万+

银河麒麟V10等保加固清单:安全基线配置一篇搞定(附逐项检查表)

通过限制使用SSH直接以root身份登录,禁用公钥登录的方式加强SSH服务的安全性。更改SSH默认端口可在一定程度上防止被黑客使用大批量扫描方式攻击。通过修改SSH的配置文件限制可以使用SSH服务远程管理的主机。

信创运维工程师 · 银河麒麟 & 容器实战 | 金融生产环境迁移·等保加固 | 142篇原创·17万+阅读 818

URP深度法线描边实战:从原理到优化的完整实现指南

屏幕空间后处理是实时渲染中提升视觉表现的关键技术,其核心原理在于对渲染完成后的图像缓冲区(如深度、法线纹理)进行像素级计算,从而提取或增强特定视觉特征。深度图记录了像素到摄像机的距离信息,法线图则存储了物体表面的朝向向量。通过分析相邻像素间深度值的突变或法线向量的夹角变化,可以智能地识别出场景中的物体边界与几何轮廓。这项技术的核心价值在于,它不依赖于特定模型结构,能对场景中所有被渲染物体生效,实现稳定、高质量且风格统一的轮廓勾勒,极大地提升了视觉层次感和物体辨识度。在游戏开发、交互应用及风格化渲染中,基于深

weixin_33913332的博客 410

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Unity学习shader笔记[一百]简单焦散Caustic效果

这种min操作使得两个黑块互相靠近的过程中,同个片源位置的颜色变深能够非常自然,因为这个片源对于单个黑块来说,是某个运动方向的,是渐变的,对于两个黑块来说的话,min操作使得该点只能取两个黑块中颜色较深的部分,当颜色较深的选择在某一帧由一个黑块切换到另一个黑块时,颜色的过渡肯定不会过大,因为上一帧该点选择了块A,说明上一帧块A比较深,下一帧的时候块B较深,黑块的颜色深浅不会突变,当下一帧又从B选择A的时候,也不会说选择A之后突然加深。对于两张图的黑色重叠的部分 因为黑色块部分是由边缘向中间的渐黑,

weixin_43149049的博客 3247

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Unity URP自定义后期处理实战:从颜色滤镜到边缘检测

在实时渲染管线中,后期处理(Post-Processing)是提升最终画面表现力的关键技术,它通过对渲染完成的图像进行像素级处理,实现诸如色彩校正、景深、泛光等视觉效果。其核心原理是在渲染管线的特定阶段插入自定义的渲染通道(Render Pass),利用着色器(Shader)对屏幕图像进行采样与计算。这项技术的价值在于能够突破引擎内置效果的局限,实现高度定制化的艺术风格与动态视觉反馈,广泛应用于风格化渲染、环境氛围营造、角色状态提示等场景。Unity的通用渲染管线(URP)为此提供了清晰、高性能的自定义框架

weixin_34111790的博客 328

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Shader入门精要-4-高级篇

高级篇学习记录

suixinger_lmh的随笔 3023

ShaderGraph纹理转法线节点:原理、应用与性能优化全解析

法线贴图是实时渲染中用于模拟表面凹凸细节的核心技术,它通过存储每个像素点的法线方向向量,在不增加模型几何复杂度的前提下,显著增强视觉立体感。其基本原理是将RGB颜色通道映射到切线空间的法线分量,通过光照计算产生明暗变化,从而欺骗人眼感知深度。这项技术的核心价值在于以极低的性能开销换取丰富的表面细节,广泛应用于游戏角色、场景材质以及各类动态表面效果中。在Unity ShaderGraph中,**纹理转法线节点**(Normal From Texture Node)基于**索贝尔算子**(Sobel Opera

weixin_33801856的博客 403
上一篇: Unity Shader总结(十二)——屏幕后处理
下一篇: Unity Shader总结(十四)——卡通和素描风格的渲染
Lingo_work
博客等级 码龄8年 12粉丝 66原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值