当前位置: 首页 > news >正文

浅聊 Three.js 屏幕空间反射SSR-SSRShader

浅聊 Three.js 屏幕空间反射SSR(2)-SSRShader

前置基础
渲染管线中的相机和屏幕示意图

 -Z  (相机朝向的方向)|||       +--------------+  <- 屏幕/投影平面|       |              ||       |              ||       |     (f)      |  <- 焦距|       |              ||       |              ||       +--------------+|              ||              ||              O  <- 相机原点 (也称为视点)|              |||+---------------------- X (水平轴)
一、计算 viewPosition

根据深度图计算屏幕空间上的 视图位置。

float clipW = cameraProjectionMatrix[2][3] * viewZ+cameraProjectionMatrix[3][3];
vec3 viewPosition = getViewPosition( vUv, depth, clipW );
二、计算反射位置 d1viewPosition
vec3 viewNormal=getViewNormal( vUv );// 入射光线方向
vec3 viewIncidentDir=normalize(viewPosition);// 反射光线方向
vec3 viewReflectDir=reflect(viewIncidentDir, viewNormal);// 反射光线最大长度
float maxReflectRayLen=maxDistance/dot(-viewIncidentDir, viewNormal);// 反射位置
vec3 d1viewPosition = viewPosition + viewReflectDir * maxReflectRayLen;

请添加图片描述

处理反射位置在近平面(即 -cameraNear)之的情况

目标:
确保反射光线的目标位置 (d1viewPosition) 不在近平面之前。如果在近平面之前,则将其调整到近平面上。

if(d1viewPosition.z > -cameraNear){//https://tutorial.math.lamar.edu/Classes/CalcIII/EqnsOfLines.aspxfloat t= (-cameraNear - viewPosition.z) / viewReflectDir.z;d1viewPosition = viewPosition + viewReflectDir * t;
}
 ^ -z||||      * 视点(viewPosition)|       \|        \|------------ (近平面,z = -cameraNear)|          \|           \|            *|             \|              \|               * d1viewPosition (初始位置)|-------------------------------------> x

解释:
反射光线的参数方程:
P ( t ) = v i e w P o s i t i o n + t ∗ v i e w R e f l e c t D i r P(t) = viewPosition + t * viewReflectDir P(t)=viewPosition+tviewReflectDir

我们需要找到 t t t 使得:
P ( t ) . z = − c a m e r a N e a r P(t).z = -cameraNear P(t).z=cameraNear

因此,我们需要解方程:
v i e w P o s i t i o n . z + t ∗ v i e w R e f l e c t D i r . z = − c a m e r a N e a r viewPosition.z + t * viewReflectDir.z = -cameraNear viewPosition.z+tviewReflectDir.z=cameraNear

解这个方程,得到:
t = − c a m e r a N e a r − v i e w P o s i t i o n . z v i e w R e f l e c t D i r . z t = \frac{-cameraNear - viewPosition.z}{ viewReflectDir.z} t=viewReflectDir.zcameraNearviewPosition.z

最后, 调整反射后目标位置:
d 1 v i e w P o s i t i o n = v i e w P o s i t i o n + v i e w R e f l e c t D i r ∗ t ; d1viewPosition = viewPosition + viewReflectDir * t; d1viewPosition=viewPosition+viewReflectDirt;

三、计算反射位置在屏幕空间下的位置
// 屏幕分辨率
uniform vec2 resolution;// 视图空间转屏幕空间
vec2 viewPositionToXY(vec3 viewPosition){vec2 xy;vec4 clip = cameraProjectionMatrix * vec4(viewPosition,1);//clipxy = clip.xy;float clipW = clip.w;//NDCxy /= clipW;//uvxy = (xy + 1.) / 2.;//screenxy *=resolution;return xy;
}vec2 d1 = viewPositionToXY(d1viewPosition);
四、屏幕空间光线步进(Ray Marching)

参考: DDA 画直线算法

