在Unity中,不管什么种类的Shader,都是基于顶点片元着色器(Vertex Fragment Shader)制作的

完整案例

  1. Shader "Hibari/VertexFragMentShader"
  2. {
  3. SubShader
  4. {
  5. pass
  6. {
  7. CGPROGRAM
  8. #pragma vertex vert //声明VertexShader函数
  9. #pragma fragment frag //声明fragmentShader函数
  10. /*输入结构体:将数据从应用程序发送至顶点着色器*/
  11. struct a2v
  12. {
  13. float4 vertex : POSITION; //传入顶点坐标
  14. float4 normal : NORMAL; //传入顶点法向
  15. float4 texcoord : TEXCOORD0; //传入纹理坐标
  16. };
  17. /*输出结构体:从顶点着色器获取数据,并输出至片元着色器*/
  18. struct v2f
  19. {
  20. float4 myPosition : SV_POSITION; //从剪裁空间中获取顶点坐标
  21. fixed3 myColor : COLOR0; //获取顶点色
  22. };
  23. /*定义顶点着色器函数*/
  24. v2f vert(a2v input)
  25. {
  26. v2f output;
  27. output.myPosition = UnityObjectToClipPos(input.vertex);
  28. output.myColor = input.normal;
  29. return output;
  30. }
  31. /*定义片元着色器函数*/
  32. fixed4 frag(v2f input) : SV_Target
  33. {
  34. return fixed4(input.myColor, 1.0);
  35. }
  36. ENDCG
  37. }
  38. }
  39. }

编译指令

编译指令用来告诉 着色器的函数 名字叫什么

注:虽然名字可以自定义,但通常会约定一个名字 vert:顶点着色器函数(Vertex Shader Function) frag:片元着色器函数(Fragment Shader Function)

  1. #pragma vertex [function Name] //声明VertexShader函数
  2. #pragma fragment [function Name] //声明fragmentShader函数

语义

在定义【变量或函数】时,后面会带一个【冒号+单词】,这个单词就是语义。

语义的作用: 在Shader编程过程中,我们需要获取渲染流水线中相关的模型数据 语义的作用就是,将【渲染流水线中相关的数据】与【函数、变量做关联】 通过变量达到读取数据和返回输出数据

  1. //语法
  2. Type varName : [语义] //将变量与语义做关联(表示读取)
  3. tpye functionName() : [语义] //将返回值与语义做关联(表示输出)
  4. typeA functionName(TypeB varName : [语义])
  5. //将输入的参数与语义做关联,
  6. //和返回值具有相同的功能(表示输出)
  7. //示例
  8. float4 vertex : POSITION;
  9. fixed4 frag(v2f input) : SV_Target
  10. {
  11. return fixed(1,1,1,1);
  12. }

顶点着色器输入输出结构体

有时候函数输入或者输出多个语义数据时,当个变量会不方便,做一个结构体会比较方便使用

a2v:应用程序输入到顶点着色器

a2v(Application To VertexShader) Application 应用程序(从cpu过来的模型数据) VertexShader 顶点着色器 将数据从应用程序中读取到顶点着色器

  1. //示例
  2. struct a2v
  3. {
  4. float4 vertex : POSITION; //传入顶点坐标
  5. float4 normal : NORMAL; //传入顶点法向
  6. float4 texcoord : TEXCOORD0; //传入纹理坐标
  7. };

v2f:从顶点着色器到片元着色器

v2f(VertexShader To FragmentShader) VertexShader 顶点着色器 FragmentShader 片元着色器 将顶点数据输出到片元着色器

  1. //示例
  2. struct v2f
  3. {
  4. float4 myPosition : SV_POSITION; //从剪裁空间中获取顶点坐标
  5. fixed3 myColor : COLOR0; //获取顶点色
  6. };

着色器函数

顶点与片元着色器算法主要就写在这里面 vert:表示顶点着色器函数(VertexShaderFunction) frag:表示片元着色器函数(FragmentShaderFunction)

Vert:顶点着色器函数

顶点着色器函数需要从【应用程序】获取数据到【顶点着色器】,所以【函数参数a2v类型】 顶点着色器函数运算完成后,需要将数据输出到【片元着色器】,所以【返回值为v2f类型】

  1. v2f vert(a2v input)
  2. {
  3. v2f output;
  4. //修改数据
  5. output.myPosition = UnityObjectToClipPos(input.vertex); //编辑顶点坐标
  6. output.myColor = input.normal; //编辑顶点颜色
  7. return output;
  8. }

Frag:片元着色器函数

片元着色器需要从【顶点着色器】获取已经【运算完成信息】,所以【函数参数v2f类型】

注:片元着色器在运算完成后,只有一个信息(即将渲染结果保存到帧缓存) 因此不需要额外定义一个结构体,直接将函数的返回值与SV_Taregt做关联即可。

  1. fixed4 frag(v2f input) : SV_Taregt
  2. {
  3. return fixed4(input.myColor, 1.0);
  4. }