打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
初入shader的教程第一课 想了解shader来看看吧 | Imagination中文技术社区

 前几天发的shader我自己都看不下去了 下面我来好好说一下

Unity shader这个东西呢 也叫shaderlab 编写语言是CgFx 也叫做Direct3D Effects (.FX) 以下是一个shader的基本形式

Shader "MyShader" {
Properties {
_MyTexture ("My Texture", 2D) = "white" { }
// 颜色和矢量等的属性 记述在这个地方
}
SubShader {
// 以下是本体记述
// - 表面着色器
// - 片段着色器或者顶点
// - 固定着色器
}
SubShader {
// 这个地方如果你的显卡比较旧 在这里运行 (简化版着色器)
}
}

Shader形式

下面是开始的时候 提取文件着色器 做的修改

Shader "Structure Example" {
Properties {
//显示在属性查看器里面的(文理或者颜色)
}
SubShader {
//着色器的顶点.
}
SubShader {
// 使用四个文理通道的着色器
}
SubShader {
// . 使用两个文理通道的着色器
}
SubShader {
// 要是不怎么好看也会执行的着色器
}
Fallback "Other Shader Name" // 如果前面都不行 在执行这个
}

顺便一提 当以斜杠分隔(“/”),就可以按类别划分。 比如:

在这里注意 有些电脑的GPU不支持固定的着色器!!!!
下面让我们来试一下简单的吧 搞起!

Shader "Solid Red" {
SubShader {
Pass { Color (1,0,0,0) }
}
}

通过预制板的命令可以指定颜色,固定着色器这个东西我也说不好。
这里为什么是红色呢,看inspector 片段着色器和顶点着色器变成了固定着色器, 因为代码中咱们命名为red了, 所以无论开不开unity灯都是红色的

来看下面的代码效果 注意 这里要把unity的灯光打开!!

Shader "VertexLit White" {
SubShader {
Pass {
Material {
Diffuse (1,1,1,1)
Ambient (1,1,1,1)
}
Lighting On
}
}
}

接下来 unity灯不要关 保持ON状态!!Material预制板中 Diffuse和Ambient 来设定。这两个东西 Diffuse是对象的基本颜色(扩散的颜色),Ambient 可以从Render Settings 里面改变, 环境光如果你不指定的话,他不会受影响。

让我们继续 在inspector里让设定颜色变为可能!

Shader "VertexLit Simple" {
Properties {
_Color ("Main Color", COLOR) = (1,1,1,1)
}
SubShader {
Pass {
Material {
Diffuse [_Color]
Ambient [_Color]
}
Lighting On
}
}
}

来吧让我们继续

Shader "VertexLit" {
Properties {
_Color ("Main Color", Color) = (1,1,1,0)
_SpecColor ("Spec Color", Color) = (1,1,1,1)
_Emission ("Emmisive Color", Color) = (0,0,0,0)
_Shininess ("Shininess", Range (0.01, 1)) = 0.7
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Pass {
Material {
Diffuse [_Color]
Ambient [_Color]
Shininess [_Shininess]
Specular [_SpecColor]
Emission [_Emission]
}
Lighting On
SeparateSpecular On
SetTexture [_MainTex] {
Combine texture * primary DOUBLE, texture * primary
}
}
}
}
看到这里,有了一些新的命令不需要全部记住。可能比较难,慢慢掌握。
可以这样做修改 看下面

Properties {
_RangeTest ("Range Test", Range (0.0, 1.0)) = 0.5
_FloatTest ("Float Test", Float) = 0.5
_ColorTest ("Color Test", Color) = (0.5, 0.5, 0.5, 0.5)
_VectorTest ("Vector Test", Vector) = (0.5, 0.5, 0.5)
_2DTest ("2D Test", 2D) = "white" {}
_RectTest ("Rect Test", Rect) = "white" {}
_CubeTest ("Cube Test", Cube) = "white" {}
}

固定着色器有点难,但是可以让许多颜色变为可能。需要写复杂的代码,比如渲染路径 和通道 ,我们来试试简单的。

Shader "Example/Diffuse Simple" {
Properties {
_MainColor("Color", Color) = (1,1,1)
}
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert
struct Input {
float4 color : COLOR;
};
float4 _MainColor;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = _MainColor.rgb;
}
ENDCG
}
Fallback "Diffuse"
}

很多新东西, 一个一个去看。首先,表面着色,最开始的pragma这个语句,表面着色器。看下面代码。
#pragma surface surfaceFunction lightModel [optionalparams]
「surfaceFunction」这个是一个相当于切入点
「lightModel」是嵌入照明
「optionalparams」这个是通过让alpha顶点变形时,要vertex等指定进行。

现在来看看这个函数的入口。

void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = _MainColor.rgb;
}