// 片段着色器中的当前像素坐标
vec2 d0 = gl_FragCoord.xy;vec2 d1 = viewPositionToXY(d1viewPosition);// x 和 y 方向上的距离
float xLen = d1.x-d0.x;
float yLen = d1.y-d0.y;// 两个点之间的欧几里得距离
float totalLen = length(d1-d0);// 在 x 和 y 方向上步数的最大值,用于决定采样的步数
float totalStep = max(abs(xLen), abs(yLen));// 每一步在 x 和 y 方向上的增量
float xSpan = xLen / totalStep;
float ySpan = yLen / totalStep;for(float i = 0.; i<float(MAX_STEP); i++) {if(i >= totalStep) break;vec2 xy = vec2(d0.x + i * xSpan, d0.y + i * ySpan);if(xy.x < 0. || xy.x > resolution.x || xy.y < 0. || xy.y > resolution.y) break;// 比例进度, 0~1float s = length(xy - d0) / totalLen;vec2 uv = xy / resolution;float d = getDepth(uv);// 当前像素的视图空间深度值float vZ = getViewZ(d);if(-vZ >= cameraFar) continue;float cW = cameraProjectionMatrix[2][3] * vZ+cameraProjectionMatrix[3][3];vec3 vP = getViewPosition( uv, d, cW );// https://comp.nus.edu.sg/~lowkl/publications/lowk_persp_interp_techrep.pdffloat recipVPZ = 1. / viewPosition.z;// 基于插值得到的透视矫正后的深度值float viewReflectRayZ = 1. / (recipVPZ + s * (1. / d1viewPosition.z - recipVPZ));if(viewReflectRayZ <= vZ){// 只处理无限厚度的情况vec3 vN = getViewNormal(uv);if(dot(viewReflectDir,vN) >= 0.) continue;float distance = pointPlaneDistance(vP, viewPosition, viewNormal);if(distance > maxDistance) break;vec4 reflectColor = texture2D(tDiffuse, uv);gl_FragColor = reflectColor;}
}

只处理 viewReflectRayZ <= vZ的情况

^ -z|||            * viewPosition (反射的起始位置)|             \|              \|               \|                \|                 \|                  * viewReflectRayZ  (矫正后的深度值)|                   \|                    \|                     * vZ (当前像素深度值)|                      \|                       \|                        \|                         \|-------------------------------------> x
  • 在透视投影下,深度值绝对值越小,表示距离相机越近。在进行光线行进时,我们希望光线从起点出发,经过所有可能的深度值,直到目标位置

  • viewReflectRayZ 是矫正后的深度值,它应该始终小于或等于 vZ,以确保光线距离起点从近到远进行插值和计算。

  • 如果 viewReflectRayZ 大于 vZ, 这种情况可能导致光线跳过当前像素,直接到达更远的像素,产生穿透问题

  • 通过确保 viewReflectRayZ <= vZ,可以保证光线在行进过程中深度值是连续变化的,从而提高插值的精度,避免因不连续的深度值变化而产生的伪影

只处理钝角的情况
点积大于或等于零,表示这两个单位向量的夹角小于或等于 90 度。

点到平面距离

float pointPlaneDistance(vec3 point,vec3 planePoint,vec3 planeNormal){// https://mathworld.wolfram.com/Point-PlaneDistance.html https://en.wikipedia.org/wiki/Plane_(geometry) http://paulbourke.net/geometry/pointlineplane/float a = planeNormal.x;float b = planeNormal.y;float c = planeNormal.z;float x0 = point.x;float y0 = point.y;float z0 = point.z;float x = planePoint.x;float y = planePoint.y;float z = planePoint.z;float d = -(a * x + b * y + c * z);float distance = (a * x0 + b * y0 + c * z0 + d)/sqrt(a * a + b * b + c * c);return distance;
}

相关文章:

浅聊 Three.js 屏幕空间反射SSR-SSRShader

浅聊 Three.js 屏幕空间反射SSR(2)-SSRShader 前置基础 渲染管线中的相机和屏幕示意图 -Z (相机朝向的方向)||| -------------- <- 屏幕/投影平面| | || | || | (f) | <- 焦距| | ||…...

