Unity中使用几何着色器制作类似于纪念碑谷的海(Unity几何着色器的一个例子)
2016-04-29 21:58
645 查看
前言
接触UNITY的shader这两年时间一直想写些关于纪念碑谷的东西,其实你完全可以用普通的顶点着色器加上片段着色器实现文中内容,今天稍稍借题发挥一下:1.关于几何着色器?
Input Assembler(IA)从顶点缓冲区上的输入流中接收顶点数据,并且把数据项转换为规范的格式。vertex shader通常用来把顶点从模型空间变换到平面空间,vertex shader读取一个顶点,输出一个顶点。Pixel Shader读取单一pixel属性,输出包含颜色和Z信息的的片断。而geometry shader是DirectX10提出的,把同一区域的所有顶点作为输入,产生新的顶点或者区域。此外数据流输出(steam output)把geometry shader输出的顶点信息复制为4个连续的输出缓冲子集。理论上来说,steamoutput的输出能力和Input Assembler的输入能力相匹配。
Shader就是一段可以改变像素、顶点和几何学特征的小程序。Vertex Shader是专门处理多边形顶点的。那么Geometry shader就是专门用来处理场景中的几何图形。在过去Vertex Shader每一次运行只能处理一个顶点的数据,并且每次只能输出一个顶点的结果。在整个游戏场景中,绘制的几何图形的任务量非常庞大,如果仅仅依靠 Vertex Shader单一来完成,效率会极其低下。
现在DX10的设计师们在顶点与像素的处理过程中又加入了(Geometry shader)几何着色器。它可以根据顶点的信息来批量处理几何图形,对Vertex附近的数据进行函数处理,快速创造出新的多边形。通过stream out将这些结果传递给其他Shader或buffer。
----几何着色器来源介绍
2.Unity3D下几何着色器实现的例子介绍
2.1 Properties的定义
Properties{
_FaceColor("Face Color",Color) = (1,1,1,1)//面向光源显示的颜色
_BackColor("Back Color",Color) = (1,1,1,1)//背向光源显示的颜色
_MaxTex("Main Texture",2D) = "white" {} //主贴图
_NormalMap("Normal Map",2D) = "bump"{}//控制海面挪动的发现图
_Hightness("Hightness",Float) = 4//调节海面的挪动高度
_TimeRate("Time Rate",Float) = 0.2//控制海面的挪动频率
}
2.2 着色器的定义
Tags{"RenderType" = "Opaque" "Queue" = "Gepmetry"}LOD 200
CGPROGRAM
# pragma 5.0
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
//定义顶点着色器
#pragma vertex vert
//定义片段着色器
#pragma fragment frag
//定义几何着色器
#pragma geometry geom
2.3 结构体的声明
struct a2v{
float4 vertex : POSITION;//模型顶点位置
float3 normal : NORMAL;//模型法线
float4 texcoord : TEXCOORD0;//输入的坐标纹理集
float4 tangent : TANGENT;//模型切线
}
struct v2g
{
float4 pos :POSITION;//顶点位置
float2 uv :TEXCOORD0;//坐标纹理集
float3 lightDir : TEXCOORD1;//光照方向
}
struct g2f
{
float4 pos : POSITION;//位置信息
float2 uv : TEXCOORD0;//坐标纹理集
float3 diffColor:TEXCOORD1;//输出颜色
}
2.4 顶点着色器
v2g vert(a2v v){
v2g output;
float d2 = tex2Dlod(_NormalMap,float4(v.texcoord.xy+_Time.xx*_TimeRate,0,0)).r;//海水根据时间抖动高度
output.pos = mul(UNITY_MATRIX_MVP,v.vertex) + float4(0,d2,0,0)*_Heightness;//平面顶点位置
output.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
float3 binormal = cross(v.normal,v.tangent.xyz);//副法线
float3x3 rotation = float3x3(v.tangent.xyz , binormal
, v.normal );//自身矩阵
output.lightDir = normalize(mul(UNITY_MATRIX_MVP,mul(rotation , ObjSpaceLightDir(v.vertex))));//光照方向
return output;
}
2.5 几何着色器
[maxvertexcount(3)]void geom (triangle v2g p[3] , inout TriangleStream<g2f> triStream)
{
//屏幕坐标的顶点位置
float3 p0 = p[0].pos.xyz;
float3 p1 = p[1].pos.xyz;
float3 p2 = p[2].pos.xyz;
//三角形三条边的矢量方向
float3 v0 = p2 - p1;
float3 v1 = p2 - p0;
float3 v2 = p1 - p0;
//计算三角形的法线
float3 trianglenormal = normalize(cross(v1,v2));
//计算三角形的光照方向
float3 triangleLightDir = normalize( p[ 0 ].lightDir
+ p[1].lightDir + p[2].lightDir);
float diff = max(dot(trianglenormal,triangleLightDir),0);
g2f pIn;
pIn.diffColor = lerp(_FaceColor,_BackColor,diff);
//输入第一个点
pIn.pos = p[0].pos;
pIn.uv = p[0].uv;
triStream.Append(pIn);
//输入第二个点
pIn.pos = p[1].pos;
pIn.uv = p[1].uv;
triStream.Append(pIn);
//输入第三个点
pIn.pos = p[2].pos;
pIn.uv = p[2].uv;
triStream.Append(pIn);
}
2.6 片段着色器
float4 frag(g2f input):COLOR{
float4 texColor = tex2D(_MainTex,input.uv);
return float4(input.diffColor,1) * texColor ;
}
2.7 总览
Shader "Citrus/Sea"{
Properties
{
_FaceColor("Face Color",Color) = (1,1,1,1)//面向光源显示的颜色
_BackColor("Back Color",Color) = (1,1,1,1)//背向光源显示的颜色
_MainTex("Main Texture",2D) = "white" {} //主贴图
_NormalMap("Normal Map",2D) = "bump"{}//控制海面挪动的发现图
_Hightness("Hightness",Float) = 1//调节海面的挪动高度
_TimeRate("Time Rate",Float) = 1//控制海面的挪动频率
}
SubShader
{
Pass
{
Tags{"RenderType" = "Opaque" "Queue" = "Gepmetry"}
LOD 200
CGPROGRAM
# pragma 5.0
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
//定义顶点着色器
#pragma vertex vert
//定义片段着色器
#pragma fragment frag
//定义几何着色器
#pragma geometry geom
struct a2v
{
float4 vertex : POSITION;//模型顶点位置
float3 normal : NORMAL;//模型法线
float4 texcoord : TEXCOORD0;//输入的坐标纹理集
float4 tangent : TANGENT;//模型切线
};
struct v2g
{
float4 pos :POSITION;//顶点位置
float2 uv :TEXCOORD0;//坐标纹理集
float3 lightDir : TEXCOORD1;//光照方向
};
struct g2f
{
float4 pos : POSITION;//位置信息
float2 uv : TEXCOORD0;//坐标纹理集
float3 diffColor:TEXCOORD1;//输出颜色
};
float4 _MainTex_ST;
sampler2D _MainTex;
float4 _NormalMap_ST;
sampler2D _NormalMap;
float _TimeRate;
float _Hightness;
fixed4 _FaceColor;
fixed4 _BackColor;
v2g vert(a2v v)
{
v2g output;
float d2 = tex2Dlod(_NormalMap,float4(v.texcoord.xy+_Time.xx*_TimeRate,0,0)).r;//海水根据时间抖动高度
output.pos = mul(UNITY_MATRIX_MVP,v.vertex) + float4(0,d2,0,0)*_Hightness;//平面顶点位置
output.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
float3 binormal = cross(v.normal,v.tangent.xyz) * v.tangent.w;//副法线
float3x3 rotation = float3x3(v.tangent.xyz , binormal , v.normal );//自身矩阵
output.lightDir = normalize(mul(UNITY_MATRIX_MVP,mul(rotation , ObjSpaceLightDir(v.vertex))));//光照方向
return output;
}
[maxvertexcount(3)]
void geom (triangle v2g p[3] , inout TriangleStream<g2f> triStream)
{
//屏幕坐标的顶点位置
float3 p0 = p[0].pos.xyz;
float3 p1 = p[1].pos.xyz;
float3 p2 = p[2].pos.xyz;
//三角形三条边的矢量方向
float3 v0 = p2 - p1;
float3 v1 = p2 - p0;
float3 v2 = p1 - p0;
//计算三角形的法线
float3 trianglenormal = normalize(cross(v1,v2));
//计算三角形的光照方向
float3 triangleLightDir = normalize( p[ 0 ].lightDir + p[1].lightDir
+ p[2].lightDir);
float diff = max(dot(trianglenormal,triangleLightDir),0);
g2f pIn;
pIn.diffColor = lerp(_FaceColor,_BackColor,diff);
//输入第一个点
pIn.pos = p[0].pos;
pIn.uv = p[0].uv;
triStream.Append(pIn);
//输入第二个点
pIn.pos = p[1].pos;
pIn.uv = p[1].uv;
triStream.Append(pIn);
//输入第三个点
pIn.pos = p[2].pos;
pIn.uv = p[2].uv;
triStream.Append(pIn);
}
float4 frag(g2f input):COLOR
{
float4 texColor = tex2D(_MainTex,input.uv);
return float4(input.diffColor,1) * texColor ;
}
ENDCG
}
}
}
相关文章推荐
- Unity5 更改鼠标样式
- 在Unity中StartCoroutine/yield return这个模式到底是怎么应用的?其中的原理是什么?
- unity, 查看.anim中的动画曲线(和帧)
- Unity3D NGUI刮刮卡效果
- 使用Unity3D 5.3.4 模仿2D游戏 FlappyBird(二)
- unity3d 实现残影特效
- unity3D 涂涂乐使用shader实现上色效果
- Unity5打包assetbundle
- Vuforia 在Unity 中失焦的问题
- 使用Unity3D 5.3.4 模仿2D游戏 FlappyBird(一)
- unity安装记录
- Unity 编辑器列表控件
- 在unity3d中用EasyTouch的操纵杆控制相对于不同角度的摄像机的第三人物视角的相对位移的代码段
- 简要分析unity3d中剪不断理还乱的yield
- 基于unity的飞行模拟设计
- unity发射弓箭轨迹的实现
- Shader之学习笔记三
- Unity3D 5.3.4的UGUI编程
- unity编译时自动结束项目运行
- unity渲染层级关系小结