Shader的学习(简单Shader)

1.什么是OpenGL、DirectX

Shader可以认为是一种渲染命令,有OpenGL或者DirectX进行解析,来控制渲染图形

GLSL shader语言用于OpenGL

HLSL shader语言用于DirectX

使用CG编写的shader可以跨平台,既可以在OpenGL上解析,也可以在DirectX上解析。

2.unity shader的分类

使用ShaderLab编写Unity中的Shader,

分类1:表面着色器 Surface Shader,相当于对顶点/片元着色器进行了一层封装

分类2:顶点/片元着色器 Vertex/Fragment Shader

分类3:固定函数着色器 Fixed Function Shader(使用不多,几乎被弃用)

3.unity Shader的属性类型有哪些

Properties//属性,属性定义好后不能直接使用,需要在Pass块中重新定义

{

//     属性名    类型      默认值

_Color("Color", Color) = (1,1,1,1) //颜色(float4)

_Vector("Vector", Vector) = (1,1,1,1) //四维向量 与Color本质上是一种类型,只 是使用上不同(float4)

_Int("Int", Int) = 12 //整数(float)

_Float("Float", Float) = 5.4 //小数(float)

_Range("Range", Range(0,1)) = 0.5 //Range类型(float)

_2D("Texture", 2D) = "white"{} //图片类型,引号内为颜色,若不使用图片, 则认为是指定颜色的图片(sampler2D)

_Cube("Cube", Cube) = "white"{} //立方体纹理,比如天空盒就会用到该 属性(samplerCube)

_3D("3D", 3D) = "black"{} //3D纹理(sampler3D)

}

4.untiy Shader属性的使用

Properties属性定义好后不能直接使用,需要在Pass块中重新定义

重新定义的名字需要与Properties属性中保持一致

注意,使用float时可以使用half和fixed进行代替

例如float4类型可以用half4和fixed4,float3可以用half3和fixed3

float可以用half和fixed代替

float4 _Color;

float4 _Vector;

float _Int; //其中int,float,range都可以使用float

float _Float;

float _Range;

sampler2D _2D;

samplerCube _Cube;

sampler3D _3D;

5.float、half、fixed类型的区别

float使用32位进行存储

half使用16位进行存储,在-60000到60000间,超出范围只能用float

fixed使用11位进行存储,在-2到2间,一般颜色使用fixed

6.顶点函数vert和片元函数frag

//顶点函数 这里只是声明了顶点函数的函数名

//作用,将模型顶点的模型空间坐标转化为剪裁空间坐标,从游戏环境转换到视野相机屏幕(裁剪坐标不完全为屏幕坐标)

#pragma vertex vert

//片元函数 这里只是声明了片元函数的函数名

//基本作用 返回模型对应的屏幕上的每一个像素的颜色值

#pragma fragment frag

//Shader中函数的返回值与参数不是固定的,但是有一定的要求

//shader中坐标一般为4位而不是3位,因为可以使用矩阵计算,第4位不会用可不用

//通过语义告诉系统,参数的作用,比如POSITION是告诉系统此处需要顶点坐标,SV_POSITION这个语义用来解释说明返回值,意思是返回值是剪裁空间下的顶点坐标

float4 vert(float4 v : POSITION) : SV_POSITION //float4 v : POSITION此为语义说明,POSITION代表将顶点坐标传递给v, SV_POSITION是对返回值进行语义说明,代表返回值为剪裁空间的坐标

{

return UnityObjectToClipPos(v);

//float4 pos = mul(UNITY_MATRIX_MVP,v); //mul(UNITY_MATRIX_MVP,v)进行矩阵计算,UNITY_MATRIX_MVP为系统的矩阵,计算结果为剪裁空间的坐标

//return pos;

}

fixed4 frag() : SV_Target

{

return _Color;

}

7.Shader中NORMAL与TEXCOORD0的语义说明

//使用结构体封装好语义说明,实现函数时就不需要进行语义说明了

struct a2v

{

        float4 vertex : POSITION; //告诉unity将模型空间的顶点坐标填充给vertex

        float3 normal : NORMAL; //告诉unity将模型空间的法线向量填充给normal

        float4 texcoord : TEXCOORD0; //告诉unity把第一套纹理坐标填充给texcoord

};

8.从应用程序传递到顶点函数的语义有哪些(a2v结构体内的语义)

POSITION 模型空间下的顶点坐标

NORMAL 模型空间下的法向量

TANGENT 模型空间下的切线

TEXCOORD0~N  纹理坐标

COLOR 顶点颜色

9.从顶点函数传递给片元函数的时候可以使用的语义(v2f结构体内的语义)

SV_POSITION 剪裁空间下的顶点坐标(一般是系统直接使用)

COLOR0 可以传递一组值 如float4类型

COLOR1 可以传递一组值 如float4类型

TEXCOORD0~7 传递纹理坐标

10.片元函数传递给系统的语义

SV_Target 颜色值,显示到屏幕上的颜色、

11.什么是光照模型

光照模型就是一个公式,用来计算光 照射在某个点上呈现的效果

标准光照模型

在标准光照模型里面,我们把进入摄像机的光分为下面4个部分

自发光

高光反射 Specular = 直射光 * pow(max(cos(夹角),0), 高光参数),其中夹角为反射光 方向与视野方向的夹角

