unity中实现地球与大气层的特效渲染(非物理向)

这篇具有很好参考价值的文章主要介绍了unity中实现地球与大气层的特效渲染(非物理向)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

       在很多太空科幻类的电影、游戏中、我们常常看到在太空中的星球的场景,在这些场景中我们可以看到真实的行星地表光影效果和云层、以及非常炫酷的大气层效果。在unity中我们也可以创建类似的效果。本文我将介绍如何在unity shader中编写地球特效渲染。

unity中实现地球与大气层的特效渲染(非物理向)

unity中实现地球与大气层的特效渲染(非物理向)

 

上图是最终的效果。实现这样的效果可以使用基于物理的大气渲染或体素渲染(详见【Unity/大气渲染】单次散射的原理和简单实现 - Relolihentai - 博客园 (cnblogs.com))。在本文我主要介绍通过特效的形式实现地球渲染,并非基于物理的大气渲染。以下是我的思路。

主要的思路是:对效果进行分层。我们使用三个同心球来渲染地球,从里到外分别是地表、云层、大气层。以下将分别描述。

1、 地表

地表的渲染其实没有太多特别之处。主体部分直接用标准冯氏光照模型,如果能够获取到高清的地表金属度和粗糙度贴图的话也也可以用PBR来达到更真实的效果(不过地球哪来的PBR贴图啊),在一些影视级别的制作中,为了追求真实性,甚至可以使用高度贴图而非法线贴图来真实模拟出地表的凹凸效果,并且将海水与大陆分离来获取更加真实的水体渲染,不过这都不是本文的重点。

我们直接将三张贴图:表面颜色贴图、表面法线贴图和陆地-海洋贴图传递给shader,其中陆地-海洋图主要用于区分不同地区的高光强度的区别。

现在的效果如下:

unity中实现地球与大气层的特效渲染(非物理向)

 

接下来,我们可以加入一个地球的标志性的夜晚灯光的特效。在冯氏光照漫反射项的计算的过程中,我们计算了光源方向与法线方向的点积。夜晚地球暗面的灯光的强度可以视为反向平行光的光照强度。因此直接用1减去点积,即可以得到初步的一个值。将这叠加上去,效果如下:

unity中实现地球与大气层的特效渲染(非物理向)

 

然后我们开始制作云层。

2、 云层

云层我们使用球体+透明度剔除的方案来制作。给一张云层贴图即可,将灰度直接映射到剔除检测值上,就可以完成一个最基础的云层,同时也使用最基础的冯氏光照。

补充说明:为了增强真实性,可以在地球表面上通过贴图的方式显示云层阴影(因为云层和地表是同心球的方式,所以无法正常投影)。在地表shader中新建一个外部变量,将云层的旋转量传入shader,通过云层的旋转量来偏移uv坐标,采样云层贴图,通过云层密度来控制阴影浓度。以上思路所得的结果如下图

unity中实现地球与大气层的特效渲染(非物理向)

 

3、 大气层

大气层是三者之中最复杂的。我们虽然不使用完全基于物理的大气渲染方法,但是我们也可以通过简化的运算来模仿大气投射的效果。

首先假设地面是一个平面,当摄像机在太空中俯瞰地表一点时,光所在大气层中穿过的距离等于大气层厚度除以观察角的正弦值,即

\(l=\frac{h}{\sinα}\)

示意图如下:

unity中实现地球与大气层的特效渲染(非物理向)

 

由此图容易知道,当我们假设大气不存在散射,并且消光效应对于各个波长的光线是均匀分布的话,那么可以知道:假设垂直向下看时的“浓度”为f,那么对于观察角度为α时,“大气浓度”为

\(\frac{f}{\sinα}\)

那么我们就将这个式子拿到球形的地球-大气层模型中套用即可。我们可以通过地球球心坐标和大气与地球半径来计算某一片元处的光在大气中穿过的距离。示意图如下:

unity中实现地球与大气层的特效渲染(非物理向)

 

最终计算得到大气的浓度是f*r/l*sinalpha. 其中f是单位距离上大气的浓度值,r是地球半径,l是地球到球心的距离,α是大气表面该点到摄像机的向量和地球球心到摄像机的向量的夹角。

注意,我们不仅需要考虑穿过大气看到地表的情况,也应该考虑穿过大气看到外太空的情况,所以此处应该分情况讨论。

