01:认识最简单的shader代码

Shader "Unlit/01minishader"

{

Properties

{

_MainTex ("Texture", 2D) = "white" {}

}

SubShader

{...}

}

这是一个简单shader的基本结构根据两个模块进行构成,其中subshader是我们需要研究学习的模块,但在此之前,我们也需要明白subshader模块之上的是什么东西,

1.1 首先就是shader第一行,指的是这个shader是创建于shader类别中的unlit(无光照)目录下面的一个shader名字是01minishader。再是我们的properties模块,这个模块是属性模块,连接了材质与unity shader。

一个通用的properties模块的样式如下:

properties{

Name("display name",propertyType)=Defaultvalue

这样的格式是为了开发者,在材质编辑面板进行材质的编辑。name是属性的名字,通常这个属性名字由一个下划线展开,就比如_MainTex这个属性名字,而displayname自然就是在材质编辑面板上的名字,我们需要给这个属性确立它的类型,所以就有了property Type,在unity中常用的属性类型如下

再赋给一个值,比如这里的white

那么我们就可以对这里的properties模块就可以进行解释了。

进行翻译为:现在属性Maintex属性,其中在材质面板上表现为texture(贴图)这个材质名字,它的属性类型是2D类型,再赋予一个初始值白色。材质与shader的联系就建立了。

1.2然后就是我们的大头任务,认识subshader

我们把shader分为了properties模块与subshader模块,我们也能把subshader模块进行细分为两个模块,一个是pass外,一个是pass内。 同上,我们对一个subshader的模板进行研究如下

SubShader {

//可选的

[Tags]

//可选的

[RenderSetup)

Pass {

}

// Other Passes

}

这个模板是什么意思呢?我们逐个研究,首先是tags(标签), SubShader的标签(Tags)是一个键值对(Key/Value Pair), 它的键和值都是字符串类型。 这 些键值对是SubShader和渲染引擎之间的沟通桥梁。 它们用来告诉Unity的渲染引擎: 我希望怎样以及何时渲染这个对象。 标签的结构如下:

显然通过对于tags的设置我们可以进行很多功能的选择。

那么rendersetup(状态设置)是什么呢? 可以设置显卡的各种状态, 例如是否开启深度/混合测试。

了解了标签与渲染状态设置,我们开始重头戏,身为要写shader人的最重要的困难以及任务写pass。

我们先展开上面的pass语句,了解其中的内容。

Pass

{

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

// make fog work

#pragma multi_compile_fog

#include "UnityCG.cginc"

struct appdata

{

float4 vertex : POSITION;

float2 uv : TEXCOORD0;

};

struct v2f

{

float2 uv : TEXCOORD0;

UNITY_FOG_COORDS(1)

float4 vertex : SV_POSITION;

};

sampler2D _MainTex;

float4 _MainTex_ST;

v2f vert (appdata v)

{

v2f o;

o.vertex = UnityObjectToClipPos(v.vertex);

o.uv = TRANSFORM_TEX(v.uv, _MainTex);

UNITY_TRANSFER_FOG(o,o.vertex);

return o;

}

fixed4 frag (v2f i) : SV_Target

{

// sample the texture

fixed4 col = tex2D(_MainTex, i.uv);

// apply fog

UNITY_APPLY_FOG(i.fogCoord, col);

return col;

}

ENDCG

}

}

}

这是我们的pass语句中的内容,和之前一样我们对模板进行研究。下面展开模板(翻译在subshader介绍完后进行)

1.3pass模板

pass{

{Name}

{Tags}

{Rendersetup}

//other code

}

很容易发现我们对于subshaderpass中的内容要简单一些,因为里面也是标签,渲染状态设置,一样的内容。那么区别在哪里呢?

区别在于我们对于这个pass语句中的标签与渲染状态设置仅仅是对于这一个pass语句起作用,而pass外的则是对所有的pass。这个点会对我们进行不同问题不同渲染的时候尤其重要。

开始对于pass内的研究,首先让我们回忆上一文中我对于渲染管线的介绍。在cpu端将模型数据传递给gpu后,要对其先通过顶点shader进行变形,再用片元shader进行逐片元上色。这个过程在代码是怎么体现的呢?答案在pass语句内,让我们对其研究。(一个pass语句一个理解为一个gpu的渲染管线)

代码的框架:CGPROGRAM

