100多行代码实现纯算法云海效果

2023-11-06 09:30

本文主要是介绍100多行代码实现纯算法云海效果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 准备工作
    • 光线步进
    • 分数噪声
    • 基本实现
    • 光照计算
    • 云层移动
    • 相机控制
    • 完整代码

准备工作

我们采用shadertoy作为工具,在它上面编写代码,查看效果。打开shadertoy,在右上角直接点击新建,即可创建一个新的着色器,可以看到如下的初始代码:

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{// Normalized pixel coordinates (from 0 to 1)vec2 uv = fragCoord/iResolution.xy;// Time varying pixel colorvec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));// Output to screenfragColor = vec4(col,1.0);
}

显示结果如下:
在这里插入图片描述

其中mainImage是入口函数,参数fragColor是输出结果,fragCoord是当前的像素坐标。将代码修改如下(后面带// new的表示新增代码):

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{vec2 uv = fragCoord / iResolution.xy;uv = 2.0 * uv - 1.0; // newuv.x *= iResolution.x / iResolution.y; // newfragColor = vec4(1.0);
}

由于画布的宽高是不一样的,也为了方便计算,所以新增了两行代码先将uv转换到[-1, 1]范围内,再根据宽高比对x的值进行调整。

光线步进

游戏采用的一般是光栅化的方式进行渲染,现在部分显卡和引擎也支持了光线追踪,光线步进的思路和追踪很相似,都是从观察点发射一束光线,然后计算它最终的颜色,只不过追踪采用的是几何体交叉判断,而步进采用的是有符号距离函数(SDF)来判断。
SDF的返回值d表示当前位置距离几何体的最近距离,其含义如下:

  • d > 0,当前位置在几何体外,距离几何体表面最近距离为d
  • d == 0,当前位置正好在几何体表面
  • d < 0, 当前位置在几何体内,距离几何体表面最近距离为-d

我们参考光线步进的做法,但是将SDF的含义修改一下,让其返回值表示当前位置的云的密度。如果小于0,则表示在云层外,如果大于0则表示当前位置云层的密度,后续我们根据这个密度来计算当前位置的颜色。我们添加一个getDensity函数来计算密度,和一个render函数来计算颜色:

float getDensity(in vec3 pos) {return 1.0;
}// ori:观察位置
// dir:观察方向
vec4 render(in vec3 ori, in vec3 dir) {return vec4(1.0);
}

在主函数中调用render函数:

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{vec2 uv = fragCoord/iResolution.xy;uv = 2.0 * uv - 1.0; // newuv.x *= iResolution.x / iResolution.y; // newvec3 ori = 4.0 * vec3(0.0, 0.3, -1.0); // newvec3 dir = normalize(vec3(uv.xy, 1.5)); // newfragColor = render(ori, dir); // new
}

此时的渲染结果应为一个纯白的画布,接下来首先来完成getDensity函数。

分数噪声

getDensity决定了云的形状,一般通过噪声贴图来实现,但由于我们不使用任何纹理,所以可以通过噪声函数来生成,普通的噪声离散性较强,与云的形状不符合,我们采用分数噪声函数来生成云的形状,其基本原理如下图所示:

修改代码如下:

float hash(vec3 p) 
{p  = fract(p * 0.3183099 + .1);p *= 17.0;return fract(p.x * p.y * p.z * (p.x + p.y + p.z));
}float noise(in vec3 x)
{vec3 i = floor(x);vec3 f = fract(x);f = f * f * (3.0 - 2.0 * f);return mix(mix(mix( hash(i+vec3(0,0,0)), hash(i+vec3(1,0,0)),f.x),mix( hash(i+vec3(0,1,0)), hash(i+vec3(1,1,0)),f.x),f.y),mix(mix( hash(i+vec3(0,0,1)), hash(i+vec3(1,0,1)),f.x),mix( hash(i+vec3(0,1,1)), hash(i+vec3(1,1,1)),f.x),f.y),f.z);
}float getDensity(in vec3 pos) {vec3 q = pos;float g = 0.5 + 0.5 * noise(q * 0.3);float f  = 0.60000 * noise(q); q = q  *

这篇关于100多行代码实现纯算法云海效果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/zhugefei/article/details/118089728
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/355796

相关文章

基于Python实现温度单位转换器(新手版)

《基于Python实现温度单位转换器(新手版)》这篇文章主要为大家详细介绍了如何基于Python实现温度单位转换器,主要是将摄氏温度(C)和华氏温度(F)相互转换,下面小编就来和大家简单介绍一下吧... 目录为什么选择温度转换器作为第一个项目项目概述所需基础知识实现步骤详解1. 温度转换公式2. 用户输入处

MySQL实现多源复制的示例代码

《MySQL实现多源复制的示例代码》MySQL的多源复制允许一个从服务器从多个主服务器复制数据,这在需要将多个数据源汇聚到一个数据库实例时非常有用,下面就来详细的介绍一下,感兴趣的可以了解一下... 目录一、多源复制原理二、多源复制配置步骤2.1 主服务器配置Master1配置Master2配置2.2 从服

Java实现TXT文件导入功能的详细步骤

《Java实现TXT文件导入功能的详细步骤》在实际开发中,很多应用场景需要将用户上传的TXT文件进行解析,并将文件中的数据导入到数据库或其他存储系统中,本文将演示如何用Java实现一个基本的TXT文件... 目录前言1. 项目需求分析2. 示例文件格式3. 实现步骤3.1. 准备数据库(假设使用 mysql

C#控制台程序同步调用WebApi实现方式

《C#控制台程序同步调用WebApi实现方式》控制台程序作为Job时,需同步调用WebApi以确保获取返回结果后执行后续操作,否则会引发TaskCanceledException异常,同步处理可避免异... 目录同步调用WebApi方法Cls001类里面的写法总结控制台程序一般当作Job使用,有时候需要控制

SpringBoot集成P6Spy的实现示例

《SpringBoot集成P6Spy的实现示例》本文主要介绍了SpringBoot集成P6Spy的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录本节目标P6Spy简介抛出问题集成P6Spy1. SpringBoot三板斧之加入依赖2. 修改

Go语言使用net/http构建一个RESTful API的示例代码

《Go语言使用net/http构建一个RESTfulAPI的示例代码》Go的标准库net/http提供了构建Web服务所需的强大功能,虽然众多第三方框架(如Gin、Echo)已经封装了很多功能,但... 目录引言一、什么是 RESTful API?二、实战目标:用户信息管理 API三、代码实现1. 用户数据

Python实现数据可视化图表生成(适合新手入门)

《Python实现数据可视化图表生成(适合新手入门)》在数据科学和数据分析的新时代,高效、直观的数据可视化工具显得尤为重要,下面:本文主要介绍Python实现数据可视化图表生成的相关资料,文中通过... 目录前言为什么需要数据可视化准备工作基本图表绘制折线图柱状图散点图使用Seaborn创建高级图表箱线图热

Redis分布式锁中Redission底层实现方式

《Redis分布式锁中Redission底层实现方式》Redission基于Redis原子操作和Lua脚本实现分布式锁,通过SETNX命令、看门狗续期、可重入机制及异常处理,确保锁的可靠性和一致性,是... 目录Redis分布式锁中Redission底层实现一、Redission分布式锁的基本使用二、Red

基于Python实现数字限制在指定范围内的五种方式

《基于Python实现数字限制在指定范围内的五种方式》在编程中,数字范围限制是常见需求,无论是游戏开发中的角色属性值、金融计算中的利率调整,还是传感器数据处理中的异常值过滤,都需要将数字控制在合理范围... 目录引言一、基础条件判断法二、数学运算巧解法三、装饰器模式法四、自定义类封装法五、NumPy数组处理

Python中经纬度距离计算的实现方式

《Python中经纬度距离计算的实现方式》文章介绍Python中计算经纬度距离的方法及中国加密坐标系转换工具,主要方法包括geopy(Vincenty/Karney)、Haversine、pyproj... 目录一、基本方法1. 使用geopy库(推荐)2. 手动实现 Haversine 公式3. 使用py