这一部分的代码如下所示:

                    // 大气
                    // 
                    // 当透过大气能看到地面时
                    // α是球心到摄像机向量与片元到摄像机向量的夹角
                    // l是摄像机到球心的距离
                    // r是地球半径
                    // F是大气雾系数(垂直看向地面时雾的强度/单位积分值)
                    // 计算公式是 (F*r)/(l*sinα)
                    //
                    // 当透过大气无法看到地面时
                    // 类似

                    float3 center = mul(unity_ObjectToWorld , float4(0,0,0,1)).xyz;// 球心
                    float3 centerDir = normalize(center.xyz - _WorldSpaceCameraPos.xyz);// 摄像机指向球心的方向
                    float3 fragDir = -normalize(UnityWorldSpaceViewDir(i.worldPos)); // 摄像机指向片元的方向
                    float cosalpha = abs(dot(centerDir, fragDir));
                    float sinalpha = abs(sin(acos(cosalpha)));
                    
                    float3 cV = (center.xyz - _WorldSpaceCameraPos.xyz);
                    float length = pow((cV.x * cV.x + cV.y * cV.y + cV.z * cV.z), 0.5);
                    float tangentAngle = asin(EarthRadius / length);
                    

                    // 最终的大气雾强度
                    float fogStrength;
                    if (sinalpha <= sin(tangentAngle) + 0.0001) { // 透过大气能看到地面
                        float sintheta = abs(sin(acos(length * sinalpha / (EarthRadius + 0.0005))));
                        fogStrength = InnerFog_Strength * AtoFog / sintheta;
                    }
                    else {                              // 透过大气看到宇宙
                        float3 AtoRadiusVec = center.xyz - i.worldPos.xyz;
                        float AtoRadius = pow((AtoRadiusVec.x * AtoRadiusVec.x + AtoRadiusVec.y * AtoRadiusVec.y + AtoRadiusVec.z * AtoRadiusVec.z), 0.5) + 0.0005;
                        float lightLength = 2 * pow((AtoRadius * AtoRadius - (length * sinalpha) * (length * sinalpha)), 0.5);
                        fogStrength = AtoFog * lightLength / (AtoRadius - EarthRadius);
                        fogStrength *= 1 - pow((((length * sinalpha) - EarthRadius) / (AtoRadius - EarthRadius)), 0.45);
                    }

 

但是由于我们没有使用基于物理的大气散射计算,所以电影中常见的从很低的角度观察大气层时的边缘辉光是不存在的,所以我们通过手工的方式添加这部分边缘辉光。边缘辉光既然存在于边缘,那么应该是越到边缘越强,在中心则极弱。于是我们可以采用类似于菲涅尔的做法来计算边缘辉光的强度,这一部分的具体代码如下:

                    fixed Alpha = dot(worldLightDir, worldNormal) * 0.5 + 0.5;
                    Alpha = pow(Alpha, 2.75);
                    
                    // 边缘辉光
                    float TheCos = dot(worldLightDir, fragDir);
                    float glowStrength_1 = 2 * pow(E, 50 * TheCos - 50);
                    float glowStrength_2 = 5 * pow(E, 200 * TheCos - 200);
                    float3 glow_1;
                    float3 glow_2;
                    if (sinalpha >= sin(tangentAngle) - 0.01) {    // 透过大气看到宇宙
                        glow_1 = glowStrength_1 * SunGlowColor.xyz;
                        glow_2 = glowStrength_2 * SunGlowColor.xyz;
                    }
                    else { 
                        glow_1 = float3(0, 0, 0);
                        glow_2 = float3(0, 0, 0);
                    }
                    fixed4 ans_atomosphere_base = fixed4(AtoCol.xyz, fogStrength * Alpha);
                    fixed4 ans_atomosphere_glow = fixed4(glow_1.xyz + glow_2.xyz, pow(fogStrength, 2) * (glow_1.x + glow_1.y + glow_1.z + glow_2.x + glow_2.y + glow_2.z) / 6);

 

这样的大气层已经非常好看了,但是当我们把摄像机运动到晨昏线附近时,晨昏线附近的大气层太蓝了,缺乏更多的太阳光的暖色部分的层次感,因此我们考虑再增加一层太阳光暖色光波长部分的散射光,尤其是在摄像机从背向对准晨昏线是,需要更多的层次来营造更好看的轮廓。我们通过计算光源(太阳)方向和大气表面片元到摄像机的向量的夹角大小来控制这部分暖色光的强度,这部分的实现如下:

                    // 背向辉光
                    float DawnGlowStrength_1 = 1 * pow(E, 8 * TheCos - 8);
                    fixed Strength = dot(worldNormal, worldLightDir);
                    fixed DawnGlowStrength = max((- 27 / 6 * Strength * pow(E, -4 * pow(Strength, 2))), 0);
                    float3 DawnGlow;
                    if (sinalpha >= sin(tangentAngle) - 0.01) {    // 透过大气看到宇宙
                        DawnGlow = DawnGlowStrength_1 * DawnGlowColor.xyz * DawnGlowStrength;
                    }
                    else {
                        DawnGlow = float3(0, 0, 0);
                    }

 

以上的每一层效果单独的效果和混合的效果如下图所示:

unity中实现地球与大气层的特效渲染(非物理向)

 

最终我们添加一些小的参数的调整,就得到了最终的结果,可以看到还是比较漂亮的,不过不够真实,如果需要真实的话还是要用大气散射模拟的方式来制作。

