【Reading Notes】CP5-Vertex Functions (着色器顶点处理)
来源:互联网 发布:淘宝商品数据包下载 编辑:程序博客网 时间:2024/05/21 09:35
写在前面
Shader主要是用来模拟3D对象光照的真实情况,但不仅仅如此,他不仅仅定义了Objects看起来怎么样,还可以完全的重定义Objects的形状。
在这一章节,将学到:
+ 在Surface Shader访问顶点颜色
+ 在Surface Shader实现顶点动画
+ 挤压使模型变形
+ 实现雪
+ 实现体积爆炸效果
简介
在第一章节,创建了第一个shader,解释了3D模型不仅仅是三角面片的集合体。每个顶点还会包含一些额外的数据,为了更好的渲染他自己。这里将探索怎么去访问这下数据,并且在我们shader中使用。
通过Surface Shader访问顶点颜色
首先需要知道的是,一个顶点函数可以返回关于顶点自身的信息,并且是我们可以控制的。我们可以接收到顶点的法向量(一个float3值),顶点的位置(float3),你还可以往里面存储颜色(float4)。这里将展示如何去保存顶点颜色,以及如果利用顶点颜色。
我们需要定义vert函数的返回结构
struct Input
{
float2 uv_MainTex;
float2 vertColor;
}从输入中获取顶点颜色,并返回
struct appdata_full {
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;
float4 texcoord2 : TEXCOORD2;
float4 texcoord3 : TEXCOORD3;
fixed4 color : COLOR;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
上面是Unity内置定义的完整顶点结构,我们将从color字段获取倒顶点颜色,所以顶点函数大概长这个样子
void vert(inout appdata_full v, out Input o){ o.verColor = v.color;}
- 在Surface中使用
最后在surf中对颜色进行最终的处理已达到我们想要的效果
void surf(Input IN, inout SurfaceOutput o){ o.Albedo = IN.vertColor.rgb * _MainTint.rgb; //简单的和主颜色叠加}
更多
我们还可以使用vert color的第四个字段,因为我们定义的结构是一个float4类型的值。这意味着我们可以传递顶点的Alpha。你可以利用这个字段去优化对象的显示,实际上第四个字段的意义可以完全由开发者自己去控制,例如Alpha,添加透明,提供一个掩码去做纹理混合。
在Unity5中,可以使用DirectX11去编译我们的shader,但有一点瑕疵是Unity将不会给你任何提醒,即使是你的shader不能通过编译。仅仅需要在vert中添加一行代码:
void vert(inout appdata_full v, out Input o){ UNITY_INITALIZE_OUTPUT(Input, o); o.vertColor = v.color;}
使顶点运动起来(Surface Shader)
在这里,着色器程序修改了mesh顶点的y值,通过CG内置的sin函数去模拟波浪的效果。通过Unity内置变量_Time去产生变化
Shader "CookbookShaders/self/vertexAni" { Properties { _MainTex("Base (RGB)", 2D) = "white"{} _tintAmount("Tint Amount", Range(0,1)) = 0.5 _ColorA("ColorA", Color) = (1, 1, 1, 1) _ColorB("ColorB", Color) = (1, 1, 1, 1) _Speed("Wave speed", Range(0.1, 80)) = 5 _Frequency("Wave Frequency", Range(0, 5)) = 2 _Amplitude("Wave Amplitude", Range(-1, 1)) = 1 } SubShader { Tags {"RenderType" = "Opaque"} LOD 200 CGPROGRAM #pragma surface surf Lambert vertex:vert sampler2D _MainTex; float4 _ColorA; float4 _ColorB; float _tintAmount; float _Speed; float _Frequency; float _Amplitude; float _OffsetVal; struct Input { float2 uv_MainTex; float3 vertColor; }; void vert(inout appdata_full v, out Input o) { float time = _Time * _Speed; float waveValueA = sin(time + v.vertex.x * _Frequency) * _Amplitude; v.vertex.xyz = float3(v.vertex.x, v.vertex.y + waveValueA, v.vertex.z); o.vertColor = float3(waveValueA, waveValueA, waveValueA); o.uv_MainTex = v.texcoord; } void surf(Input IN, inout SurfaceOutput o) { half4 c = tex2D(_MainTex, IN.uv_MainTex); float3 tintColor = lerp(_ColorA, _ColorB, IN.vertColor).rgb; o.Albedo = c.rgb * (tintColor * _tintAmount); o.Alpha = c.a; } ENDCG } FallBack "Diffuse"}
Extruding(挤压?修改?)你的模型
在游戏制作的过程中,一个很大的问题是重复性,重复的创建内容是很消耗时间,例如想像你面对成千上万的敌人,他们都将长都一个样子。这里介绍一个以比较低的代价是的你的模型有不同的表现,通过shader去修改模型的几何数据,称作Normal extrusion。可以创建胖乎乎和瘦莽莽的模型。
主要思想是使得模型沿我们想要的方向变型。在这里的Shader中,我们沿模型的法线方向变化顶点的位置
void vert(inout appdata_full v){ float3 N = normalize(v.normal); v.vertex.xyz += N * _Amount;}
想要对形变达到更过的控制,可以添加一个包含形变方向的Extrusion map 控制那些位置往外变化,那些往里变化,要注意的是texture里面存储的数据时候(0,1)范围的,需要把他转化为(-1, 1)
sampler2D _ExtrusionTex;void vert(inout appdata_full v) {float4 tex = tex2Dlod (_ExtrusionTex, float4(v.texcoord.xy,0,0)); float extrusion = tex.r * 2 - 1; v.vertex.xyz += v.normal * _Amount * extrusion;}
雪,模型表面
雪的模拟游戏中也是个挑战,大量的游戏都是简单的使用雪的纹理贴图。这一小节将介绍如果达到雪的效果,而仅仅使用shander(不过是十分简单的版本,随便找个模型来试验,发现效果不好,需要对不同的模型做更多的调整)
实现体积爆炸
游戏艺术需要在真实效果和效率之间做聪明的取舍,这对于场景的爆炸效果也是一样。爆炸出现在很多游戏的核心部分,而且爆炸的物理模拟常常超出了当代计算机的运算能力。很多游戏使用粒子特效去做这类的效果,当爆炸发生的时候需要实例化很多火焰,烟雾等等粒子来达到效果,不幸的是这并没有显得很真实并且常常伴有斑点。本小节将介绍一个技术,可以达到更真实的效果:Volumetric explosions(体积爆炸),直接展开3D对象,而不是使用2D纹理去模拟。
着色器的核心是通过使用噪声贴图(Perlin noise)来改变3D对象的顶点,使用sin函数在控制时间维度的变化。
第二部分,在surf函数中使用Nosetex来随机一个颜色。并对颜色进行裁剪,RampTex是一个颜色的渐变贴图
Shader "CookbookShaders/self/explosion" { Properties { _RampTex("Color Ramp", 2D) = "white"{} _RampOffset("Ramp offset", Range(-0.5, 0.5)) = 0 _NoiseTex("Noise Tex", 2D) = "gray" {} _Period("Period", Range(0, 1)) = 0.5 _Amount("_Amount", Range(0, 1.0)) = 0.1 _ClipRange("ClipRange", Range(0, 1)) = 1 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Lambert vertex:vert nolightmap // Use shader model 3.0 target, to get nicer looking lighting //#pragma target 3.0 sampler2D _RampTex; half _RampOffset; sampler2D _NoiseTex; float _Period; half _Amount; half _ClipRange; struct Input { float2 uv_NoiseTex; }; void vert(inout appdata_full v) { float3 disp = tex2Dlod(_NoiseTex, float4(v.texcoord.xy, 0, 0)); float time = sin(_Time[3] * _Period + disp.r * 10); v.vertex.xyz += normalize(v.normal) * disp.r * _Amount * time; } void surf (Input IN, inout SurfaceOutput o) { float3 noise = tex2D(_NoiseTex, IN.uv_NoiseTex); float n = saturate(noise.r + _RampOffset); clip(_ClipRange - n); half4 c = tex2D(_RampTex, float2(n, 0.5)); o.Albedo = c.rgb; o.Emission = c.rgb * c.a; } ENDCG } FallBack "Diffuse"}
- 【Reading Notes】CP5-Vertex Functions (着色器顶点处理)
- 顶点着色器(vertex shader)
- 顶点着色器详解 (Vertex Shaders)
- unity shader 可编程管线(二) 顶点和片段着色器(Vertex Shader and Fragmet Shader)
- OpenGL ES 2.0——顶点着色器Vertex Shader
- OpenGL ES 2.0——顶点着色器Vertex Shader
- 2.1.3 Debugging of Shaders (about vertex input parameters) 着色器的调试(关于顶点输入参数)
- 顶点着色器(1)
- Unity Shader 顶点和片段着色器(Vertex and Fragment Shader)
- Shader(顶点片段着色器)
- 顶点着色器入门
- HLSL顶点着色器
- 顶点、片段着色器
- 顶点,片段着色器
- opengl顶点着色器
- OGLES顶点着色器
- Shader山下(十四)顶点片段着色器处理光照
- opengl顶点数据传送和着色器处理(vao,vbo)
- 磁盘加密,磁盘阵列,lvm
- RuntimeException
- 机器学习概述
- Classifying ImageNet: the instant Caffe way
- oracle数据库中的函数和对应的表关系
- 【Reading Notes】CP5-Vertex Functions (着色器顶点处理)
- 常见类---Integer类
- UVA-11059 Maximum Product
- UVALive7045 Last Defence(GCD思想)
- LightOJ
- 数据库中表的检索和排序
- 【POJ 3159】Candies
- Java支付宝支付集锦
- Opencv距离变换distanceTransform应用