Windows图形界面(GUI)-DLG-C/C++ - 月历控件(MonthCalendar)

公开视频 -> 链接点击跳转公开课程博客首页 -> e​​​​​​链接点击跳转博客主页 目录 月历控件(MonthCalendar) 使用场景 控件操作 月历控件(MonthCalendar) 使用场景 日程安排&#xff1a;用户可以通过月历控件选择特定的日期来安排会议或活动。事件管理&#x…...

【Langchain大语言模型开发教程】基于文档问答

&#x1f517; LangChain for LLM Application Development - DeepLearning.AI Embedding&#xff1a; https://huggingface.co/BAAI/bge-large-en-v1.5/tree/main 学习目标 1、Embedding and Vector Store 2、RetrievalQA 引包、加载环境变量 import osfrom dotenv import…...

大厂面试-基本功

大厂面试第4季 服务可用性多少个9是什么意思遍历集合add或remove操作bughashcode冲突案例BigdecimalList去重复IDEA Debugger测试框架ThreaLocal父子线程数据同步 InheritableThreadLocal完美解决线程数据同步方案 TransmittableThreadLocal 服务可用性多少个9是什么意思 遍历集…...

RV1103使用rtsp和opencv推流视频到网页端

参考&#xff1a; Luckfox-Pico/Luckfox-Pico-RV1103/Luckfox-Pico-pinout/CSI-Camera Luckfox-Pico/RKMPI-example Luckfox-Pico/RKMPI-example 下载源码 其中源码位置&#xff1a;https://github.com/luckfox-eng29/luckfox_pico_rtsp_opencv 使用git clone由于项目比较大&am…...

与Bug较量:Codigger之软件项目体检Software Project HealthCheck来帮忙

在软件工程师的世界里&#xff0c;与 Java 小程序中的 Bug 作战是一场永不停歇的战役。每一个隐藏在代码深处的 Bug 都像是一个狡猾的敌人&#xff0c;时刻准备着给我们的项目带来麻烦。 最近&#xff0c;我就陷入了这样一场与 Java 小程序 Bug 的激烈较量中。这个小程序原本应…...

Git --- Branch Diverged

Git --- Branch Diverged Branch Diverged是如何形成的如何解决RebaseMerge Branch Diverged是如何形成的 尝试提交并将更改推送到 master 分支时&#xff0c;是否看到这条烦人的消息 原因是&#xff1a; 直到更改 B 之前&#xff0c;我的分支和“origin/master”完全相同。从…...

go标准库---net/http服务端

1、http简单使用 go的http标准库非常强大&#xff0c;调用了两个函数就能够实现一个简单的http服务&#xff1a; func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) func ListenAndServe(addr string, handler Handler) error handleFunc注册一个路…...

Linux文件和目录常用命令

1.操作命令 查看目录内容 ls 切换目录 cd 创建和删除操作 touch rm mkdir 拷贝和移动文件 cp mv 查看文件内容 cat more grep 其他 echo 重定向 > 和 >> 管道 | 1.1 终端实用技巧 1>自动补全 在敲出 文件/目录/命令 的前几个字母之后&#xff0c;按下…...

【C++刷题】优选算法——链表

链表常用技巧和操作总结 常用技巧 画图 引入虚拟头节点 不要吝啬空间&#xff0c;大胆定义变量 快慢双指针常用操作 创建一个新节点 尾插 头插 两数相加 ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {int carry 0;ListNode* newHead new ListNode, *cur newHea…...

Flex和Bison

Flex和Bison是Linux和Unix环境下两个非常强大的工具&#xff0c;分别用于生成词法分析器和语法分析器。它们在编译器设计、文本处理等领域有着广泛的应用。下面我将详细介绍Flex和Bison的基本概念、功能、用法以及它们之间的关系。 一、Flex 1. 基本概念 Flex&#xff08;其…...

Matlab-FPGA 小数转换为定点二进制小数脚本和转coe文件格式脚本

