shader之DetailTextureInScreenSpace

Shader学习笔记之DetailTextureInScreenSpace

注:代码来自于官方,下面是我的理解。不对之处请指正。

Shader "Custom/OfficialEaxm6_DetailTextureInScreen" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_Detail("Detail (RGB)",2D) = "gray"{}
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		#pragma surface surf Lambert

		sampler2D _MainTex;
		sampler2D _Detail;

		struct Input {
			float2 uv_MainTex;
			float4 screenPos;
		};

		void surf (Input IN, inout SurfaceOutput o) {
			half4 c = tex2D (_MainTex, IN.uv_MainTex);
			o.Albedo = c.rgb;
//			o.Alpha = c.a;
			float2 screenUV = IN.screenPos.xy/IN.screenPos.w;
			screenUV *= float2(8,6);
			o.Albedo *= tex2D(_Detail,screenUV).rgb *2;
		}
		ENDCG
	} 
	FallBack "Diffuse"
}
首先对shader语法做一些解释。

shader命令后跟一个字符串作为shader的名字出现在inspector视图的层级列表中。

shader 由几个属性构成:properties,subshader,fallback;

properties模块中的属性将会出现在 material inspector中,供美工使用。

一个shader包含若干subshader,计算机将会选择第一个硬件支持的subshader执行。

fallback 当所有subshader都不被硬件所支持的时候执行。也就是说fallback 后面的shader必须支持最低端的硬件设备才能保证在所有机器上执行。


本例中使用的是Surface Shader,在unity3d中在Shaderlab中嵌入Cg/hlsl来变现surface Shader 程序 和 vertex & fragment shader。

使用CGPROGRAM 和ENDCG作为cg/hlsl程序的开始和结束。

#pragma surface surf Lambert, 表示使用surface shader, 要调用的函数为 surf,Lambert表示光照模型(diffuse)。

sampler2D _MainTex;  这里对应properties属性中的_MainTex, 在properties中的属性是显示在可视化界面中的并不直接与cg程序关联,这里声明之后将会与之前的关联起来。(名字必须一样!)


先来看核心函数:

<span style="font-size:18px;">void surf (Input IN, inout SurfaceOutput o) {}</span>

注意到这里有两个参数,Input 也就是上面我们定义的Input结构体,SurfaceOutput 这个结构体事由系统自定义的一个结构。我们通过输入的Input计算之后,填充surfaceOutput结构,硬件使用这个结构中的内容进行渲染。

再来看Input结构:我们把在surf函数中要用到的变量在这里声明。比如,我们这里的uv_MainTex 。需要说明的是,在变量名之前加上uv系统会默认使用他的uv坐标进行采样。准确的说将其uv是保存在一个float2中,在surf函数中使用。 

float2 - 4 这样子的类型是一个float 类型的2-4维向量。

一个着色器最重要的是其渲染方法,这里做的事使用一个2维浮点向量取屏幕坐标,再在x轴,y轴分贝乘 8 和 6。 最后使用这个uv坐标来对用户输入的Detail贴图取样。

最后看到的效果就会这样:


下面将代码具体分析:

<span style="font-size:18px;">float2 screenUV = IN.screenPos.xy/IN.screenPos.w;
			screenUV *= float2(8,6);
			o.Albedo *= tex2D(_Detail,screenUV).rgb *2;</span>

screenPos 是一个四元数即(x,y,z,w)其三维向量为(x/w,y/w,z/w),我们知道屏幕坐标没有z轴。所以标准化向量为(x/w,y/w)。将其x,y乘以8,6之后这个uv将会为分别在x,y轴扩大8,6倍。使用tex2D函数采样,第一个参数为采样贴图,第二个为uv坐标。

试试:我们把8,6改为1,1之后将shader赋给一个材质再将材质赋给一个plane或者quad 将其放缩到screen视口大小,出现了整个视口出现一张贴图,贴图不随对象放缩而改变。

由此猜测 :贴图normalize 之后与一个单位uv 所对应。理解为:x(0~1),y(0~1)当乘以倍数之后 x(0,m),y(0,n)。这样就明白了。

注:这事我的理解不对之处请大虾指正。


                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值