UnityShader学习笔记(八)利用镜面反射让游戏闪耀起来
2017-01-13 14:52
393 查看
大家好,我是Zander。 今天来说一下在游戏中如何使用镜面反射来给玩家制造出强烈的视觉冲击和超现实感。
在Unity中,已经为我们提供了一个高光函数,我们可以在自己的着色器中使用。这个函数也就是BlinnPhong镜面反射光照模型,它是高光类型中的俄译中更加基础且高效的形式。由于它已经集成到Unity着色器语言挡住,所以我们可以在Unity着色器中建立高光效果:
首先创建一个新的着色器SpecShader,添加属性代码
我们将BlinnPhong添加到#pragma语句后面:
然后修改我们的Surf()函数
运行Unity,就会看到如下图所示:
详细代码如下:
接下来我们来介绍一下Phong高光类型,Phong高光模型是最基础且表现最友好的高光类型。它会计算出光在物体表面的反射方向与观察者视线方向之间的对比结果。虽然在镜面反射的精确建模上它并不是最接近现实的,但在大多数情况下它都显得极其逼真。
接下来我们来实现一下Phong:
首先创建一个着色器PhongShader,第一步还是添加属性代码:
我们会看到Phong更加的自然光滑
全部代码如下:
所需要的图片:
效果如图:
好了,这一章就写到这,欢迎大家加入QQ群:280993838 。或者关注我的公众号:
在Unity中,已经为我们提供了一个高光函数,我们可以在自己的着色器中使用。这个函数也就是BlinnPhong镜面反射光照模型,它是高光类型中的俄译中更加基础且高效的形式。由于它已经集成到Unity着色器语言挡住,所以我们可以在Unity着色器中建立高光效果:
首先创建一个新的着色器SpecShader,添加属性代码
Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _MainTint("Diffuse Tint",Color) = (1,1,1,1) _SpecColor("Specular Color",Color) = (1,1,1,1) _SpecPower("Specular Power",Range(0,1)) = 0.5 }然后,我们在CGPROGRAM中添加相应的变量,这样我们才能在着色器的CGPROGRAM中使用属性中的数据,这里我们没有声明_SpecColor属性做变量,因为在内存的高光模型中Unity已经为我们声明了该变量:
sampler2D _MainTex; float4 _MainTint; float _SpecPower;
我们将BlinnPhong添加到#pragma语句后面:
#pragma surface surf BlinnPhong
然后修改我们的Surf()函数
void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint; o.Specular = _SpecPower; o.Gloss = 1.0; o.Albedo = c.rgb; o.Alpha = c.a; }
运行Unity,就会看到如下图所示:
详细代码如下:
Shader "Custom/SpecShader" {
Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _MainTint("Diffuse Tint",Color) = (1,1,1,1) _SpecColor("Specular Color",Color) = (1,1,1,1) _SpecPower("Specular Power",Range(0,1)) = 0.5 }
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf BlinnPhong
sampler2D _MainTex; float4 _MainTint; float _SpecPower;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint; o.Specular = _SpecPower; o.Gloss = 1.0; o.Albedo = c.rgb; o.Alpha = c.a; }
ENDCG
}
FallBack "Diffuse"
}
接下来我们来介绍一下Phong高光类型,Phong高光模型是最基础且表现最友好的高光类型。它会计算出光在物体表面的反射方向与观察者视线方向之间的对比结果。虽然在镜面反射的精确建模上它并不是最接近现实的,但在大多数情况下它都显得极其逼真。
接下来我们来实现一下Phong:
首先创建一个着色器PhongShader,第一步还是添加属性代码:
Properties { _MainTint ("Diffuse Tint", Color) = (1,1,1,1) _MainTex ("Base (RGB)", 2D) = "white" {} _SpecularColor ("Specular Color", Color) = (1,1,1,1) _SpecPower ("Specular Power", Range(0.1,30)) = 1 }在CGRPAGRAM中添加相应的变量
float4 _SpecularColor; sampler2D _MainTex; float4 _MainTint; float _SpecPower;现在我们添加自定义的光照模型,以便计算Phong高光
inline fixed4 LightingPhong (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten) { //Calculate diffuse and the reflection vector float diff = dot(s.Normal, lightDir); float3 reflectionVector = normalize((2.0 * s.Normal * diff) - lightDir); //Calculate the Phong specular float spec = pow(max(0,dot(reflectionVector, viewDir)), _SpecPower); float3 finalSpec = _SpecularColor.rgb * spec; //Create final color fixed4 c; c.rgb = (s.Albedo * _LightColor0.rgb * diff) + (_LightColor0.rgb * finalSpec); c.a = 1.0; return c; }因为我们使用了自定义的光照函数,所以我们要在#pragma语句进行修改:
#pragma surface surf Phong运行Unity ,和之前的镜面反射对比如图:
我们会看到Phong更加的自然光滑
全部代码如下:
Shader "Custom/PhongShader" {最后我们来实现一个金属软高光的效果:代码如下:
Properties
{
_MainTint ("Diffuse Tint", Color) = (1,1,1,1)
_MainTex ("Base (RGB)", 2D) = "white" {}
_SpecularColor ("Specular Color", Color) = (1,1,1,1)
_SpecPower ("Specular Power", Range(0.1,30)) = 1
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Phong
float4 _SpecularColor; sampler2D _MainTex; float4 _MainTint; float _SpecPower;
inline fixed4 LightingPhong (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
{
//Calculate diffuse and the reflection vector
float diff = dot(s.Normal, lightDir);
float3 reflectionVector = normalize((2.0 * s.Normal * diff) - lightDir); //这样做是为了实现法线朝向光源弯曲的效果
//Calculate the Phong specular
float spec = pow(max(0,dot(reflectionVector, viewDir)), _SpecPower);
float3 finalSpec = _SpecularColor.rgb * spec;
//Create final color
fixed4 c;
c.rgb = (s.Albedo * _LightColor0.rgb * diff) + (_LightColor0.rgb * finalSpec);
c.a = 1.0;
return c;
}
struct Input
{
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o)
{
half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
Shader "Custom/MetallicSoft" { Properties { _MainTint ("Diffuse Tint", Color) = (1,1,1,1) _MainTex ("Base (RGB)", 2D) = "white" {} _RoughnessTex ("Roughness texture", 2D) = "" {} _Roughness ("Roughness", Range(0,1)) = 0.5 _SpecularColor ("Specular Color", Color) = (1,1,1,1) _SpecPower ("Specular Power", Range(0,30)) = 2 _Fresnel ("Fresnel Value", Range(0,1.0)) = 0.05 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf MetallicSoft #pragma target 3.0 sampler2D _MainTex; sampler2D _RoughnessTex; float _Roughness; float _Fresnel; float _SpecPower; float4 _MainTint; float4 _SpecularColor; inline fixed4 LightingMetallicSoft (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten) { //Compute simple diffuse and view direction values float3 halfVector = normalize(lightDir + viewDir); float NdotL = saturate(dot(s.Normal, normalize(lightDir))); float NdotH_raw = dot(s.Normal, halfVector); float NdotH = saturate(dot(s.Normal, halfVector)); float NdotV = saturate(dot(s.Normal, normalize(viewDir))); float VdotH = saturate(dot(halfVector, normalize(viewDir))); //Micro facets distribution float geoEnum = 2.0*NdotH; float3 G1 = (geoEnum * NdotV)/NdotH; float3 G2 = (geoEnum * NdotL)/NdotH; float3 G = min(1.0f, min(G1, G2)); //Sample our Spceular look up BRDF float roughness = tex2D(_RoughnessTex, float2(NdotH_raw * 0.5 + 0.5, _Roughness)).r; //Create our custom fresnel value float fresnel = pow(1.0-VdotH, 5.0); fresnel *= (1.0 - _Fresnel); fresnel += _Fresnel; //Create the final spec float3 spec = float3(fresnel * G * roughness * roughness) * _SpecPower; float4 c; c.rgb = (s.Albedo * _LightColor0.rgb * NdotL)+ (spec * _SpecularColor.rgb) * (atten * 2.0f); c.a = s.Alpha; return c; } struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint; o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }
所需要的图片:
效果如图:
好了,这一章就写到这,欢迎大家加入QQ群:280993838 。或者关注我的公众号:
相关文章推荐
- 利用镜面反射让游戏闪耀起来 - 利用Unity3D内置的高光模型
- 利用镜面反射让游戏闪耀起来 - 创建Phong高光类型
- 利用镜面反射让游戏闪耀起来 - 金属与软高光
- 利用镜面反射让游戏闪耀起来 - 使用贴图对模型的高光进行遮罩
- 利用镜面反射让游戏闪耀起来 - 创建各向异性高光类型
- 游戏安全资讯精选 2018年第八期:3975款游戏被查处,游戏圈重击;Memcached被利用UDP反射攻击漏洞预警;VentureBeat称区块链或可定位和消除恶意可执行代码的安全问题
- 利用反射和标签自动解析游戏配置
- 利用反射将一个对象的值转存到另一对象
- 利用反射调用方法抛出的异常如何被捕获?
- 利用java反射原理给实体类注值
- 一个在java运行时利用反射动态调用方法的例子
- 三层架构之数据访问层,利用反射返回IList泛型集合
- Java多态(利用向上向下转型和反射机理)
- 利用easy_install 工作效率提升起来
- 关于利用反射调用程序集中的函数属性的代码
- 利用java的反射原理实现数据注入功能
- 利用java的反射机制调用类的私有方法及私有属性
- Android利用泛型和反射来实现对数据库的操作--SqlHelper
- [Torque社区活动] 我们TORQUE社区将开始利用TORQUE引擎开发我们的第一个范例游戏[坦克],欢迎参加
- 利用反射得出某个类的所有属性