Shader笔记——初识

声明:本文仅供自己记录学习使用

Shader其实就是专门用来渲染图形的一种技术,通过shader,我们可以自定义显卡渲染画面的算法,使画面达到我们想要的效果。

GPU,CPU,显卡驱动,Directx,OpenGL,shader(无序排列)。这些都是图形渲染相关。

从unity的基础上来讲,一个模型,首先会在硬盘中加载到内存中,然后CPU读取,并且告诉GPU想要渲染成什么效果,而GPU收到CPU的指令进行渲染,而渲染的过程

上图中,在渲染时,我们可以对其中一些步骤进行编辑,按照自己的需求(改变顶点,改UV)等,cg语言编写控制,最终达到想要的效果。

而我们的主角shader并不是直接能被识别的,他在unity中编译成可识别的程序,我们可以称之为ShaderLab

Shader的两种类型

  • 顶点shader,对三角形面片的顶点操作,计算每个三角面片上的顶点,并为最终像素渲染做准备
  • 以像素为单位,计算光照、颜色的一系列算法。
    • DirectX中
      • 顶点shader叫做 Vertex Shader
      • 像素Shader叫做 Pixel Shader
    • OpenGL
      • 顶点Shader也叫做 Vertex Shader
      • 像素Shader叫做 Fragment Shader(片断Shader或者片元Shader);

Shader的语言       

  1. 基于DirectX的High Level Shading Language,简称HLSL。
  2. 基于OpenGL的OpenGL Shading Language,简称GLSL。
  3. 还有NVIDIA公司的C for Graphic,简称Cg语言。

在pc端,基本上使用的DirectX,而在android和ios,linux则使用的OpenGL

而unity作为跨平台的编辑器,无疑选择Cg语言

在unity中有三种shader:

  • Surface Shaders 表面着色器
  • Vertex/Fragment Shaders 顶点/片断着色器
  • Fixed Function Shaders 固定管线着色器

下面是干货

ShaderLab语法基础

1.定义一个Shader,每一个着色程序都要有一个shader
Shader“name”
{
    //name:shader的名字    
    //定义的一些属性,定义在这里会在属性查看器显示
    [Propertes]
    //子着色器列表,一个shader至少有一个子着色器
    Subshaders{...}  
    //如果子着色器显卡不支持,就会降级处理,Fallback
    [Fallback]
}

 

Propertes属性

2.Propertes定义
name("displayname",type)=值
name指属性的名字,Unity中使用下划线开始 _xxx
displayname,在属性检查器显示的名字
type这个属性的类型
值,默认值

3.类型
Float,
Int,
Color(r,g,b,a)(0~1),
Vector(4维向量),
Range(start,end),
2D:2D纹理
Rect:矩形纹理属性
Cube:立方体纹理属性
3D:3D纹理属性
例:name("displayname",2D)="name"{options}

4.Options:纹理属性选项
TexGen:纹理生成模式,纹理自动生成纹理坐标的模式,顶点shader自动忽略
ObjectLinear,EyeLinear,SphereMap,CubeReflect CubeNormal
LightmapMod:光照贴图模式如果设置,纹理会被渲染器的光线贴图影响

5.prepertes定义案例
_Range("range value",Range(0,1))=0.3;//定义一个范围值
_Color("color",Color(1,1,1,1))=(1,1,1,1);//定义一个颜色
_FloatValue("float value",Float)=1;定义一个浮点
_MainTex("Altobo",Cube)="skybox"{TexGen CubeReflect}//定义一个立方贴图纹理属性

SubShader

组成:SubShader{[Tags],[CommonState],Pass{}}

子着色器由 标签+通用状态+渲染通道并可选为所有通道初始化的通用状态

渲染的时候将优先渲染一个被每个通道所定义的对象

通道的类型:

  • RegularPass
  • UserPass
  • GrabPass

在通道中定义状态同时对整个子着色器可见,所有通道可以共享状态

SubShader
{
    Tags{"Queue","Transparent"}  
    Pass{
        Lighting Off  //关闭光照
... } }

Tags

Tags{"key1"="value1" "key2"="value2" "key3"="value3"}//空格隔开

Tags类型

  • Queue tag队列标签
  • RenderType tag渲染类型标签
  • DisableBatching tag禁用批处理标签
  • ForceNoShadowCasting tag强制不投影标签
  • IngoreProjecttor忽略投影标签
  • CanUseSpriteAtlas tag使用精灵图集标签
  • PreviewType tag预览类型标签

Pass

SubShader包装了自定义的渲染方案,由一个个通道(Pass)执行,一个SubShader可以包含多个通道,每个通道都渲染一次

Pass基本写法 Pass{[Name and Tags][RenderSetup][TextureSetup]}

Pass块的Name引用此Pass,可以在其他着色器的Pass块中引用他,减少重复,Name命令必须大写

 

RegularPass设置

  • Linghting:光照开启/关闭定点光照 On/Off
  • Material:(材质)定义一个使用定点光照管线的材质
  • ColorMaterial:颜色集:计算使用定点光照使用顶点颜色
  • SeparateSpecular:开光状态:开启或关闭顶点光照相关的镜面高光颜色 On/Off
  • Color:设置定点光照关闭时使用的颜色
  • Fog:设置雾参数
  • AlphaTest:Alpha测试
  • ZTest:深度测试模式
  • ZWrite:深度写模式
  • Blend:混合模式SourceBlendMode,DestBlendMode,AlphaSourceBlendMode,AlphaDestBlendMode
  • ColorMask:颜色遮罩,颜色值可以由RGB或A或0或R,G,B,A的组合,设置为0,关闭所有颜色通道渲染
  • Offset:偏移因子,设置深度偏移

 特殊通道Pass

UsePass:插入所有来自其他着色器的给定名字的通道

也叫通道的复用,简单地说,我有一个shader,要使用两个pass,其中一个pass已经在其他shader中使用过,那么,我们可以直接复用这个pass

UsePass"Shader/Name"  Name为着色器通道

UsePass"Specular/BBB"  插入Specular中为BBB的通道

即   Pass{[Name and Tags][RenderSetup][TextureSetup]}

GrabPass:一种特殊的通道

获取物体所在位置的屏幕内容,写入一个纹理,后续可被使用

_GrabTexture访问

GrabPass{"纹理名"}获取屏幕内容到指定的纹理,后续通道可以使用纹理名访问

FallBack:对于一个shader中,所有的子着色器都无法被显卡使用,那么就会降级处理

FallBack"着色器名"

FallBack Off:没有降级,并且无任何警告

 

Categroy分类

分类是渲染命令的逻辑组,例如着色器可以有多个子着色器,如果他们都需要关闭雾效和和混合

Shader"xxx"{
  Categroy{
     Fog{Mode Off}
     SubShader{...}
     SubShader{...}
  } 
}

 

posted @ 2020-09-03 18:05  密斯塔Joe  阅读(335)  评论(0)    收藏  举报