视差贴图(Parallax Texture)

https://bzyzhang.github.io/2020/11/29/2020-11-29-%EF%BC%88%E4%B8%89%EF%BC%89%E8%A1%A8%E9%9D%A2%E5%87%B9%E5%87%B8%E6%8A%80%E6%9C%AF/
https://www.jianshu.com/p/fea6c9fc610f
[learn OpenGL] https://learnopengl-cn.github.io/05%20Advanced%20Lighting/05%20Parallax%20Mapping/
这里要感谢一下我的同事,这是他的博客 https://bzyzhang.github.io/

视差贴图(Parallax Texture)

简介

视差贴图是表面凹凸技术的一种,原理是通过利用一张高度图去偏移UV伪装成真实高模,一般与法线贴图合用,因为一个项目里有用到,这里就研究了下,但是只是非常浅显的研究。

视差贴图(Parallax Texture)

代码

Shader "Kaima/Bump/SimpleParallax"
{
	Properties
	{
		[NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
		[NoScaleOffset] _NormalMap("Normal Map", 2D) = "bump" {}
		[NoScaleOffset] _DepthMap("Depth Map", 2D) = "white" {}
		_SpecularColor("Specular Color", Color) = (1,1,1,1)
		_Gloss("Gloss", Range(32, 256)) = 64
		_HeightScale("Height Scale", Range(0,1)) = 0.1
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }

		Pass
		{
			Tags {"LightMode"="ForwardBase"}
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"
			#include "Lighting.cginc"

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
				float3 lightDir_tangent : TEXCOORD1;
				float3 viewDir_tangent : TEXCOORD2;
			};

			sampler2D _MainTex;
			sampler2D _NormalMap;
			sampler2D _DepthMap;
			fixed4 _SpecularColor;
			float _Gloss;
			float _HeightScale;

			//最简单的实现,只是根据高度进行偏移
			float2 ParallaxMapping(float2 uv, float3 viewDir_tangent)
			{
				float3 viewDir = normalize(viewDir_tangent);
				float height = tex2D(_DepthMap, uv).r;
				//因为viewDir是在切线空间的(xy与uv对齐),所以只用xy偏移就行了
				float2 p = viewDir.xy / viewDir.z * (height * _HeightScale); 
				return uv - p;
			}
			
			v2f vert (appdata_tan v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = v.texcoord;
				
				TANGENT_SPACE_ROTATION;
				o.lightDir_tangent = normalize(mul(rotation, ObjSpaceLightDir(v.vertex)));
				o.viewDir_tangent = normalize(mul(rotation, ObjSpaceViewDir(v.vertex)));

				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				float3 lightDir = normalize(i.lightDir_tangent);
				float3 viewDir = normalize(i.viewDir_tangent);

				float2 uv = ParallaxMapping(i.uv, viewDir);
				if(uv.x > 1.0 || uv.y > 1.0 || uv.x < 0.0 || uv.y < 0.0) //去掉边上的一些古怪的失真,在平面上工作得挺好的
					discard;

				float3 normal = normalize(UnpackNormal(tex2D(_NormalMap, uv)));
				fixed4 albedo = tex2D(_MainTex, uv);

				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
				fixed3 diffuse = _LightColor0.rgb * albedo.rgb * saturate(dot(normal, i.lightDir_tangent));
				float3 halfDir = normalize(lightDir + viewDir);
				fixed3 specular = _LightColor0.rgb * _SpecularColor.rgb * pow(saturate(dot(halfDir, normal)), _Gloss);

				fixed4 finalColor = fixed4(ambient + diffuse + specular, 1.0);
				return finalColor;
			}
			ENDCG
		}
	}
}
上一篇:k8s label 添加、修改、删除、查询操作


下一篇:数学 · 神经网络(四)· Normalize