{

}//这个括号代表之间存在东西。

ENDCG

什么意思呢?代表我们这个pass语句是cgshader编写语言书写的一个pass语句(hlsl,glsl,cg是三种编写shader的语言,本文不做阐述),那么了解这个框架后,我们开始正式写shader

通过对于渲染管线的了解后,我们会发现我们需要写两个shader,顶点shader(vertex shader)与片元shader(fragment shader),但是正式编写代码的时候,我们要尽量简化工作流,因此我们会#pragma vertex vert 与 # pragma fragment frag,代表着我们的顶点shader已经被称呼为了vert,片元shader称呼为frag。方便进行后文代码的编写,实际编写过程中,名字是可以随意变化的,当然要被你同事看的懂(笑), #pragma multi_compile_fog这个是unity帮助我们方便写shader的一个头文件,里面有许多函数与变量可以让我们使用。前期准备结束,shader编写开始:

第一步:拿到模型数据

第二步:进行空间变换

第三步:逐片元上色

1.3.1:拿到数据:

struct appdata//这个指的是拿到模型数据,appdata是这个输入结构体的名字

{

float4 vertex : POSITION;//拿到这个模型的顶点坐标

float2 uv : TEXCOORD0;//拿到模型的uv

float3 normal:NORMAL;//拿到模型的法线

float4 color:COLOR;//拿到模型的顶点色

//:后的都是特定的语义词,更多语义词可以上unity官方文档进行查看与使用,列举了常用的一些语义词

};

我们有一个输入的结构体,拿到了模型的数据,那么经过顶点shader后,自然会产生一个不一样的数据,因此要写一个输出结构体

struct v2f//输出结构体

{

float2 uv : TEXCOORD0;//uv的输出

float4 vertex : SV_POSITION;//顶点坐标的输出

};

结构体的部分阐述到此,更多部分后续说明与补充,或者在官方文档进行个人研究。有了数据,那么就能开始写顶点shader与片元shader了。首先就是顶点shader

1.3.2:顶点shader(vertex shader)的编写:

v2f vert(appdata v)//从appdata中拿到(u)v的数据进行传参数再输出(v2f)

{

v2f a;//初始化输出数据为a

}

那么顶点shader之后的内容到底怎么写?这个涉及到顶点shader的作用,在笔者看来就是变化,从模型空间到世界空间再到相机空间再到裁剪空间(这就是mvp矩阵变换的作用地)(本文不做说明,后续进行mvp矩阵变化的数学原理以及在顶点shader中的具体原理),知道了原理,所以我们的任务就是写矩阵(笑,回到很多人不喜欢的数学部分,线性代数)

矩阵不想自己计算的话,可以到unity的官方文档研究官方提供的矩阵

有了矩阵,那么可以进行顶点shader的书写了

v2f vert(appdata v)//从appdata中拿到(u)v的数据进行传参数再输出(v2f)

{

v2f a;//初始化输出数据为a

float4 pos_world=mul(_ObjectToWorld,v.vertex);//mul指的是矩阵的乘法,v.vertex指的是向量的坐标点,从模型空间到世界空间

float4 pos_view=mul(_MATRIX_V,pos_world);//从世界空间到相机空间

float4 pos_cilp=mul(_MATRIX_P,pos_view);//从相机空间到裁剪空间

a.pos=pos_cilp;//把裁剪空间的数据给与a

return a;

}

顶点shader的书写也就完成了。其实是很简单的,那么片元shader也是一样书写。

1.3.3:片元shader的编写

float4 frag (v2f i) : SV_Target//片元shader输出的是一个颜色值,SV_Target是我们渲染的一个目标

{

return float4(0.4,0.5,0.1,1.0);//数字类比rgb值

}

到此一个简单的基本shader就写完了,并且可以实现用代码更改颜色等等功能。

1.4总结

一个简单的shader代码,对于开发者来说,最为重要的是其pass语句的编写,另外对一个TA来说,属性界面也尤其重要,学会用shader来让项目开发更加简单,给与美术更好的体验,给与项目更丰富的画面表现才是shader编写的意义

那么我们开始对于这一个简单的shader的汉语翻译

首先我们要确立属性面板,确立材质与unity shader之间的关系,再是书写pass语句,正式写shader,我们要得到模型的数据,需要写两个结构体,输入结构体,输出结构体,并且开始写我们的shader,顶点shader与片元shader。这就是我们的工作流,也是shader编写最简单最基本的框架。