Matlab-FPGA 小数转换为定点二进制小数脚本&#xff1a; % 更新于2023年6月17日&#xff0c;修改旋转因子文件&#xff0c;不修改fpga %首先明确我们的二维FFT的数组维数,此为1024*8的二维矩阵&#xff0c;1024行&#xff0c;8列 column 1024; row 8; nk[]; Ncolumn*row; fo…...

逆向案例二十三——请求头参数加密,某区块链交易逆向

网址&#xff1a;aHR0cHM6Ly93d3cub2tsaW5rLmNvbS96aC1oYW5zL2J0Yy90eC1saXN0L3BhZ2UvNAo 抓包分析&#xff0c;发现请求头有X-Apikey参数加密&#xff0c;其他表单和返回内容没有加密。 直接搜索关键字&#xff0c;X-Apikey&#xff0c;找到疑似加密位置&#xff0c;注意这里…...

CSS 导航栏:设计、定制与优化

CSS 导航栏&#xff1a;设计、定制与优化 CSS&#xff08;层叠样式表&#xff09;是网页设计中不可或缺的一部分&#xff0c;它允许开发者通过定义样式来控制网页的布局和外观。在网页设计中&#xff0c;导航栏是一个关键元素&#xff0c;它帮助用户浏览网站并找到他们感兴趣的…...

JS 如何处理链接被用户点击中键的操作

今天在开发中遇到一个问题&#xff0c;在使用类似Bootstrap中的Tabs组件时&#xff0c;当在tab导航链接点击中键时会打开一个新的窗口访问链接&#xff0c;于是我尝试在别的普通链接上点击中键时也会如此&#xff0c;我猜测这是浏览器的默认行为。 由于我开发的是一个浏览器在…...

Android 11 使用HAL层的ffmpeg库(1)

1.frameworks/av/media目录下面的修改 From edd6f1374c1f15783d9920ebda22ea915e503775 Mon Sep 17 00:00:00 2001 From: GW00219471 <zhumingxingnoboauto.com> Date: Wed, 17 Jan 2024 15:16:10 0800 Subject: [PATCH] ?UTF-8?q?[V35CUX-4542]:E7A7BBE6A48Dcux20E8…...

友力科技数据中心搬迁方案

将当前运行机房中的所有设备、应用系统安全搬迁至新数据中心机房&#xff0c;实现平滑切换、平稳过渡&#xff0c;最大限度地降低搬迁工作对业务的影响。 为了确保企事业单位能够顺利完成数据中心机房搬迁工作&#xff0c;我们根据实际经验提供了4个基本原则&#xff0c;希望能…...

GitHub敏感信息扫描工具

目录 功能设计 技术实现 程序使用 文件配置 下载地址 功能设计 GitPrey是根据企业关键词进行项目检索以及相应敏感文件和敏感文件内容扫描的工具,其设计思路如下: 根据关键词在GitHub中进行全局代码内容和路径的搜索(in:file,path),将项目结果做项目信息去重整理得到…...

Linux云计算 |【第一阶段】ENGINEER-DAY4

主要内容&#xff1a; 配置Linux网络参数、配置静态主机名、查看/修改/激活/禁用网络连接、指定DNS、虚拟网络连接、虚拟机克隆、SSH客户端、SCP远程复制、SSH无密码验证&#xff08;SERVICE-DAY5&#xff09;、虚拟网络类型 一、网络参数配置 修改网卡配置文件主要是需要配置…...

C++与VLC制作独属于你的动态壁纸背景

文章目录 前言效果展示为什么要做他如何实现他实现步骤获取桌面句柄代码获取桌面句柄libvlc_media_player_set_hwnd函数 动态壁纸代码 总结 前言 在当今的数字世界中&#xff0c;个性化和自定义化的体验越来越受到人们的欢迎。动态壁纸是其中一种很受欢迎的方式&#xff0c;它…...

[特殊字符] 科普:论文查重的AI原理是什么?这个免费工具把“黑科技“讲明白了

同学们好&#xff0c;我是你们的论文写作科普博主。 今天不聊怎么选题&#xff0c;不聊怎么写文献综述&#xff0c;咱们来聊一个99%的同学都踩过坑的环节——查重。 先问大家一个问题&#xff1a;你知道查重到底是怎么查的吗&#xff1f; 很多同学以为查重就是"把你的文…...

