版本:unity 5.4.1 语言:C#
在上节博文实现后,我添加了一些场景的元素,海水的效果大概是这个样子的:
接下来的目标是实现海水的折射和反射,书中使用的Unity应该是4.x时代的,Unity自带基础包是5.x的,然后我再在网上看了一个例子,看了下来基本原理都差不多。
还记得移动端简单阴影的实现吧,对,就是添加一个相机把照到的玩家传给Shader后,显示在地上,原理是一样的。
首先获取到玩家的相机,新建相机到玩家当前相机,经过一个反射矩阵的旋转后,截取海平面以上的渲染,然后再将渲染出来的Texture传递给Shader处理;折射更加简单,不用矩阵旋转,当前位置的海平面以下渲染出Texture,再传递给Shader。
下面是代码,生成Mesh的代码,我就去掉了:
public class Ocean : MonoBehaviour
{
// 一片区域网格横纵数量
public int width = 32;
public int height = 32;
int g_height; // 组成网格横纵的线条数量
int g_width;
Vector2 sizeInv;
// 区域的数量和大小
public int tiles = 2;
public Vector3 size = new Vector3(150f, 1f, 150f);
// 材质
public Material material;
public Shader oceanShader;
public Transform player;
public Transform sun;
public Vector4 SunDir;
// 网格相关
Vector3[] vertices; //顶点
Vector3[] normals; //法线
Vector4[] tangents; //三角
Mesh baseMesh;
// LOD,越在靠后List的Mesh,网格越少
int maxLOD = 4;
List<List<Mesh>> tiles_LOD;
// 折射反射相关
public bool renderReflection = true; //是否启用反射折射
public int renderTexWidth = 128;
public int renderTexHeight = 128;
RenderTexture reflectionTexture = null;
RenderTexture refractionTexture = null;
Camera offscreenCam = null;
bool reflectionRefractionEnabled = false; //是否初始化完成
// Use this for initialization
void Start()
{
// 折射反射
sizeInv = new Vector2(1f / size.x, 1f / size.z);
SetupOffscreenRendering(); // 添加离屏相机
if (!renderReflection)
EnableReflection(false);
else
EnableReflection(true);
// 计算线条数量
g_height = height + 1;
g_width = width + 1;
// LOD,Mesh所在的List的LOD List编号越小,Mesh的网格越多
tiles_LOD = new List<List<Mesh>>();
for (int LOD = 0; LOD < maxLOD; LOD++)
{
tiles_LOD.Add(new List<Mesh>());
}
for (int y = 0; y < tiles; ++y)
{
for (int x = 0; x < tiles