光线步进Ray Marching 与 体积绘
时间:2019-02-20
本文章向大家介绍光线步进Ray Marching 与 体积绘,主要包括光线步进Ray Marching 与 体积绘使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
效果如下:
第一步,定义视角相关的参数,观察点位置离观察目标点位置的距离,观察点视角度数,观察者头顶方向,得到摄像机矩阵
第二步,光线步进,每步进一次进行采样,定义最小步进深度,最大步进深度,如果光线和目标的距离小于0.01就算作捕捉到目标,返回光线的步进深度(长度),如果N次光线步进没有捕获到目标或步进深度大于最大步进深度,就返回最大步进深度。
代码如下:
Shader "Unlit/howRayMarching"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
//1.定义view matrix 的3参数
_EyePosition("观察点位置",Vector) = (0,0,-2,0)
_EyeUp("观察点上方",Vector) = (1,0,0,0)
_EyeTarget("观察点目标",Vector) = (0,0,0,0)
_FieldOfView("观察者视角角度",Float) = 60
minDist ("光线步进的最小距离",Float) = 0.0
maxDist ("光线步进的最大距离",Float) = 10.0
r("视角的旋转角度",Range(0,6.283))=0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
//2.在pass里重新写入一次
float4 _EyePosition;
float4 _EyeUp;
float4 _EyeTarget;
float _FieldOfView;
float minDist;
float maxDist;
float r;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
float4x4 GetWorldCameraMatrix(float3 eyePosition,float3 eyeUp,float3 eyeTarget)
{
eyeUp = normalize(eyeUp);
float3 viewDirection = normalize( float3(eyeTarget - eyePosition));
float3 eyeRight = cross(eyeUp,viewDirection);
float4x4 worldCameraMatrix = float4x4(eyeRight,0,
eyeUp,0,
viewDirection,0,
0,0,0,1);
return worldCameraMatrix;
}
//光线到四方体的距离检测
float cubeSDF(float3 p) {
p = mul(float3x3(1.0,0.0,0.0,
0.0,cos(r),sin(r),
0.0,-sin(r),cos(r)),p);
float3 d = abs(p) - float3(1.0, 1.0, 0.001); //这里四面体的z轴长度设置为极小值,假设四面体为面片
float insideDistance = min(max(d.x, max(d.y, d.z)), 0.0);
float outsideDistance = length(max(d, 0.0));
float dis=insideDistance + outsideDistance;
return dis;
}
float overlay(float3 p)
{
return cubeSDF(p);
}
float getDist(float3 cameraOrign , float3 dir)
{
float depth = minDist;
for(int i=0;i<500;i+=1){
float3 rayPosition = cameraOrign + depth*dir;
float dist = overlay(rayPosition);
if(dist<0.01){ //如果光线和目标的距离小于0.01,就返回光线的长度
return depth;
}
depth += dist;
if(depth>=maxDist){
return maxDist;
}
}
return maxDist;
}
fixed4 frag (v2f i) : SV_Target
{
float2 uv = i.uv;
uv-=0.5;
float2 size = float2(1.0,1.0);
float z = size.y/tan(radians(_FieldOfView) / 2.0);
float3 rayDir = normalize(float3(uv.xy,z));
float4x4 worldCameraMatrix = GetWorldCameraMatrix(_EyePosition,_EyeUp,_EyeTarget);
//3.将视线的世界坐标转化为视角坐标
float3 ViewDirectionCamera = mul(worldCameraMatrix,float4(rayDir.xyz,0)).xyz;
//4.光线步进进行采样
float dist=getDist(_EyePosition,ViewDirectionCamera);
//5.光线步进深度超过最大步进深度就忽略当前像素
if(dist>maxDist-0.001){
return float4(0.0,0.0,0.0,1.0);
}
//其他:对一面进行绘制图片
float3 p = _EyePosition + dist * ViewDirectionCamera;
p = mul( float3x3(1.0,0.0,0.0,
0.0,cos(r),sin(r),
0.0,-sin(r),cos(r)),p);
float3 onRectUV = (p.xyz +float3(1,1,0))*0.5;
float4 finalColor = float4(tex2D(_MainTex,onRectUV.xy));
finalColor.xyz*=finalColor.a;
if(finalColor.a<0.001){
return float4(0.0,0.0,0.0,1.0);
}
return finalColor;
}
ENDCG
}
}
}
- 使用Docker的Alluxio群集设置
- 通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[中]:管道如何处理请求
- ASP.NET MVC Model元数据及其定制: 初识Model元数据
- 如何在企业中融入机器学习
- How ASP.NET MVC Works?
- 如果没有Visual Studio 2015,我们如何创建.NET Core项目 ?
- “前.NET Core时代”如何实现跨平台代码重用 ——源文件重用
- 简析Linux主要应用领域及范围
- ASP.NET MVC Controller激活系统详解:默认实现
- 机器之心年度盘点:2017年人工智能领域度备受关注的科研成果
- 为什么GAC和VS引用的程序集不一致?
- GraphQL 浅谈,从理解 Graph 开始
- 分布式系统CAP理论
- 美媒盘点2018年将改变世界的四大技术趋势
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python大作网图片采集下载,多线程图片爬虫
- Python素材下载爬虫,多线程rar下载爬虫
- 一个简单的图片爬虫,Python图片采集下载
- 百度统计后台总是被广告骚扰?看看应用python是如何实现的
- Python电商爬虫,法国亚马逊商品采集
- Python堆糖网图片爬虫,多进程及多线程的使用例子
- Python Post提交简单案例,文本内容在线语音合成
- Python多线程爬虫,主播信息资料爬取采集
- 基于Tensorflow2 Lite在Android手机上实现图像分类
- Python知乎专栏爬虫,pdfkit专栏文章制作PDF电子书
- Python爬虫练手,一个简单的Python资讯采集案例
- Python与seo,百度关键词相关搜索关键词采集源码
- istio请求路由分析
- [剑指]2空格替换
- (补充)SPAN+AVISPA for Verifying Cryptographic Protocols