以上就是本文的全部内容了,因为距离我实现这个效果已经有一段时间了,有些细节我也无法说得很清楚了,还请见谅。文章来源地址https://www.toymoban.com/news/detail-482223.html

到了这里,关于unity中实现地球与大气层的特效渲染(非物理向)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • java实现大气污染排放传输路径模拟(iClientOpenlayer前端渲染)

    开头先看下模拟实现效果图   一、技术应用及背景说明 了解大气污染传输路径模拟可以帮助我们更好地了解空气污染的来源和传播方式,从而采取更有效的控制措施。这种模拟技术可以根据大气环境和气象条件,模拟出污染物在大气中的传播路径和影响范围,提供科学依据

    2024年02月03日
    浏览(41)
  • 高端大气自适应全屏酷炫渐变卡片html源码图片切换特效html5源码导航引导网站源码

    源码特点: 1:手工书写DIV+CSS、代码精简无冗余。 2:自适应结构,全球先进技术,高端视觉体验。 3:SEO框架布局,栏目及文章页均可独立设置标题//描述。 4:附带测试数据、安装教程、入门教程、安全及备份教程。 5:后台直接修酷炫渐变卡片html源码,可以做个人

    2024年04月13日
    浏览(34)
  • 地球物理专业毕业生毕业后能干高性能计算工程师吗?

    很多高校都开设有地球物理专业,但是很多身为地球物理专业的毕业生,很多同学却不清楚以后能做什么工作,做什么工作有前景,十分迷茫。在这里,我们有很多从事高性能计算领域的前地球物理专业学长现身说法——地球物理专业的同学非常适合做高性能计算。 原因如下

    2024年02月09日
    浏览(49)
  • 游戏物理引擎+特效系统

    原文链接:游戏开发入门(六)游戏物理引擎_游戏开发物理引擎-CSDN博客 游戏开发入门(七)特效系统_csdn 游戏效果开发-CSDN博客 1.游戏应用物理的目的就是为了真实 2.物理引擎: 可以认为属于游戏引擎的一个构成部分,但是可以独立剥离开来。游戏中的物理模拟的计算都是

    2024年02月22日
    浏览(35)
  • 【Unity大气散射】GAMES104:3A中如何实现大气散射

    写在前面 前两天学习并整理的大气散射基础知识:【Unity大气渲染】关于单次大气散射的理论知识,收获了很多,但不得不承认的是,这其实已经是最早的、90年代的非常古老的方法了,后来也出现了一些优化性的计算思路和方法。因此,我打算先不急着跟各种教程在Unity中实

    2024年02月02日
    浏览(50)
  • unity大气散射

    大气散射效果对游戏画质提升来说巨大,本文主要从代码层面讲解下大气散射 路径 AB 观察大气,并且求解 B 点的大气颜色,光线在大气中只发生一次散射,散射点为 P 阳光进入大气层CP开始衰减,在P点发生散射,然后PA衰减进入A点相机 T表示衰减系数 表示某段路径上光照的

    2024年03月21日
    浏览(40)
  • Android视频融合特效播放与渲染

    一个有趣且很有创意的视频特效项目。 https://github.com/duqian291902259/AlphaPlayerPlus 前言 直播产品,需要更多炫酷的礼物特效,比如飞机特效,跑车特效,生日蛋糕融特效等,融合了直播流画面的特效。所以在字节开源的alphaPlayer库和特效VAP库的基础上进行改造,实现融合特效渲染

    2023年04月13日
    浏览(30)
  • 用WebGPU实现基于物理的渲染

    推荐:用 NSDT编辑器 快速搭建可编程3D场景 最近,我花了相当多的时间在 WebGPU 中使用 IBL(基于图像的照明)编写 PBR(基于物理的渲染)渲染器。 PBR 本身并没有什么新奇之处。 这是一项自 2014 年以来就存在的技术,所有现代图形引擎都使用它。 但我还没有看到任何在 Web

    2024年02月10日
    浏览(56)
  • Unity WebGL三维地球

    1.支持arcgis,天地图,bingmap,谷歌地图,高德地图等影像加载 2.支持高程三维地形加载 3.支持在线,离线数据加载 4.支持unity坐标和经纬度坐标互相转换 5.支持fbx模型放置在地球上 6.支持倾斜摄影数据放置在地球上 7.支持pc,webgl平台发布 weixin:huazaikv 相关视频: unity三维地球_W

    2024年02月12日
    浏览(30)
  • 如何在Vue表单处理中实现表单的条件渲染

    在Vue开发中,我们经常会遇到需要根据某些条件来渲染表单的情况。这种情况下,我们需要灵活地根据条件来展示或隐藏一些表单字段。本文将介绍如何在Vue中实现表单的条件渲染,并提供了代码示例。 一、使用v-if指令实现简单的条件渲染 在Vue中,我们可以使用v-if指令来根

    2024年02月12日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包