文章目录
- Fresnel
- shader forge实现
- UE4蓝图实现
- Matcap
- shader forge实现
- UE4蓝图实现
- CubeMap
- SD和PS制作所需的贴图
- shader forge实现
- unity代码实现
- UE4蓝图实现(未实现)
Fresnel
shader forge实现
- 个人理解是,使用观察方向和法向方向点乘,那就相当于我们的视线看到哪里,哪里就是亮的,相当于头顶探照灯了。
- 但是菲尼尔效果则是观察方向和法线方向离得越近,折射或者反射效果越弱;而如果观察方向和法线方向越接近90°时,反射的效果就越强。所以我们采用onemiuns(用1减去观察方向和法线方向的点乘),就能取得我们想要的效果。
- 最后再使用power函数来增强这个菲涅尔的强度。
UE4蓝图实现
然后是ue4中的fresnel效果的实现,跟shader forge的节点差不多:
- ue4中对应于shader forge中使用的法线方向的节点是PixelNormalWS,而不是VertexNormalWS这点需要注意。
- 和unity中不同的时我们的观察方向需要通过摄像机方向取反来得到,因为shader forge的观察方向是从着色点为起点发射到相机的位置。这与ue4中的相机方向刚好相反。
Matcap
具体请参考毛星云大佬的blog
不像一般的Shader,需要提供光照,需要在Shader代码中进行漫长的演算,基于MatCap思想的Shader相当于MatCap贴图就把光照结果应该是怎样的标准答案告知Shader,我们只用在试卷下写出答案,进行一些加工即可。
需要注意,MatCap Shader有一定的局限性。因为从某种意义上来说,基于MatCap的Shader,就是某种固定光照条件下,从某个特定方向,特定角度的光照表现结果。
正是因为是选择的固定的MatCap贴图,得到相对固定的整体光照表现,若单单仅使用MatCap,就仅适用于摄像机不调整角度的情形,并不适合摄像机会频繁旋转,调节角度的情形。但我们可以在某些Shader中,用MatCap配合与光照交互的其他属性,如将MatCap结合一个作为光照反射的颜色指导的Reflection
Cube Map,就有了与光照之间的交互表现。这样,就可以适当弥补MatCap太过单一整体光照表现的短板。
shader forge实现
unity中的效果:
UE4蓝图实现
ue4中的效果:
- ue和unity的亮度不一样啊…只能手动调参了,这里学习为主,暂时就不折腾这个了。
CubeMap
这个东西其实很多地方都讲过,如果感兴趣可以看看:
- games202的Precomputed Radiance Transfer的课
- 或者直接参考LearnOpenGl中IBL章节
- 庄老师PPT主要是讲了以反射形式为主的环境映射:
- 也就是我们要求的是那根绿线R。
SD和PS制作所需的贴图
下面说一下怎么用ps处理cubemap需要的贴图:
首先找到一张全景图,类似于这样的:
- 具体可以上subtance designer里面找3D View里的全景图,打开其中一个的文件夹,然后直接拖到ps里面:
- 拖进ps里后选择作为alpha通道:
- 选择:
- 调整图像大小:
- 然后设置图像模式,默认参数确认就行,这一步是为了将图片的亮度高于1和暗度低于0的部分限制在0到1范围内:
然后导出为tga格式:
- 导入到unity中,红色的需要调整,绿色的自己选择调不调整:
- 调整完应用之后就是下面这个样子,一个材质球:
shader forge实现
-
然后放下课程上的实现:
-
unity中自己的实现:
-
因为我们要得到的是视线看过去与法线形成的反射方向,所以需要获取到观察方向的反方向。
-
感兴趣的可以去了解下reflect函数的实现。
-
和课程上的实现图相比多了AO,也就是环境光遮蔽贴图的部分。
unity的效果图:
unity代码实现
Shader "shader forge/L9_CubeMap2"
{
Properties
{
_normalmap ("normal map", 2D) = "bump" {}
_cubeMap ("cubeMap", Cube) = "_Skybox" {}
_AOTex ("AO Texture",2D) = "White" {}
_n1 ("n1", Float ) = -1
_MipMap_Level ("MipMap_Level", Range(0, 7)) = 0
_fresnel_exp ("fresnel_exp", Range(0, 10)) = 1
_EnvSpecInt ("EnvSpecInt", Range(0, 5)) = 1
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv0 : TEXCOORD0;
float4 tangent : TANGENT;
float3 normal : NORMAL;
};
struct v2f
{
float2 uv0 : TEXCOORD0;
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD1;
float3 nDirWS : TEXCOORD2;
float3 tDirWS : TEXCOORD3;
float3 biDirWS : TEXCOORD4;
};
uniform sampler2D _normalmap;
uniform samplerCUBE _cubeMap;
uniform sampler2D _AOTex;
uniform float _n1;
uniform float _MipMap_Level;
uniform float _fresnel_exp;
uniform float _EnvSpecInt;
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv0 = v.uv0;
o.nDirWS = UnityObjectToWorldNormal(v.normal);
o.tDirWS = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz,0.0)).xyz);
o.biDirWS = normalize(cross(o.nDirWS,o.tDirWS) * v.tangent.w);
o.posWorld = mul(unity_ObjectToWorld, v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//贴图采样
float3 nDirTS = UnpackNormal(tex2D(_normalmap,i.uv0)).rgb;
float AO_R = tex2D(_AOTex,i.uv0);
//向量准备
float3x3 TBN_Matrix = float3x3(i.tDirWS,i.biDirWS,i.nDirWS);
float3 nDirWS_FT = normalize(mul(nDirTS,TBN_Matrix));
float3 nDirVS_FT = normalize(mul(UNITY_MATRIX_V,float4(nDirWS_FT,0.0)).xyz);
float3 vDirWS = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
float3 vrDirWS = normalize(reflect(-vDirWS,nDirWS_FT));
//中间量准备
fresnel
float NoV = max(0.0,dot(nDirWS_FT,vDirWS));
float OneMinusNoV = 1 - NoV;
float fresnel = pow(OneMinusNoV,_fresnel_exp);
cubemap
float3 cubemap_uv = vrDirWS;
float3 cubemap_color = texCUBElod(_cubeMap,float4(cubemap_uv,_MipMap_Level));
//光照模型
float3 finalColor = cubemap_color * fresnel;
float3 EnvSpecLighting = finalColor * _EnvSpecInt * AO_R;
//后处理
//最后返回值
return float4(EnvSpecLighting,1.0);
}
ENDCG
}
}
}
UE4蓝图实现(未实现)
额,虽然还想在ue4中实现一编,但是ue4的cubemap好像是直接用来制作天空盒的,跟本节课只是单纯作为贴图参与材质的编辑不一样,当然也有可能是我自己原因没有搜到相关教程,如果有大佬知道也可以在评论区告诉我一声。
如果对制作ue4的cubemap有兴趣的话也可移步至:
- Unreal Engine UE4虚幻引擎,生成Cubemap(HDR高动态范围贴图)
- UE4笔记:引擎内部制作cubemap步骤
- UE4_SkyLight立方体贴图的创建与应用