Shader基础

Shader "Custom/TestShader" {
	Properties {
		_MainTex("主贴图",2D) = "white" {}
		_Eliminate("剔除",range(0,1)) = 0
		_Strength("亮度",range(0,30)) = 1
		_Color("color",color) = (1,1,1,1)
	}
	SubShader {
		Tags { "RenderType"="Opaque" }

        // Blend SrcAlpha OneMinusSrcAlpha // 这个是透明混合 
        // 透明混合说明 http://blog.sina.com.cn/s/blog_471132920101d8z5.html 

		LOD 200
		pass{
		CGPROGRAM
		#include "unityCG.cginc"
		#pragma vertex vert
		#pragma fragment frag

		sampler2D _MainTex;
		float _Eliminate;
		fixed4 _Color;
		float _Strength;

		struct v2f {
			float2 uv : TEXCOORD;
			float4 vertex : POSITION;
		};

		fixed luminance(fixed4 color) // 计算片元亮度
		{
			return  0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b; 
		}

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

		half4 frag(v2f v) : SV_Target
		{
			fixed4 color = tex2D(_MainTex,v.uv) * _Strength;
			clip(color - _Eliminate);
			clip(color.a + color.g + color.b -0.9);
			return lerp(color,_Color,_Eliminate);
		}

		ENDCG
		}
	}
	FallBack "diffuse"
}

 

