Vulkan_Ray Tracing 13_Callable Shader
本文主要参考NVIDIA Vulkan Ray Tracing Tutorial教程,环境配置与程序均可参照此文档执行(个人水平有限,如有错误请参照原文)。
一、可调用着色器
可调用着色器可以访问一个可调用的有效荷载,类似光线有效荷载值的使用来处理光追程序。 并且可调用着色器通过从一个允许的着色器阶段调用OpExecuteCallableKHR来执行。
光线追踪允许在光线生成,最近命中,未命中或其他可调用着色器阶段使用可调用着色器。它类似于间接函数调用,无需将这些着色器与可执行程序链接。
1.1 数据存储
数据只能访问从父阶段(上阶段)传入可调用对象的数据。每次只有一个结构传递,并且应该像有效载荷一样定义。
在父阶段(上阶段),使用callableDataEXT存储限定符数据,它可以声明为以下模样:
layout(location = 0) callableDataEXT rayLight cLight;
布局(位置 = 0) callableDataEXT rayLight cLight;
其中rayLight结构体在公共文件中定义为:
struct rayLight
{vec3 inHitPosition;float outLightDistance;vec3 outLightDir;float outIntensity;
};
之后在传入的可调用着色器中,您必须使用callableDataInEXT存储限定符数据。
layout(location = 0) callableDataInEXT rayLight cLight;
1.2 执行
要执行可调用着色器,父阶段(上阶段)需要调用executeCallableEXT函数
executeCallableEXT(pushC.lightType, 0);
- 第一个参数是 SBT 记录索引
- 第二个参数对应于“位置”索引
二、向 SBT 添加可调用着色器
2.1 创建着色器模块
在 HelloVulkan::createRtPipeline() 中,在添加最近命中着色器之后,我们将立即为每种类型的光添加 3 个可调用着色器。
首先,创建着色器模块
enum StageIndices{eRaygen,eMiss,eMiss2,eClosestHit,eCall0,eCall1,eCall2,eShaderGroupCount};...// Call0stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/light_point.rcall.spv", true, defaultSearchPaths, true));stage.stage = VK_SHADER_STAGE_CALLABLE_BIT_KHR;stages[eCall0] = stage;// Call1stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/light_spot.rcall.spv", true, defaultSearchPaths, true));stage.stage = VK_SHADER_STAGE_CALLABLE_BIT_KHR;stages[eCall1] = stage;// Call2stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/light_inf.rcall.spv", true, defaultSearchPaths, true));stage.stage = VK_SHADER_STAGE_CALLABLE_BIT_KHR;stages[eCall2] = stage;
然后是 3 组可调用着色器以及与之相关的阶段。
// 可调用着色器group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;group.closestHitShader = VK_SHADER_UNUSED_KHR;group.generalShader = eCall0;m_rtShaderGroups.push_back(group);group.generalShader = eCall1;m_rtShaderGroups.push_back(group);group.generalShader = eCall2;m_rtShaderGroups.push_back(group);
2.2 着色器源码
light_point.rcall
#version 460 core
#extension GL_EXT_ray_tracing : enable
#extension GL_GOOGLE_include_directive : enable
#include "raycommon.glsl"layout(location = 0) callableDataInEXT rayLight cLight;layout(push_constant) uniform Constants
{vec4 clearColor;vec3 lightPosition;float lightIntensity;vec3 lightDirection;float lightSpotCutoff;float lightSpotOuterCutoff;int lightType;
};void main()
{vec3 lDir = lightPosition - cLight.inHitPosition;cLight.outLightDistance = length(lDir);cLight.outIntensity = lightIntensity / (cLight.outLightDistance * cLight.outLightDistance);cLight.outLightDir = normalize(lDir);
}
light_spot.rcall
#version 460 core
#extension GL_EXT_ray_tracing : enable
#extension GL_GOOGLE_include_directive : enable
#include "raycommon.glsl"layout(location = 0) callableDataInEXT rayLight cLight;layout(push_constant) uniform Constants
{vec4 clearColor;vec3 lightPosition;float lightIntensity;vec3 lightDirection;float lightSpotCutoff;float lightSpotOuterCutoff;int lightType;
};void main()
{vec3 lDir = lightPosition - cLight.inHitPosition;cLight.outLightDistance = length(lDir);cLight.outIntensity = lightIntensity / (cLight.outLightDistance * cLight.outLightDistance);cLight.outLightDir = normalize(lDir);float theta = dot(cLight.outLightDir, normalize(-lightDirection));float epsilon = lightSpotCutoff - lightSpotOuterCutoff;float spotIntensity = clamp((theta - lightSpotOuterCutoff) / epsilon, 0.0, 1.0);cLight.outIntensity *= spotIntensity;
}
light_inf.rcall
#version 460 core
#extension GL_EXT_ray_tracing : enable
#extension GL_GOOGLE_include_directive : enable
#include "raycommon.glsl"layout(location = 0) callableDataInEXT rayLight cLight;layout(push_constant) uniform Constants
{vec4 clearColor;vec3 lightPosition;float lightIntensity;vec3 lightDirection;float lightSpotCutoff;float lightSpotOuterCutoff;int lightType;
};void main()
{cLight.outLightDistance = 10000000;cLight.outIntensity = 1.0;cLight.outLightDir = normalize(-lightDirection);
}
三、着色器绑定表
在本例中,我们将使用nvvk::SBTWrapper来创建光线追踪管线,并为着色绑定表创建缓冲区。
在头文件hello_vulkan.h中,需要添加其头文件并添加一个新成员。
#include "nvvk/sbtwrapper_vk.hpp"
...
nvvk::SBTWrapper m_sbtWrapper;
在 HelloVulkan::initRayTracing() 中,按以下方式对其进行初始化。
m_sbtWrapper.setup(m_device, m_graphicsQueueIndex, &m_alloc, m_rtProperties);
在HelloVulkan::createRtPipeline()中,在创建对vkCreateRayTracingPipelinesKHR()的管道调用之后,立即使用以下命令创建SBT。
m_sbtWrapper.create(m_rtPipeline, rayPipelineInfo);
在 HelloVulkan::raytrace() 中,我们必须告诉可调用着色器从哪里开始。由于它们是在命中着色器之后添加的,因此我们在 SBT 中添加以下内容。
SBT 封装类中可以直接返回我们需要的信息。因此,我们可以直接VkStridedDeviceAddressRegionKHR获取每个组类型的,而不是计算各种偏移量 。
四、调用着色器
在最近命中着色器中,我们现在可以根据光的类型直接调用对应的着色器,而不是使用 if-else 情况。
cLight.inHitPosition = worldPos;
//#define DONT_USE_CALLABLE
#if defined(DONT_USE_CALLABLE)// Point lightif(pushC.lightType == 0){vec3 lDir = pushC.lightPosition - cLight.inHitPosition;float lightDistance = length(lDir);cLight.outIntensity = pushC.lightIntensity / (lightDistance * lightDistance);cLight.outLightDir = normalize(lDir);cLight.outLightDistance = lightDistance;}else if(pushC.lightType == 1){vec3 lDir = pushC.lightPosition - cLight.inHitPosition;cLight.outLightDistance = length(lDir);cLight.outIntensity =pushC.lightIntensity / (cLight.outLightDistance * cLight.outLightDistance);cLight.outLightDir = normalize(lDir);float theta = dot(cLight.outLightDir, normalize(-pushC.lightDirection));float epsilon = pushC.lightSpotCutoff - pushC.lightSpotOuterCutoff;float spotIntensity = clamp((theta - pushC.lightSpotOuterCutoff) / epsilon, 0.0, 1.0);cLight.outIntensity *= spotIntensity;}else // Directional light{cLight.outLightDir = normalize(-pushC.lightDirection);cLight.outIntensity = 1.0;cLight.outLightDistance = 10000000;}
#elseexecuteCallableEXT(pushC.lightType, 0);
#endif
对应执行效果如下:
Vulkan_Ray Tracing 13_Callable Shader相关推荐
- Vulkan_Ray Tracing 11_Intersection Shader(相交着色器)
本文主要参考NVIDIA Vulkan Ray Tracing Tutorial教程,环境配置与程序均可参照此文档执行(个人水平有限,如有错误请参照原文). 本部分主要展示如何使用相交着色器及不同的材 ...
- Vulkan_Ray Tracing 05_光线追踪管线
本文主要参考NVIDIA Vulkan Ray Tracing Tutorial教程,环境配置与程序均可参照此文档执行(个人水平有限,如有错误请参照原文). 一.光线追踪管线 在光线追踪时,与光栅化不 ...
- 微软究竟意欲何为 DirectX 11.1特性解析
好生猛的"X.1" 2011年的9月注定是一个不平凡的9月,在这个9月里,微软为我们封上了大量惊艳的甚至是富有开拓性的新作.这其中不仅有极富突破性,甚至打破了wintel联盟的wi ...
- 【GPU精粹与Shader编程】(一) 全系列核心知识点总览
系列文章前言 <GPU Gems>1~3 .<GPU Pro>1~7 以及<GEM Zen>组成的GPU精粹系列书籍,是游戏开发.计算机图形学和渲染领域的业界大牛们 ...
- Ray tracing 光线追踪 之 embree ,从入门到精通 01 安装与体验
1. 什么是光线追踪 渲染技术之一,区别于光栅化图形学OpenGL等与体渲染图形学 VTK等 2. embree 安装 2.1 下载: Releases · embree/embree · GitHu ...
- 【GPU精粹与Shader编程】(四) 《GPU Gems 2》全书核心内容提炼总结 · 上篇
本文由@浅墨_毛星云 出品,首发于知乎专栏,转载请注明出处 文章链接: https://zhuanlan.zhihu.com/p/38411575 <GPU Gems 2>这本书除了丰富的 ...
- Unity学习之Shader
Shader 是用来实现图像渲染的,用来替代固定渲染管线的可编辑程序.其中Vertex Shader(顶点着色器)主要负责顶点的几何关系等的运算,Pixel Shader(像素着色器)主要负责片元颜色 ...
- Anatomy of Nvidia's Voxel Cone Tracing Code (VXGI)
Here is diffuse cone tracing code. 1 // 2 Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011 ...
- 【Unity Shader】用Cubemap实现天空盒和环境映射
1 关于Cubemap Cubemap在实时渲染中有很多应用,最常见的就是实现天空盒(Skybox)和环境映射(Environment Mapping). 2 实现天空盒 2.1 实现原理 天空盒不陌 ...
最新文章
- mysql临时表如何分页查询慢_数据量很大,分页查询很慢,怎么优化?
- 学习网络请求返回json对应的model
- 深入Managed DirectX9(四)
- python 打包文件
- 0402封装ESD二极管选型
- 强烈推荐:程序员必备的两个超级工具,一个是百宝箱,一个是百宝库
- 其它综合-VMware虚拟机安装Ubuntu 19.04 版本
- 优化PHP程序的方法(温故知新)
- mysql如何实现acid中的a_MySQL如何实现事务的ACID
- mysql-演练0722
- IntelliJ IDEA中创建jsp项目
- AP6212 蓝牙调试步骤
- 目前微型计算机硬件主要采用,目前使用的微型计算机硬件主要采用的电子器件是()。 A. 真空管 B. 晶体管 C. 大规模和超大规模集成电路...
- 域名ICP备案查询API接口,免费好用
- 【百战GAN】SRGAN人脸低分辨率老照片修复代码实战
- 网线百兆与千兆的接法
- 附件携马之CS免杀shellcode过国内主流杀软
- 《非计算机毕业生2015互联网校招求职之路》2014-10-15
- verilog将100mhz分频为1hz_verilog—分频器设计
- 红宝书初步研读随手笔记
热门文章
- 软件设计师教程(一)计算机系统知识-计算机系统基础知识
- c语言写自动填写表单提交,利用C语言实现POST数据包如此简单【模拟网页提交表单】...
- papaparse 使用_javascript – 如何使用Papa Parse从CSV文件中提取数据到React状态?
- [NOI2015]荷马史诗【哈夫曼编码】
- 20220518面试题
- 如何在IDEA内设置启动参数和环境变量
- Jim's游戏外挂学习笔记3——继续找当前地图数据和所处坐标存放的地址
- 手机浏览器Cookie保存不上的问题
- 厉害了,我汇总了43个EMC专业术语
- 嵌入式GSM短信息接口的软硬件设计