本文主要参考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相关推荐

  1. Vulkan_Ray Tracing 11_Intersection Shader(相交着色器)

    本文主要参考NVIDIA Vulkan Ray Tracing Tutorial教程,环境配置与程序均可参照此文档执行(个人水平有限,如有错误请参照原文). 本部分主要展示如何使用相交着色器及不同的材 ...

  2. Vulkan_Ray Tracing 05_光线追踪管线

    本文主要参考NVIDIA Vulkan Ray Tracing Tutorial教程,环境配置与程序均可参照此文档执行(个人水平有限,如有错误请参照原文). 一.光线追踪管线 在光线追踪时,与光栅化不 ...

  3. 微软究竟意欲何为 DirectX 11.1特性解析

    好生猛的"X.1" 2011年的9月注定是一个不平凡的9月,在这个9月里,微软为我们封上了大量惊艳的甚至是富有开拓性的新作.这其中不仅有极富突破性,甚至打破了wintel联盟的wi ...

  4. 【GPU精粹与Shader编程】(一) 全系列核心知识点总览

    系列文章前言 <GPU Gems>1~3 .<GPU Pro>1~7 以及<GEM Zen>组成的GPU精粹系列书籍,是游戏开发.计算机图形学和渲染领域的业界大牛们 ...

  5. Ray tracing 光线追踪 之 embree ,从入门到精通 01 安装与体验

    1. 什么是光线追踪 渲染技术之一,区别于光栅化图形学OpenGL等与体渲染图形学 VTK等 2. embree 安装 2.1 下载: Releases · embree/embree · GitHu ...

  6. 【GPU精粹与Shader编程】(四) 《GPU Gems 2》全书核心内容提炼总结 · 上篇

    本文由@浅墨_毛星云 出品,首发于知乎专栏,转载请注明出处 文章链接: https://zhuanlan.zhihu.com/p/38411575 <GPU Gems 2>这本书除了丰富的 ...

  7. Unity学习之Shader

    Shader 是用来实现图像渲染的,用来替代固定渲染管线的可编辑程序.其中Vertex Shader(顶点着色器)主要负责顶点的几何关系等的运算,Pixel Shader(像素着色器)主要负责片元颜色 ...

  8. 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 ...

  9. 【Unity Shader】用Cubemap实现天空盒和环境映射

    1 关于Cubemap Cubemap在实时渲染中有很多应用,最常见的就是实现天空盒(Skybox)和环境映射(Environment Mapping). 2 实现天空盒 2.1 实现原理 天空盒不陌 ...

最新文章

  1. mysql临时表如何分页查询慢_数据量很大,分页查询很慢,怎么优化?
  2. 学习网络请求返回json对应的model
  3. 深入Managed DirectX9(四)
  4. python 打包文件
  5. 0402封装ESD二极管选型
  6. 强烈推荐:程序员必备的两个超级工具,一个是百宝箱,一个是百宝库
  7. 其它综合-VMware虚拟机安装Ubuntu 19.04 版本
  8. 优化PHP程序的方法(温故知新)
  9. mysql如何实现acid中的a_MySQL如何实现事务的ACID
  10. mysql-演练0722
  11. IntelliJ IDEA中创建jsp项目
  12. AP6212 蓝牙调试步骤
  13. 目前微型计算机硬件主要采用,目前使用的微型计算机硬件主要采用的电子器件是()。 A. 真空管 B. 晶体管 C. 大规模和超大规模集成电路...
  14. 域名ICP备案查询API接口,免费好用
  15. 【百战GAN】SRGAN人脸低分辨率老照片修复代码实战
  16. 网线百兆与千兆的接法
  17. 附件携马之CS免杀shellcode过国内主流杀软
  18. 《非计算机毕业生2015互联网校招求职之路》2014-10-15
  19. verilog将100mhz分频为1hz_verilog—分频器设计
  20. 红宝书初步研读随手笔记

热门文章

  1. 软件设计师教程(一)计算机系统知识-计算机系统基础知识
  2. c语言写自动填写表单提交,利用C语言实现POST数据包如此简单【模拟网页提交表单】...
  3. papaparse 使用_javascript – 如何使用Papa Parse从CSV文件中提取数据到React状态?
  4. [NOI2015]荷马史诗【哈夫曼编码】
  5. 20220518面试题
  6. 如何在IDEA内设置启动参数和环境变量
  7. Jim's游戏外挂学习笔记3——继续找当前地图数据和所处坐标存放的地址
  8. 手机浏览器Cookie保存不上的问题
  9. 厉害了,我汇总了43个EMC专业术语
  10. 嵌入式GSM短信息接口的软硬件设计