Unity3D 海水多线程渲染算法实现

本文介绍了如何在Unity3D中实现逼真的海水渲染和船只航行轨迹,通过面片拼接和LOD优化提高效率。核心代码包括海水网格的生成、Shader实现、船只轨迹及海水起伏效果,以及多线程渲染优化。文章提供了一组实际渲染效果展示,并附带工程Demo链接。
摘要由CSDN通过智能技术生成

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。

CSDN视频网址:http://edu.csdn.net/lecturer/144

海水仿真渲染一直是比较困难的事情,虽然市面上有了各种海水的渲染算法,但是真正做到仿真渲染的少之又少。大多停留在试验阶段,达到了仿真的要求,但是硬件配置要求高,不利于推广。本篇博客给读者介绍的是关于海水的实施渲染以及通过算法实现船只航行轨迹效果,真实的达到了海水的渲染,海水的网格采用了多个面片网格拼接的方式,网格采用的是LOD处理的,这样就优化了效率。同时将海水的绘制以及算法实现放到C++中进行,这样对于复杂算法的实现效率明显提升。先给读者看几幅效果图:

船在海水中航行的轨迹效果图,轨迹是实时绘制的。再来一副海水到岸边产生的泡沫效果图:

除了岸边的效果图外,船在水中周围也会产生泡沫效果。最后一副效果图如下:

海水的反射折射效果。下面开始给读者介绍实现该海水的原理以及核心代码,最后把整个工程奉献给读者。

第一步:海水网格的实现,海水网格采用的是面片拼接的方式,并且面片采用了LOD运算,其在Unity中的效果如下所示:

从里向外,面片的数量逐步减少,它是根据摄像机的远近处理的,对应的核心代码如下所示:

 

	//update the meshes with the final calculated mesh data
	void updateTiles(int a, int b) {

		if(skipLods) {
			lodSkip++;
			if(lodSkip >= lodSkipFrames+1) lodSkip=0;
		}

		for (int L0D=a; L0D<b; L0D++) {
			//if(L0D>
			//this will skip one update of the tiles higher then Lod0
			if(L0D>0 && lodSkip==0 && !ticked && skipLods) { break; }
			//this will skip one update of the LOD0 tiles because they got updated earlier when they should.
			if(ticked2 && L0D==0) { ticked2=false; continue; }

			#if !NATIVE
				int den = MyIntPow (2, L0D);
				int idx = 0;

				for (int y=0; y<g_height; y+=den) {
					for (int x=0; x<g_width; x+=den) {
						int idx2 = g_width * y + x;
						verticesLOD[L0D] [idx] = vertices [idx2];
						//lower the far lods to eliminate gaps in the horizon when having big waves
						if(L0D>0) {
							if(farLodOffset!=0) {
								verticesLOD[L0D] [idx].y += flodoffset[L0D] * flodFact;
							}
						}
						tangentsLOD[L0D] [idx] = tangents [idx2];
						normalsLOD[L0D] [idx++] = normals [idx2];
					}			
				}
			#else
				uocean._updateTilesA(verticesLOD[L0D], vertices, tangentsLOD[L0D], tangents, normalsLOD[L0D], normals, L0D, farLodOffset, flodoffset, flodFact);
			#endif

			btiles_LOD[L0D].vertices = verticesLOD[L0D];
			btiles_LOD[L0D].normals = normalsLOD[L0D];
			btiles_LOD[L0D].tangents = tangentsLOD[L0D];
		}

		if(ticked) ticked = false;
	}
	
		
	void GenerateTiles() {

		int chDist, nmaxLod=0; // Chebychev distance
		
		for (int y=0; y<tiles; y++) {
			for (int x=0; x<tiles; x++) {
				chDist = System.Math.Max (System.Math.Abs (tiles / 2 - y), System.Math.Abs (tiles / 2 - x));
				chDist = chDist > 0 ? chDist - 1 : 0;
				if(nmaxLod<chDist) nmaxLod = chDist;
			}
		}
		max_LOD = nmaxLod+1;

		flodoffset = new float[max_LOD+1];
		float ffact = farLodOffset/max_LOD;
		for(int i=0; i<max_LOD+1; i++) {
			flodoffset[i] = i*ffact;
		}

		btiles_LOD = new List<Mesh>();
		tiles_LOD = new List<List<Mesh>>();

		for (int L0D=0; L0D<max_LOD; L0D++) {
			btiles_LOD.Add(new Mesh());
			tiles_LOD.Add (new List<Mesh>());
		}

		GameObject tile;

		int ntl = LayerMask.NameToLayer ("Water");

	
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海洋_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值