Shader "Custom/TestShader" {
	Properties {
		_MainTex("主贴图",2D) = "white" {}
		_Eliminate("剔除",range(0,1)) = 0
		_Strength("亮度",range(0,30)) = 1
		_Color("color",color) = (1,1,1,1)
	}

...

        sampler2D _MainTex;
		float _Eliminate;
		fixed4 _Color;
		float _Strength;

shader "" 也就是第一行,代表的是这个shader的位置(文件夹/shader名)

第二行之后的大括号代表的则是这个shader里面的一些声明,但是这些只是声明,类似于c++里面的include.c,对,是.c而不是.cpp,实现还需要再次在下面重新声明,真正用到的是下面的声明,而上面的则是显示到面板上的一些参数,如果下面没有同样的参数重载,则本参数无效

SubShader {
        // Tags 的一些说明 https://blog.csdn.net/treepulse/article/details/53484505
		Tags { "RenderType"="Opaque" } // 标签,如同程序里面的Attribute属性一样,指定这个shader可以拥有什么属性
		LOD 200
		pass{ // 一个渲染代码块 一个shader可以拥有很多个pass 其实看来有些类似于代码中的多态,
//但是在一些情况下我可以将一个参数(贴图) 通过一个子类进行参数的变化 在传入另一个子类的多态中 就是通常所说的多pass渲染
		CGPROGRAM // Unity的Cg程序预编译命令
		#include "unityCG.cginc" // 头文件 路径为 C:\Program Files\Unity\Editor\Data\CGIncludes
		#pragma vertex vert // 指定为 顶点 片元渲染
		#pragma fragment frag
ENDCG
struct v2f { 
	float2 uv : TEXCOORD;  // 第一个贴图 获取其他的贴图可以 用TEXCOORDX //x为数值
    // 这个的解释在 https://blog.csdn.net/zhao_92221/article/details/46797969
	float4 vertex : POSITION; // 代表每个像素点在屏幕上的位置 
};
/*
struct appdata_img //结构体原型
{
    float4 vertex : POSITION;
    half2 texcoord : TEXCOORD0;
    UNITY_VERTEX_INPUT_INSTANCE_ID
};
*/


v2f vert(appdata_img v) // 函数体 顶点着色器 逐顶点进行操作
{
	v2f o; // 初始化结构体 
	o.uv = v.texcoord; // 给我们初始化的结构体赋值
	o.vertex = UnityObjectToClipPos(v.vertex); // 将顶点变换到裁剪空间 也就是相机可以看到的区域
    // 等同于 mul(UNITY_MATRIX_MVP,v.vertex); mul 矩阵相乘
	return o;
}

half4 frag(v2f v) : SV_Target  // 片元着色器 逐像素进行操作 那个SV_Target暂时没有找到相关定义 但是我尝试省略的时候 会爆出一个 返回值错误 
{
	fixed4 color = tex2D(_MainTex,v.uv) * _Strength; // tex2D(sampler2D,float2) 获取uv坐标对应的颜色数值,后面的相乘则是加强亮度
	clip(color - _Eliminate); // clip(float - float) // 如果最终数值小于0 则将这个像素点舍弃 
	clip(color.a + color.g + color.b -0.9); // 黑色代表的是0,0,0 这个是舍弃黑色 也可以使用discard; 同样都是舍弃本像素,但是discard需要自己手动判断
	return lerp(color,_Color,_Eliminate); // 插值
}

也就是说,一个标准的顶点片元着色器的书写格式为

Shader "FolderName/ShaderName"
{
	Properties
	{	
		显示在面板上的变量,注意,变量必须要有初始值
		如 :
		变量名("显示在面板上变量的名字",变量的类型) = 初始值
		_Color("color",color) = (1,1,1,1)
	}
	
	SubShader 
	{
		Tags { Attribute (一些需要的属性) 如-> “Queue”="Transparent" // 渲染优先级 Transparent == 3000}
		Zwrite Off Blend SrcAlpha OneMinusSrcAlpha 一些其他的设置 如是否进行深度写入,透明混合等
		
		pass  // 注意,每个顶点片元shader至少要有一个pass
		{
			CGPROGRAM // CG预编译指令,没有则抛出异常
			
			#include ... 头文件声明位置
			#pragma vertex vert // 顶点函数
			#pragam fragment frag // 片元函数 
			
			fixed4 _Color; 变量的声明位置,注意于上面变量名和参数的一致 
			
			struct XXX 结构体位置,结构体更多的是为了顶点函数和片元函数之间进行参数的传递
			{
				float2 uv : TEXCOORD; 第一个纹理
				float4 vertex : POSITION; 像素的位置
			};
			顶点函数位置,shader是类C++写法,所以在写一些计算函数的时候要注意书写顺序
                        appdata_img 是unity里面自带的一个结构体,当unity调用这个shader时,会将相应的参数直接传递进来
			v2f vert(appdata_img v) 
			{
				v2f o;
				方法体,其实就是处理v,并且给v2f赋值
				return o;
			}
			
			SV_Target 为语义,注意上面的结构体,我们在声明的时候都会在后面添加上相应的语义,目的则是告诉GPU
			我这个参数时干嘛的,它拥有什么意义,否则的话,就拿上面的uv来说,GPU根本无法识别一个float[2]的数组是什么意思
			同样的,还有POSITION COLOR等
			参考 -> https://shenjun4shader.github.io/shaderhtml/1.%20ShaderLab%20%E6%A1%86%E6%9E%B6/12-shader-%E8%AF%AD%E4%B9%89%EF%BC%88semantics%EF%BC%89.html
			fixed4 frag(v2f v) : SV_Target
			{
				片元代码块,处理最终显示的像素
				return (1,1,1,1);
			}
			ENDCG
		}
	}
	FallBack "diffuse"; 如果这个shader因为目标配置等问题无法使用,则使用其他指定shader 
}

 

 

=======================================函数的实验========================================

mul(UNITY_MATRIX_MVP,v.vertex); //效果如下

对,如果我没有变换坐标到裁剪空间,他会直接变成这样,只要相机可以看到物体,这个材质就会一直出现在屏幕正中心

Clip的效果图如下

一些内置的变量说明(这里暂时就只我用到过的,或者我在更新这篇博客的时候想起来的 - - )

                     以下变量为我本身使用或是书籍获得,所以有可能有多重参数重载
-----------------------------------------------------------------------------------------

#UNITY_SHADER_NO_UPGROUP 1 禁止unity自动优化,比如MVP会被优化为 objecxxx,不过偶尔有用,不知道为啥


Cull Back || Front   宏指令,放在pass最前方,指定这个shader是否渲染背面 || 正面 有时候我们不用Zwrite 时,可以考虑一下这个

Clip(float - float)  如果里面的表达式在计算之后小于0,则直接忽略这个像素,clip后的语句不在执行 

mul(x , y)           矩阵相乘,必须满足矩阵乘法,一般用于将某个矩阵变换到另一个空间,比如世界空间到裁剪空间

UnityObjectToClipPos(float4) 将目标变换到裁剪空间 等同于 mul(UNITY_PATRIX_MVP , float4)

dot(float3 , float3) 计算两个向量的夹角,比如我们需要光照的强度,那么就可以使用点乘来进行计算本像素是否应该受到完整的光照

unity_WorldToObject  float4*4的矩阵,一般用在矩阵相乘里,用以将模型坐标从世界空间变换到模型空间

unity_ObjectToWrold  同上,用以将模型坐标到世界坐标的变换矩阵

normalize            归一化,如果我们只需要方向,而不需要长度可以使用

_WorldSpaceLightPos0 获取到世界光照的方向,多光源暂时没涉及,不知道他这个0用处 - - 

saturate(float)      程序里面的Clamp,将一个数值限制在 0 - 1 

reflect(x,y)         x = 入射方向 ,y = 法线方向->获取反射方向->如果本物体自发光,则返回光线进入本物体后,本物体应该
反射光线的方向 《Shader入门精要 P.134出现》

pow(floatNum,float)  第一个参数的第二个参数的次方,

_WorldSpaceCameraPos 相机在世界空间的位置,我们可以很简单的相减来获取某个向量对比相机的方向

tex2D(_MainTex,uv.xy)获取普通贴图像素,后面的uv则是顶点传递给片元的数据

UnpackNormal         获取法线贴图,这个略微有点不一样,他需要先对法线贴图进行一个tex2D操作,对这个值进行取法线操作,目前没看源码不知道为什么(估计看也看不懂 = =),例如:
{
    float4 normalColor = tex2D(_NormalTex,v.uv.xy);
	fixed3 normal = UnpackNormal(normalColor);
}

===========================================================================================
                                 头文件 Lighting.cginc 
===========================================================================================

fixed3->UNITY_LIGHTMODLE_AMBIENT 周围的环境光,如果周围又可以自发光的物体并且本物体在影响范围,则可以直接获取到受到间接光照的强度和颜色

_LightColor0          获取到光照颜色,多光源暂时没涉及,不知道他这个0用处 - -

=============================================未完。。。========================================

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值