漫反射 Diffuse  = 直射光颜色*cos(夹角)表示光和法线的夹角,当夹角小于0时, 使用0,大于0时使用该夹角

环境光 UNITY_LIGHTMODEL_AMBIENT.rgb

12.实现漫反射时的注意点

只有定义了正确的LightMode才能得到一些Unity的内置光照变量

Tags{"LightMode"="ForwardBase"}

可以取到第一个直射光的颜色 _LoghtColor0,以及第一个直射光的位置_WorldSpaceLightPos0;

包含unity的内置文件,才可以使用unity内置的一些变量

#include "Lighting.cginc"

normalize()方法用来将一个向量进行归一化

max()方法用来取得最大值

dot()用来取得两个向量的点积

_WorldSpaceLightPos0 取得平行光的方向(位置)

_LoghtColor0 取到平行光的颜色

UNITY_MATRIX_MVP 这个矩阵将一个坐标从模型空间转换到剪裁空间

_World2Object这个矩阵用来把一个向量总世界空间转换到模型空间

UNITY_LIGHTMODEL_AMBIENT用来获取系统内置的环境光

13.兰伯特光照模型与半兰伯特光照模型

兰伯特光照模型就是漫反射光照模型,公式为Diffuse  = 直射光颜色*cos(夹角)表示光和法线的夹角,当夹角小于0时, 使用0,大于0时使用该夹角

半兰伯特光照模型,公式为:Diffuse  = 直射光颜色*(cos(夹角) * 0.5 + 0.5)

14.高光反射的实现

公式为:Specular = 直射光 * pow(max(cos(夹角),0), 高光参数),其中夹角为反射光方向与视野方向的夹角

/计算得到视野方向其中_WorldSpaceCameraPos为相机在世界空间的位置

normalize(_WorldSpaceCameraPos.xyz - mul(v.vertex, unity_WorldToObject).xyz);

//此处计算得到光的反射向量reflext方法是计算光的反射方向的,其中-lightDir是光照方向,normal是在世界空间下的法线方向

fixed3 reflectDir = normalize(reflect(-lightDir, normal));

15.高光反射也叫作Blinn光照模型,他存在一个优化的模型叫做Blinn-Phong光照模型

Blinn-Phong光照模型的计算公式为:

Specular = 直射光 * pow(max(cos(夹角),0), 高光参数),其中夹角为法线与向量X的夹角,

其中X为平行光与视野方向的平分线

16.UnityCG.cginc中一些常用的函数

摄像机方向:

float3 WorldSpaceViewDir(float4 v) 根据模型空间中的顶点左边得到(世界空间)从这 个点到摄像机的观察方向

float3 UnityWorldSpaceViewDir(float4 v) 世界空间中的顶点坐标-->世界空间从这个点到摄 像机的观察方向

float3 ObjSpaceViewDir(float4 v) 模型空间中的顶点坐标-->模型空间从这个点到摄 像机的观察方向

光源方向:

float3 WorldSpaceLightDir(float4 v) 模型空间中的顶点坐标-->世界空间中从这个点到 光源的方向

float3 UnityWorldSpaceLightDir(float4 v) 世界空间中的顶点坐标-->世界空间中从这个点到 光源的方向

float3 ObjSpaceLightDir(float4 v) 模型空间中的顶点坐标-->模型空间中从这个点到 光源的方向

方向转换

float3 UnityObjectToWorldNormal(float3 norm) 把法线方向由模型空间-->世界空间

float3 UnityObjectToWorldDir(float3 dir) 把方向由模型空间-->世界空间

float3 UnityWorldToObjectDir(float3 dir) 把方向由世界空间-->模型空间

17.关于纹理贴图的实现

首先在a2v中定义纹理float4 texcoord : TEXCOORD0;

然后在v2f中定义一个uv,贴图其实就是uv,float2 uv : TEXCOORD1;

然后在顶点函数中赋值f.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw; //添加贴图的旋转与缩放,使Tiling与Offest参数可用其中_MainTex_ST是贴图的旋转缩放数据

float4 _MainTex_ST; //固定格式,使用贴图变量的名称加上"_ST"_MainTex_ST.xy 为x和y轴的缩放,_MainTex_ST.zw为x和y轴上得到旋转

fixed3 texColor = tex2D(_MainTex, f.uv.xy)tex2D方法为获取贴图在uv上各点的颜色,

然后使用该颜色代替漫反射的颜色,是物体表面显示图片

fixed3 diffuse = _LightColor0.rgb * (dot(normalDir, lightDir) * 0.5 + 0.5) * texColor;

18.法线映射的前置知识

法线normal = (法线贴图的rgb)pixel * 2 - 1;

使用 UnpackNormal法线贴图颜色可得到切线空间的法线

//得到法线贴图的颜色

fixed4 normalColor = tex2D(_NormalMap, f.uv.zw);

//得到切线空间的法线

fixed3 normalDir = normalize(UnpackNormal(normalColor));

19.修改透明度的前置条件

首先添加Tags,

Tags{"Queue"="Transparent" "IngnoreProjector"="True" "RenderType"="Transparent"}

然后

ZWrite off  

Blend SrcAlpha OneMinusSrcAlpha

最后在片元函数中返回的颜色中修改Alpha值 return fixed4(value, _AlphaScale);

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值