shader可分为vertex与fragment
1、vertex称为定点着色器,负责对模型中每个定点进行定义,可包括位置、法向量、切向量等,vertex可去到所有模型中的定点,并传递给fragment进行像素颜色返回
2、fragment称为片段着色器,是对于每个定点间进行过度处理,可认为是对于每个需渲染的像素的处理,一个像素对应一个fragment,所以在fragment中处理事物会十分消耗资源。
shader“name”{
[Properties] //提供一些变量提供给编辑器调控
SubShaders //Shader渲染方案,可以写多个,优先执行靠前的方案,如果执行有问题,则会选择下一个执行
[FallBack] //所有方案都没有执行成功,调用自带的基本方案
}
Shader "Sbin/vf1"{
SubShader{
pass{
CGPROGRAM //CG语言起始,大写表示
#pragma vertex vert //定义顶点着色器函数
#pragma fragment frag //定义片段着色器函数,两个函数都需要编写
#define TE FL4(fl4.ab, fl3.zy);
struct rec
{
float4 pos;
float2 uv;
}; //声明结构体,与C中相同
typeof float4 FL4; //别名
void vert(in float2 objPos:POSTION, out float4 pos:POSTION, out float4 col:COLOR){ //in代表输入,out代表输出,inout代表输入并且输出,:后跟着语意
pos float4(objPos, 0, 1);
col = float4(0, 0, 0, 1);
}
void frag(inout float4 col:COLOR){
//col = folat4(1, 0, 0, 1);
float r = 1;
float g = 0;
float b = 0;
float a = 1;
col = float4(r, g, b, a);
float2 f12 = float(1, 0);
float3 f13 = float(1, 0, 1);
float4 f14 = float(1, 1, 0, 1);
FL4 f1 = TE // 使用xyzw或rgba取得分量,swizzle操作可以颠倒、组合、重复顺序,但是每次取值rgba和xyzw只能选一种
col = f1;
float2x4 M2x4 = (f14, 0, 1, 0, 1); //矩阵定义
col = M2x4[0];
float arr[4] = {1, 2, 3, 4}; //数组不可以使用swizzle,只能使用[角标],从0开始,参数传递按照值拷贝方式
}
ENDCG
}
}
}
内建函数
数学
几何
纹理
导数
语意:
语意名 | 含义 |
---|---|
POSITION | 输出坐标点 |
COLOR | 颜色 |
TEXCOORD | 纹理 |
uniform float4 _SecondColor; //可以通过csharp脚本赋值,默认为黑(0, 0, 0, 0)
GetComponent<Render>().material.SetVector("_SecondColor", new Vector4(1, 0, 0, 1));
模型->世界->摄像机->投影
Camera.main.projectionMatrix * transform.localToWorldMarix * Camera.main.worldToCameraMatrix;
CG中使用mul函数进行矩阵相乘
使用判断xyz坐标改变颜色语意传递给fragment
使用屏幕空间(-1,1)处理物体 mvp后手动投影变换
mvp乘以位移顶点
Shader"Sbin/vf1"{ //shader名字以层级命名(vf1是名字,前面的为相对路径)
properties{ //提供编辑器可以改变的属性
_Color("Color", color) = (1, 1, 1, 1) //属性名(自定义名字,类型) = 默认值
_Ambient("Ambient", color) = (0.3, 0.3, 0.3, 1)
_Specular("Specular", color) = (1, 1, 1, 1)
_Shininess("Shininess", range(0, 8)) = 4 //range范围,返回float
_Emission("Emission", color) = (1, 1, 1, 1)
_Constant("ConstantColor", color) = (1, 1, 1, 0.3)
_MainTex("MainTex", 2d) = ""{}
_SecondTex("SecondTex", 2d) = ""{}
}
SubShader{
Tags {"Queue" = "Transparent"} //设置渲染队列标签
pass{ //pass通道
Blend SrcAlpha OneMinusSrcAlpha //采用当前目标阿尔法值,与1-当前目标阿尔法值的比例进行阿尔法混合,具体内容查询ShaderLab:Blending
//color(1, 1, 1, 1) //设置颜色为固定值值1,1,1,1,顺序为红、绿、蓝、阿尔法
//color[_Color] //设置颜色为变量_Color,[]代表颜色可变,但还是没有立体效果
material{ //设置材质
diffuse(_Color) //设置漫反射颜色,或者是说本身的固有色
ambient[_Ambient] //设置环境光强度
specular[_Specular] //设置镜面高光强度
shininess[] //设置镜面高光反射区域
emission[_Emission] //设置自身发光
}
lighting on //固定管线功能,打开光照
separatespecular on //设置集中高光,在使用specular时开启
//进行贴图和材质混合
settexture[_MainTex]
{
combine texture * primary double//使用_MainTex贴图,primary是fixfunctionshader自带的,使用之前设置好的材质,相乘代表贴图和材质进行混合,double代表乘以2,quad代表乘以4,参数越大越亮
}
//进行第二个贴图混合,不能使用primary,primary只会和初始顶点光照进行混合,使用previous采用和之前所有材质进行混合,但混合个数也是有限的
settexture[_SecondTex]
{
//matrix[] //可设置矩阵来进行更复杂的图形运算
combine texture * previous double, texture * _Constant //阿尔法参数,texture只使用这个贴图的阿尔法,_Constant可调整阿尔法透明度
}
}
}
}
更容易编写光处理,对vertex和fragment的包装
Shader "Custom/sf" {
Properties {
_Color ("Color", Color) = (1,1,1,1) //颜色
_MainTex ("Albedo (RGB)", 2D) = "white" {} //主纹理
_Glossiness ("Smoothness", Range(0,1)) = 0.5 //计算高光
_Metallic ("Metallic", Range(0,1)) = 0.0 //金属光泽
}
SubShader {
// SurfaceShader自动添加pass通道
Tags { "RenderType"="Opaque" } //不透明标签
LOD 200 //程序细节
CGPROGRAM //CG语法起始
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows //pragma编译指令,以#开头 surface以SurfaceShader编写,函数名,Standard光照模型,[其他选项],fullforwardshadows阴影类型
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0 //使用硬件shader model 3.0,默认2.0
sampler2D _MainTex; //二维纹理,对应Properties属性
struct Input {
float2 uv_MainTex; //纹理属性结构体必须使用uv或者uv2开头
};
//与Properties属性对应
half _Glossiness;
half _Metallic;
fixed4 _Color;
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG //CG语法结束
}
FallBack "Diffuse"
}
forward rendering path details
光照建议使用surfaceshader
vertex光处理不真实,但计算量比较小
fragment光处理计算量大大提升,模拟效果比较好
一般使用在fragment处理光
vertex传递物体法向量和点位置
在fragment计算世界法向量和光照向量
法向量点击视角方向为0
使用多个pass blend混合 查询blend混合因子等
设计距离公式,实现动态变换颜色fragment
tex2D(sampler2d, uv)
maintex_st计算平铺和偏移,可以使用transform_tex
用一个数组迭代,周围8个状态<<2减去自身,成为下一个迭代状态,可以限定一个值区域,uv值可以由左边减去右边除以2计算,通过color传递给shader(注意color只接收0到1范围,注意变换范围传递),状态能量值缩小
computshader gpgpu dx11可以支持,具体代码以后会给出~
tags transparent渲染队列
ZWrite off,半透明物体选择深度关闭
Ztest 选择深度测试方式,与深度缓存比较方式,真才能显示像素颜色
如果要渲染一个被遮挡的物体,可以选择其他深度测试来进行渲染,注意zwrite的开关
(*)半透明物体使用camera.setreplaceshader
从灰度产生法线纹理,计算像素上下灰度差,与左右灰度差进行叉乘,作为一个颜色存入图片,即使用法线纹理
通过给出的6个纹理面,计算视野到对应像素点反射的方向,采取对应纹理进行渲染