他作为一种形式。他可以Input输入,在SurfaceOutput里进行处理。
如果你什么也没写,他会变黑。
struct Input {
float4 color : COLOR;
};

Input可以来弄UV坐标 但不是说设置了变量。
SurfaceOutput可以设置反光。
struct SurfaceOutput {
half3 Albedo;
half3 Normal;
half3 Emission;
half Specular;
half Gloss;
half Alpha;
};

这里可以看见各种指定变化,比如Properties在被_MainColor的三元色照看着。你设定成红色就是红色,我们改良一下optionalparams 让颜色变得透明一点。
Shader "Example/Diffuse Simple" {
Properties {
_MainColor("Color", Color) = (1,1,1)
}
SubShader {
Tags { "RenderType" = "Transparent" }
CGPROGRAM
float4 _MainColor;
#pragma surface surf Lambert alpha
struct Input {
float4 color : COLOR;
};
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = _MainColor.rgb * half3(1, 0.5, 0.5);
o.Alpha = 0.5;
}
ENDCG
}
Fallback "Diffuse"
}

这里在pragma后面加了alpha,这个就是说他们可以混合,咱们刚刚写了0.5么。
下面我们来干点别的吧。
Shader "Example/Diffuse Texture" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
}
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
}
Fallback "Diffuse"
}

变成这样的原因呢,是因为UV坐标 在input里面添加了纹理坐标。 使用CG的内置函数的tex2D,因为他们看不到纹理的色彩坐标,所以。。。
然后,我们要输入法线地图和阴影装饰等内在函数。如果用什么样的代码写的话,来吧我们干点什么。
让我们变一下顶点
Shader "Example/Transform Vertex" {
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert vertex:vert
struct Input {
float4 color : COLOR;
};
void vert (inout appdata_full v) {
v.vertex.x += 0.2 * v.normal.x * sin(v.vertex.y * 3.14 * 16);
v.vertex.z += 0.2 * v.normal.z * sin(v.vertex.y * 3.14 * 16);
}
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = half3(1, 0.5, 0.5);
}
ENDCG
}
Fallback "Diffuse"
}

哈哈 有趣么

在Properties变量拉的话就能变形啦。但是,上述的例子。只是单纯的顶点位置移动而已,所以有奇怪的感觉。

作为固定着色器。我一直用SM2.0 意思是支持Shader Model2.0。” 2.0对应的GPU比较多。
这些比较。。额 灵活吧看下面
Shader "Custom/SolidColor" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float4 vert(float4 v:POSITION) : SV_POSITION {
return mul (UNITY_MATRIX_MVP, v);
}
fixed4 frag() : COLOR {
return fixed4(1.0,0.0,0.0,1.0);
}
ENDCG
}
}
}

在这次记述中,pragma的顶点 片段着色器 和顶点着色器 比较简单 vert顶点着色器,对所有的顶点坐标进行变化。在这里,参数中被给予的顶点坐标UNITY _ MATRIX _ MVP的嵌入式值的MVP矩阵 会在显示器在哪个位置进行计算的二维显示
FRAG是片段着色器,我们要会计算所有像素。看到刚刚的这里的顶点不透明的红色,是因为你还没有做光照计算,它已经成为完全的红色。

恩。。。。 VERT已被指定为接收类型为float4 但还是应该得到什么?它被指定为一种形式,位置。
额!我也理解的不好 看下表

Type(s)

Tag

Notes

float4

POSITION

该模型的局部坐标

float3

NORMAL

法线

float4

TEXCOORD0

UV坐标

float4

TEXCOORD1

第二个UV坐标

float4

TANGENT

切线

float4

COLOR

颜色

 

Type(s)

Tag

Description

float4

SV_POSITION

MVP 变换后的坐标

float3

NORMAL

MVP 变化后的法线

float4

TEXCOORD0

第一UV纹理坐标

float4

TEXCOORD1

第二UV纹理坐标

float4

TANGENT

切线

float4, fixed4

COLOR0

线性插值的颜色

float4, fixed4

COLOR1

线性插值的颜色(这个我也不知道)

Any

 

标签。没有什么值

来看下面
Shader "Custom/WindowCoordinates/Base" {
SubShader {
Pass {
CGPROGRAM

#pragma vertex vert
#pragma fragment frag
#pragma target 3.0

struct appdata_base {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};

float4 vert(appdata_base v) : POSITION {
return mul (UNITY_MATRIX_MVP, v.vertex);
}

fixed4 frag(float4 sp:WPOS) : COLOR {
fixed2 red_green = sp.xy / _ScreenParams.xy;
fixed blue = 0.0;
fixed alpha = 1.0f;
return fixed4(red_green, blue, alpha);
}

ENDCG
}
}
}

