Unity渲染(二):图片渲染
通过这里,你会学习到怎么将一张图片渲染到UI的Image组件或者SpriteRenderer上,以及透明物体的渲染。
上一章:Unity渲染(一):着色器基础入门之纯色Shader
开发环境:Unity5.0或者更高
概述
1. Shader获取Image或者SpriteRenderer组件上的sprite
2. 图像采样
3. 透明物体渲染
1.1 开始
- 创建场景并取名为Image并在场景中添加
Camera
与Image
和2D Sprite Square
- 创建
Material
和Shader
并在删除Shader中自带的代码写下如下代码
代码解释:Unity渲染(一):着色器基础入门之纯色Shader
Shader "Toturial/Image"
{
Properties
{
_MainTex("MainTex",2D) = "white"{}
_Color("Color",Color) = (1,1,1,1)
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
fixed4 _Color;
struct a2v
{
float4 vertex : POSITION;
fixed4 color : COLOR;
};
struct v2f
{
float4 pos : SV_POSITION;
fixed4 color : COLOR;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.color = v.color;
return o;
}
fixed4 frag(v2f i) : SV_TARGET
{
return _Color;
}
ENDCG
}
}
}
- 将材质给Image与SpriteRenderer 赋值
- 将以下两张图给Image和SpriteRenderer设置
因为Shader最终返回白色所以 效果下图
接下来我们修改代码让图像显示出来。
1.2 图像采样
首先我们在CGPROGRAM ... ENDCG
中定义一个Sampler2D 类型的变量_MainTex
用于获取Properties中的属性_MainTex
,两者名称需要相同,这是Unity规定的,Properties类型与CGPROGRAM类型对应关系如下
Properties | CGPROGRAM |
---|---|
Color | float4、half4、fixed4 |
Range、Float | float、half、fixed |
2D | sampler2D |
3D | sampler3D |
Cube | samplerCube |
在struct a2v 上方添加如下代码:
...
sampler2D _MainTex;
...
接下来我们需要获取这个sampler2D上的每个像素颜色,最终从片元着色器输出,是怎么做到这步的呢?
首先我们需要获取到这张图像的UV,然后使用这个UV坐标对这个sampler2D 进行采样查询每个点的颜色最终输出。
上面这个过程我们可以使用tex2D(_MainTex,UV)
函数来达到我们的目的
UV
:可以理解为这张图像的每个像素点在屏幕上的坐标
- 我们在a2v结构体中添加
float2 uv : TEXCOORD0;
用于获取Properties定义的第一个sampler2D的坐标,
...
struct a2v
{
float4 vertex : POSITION;
fixed4 color : COLOR;
float2 uv : TEXCOORD0;
};
...
- 在 v2f结构体中添加
float2 uv : TEXCOORD0;
用于在顶点着色器将uv传递到片元着色器使用
...
struct v2f
{
float4 pos : SV_POSITION;
fixed4 color : COLOR;
float2 uv : TEXCOORD0;
};
...
- 在vert函数中为v2f赋值,添加代码
...
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.color = v.color;
o.uv = v.uv;
return o;
}
...
- 修改frag函数的返回值为
tex2D(_MainTex,i.uv);
...
fixed4 frag(v2f i) : SV_TARGET
{
return tex2D(_MainTex,i.uv);
}
...
回到Unity发现第二张有透明部分的图片出现了异常
1.3 透明物体渲染
首先我们先让图片正常渲染,在Pass中添加如下代码
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
...
回到Unity 看到结果已经正常了
代码说明
Shader混合模式:
Blend SrcAlpha OneMinusSrcAlpha
,用于将当前要渲染的颜色(挂上此Shader的物体)与已经渲染的颜色(叫背景或者叫颜色缓冲区)进行混合,最终输出到屏幕上
当要渲染的物体的像素是不透明时,alpha值取要渲染的物体的alpha
当要渲染的物体的像素时全透明时,alpha值取颜色缓冲区的颜色的alpha
当要渲染的物体的像素时半透明时,alpha值取要渲染的物体的alpha,颜色取
缓冲区颜色*要渲染的物体alpha +要渲染的物体颜色*(1-要渲染物体的alpha )
例如有一个半透明红色的点Color(1,0,0,0.8),背景为不透明的蓝色Color(0,0,1,1)
则最终颜色=(1,0,0) 0.8 +(0,0,1)(1 - 0.8) = (0.8,0,0.2)
1.4 完整代码
Shader "Toturial/Image"
{
Properties
{
_MainTex("MainTex",2D) = "white"{}
_Color("Color",Color) = (1,1,1,1)
}
SubShader
{
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
fixed4 _Color;
sampler2D _MainTex;
struct a2v
{
float4 vertex : POSITION;
fixed4 color : COLOR;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
fixed4 color : COLOR;
float2 uv : TEXCOORD0;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.color = v.color;
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_TARGET
{
return tex2D(_MainTex,i.uv);
}
ENDCG
}
}
}