如何快速掌握TreeViewer:系统发育树可视化工具的完整指南

如何快速掌握TreeViewer&#xff1a;系统发育树可视化工具的完整指南 【免费下载链接】TreeViewer Cross-platform software to draw phylogenetic trees 项目地址: https://gitcode.com/gh_mirrors/tr/TreeViewer TreeViewer是一款功能强大的跨平台系统发育树可视化软件…...

ArcGIS Pro新手教程:用‘创建常量栅格’和‘镶嵌’工具,5步精准提取中国区域气温NC数据

ArcGIS Pro精准提取中国区域气温数据的5步进阶指南 当全球气象数据遇上区域研究需求&#xff0c;如何高效提取目标范围信息成为地理信息科学领域的常见挑战。以中国陆地区域气温分析为例&#xff0c;传统方法往往面临数据冗余、边界锯齿和格式转换三大痛点。本文将揭示一套基于…...

085、命令行工具开发:argparse模块实战笔记

085、命令行工具开发:argparse模块实战笔记 昨天帮同事调试一个数据清洗脚本,问题出在参数解析上。脚本接收三个输入路径,结果他少传了一个参数,程序直接崩溃报“IndexError”。这种体验太糟糕了——用户不知道哪里错了,也不知道该怎么用。这就是为什么我们需要专业的命令…...

MPU6050姿态解算实战:从互补滤波到卡尔曼融合的工程实现

1. MPU6050传感器基础与姿态解算原理 MPU6050作为一款经典的6轴运动处理传感器&#xff0c;在平衡车、无人机等嵌入式项目中扮演着关键角色。它集成了三轴加速度计和三轴陀螺仪&#xff0c;能够同时测量线性加速度和角速度。但很多新手第一次拿到传感器数据时会困惑&#xff1a…...

智能手机如何重塑芯片市场:从基带到SoC的平台化竞争

1. 市场格局的剧变&#xff1a;一部智能手机如何重塑芯片江湖如果你在2007年问一个半导体行业的从业者&#xff0c;手机核心芯片市场的格局会怎样&#xff0c;他大概率会给你描绘一个由德州仪器、飞思卡尔、英飞凌等传统巨头主导的图景。然而&#xff0c;仅仅五年后&#xff0c…...

AI Agent变现难题与破局之道:小白程序员必备收藏,2026年蓝海掘金指南!

文章深入分析了当前AI Agent行业的冰火两重天现象&#xff0c;揭示了技术不成熟、伪需求泛滥、基础设施不完善等六大核心底层逻辑导致变现困难。同时&#xff0c;文章指出了电商全链路、企业办公自动化、本地生活商家、开发者垂直、垂类定制化等五大变现蓝海赛道&#xff0c;并…...

Pearcleaner技术深度解析:macOS应用清理的架构设计与实现原理

Pearcleaner技术深度解析&#xff1a;macOS应用清理的架构设计与实现原理 【免费下载链接】Pearcleaner A free, source-available and fair-code licensed mac app cleaner 项目地址: https://gitcode.com/gh_mirrors/pe/Pearcleaner Pearcleaner是一款面向技术开发者和…...

Java 数字校验实战:从工具类到正则,性能与场景的深度抉择

1. 数字校验的常见场景与挑战 在Java开发中&#xff0c;数字校验是个看似简单却暗藏玄机的基础操作。我见过太多项目因为数字校验不严谨导致的数据异常&#xff0c;比如用户输入"12a3"被误认为金额&#xff0c;或者接口接收"-1.2.3"这样的非法浮点数。这些…...

员工管理(新增员工)、事务管理和文件上传(阿里云OSS)

员工管理(新增员工) 思路就是就是新增的员工基本信息和批量保存员工的工作经历信息&#xff0c;也就是后端对应了两条sql语句&#xff0c; 1.保存员工基本信息 Emp实体类中新添一个字段用于保存员工工作经历 //封装工作经历 private List<EmpExpr> exprList; (1)Cont…...