立体渲染 Volumetric Rendering
基础概念
在3D游戏引擎中,球体、立方体以及所有其它复杂的集合体都是由三角面片组成的。引擎只会渲染物体的表面,比如球体,半透明物体等.整个世界由各种空壳构成.
立体渲染(Volumetric Rendering)的基本概念:模拟光线在物体内部的传送,从而实现更震撼也更真实的视觉效果。
片段着色器最后返回的对象,是从特定角度看过去特定位置的颜色。
这种方式计算的颜色是完全随意的,因此返回的内容可以不必匹配几何体的真实渲染情况。
下图展示了一个3D立方体的例子。当片段着色器检测到立方体表面的颜色时,模拟光线传送,使得结果如同一个球体
立体射线投射 Volumetric Raycasting
用一个函数判断光线与自定义的几何体相交的问题,限制较大,只能模拟简单几何体比如球,圆柱等。
固定步长立体光线追踪 Volumetric Raymarching with Constant Step
不依赖相交函数的,基于迭代的,可以模拟任意几何体
一步一步的检测光线是否已经投射到红色球体
bool raymarchHit (float3 position, float3 direction)
{for (int i = 0; i < STEPS; i++){if ( sphereHit(position) )return true;position += direction * STEP_SIZE;}return false;
}bool sphereHit (float3 p)
{return distance(p,_Centre) < _Radius;
}
距离辅助的光线追踪 Distance Aided Raymarching
固定步长的光线追踪非常低效,需要一种方法估算在遇到几何体之前需要走多远,
比如之前的sphereHit函数,不是返回bool值,而是距离球面的距离
float sphereDistance (float3 p)
{return distance(p,_Centre) - _Radius;
}
该函数就是一个有向距离函数(signed distance function),正数在几何体外,负数在几何体上,0在几何体表面
距离辅助的光线追踪实现代码:
fixed4 raymarch (float3 position, float3 direction)
{for (int i = 0; i < STEPS; i++){float distance = sphereDistance(position);if (distance < MIN_DISTANCE)return i / (float) STEPS;position += distance * direction;}return 0;
}
在一个比较复杂的场景运行的效果如下
STEPS 最大步数,需要根据图像形状调整
MIN_DISTANCE 不能是0,给一个比较合适的误差值0.01左右
SDF Signed Distance Fields(Functions) 有向距离场(函数) 组合
可以用组合的方式做出比较复杂的图形,例如那个很出名的蜗牛
简单来说 min返回并集,max返回交集
可以用类似Alpha混合的方式做多个形状的混合 as1 + (1-a)s2
还有很多种别的合并方式,如光滑合并
float sdf_smin(float a, float b, float k = 32)
{float res = exp(-k*a) + exp(-k*b);return -log(max(0.0001,res)) / k;
}
法线预估
Íñigo Quílez的方法是对周围其它点的距离场进行取样,来估算局部表面的曲率
float3 normal (float3 p)
{const float eps = 0.01; return normalize( float3 (map(p + float3(eps, 0, 0) ) - map(p - float3(eps, 0, 0)),map(p + float3(0, eps, 0) ) - map(p - float3(0, eps, 0)),map(p + float3(0, 0, eps) ) - map(p - float3(0, 0, eps))) );
}
更多
ShaderToy中有很多效果很好的例子
MERCURY团队创建的hg_sdf库,有很多元物件与操作
一个简单的实例Unity Shader
效果如下,在Cube内绘制了一个球
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'Shader "Unlit/VolumetricText"
{Properties{_BaseColor ("Base Color", Color) = (1,1,1,1)_SphereColor ("Sphere Color", Color) = (1,0,0,1)_SphereCentre("Sphere Centre",Vector) = (0,0,0)_ShpereRange ("Sphere Range", Range(0.1,2)) = 0.8}SubShader{Tags { "RenderType"="Opaque" "LightMode" = "ForwardBase" }LOD 100Pass{CGPROGRAM#include "Lighting.cginc"#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION; };struct v2f{float4 vertex : SV_POSITION;float3 wPos : TEXCOORD0; //世界坐标};float4 _BaseColor;float4 _SphereColor;float3 _SphereCentre;fixed _ShpereRange;//有向距离函数float SphereDistance(float3 p){return distance(p, _SphereCentre) - _ShpereRange;}//光线追踪fixed Raymarch(float3 position, float3 direction){float STEPS = 10;float MIN_DISTANCE = 0.01;for (int i = 0; i < STEPS; i++){float distance = SphereDistance(position);if (distance < MIN_DISTANCE)return i / (float)STEPS;position += distance * direction;}return 0;}//法线模拟_简单球形测试float3 NormalEstimation_Sphere(float3 p){return normalize(p - _SphereCentre);}v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;return o;}fixed4 frag (v2f i) : SV_Target{fixed4 col = _BaseColor;float3 viewDirection = normalize(i.wPos - _WorldSpaceCameraPos);fixed rayHit = Raymarch(i.wPos, viewDirection);if (rayHit >= 0.01)col = _SphereColor;//丢弃不在形状内的,测试,不在的改为白色clip(col.a - 0.01);fixed3 normal = NormalEstimation_Sphere(i.wPos);//简单处理下光照fixed3 lightDir = _WorldSpaceLightPos0.xyz; // Light directionfixed3 lightCol = _LightColor0.rgb; // Light colorfixed NdotL = max(dot(normal, lightDir), 0);col.rgb = col * lightCol * NdotL;return col;}ENDCG}}
}
参考网页
Unity教程|立体渲染
Unity3D体积烟雾制作思路分享
梯度下降法
comprehensive guide to volume rendering
转载于:https://www.cnblogs.com/Hichy/p/9584068.html
立体渲染 Volumetric Rendering相关推荐
- 游戏中的Volumetric Rendering
总结下游戏中常见的Volumetric Rendering的实现方法 1. 一些理论知识 快速简要地介绍一些理论知识. 光打到粒子上之后的效果: 光在介质上的散射,入射光分为吸收,透射,外散射三个部分 ...
- 【理解】神经立体渲染,NeRF
https://www.zhihu.com/question/528913695/answer/2568694310 2020年是神经立体渲染(neural volume rendering)爆发的一 ...
- OpenGL 分层渲染Layered Rendering的实例
OpenGL 分层渲染Layered Rendering 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <string> #incl ...
- OpenGL 文本渲染Text Rendering
OpenGL文本渲染Text Rendering 文本渲染Text Rendering简介 经典文本渲染:位图字体 现代文本渲染:FreeType 着色器 渲染一行文本 更进一步 文本渲染Text R ...
- CSharpGL(30)用条件渲染(Conditional Rendering)来提升OpenGL的渲染效率
CSharpGL(30)用条件渲染(Conditional Rendering)来提升OpenGL的渲染效率 当场景中有比较复杂的模型时,条件渲染能够加速对复杂模型的渲染. 条件渲染(Conditio ...
- 延迟渲染(Deferred Rendering)
什么是延迟渲染?( Deferred Rendering) 在计算机图形学中,延迟渲染( Deferred Rendering) ,即延迟着色(Deferred Shading),是将着色计算延迟到深 ...
- 实例渲染Instanced Rendering
实例渲染Instanced Rendering 0.前言 在此之前红宝书已经介绍了不少关于缓存和绘制的命令,并给出了用同样的顶点绘制几个三角形的例程,但是此前的例程实现起来非常麻烦,每个三角形要指定一 ...
- UE4 Medical Data Volumetric Rendering
UE4 Medical Data Volumetric Rendering TBRaymarchPlugin - UE4 Medical Data Volumetric Rendering (Raym ...
- 一种快速制作立体渲染效果地形图方法
概述 制作立体渲染地形图的方法网上有很多,常见的方法就是在ArcToolbox中使用山体阴影工具制作山体阴影,再调整透明度,这里给大家介绍另外一种方法,该方法更加的快速. 数据来源 本教程所使用的数据 ...
最新文章
- 用C#生成随机中文汉字验证码的基本原理
- IBM大裁70% 员工,撕掉了国内大批伪AI企业最后一块遮羞布!
- apache解析php的方法
- 三菱plc编程实例3000_三菱PLC十字路口的红绿灯编程实例
- python中代理模式分为几种类型_代理模式
- MyBatis(四)MyBatis插件原理
- 学习JavaScript的24条实用建议
- 【SQL语句】MySql、SqlServer查询近期记录
- Java数据库篇9——备份与还原、忘记密码
- 下岗工人到达退休年龄,养老保险未缴纳满15年,补缴合适吗?
- 寻找开发区块链协议的完美编程语言
- Ubuntu安装网易云音乐
- 鸿蒙曰意心养翻译,文言文情话及翻译
- 基于51单片机的多点8路温度采集系统 proteus仿真程序原理图设计
- 计算机技术对人脸识别的作用,人脸识别技术有什么功能特点
- Intel显卡跑ROS与CUDA总结(MacBook Pro 11.6.3)
- 还在用ES查日志吗,快看看石墨文档 Clickhouse 日志架构玩法
- 【现成工具】java获取国家法定节假日包含指定月份节假日和周末
- 搭建K8S 的dashboard的坑the server could not find the requested resource
- PnPUtil (PnPUtil.exe) 是一个命令行工具,使管理员可以执行以下操作驱动程序包