(至此本文对于unity shader代码最简单的介绍到此结束,后续会说明深度测试等等功能在代码中的实现以及数学原理)

感谢《unity shader入门精要》

TA 认识 unity shader最基本的代码结构与书写01相关推荐

  1. Unity Shader 常规光照模型代码整理

    Unity Shader 常规光照模型代码整理 本次整理在Unity中几种常见的光照模型,包含 1.BlinnPhong(常规光照模型) 2.ForwardRender(多灯光带有衰弱前向渲染) 3. ...

  2. unity Shader

    unity Shader 前言 1 unity shader代码结构 1.1 shader命名 1.2 Properties语义块 1.3 SubShader 1.3.1 Pass 1.3.2 Sub ...

  3. Unity shader入门精要(学习总结)

    (学习总结) 一,基础概念 什么是shader? Unity Shader定义了渲染所需的各种代码(如顶点着色器和片元着色器).属性(如使用哪些纹理等)和指令(渲染和标签设置等),而材质则允许我们调节 ...

  4. Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照

    转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交 ...

  5. Unity shader学习之屏幕后期处理效果之高斯模糊

    高斯模糊,见 百度百科. 也使用卷积来实现,每个卷积元素的公式为: 其中б是标准方差,一般取值为1. x和y分别对应当前位置到卷积中心的整数距离. 由于需要对高斯核中的权重进行归一化,即使所有权重相加 ...

  6. Unity Shader着色器优化

    对游戏开发者而言,着色器长久以来就是游戏开发中的重要部分,在Unity中编写并实现着色器的过程直观且高效,优秀的着色器还可以创造非常精美的游戏画面,同时保证极高的性能.今天将由Unity的技术工程师张 ...

  7. qnetworkreply 获取状态_谈谈Unity Shader中的采样器状态和(Texture Filtering)纹理滤波方式

    参考文章: 使用采样器状态 - Unity 手册​docs.unity3d.comhttps://blog.csdn.net/chenjinxian_3D/article/details/518169 ...

  8. Unity Shader 之 透明效果

    本文引用 Unity Shader入门精要 开启透明混合后,一个物体被渲染到屏幕上时,每个片元除了颜色值和深度值外,还有--透明度.透明度为1,则完全不透明,透明度为0,则完全不会显示. 在Unity ...

  9. 【Unity Shader】(六) ------ 复杂的光照(上)

    笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题.              [Unity Sha ...

最新文章

  1. B树,B+树,B-树和B*树
  2. 数据仓库的未来 MariaDB ColumnStore
  3. Class类文件的结构
  4. why process type for MyOpportunity creation is empty
  5. html给box加超链接,java – 如何使用pdfbox在pdf中添加超链接
  6. 谈论 NOD32: 教育网超级 病毒更新服务器: http://222.197.166.33/main.htm
  7. C语言冒泡排序法及代码
  8. C语言:求X的Y次方
  9. eclipse的代码突然变成红色块或绿色块
  10. treeoj 1206~1208 1212
  11. 防火墙、waf、ips和ddos的部署
  12. 学术小白:如何区分SCI、EI
  13. 凌晨3点不回家:因为想不到的心酸!
  14. 视频点播和OSS两个产品之间的区别与联系
  15. 一个好的学习算法的网站
  16. 关于赛车游戏制作的一点体会
  17. 「可口可乐 + Zion」7天上线小程序是如何做到的?
  18. 3S基础知识:MapInfo点符号的制作方法
  19. 隐私计算加密技术基础系列(下)对称与非对称加密的应用场景
  20. 大学计算机基础试题二

热门文章

  1. android 软件备份工具,android备份软件 知乎 备份软件 知乎
  2. Ubuntu14.04安装搜狗拼音输入法后无法使用解决方案
  3. Matlab——彩色图像的拼接与裁剪
  4. k神讲故事-金融的结局
  5. perl对日志进行压缩备份小程序
  6. 懂车帝新能源汽车销量分析
  7. 当我们在谈SWIFT时,到底在谈什么?
  8. Laravel 文件系统/存储
  9. 计算机硬件设备介绍 ppt,计算机硬件设备的认识课件.ppt
  10. Pnadas学习day-01