appdata _ base的构造体,其中vertex,normal,texcoord 这个3个东西,各自POSITION NORMAL,TEXCOORD 0的定义给予宣言。然后 ,你将使用的是作为一个参数传递给VERT这种情况。它也是现在使用的方式名为UnityCG.cginc 这个文件已被宣布为appdata_base,并将其列入。
Shader "Custom/WindowCoordinates/Base" {
SubShader {
Pass {
CGPROGRAM

#pragma vertex vert
#pragma fragment frag
#pragma target 3.0

#include "UnityCG.cginc"

float4 vert(appdata_base v) : POSITION {
return mul (UNITY_MATRIX_MVP, v.vertex);
}

fixed4 frag(float4 sp:WPOS) : COLOR {
fixed2 red_green = sp.xy / _ScreenParams.xy;
fixed blue = 0.0;
fixed alpha = 1.0f;
return fixed4(red_green, blue, alpha);
}

ENDCG
}
}
}

除了结构的各种辅助功能,appdata_base也是UnityCG.cginc准备的。
好了让我们再看看着色器的代码。

在屏幕中的片段着色器的坐标 是通过_ScreenParams.xy划分的值,屏幕左下角(0,0),右上(1,1)。

到这里 请给位检查一下 是否你们是着色器3.0的 咱们要配合用WPOS。。
return fixed4(fixed2(1.0), 0.0, 1.0);

用fixed2(1.0),改变(1.0,1.0),fixed4是一种形式展开,(1.0,1.0,0.0,1.0),这是黄色。

恩 ,我们要看到更广泛的UV坐标 使用在UnityCG.cginc定义顶点着色器的vert_img很方便,在v2f_img里去弄。
Shader "Custom/TextureCoordinates/UV" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag

#include "UnityCG.cginc"

float4 frag(v2f_img i) : COLOR {
return float4(i.uv, 0.0, 1.0);
}
ENDCG
}
}
}

现在一个面的颜色完整了。 现在我们让他变完整 使用Properties
Shader "Custom/TextureCoordinates/Hecomi" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag

#include "UnityCG.cginc"

uniform sampler2D _MainTex;

float4 frag(v2f_img i) : COLOR {
return tex2D(_MainTex, i.uv);
}
ENDCG
}
}
}

哎呀 呵呵
下面我给出几个列子 大家自己看看

第一个

Shader "Custom/Chou" {
Properties {
_BendScale("Bend Scale", Range(0.0, 1.0)) = 0.2
_MainTex("Main Texture", 2D) = "white" {}
}
SubShader {
Tags { "RenderType" = "Transparent" }
Cull Off Zwrite On
CGPROGRAM
#pragma surface surf Lambert alpha vertex:vert
#define PI 3.14159
struct Input {
float2 uv_MainTex;
float4 color : Color;
};
sampler2D _MainTex;
float _BendScale;
void vert (inout appdata_full v) {
float bend = sin(PI * _Time.x * 1000 / 45 + v.vertex.y);
float x = sin(v.texcoord.x * PI) - 1.0;
float y = sin(v.texcoord.y * PI) - 1.0;
v.vertex.y += _BendScale * bend * (x + y);
}
void surf (Input IN, inout SurfaceOutput o) {
float4 tex = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = IN.color.rgb;
o.Alpha = IN.color.a * tex.a;
}
ENDCG
}
Fallback "Diffuse"
}

第二个

Shader "Custom/Chou" {
Properties {
_BendScale("Bend Scale", Range(0.0, 1.0)) = 0.1
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Pass {
Blend SrcAlpha One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define PI 3.14159

#include "UnityCG.cginc"

uniform float _BendScale;
uniform sampler2D _MainTex;

struct v2f {
float4 position : SV_POSITION;
fixed4 color : COLOR;
float2 uv : TEXCOORD0;
};

v2f vert(appdata_full v) {
float bend = sin(PI * _Time.x * 1000 / 45 + v.vertex.y + v.vertex.x);
float x = sin(v.texcoord.x * PI) - 1.0;
float y = sin(v.texcoord.y * PI) - 1.0;
v.vertex.y += _BendScale * bend * (x + y);

v2f o;
o.position = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = MultiplyUV(UNITY_MATRIX_TEXTURE0, v.texcoord);
o.color = v.color;
return o;
}

fixed4 frag(v2f i) : COLOR {
fixed4 tex = tex2D(_MainTex, i.uv);
tex.rgb *= i.color.rgb;
tex.a *= i.color.a;
return tex;
}
ENDCG
}
}
}
好了就告一段落吧。

来源:泰科在线

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
UnityShader学习教程之<UsePass和#include>
边缘高光(附上代码)
UnityShader快速上手指南(一)
Unity Shader 基础教程
Unity Shader变量结构
Unity shader 官网文档全方位学习(一)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服