Refactoring
This commit is contained in:
parent
3e399adf0a
commit
d90ce79135
222 changed files with 9045 additions and 5734 deletions
|
|
@ -10,7 +10,6 @@ The ray tracing tutorial only uses one closest hit shader, but it is also possib
|
|||
For example, this could be used to give different models different shaders, or to use a less complex shader when tracing
|
||||
reflections.
|
||||
|
||||
|
||||
## Setting up the Scene
|
||||
|
||||
For this example, we will load the `wuson` model and create another translated instance of it.
|
||||
|
|
@ -21,11 +20,8 @@ Then you can change the `helloVk.loadModel` calls to the following:
|
|||
// Creation of the example
|
||||
helloVk.loadModel(nvh::findFile("media/scenes/wuson.obj", defaultSearchPaths, true),
|
||||
nvmath::translation_mat4(nvmath::vec3f(-1, 0, 0)));
|
||||
|
||||
HelloVulkan::ObjInstance inst = helloVk.m_objInstance[0]; // Instance the wuson object
|
||||
inst.transform = nvmath::translation_mat4(nvmath::vec3f(1, 0, 0));
|
||||
inst.transformIT = nvmath::transpose(nvmath::invert(inst.transform));
|
||||
helloVk.m_objInstance.push_back(inst); // Adding an instance of the wuson
|
||||
|
||||
helloVk.m_instances.push_back({nvmath::translation_mat4(nvmath::vec3f(1, 0, 0)), 0}); // Adding an instance of the Wuson
|
||||
|
||||
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths, true));
|
||||
~~~~
|
||||
|
|
@ -93,43 +89,28 @@ If you set the offset to `1`, then all ray hits will use the new CHIT, and the r
|
|||
|
||||

|
||||
|
||||
!!! Warning
|
||||
After testing this out, make sure to revert this change in `raytrace.rgen` before continuing.
|
||||
**:warning:** After testing this out, make sure to revert this change in `raytrace.rgen` before continuing.
|
||||
|
||||
### `hello_vulkan.h`
|
||||
|
||||
In the `ObjInstance` structure, we will add a new member variable that specifies which hit shader the instance will use:
|
||||
In the `ObjInstance` structure, we will add a new member `hitgroup` variable that specifies which hit shader the instance will use:
|
||||
|
||||
~~~~ C++
|
||||
uint32_t hitgroup{0}; // Hit group of the instance
|
||||
struct ObjInstance
|
||||
{
|
||||
nvmath::mat4f transform; // Matrix of the instance
|
||||
uint32_t objIndex{0}; // Model index reference
|
||||
int hitgroup{0}; // Hit group of the instance
|
||||
};
|
||||
~~~~
|
||||
|
||||
This change also needs to be reflected in the `sceneDesc` structure in `wavefront.glsl`:
|
||||
|
||||
~~~~ C++
|
||||
struct SceneDesc
|
||||
{
|
||||
mat4 transfo;
|
||||
mat4 transfoIT;
|
||||
int objId;
|
||||
int txtOffset;
|
||||
uint64_t vertexAddress;
|
||||
uint64_t indexAddress;
|
||||
uint64_t materialAddress;
|
||||
uint64_t materialIndexAddress;
|
||||
int hitGroup;
|
||||
};
|
||||
~~~~
|
||||
|
||||
**Note:**
|
||||
The solution will not automatically recompile the shaders after this change to `wavefront.glsl`; instead, you will need to recompile all of the SPIR-V shaders.
|
||||
|
||||
### `hello_vulkan.cpp`
|
||||
|
||||
Finally, we need to tell the top-level acceleration structure which hit group to use for each instance. In `createTopLevelAS()` in `hello_vulkan.cpp`, change the line setting `rayInst.hitGroupId` to
|
||||
Finally, we need to tell the top-level acceleration structure which hit group to use for each instance. In `createTopLevelAS()`
|
||||
in `hello_vulkan.cpp`, we will offset the record of the shading binding table (SBT) with the hit group.
|
||||
|
||||
~~~~ C++
|
||||
rayInst.hitGroupId = m_objInstance[i].hitgroup;
|
||||
rayInst.instanceShaderBindingTableRecordOffset = inst.hitgroup; // Using the hit group set in main
|
||||
~~~~
|
||||
|
||||
### Choosing the Hit shader
|
||||
|
|
@ -137,8 +118,8 @@ rayInst.hitGroupId = m_objInstance[i].hitgroup;
|
|||
Back in `main.cpp`, after loading the scene's models, we can now have both `wuson` models use the new CHIT by adding the following:
|
||||
|
||||
~~~~ C++
|
||||
helloVk.m_objInstance[0].hitgroup = 1;
|
||||
helloVk.m_objInstance[1].hitgroup = 1;
|
||||
helloVk.m_instances[0].hitgroup = 1;
|
||||
helloVk.m_instances[1].hitgroup = 1;
|
||||
~~~~
|
||||
|
||||

|
||||
|
|
@ -149,33 +130,24 @@ When creating the [Shader Binding Table](https://www.khronos.org/registry/vulkan
|
|||
|
||||
This information can be used to pass extra information to a shader, for each entry in the SBT.
|
||||
|
||||
**Note:**
|
||||
**:warning: Note:**
|
||||
Since each entry in an SBT group must have the same size, each entry of the group has to have enough space to accommodate the largest element in the entire group.
|
||||
|
||||
The following diagram represents our current SBT, with the addition of some data to `HitGroup1`. As mentioned in the **note**, even if
|
||||
`HitGroup0` doesn't have any shader record data, it still needs to have the same size as `HitGroup1`.
|
||||
`HitGroup0` doesn't have any shader record data, it still needs to have the same size as `HitGroup1`, the largest of the hit group.
|
||||
|
||||
~~~~ Bash
|
||||
+-----------+----------+
|
||||
| RayGen | Handle 0 |
|
||||
+-----------+----------+
|
||||
| Miss | Handle 1 |
|
||||
+-----------+----------+
|
||||
| Miss | Handle 2 |
|
||||
+-----------+----------+
|
||||
| HitGroup0 | Handle 3 |
|
||||
| | -Empty- |
|
||||
+-----------+----------+
|
||||
| HitGroup1 | Handle 4 |
|
||||
| | Data 0 |
|
||||
+-----------+----------+
|
||||
~~~~
|
||||
|Group|Handle|
|
||||
| ------ | ------ |
|
||||
| RayGen | Handle 0 |
|
||||
| Miss0 | Handle 1 |
|
||||
| Miss1 | Handle 2 |
|
||||
| HitGroup0 | Handle 3 </br>-Empty- |
|
||||
| HitGroup1 | Handle 4 </br> Data 0 |
|
||||
|
||||
## `hello_vulkan.h`
|
||||
|
||||
In the HelloVulkan class, we will add a structure to hold the hit group data.
|
||||
|
||||
<script type="preformatted">
|
||||
~~~~ C++
|
||||
struct HitRecordBuffer
|
||||
{
|
||||
|
|
@ -183,14 +155,13 @@ In the HelloVulkan class, we will add a structure to hold the hit group data.
|
|||
};
|
||||
std::vector<HitRecordBuffer> m_hitShaderRecord;
|
||||
~~~~
|
||||
</script>
|
||||
|
||||
### `raytrace2.rchit`
|
||||
|
||||
In the closest hit shader, we can retrieve the shader record using the `layout(shaderRecordEXT)` descriptor
|
||||
|
||||
~~~~ C++
|
||||
layout(shaderRecordEXT) buffer sr_ { vec4 c; } shaderRec;
|
||||
layout(shaderRecordEXT) buffer sr_ { vec4 shaderRec; };
|
||||
~~~~
|
||||
|
||||
and use this information to return the color:
|
||||
|
|
@ -198,14 +169,13 @@ and use this information to return the color:
|
|||
~~~~ C++
|
||||
void main()
|
||||
{
|
||||
prd.hitValue = shaderRec.c.rgb;
|
||||
prd.hitValue = shaderRec.rgb;
|
||||
}
|
||||
~~~~
|
||||
|
||||
**Note:**
|
||||
**:warning: Note:**
|
||||
Adding a new shader requires to rerun CMake to added to the project compilation system.
|
||||
|
||||
|
||||
### `main.cpp`
|
||||
|
||||
In `main`, after we set which hit group an instance will use, we can add the data we want to set through the shader record.
|
||||
|
|
@ -217,13 +187,13 @@ In `main`, after we set which hit group an instance will use, we can add the dat
|
|||
|
||||
### `HelloVulkan::createRtShaderBindingTable`
|
||||
|
||||
**NEW**
|
||||
**:star:NEW:star:**
|
||||
|
||||
The creation of the shading binding table as it was done, was using hardcoded offsets and potentially could lead to errors.
|
||||
Instead, the new code uses the `nvvk::SBTWraper` that uses the ray tracing pipeline and the `VkRayTracingPipelineCreateInfoKHR` to
|
||||
create the SBT information.
|
||||
The creation of the shading binding table as it was done, was using hardcoded offsets and potentially could lead to errors.
|
||||
Instead, the new code uses the `nvvk::SBTWraper` that uses the ray tracing pipeline and the `VkRayTracingPipelineCreateInfoKHR` to
|
||||
create the SBT information.
|
||||
|
||||
The wrapper will find the handles for each group and will add the
|
||||
The wrapper will find the handles for each group and will add the
|
||||
data `m_hitShaderRecord` to the Hit group.
|
||||
|
||||
```` C
|
||||
|
|
@ -238,19 +208,17 @@ The buffer for Hit will have the following layout
|
|||
|
||||
```
|
||||
| handle | handle,data | handle,data |
|
||||
```
|
||||
```
|
||||
|
||||
The wrapper will make sure the stride covers the largest data and is aligned
|
||||
The wrapper will make sure the stride covers the largest data and is aligned
|
||||
based on the GPU properties.
|
||||
|
||||
|
||||
|
||||
**OLD - for reference**
|
||||
|
||||
Since we are no longer compacting all handles in a continuous buffer, we need to fill the SBT as described above.
|
||||
~~Since we are no longer compacting all handles in a continuous buffer, we need to fill the SBT as described above.~~
|
||||
|
||||
After retrieving the handles of all 5 groups (raygen, miss, miss shadow, hit0, and hit1)
|
||||
using `getRayTracingShaderGroupHandlesKHR`, store the pointers to easily retrieve them.
|
||||
~~After retrieving the handles of all 5 groups (raygen, miss, miss shadow, hit0, and hit1)
|
||||
using `getRayTracingShaderGroupHandlesKHR`, store the pointers to easily retrieve them.~~
|
||||
|
||||
~~~~ C++
|
||||
// Retrieve the handle pointers
|
||||
|
|
@ -261,7 +229,7 @@ using `getRayTracingShaderGroupHandlesKHR`, store the pointers to easily retriev
|
|||
}
|
||||
~~~~
|
||||
|
||||
The size of each group can be described as follows:
|
||||
~~The size of each group can be described as follows:~~
|
||||
|
||||
~~~~ C++
|
||||
// Sizes
|
||||
|
|
@ -272,7 +240,7 @@ The size of each group can be described as follows:
|
|||
uint32_t newSbtSize = rayGenSize + 2 * missSize + 2 * hitSize;
|
||||
~~~~
|
||||
|
||||
Then write the new SBT like this, where only Hit 1 has extra data.
|
||||
~~Then write the new SBT like this, where only Hit 1 has extra data.~~
|
||||
|
||||
~~~~ C++
|
||||
std::vector<uint8_t> sbtBuffer(newSbtSize);
|
||||
|
|
@ -299,16 +267,15 @@ Then write the new SBT like this, where only Hit 1 has extra data.
|
|||
}
|
||||
~~~~
|
||||
|
||||
Then change the call to `m_alloc.createBuffer` to create the SBT buffer from `sbtBuffer`:
|
||||
~~Then change the call to `m_alloc.createBuffer` to create the SBT buffer from `sbtBuffer`:~~
|
||||
|
||||
~~~~ C++
|
||||
m_rtSBTBuffer = m_alloc.createBuffer(cmdBuf, sbtBuffer, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR);
|
||||
~~~~
|
||||
|
||||
|
||||
### `raytrace`
|
||||
|
||||
**NEW**
|
||||
**:star:NEW:star:**
|
||||
|
||||
The mvvk::SBTWrapper gives use the information without having to compute the `VkStridedDeviceAddressRegionKHR`
|
||||
|
||||
|
|
@ -319,7 +286,7 @@ The mvvk::SBTWrapper gives use the information without having to compute the `Vk
|
|||
|
||||
**OLD**
|
||||
|
||||
Finally, since the size of the hit group is now larger than just the handle, we need to set the new value of the hit group stride in `HelloVulkan::raytrace`.
|
||||
~~Finally, since the size of the hit group is now larger than just the handle, we need to set the new value of the hit group stride in `HelloVulkan::raytrace`.~~
|
||||
|
||||
~~~~ C++
|
||||
VkDeviceSize hitGroupSize =
|
||||
|
|
@ -327,7 +294,7 @@ Finally, since the size of the hit group is now larger than just the handle, we
|
|||
m_rtProperties.shaderGroupBaseAlignment);
|
||||
~~~~
|
||||
|
||||
The stride device address will be modified like this:
|
||||
~~The stride device address will be modified like this:~~
|
||||
|
||||
~~~~ C++
|
||||
using Stride = VkStridedDeviceAddressRegionKHR;
|
||||
|
|
@ -338,8 +305,8 @@ The stride device address will be modified like this:
|
|||
Stride{0u, 0u, 0u}}; // callable
|
||||
~~~~
|
||||
|
||||
**Note:**
|
||||
The result should now show both `wuson` models with a yellow color.
|
||||
~~**Note:**
|
||||
The result should now show both `wuson` models with a yellow color.~~
|
||||
|
||||

|
||||
|
||||
|
|
@ -349,25 +316,14 @@ The SBT can be larger than the number of shading models, which could then be use
|
|||
|
||||
The following modification will add another entry to the SBT with a different color per instance. The new SBT hit group (2) will use the same CHIT handle (4) as hit group 1.
|
||||
|
||||
~~~~ Bash
|
||||
+-----------+----------+
|
||||
| RayGen | Handle 0 |
|
||||
+-----------+----------+
|
||||
| Miss | Handle 1 |
|
||||
+-----------+----------+
|
||||
| Miss | Handle 2 |
|
||||
+-----------+----------+
|
||||
| HitGroup0 | Handle 3 |
|
||||
| | -Empty- |
|
||||
+-----------+----------+
|
||||
| HitGroup1 | Handle 4 |
|
||||
| | Data 0 |
|
||||
+-----------+----------+
|
||||
| HitGroup2 | Handle 4 |
|
||||
| | Data 1 |
|
||||
+-----------+----------+
|
||||
~~~~
|
||||
|
||||
|Group|Handle|
|
||||
| ------ | ------ |
|
||||
| RayGen | Handle 0 |
|
||||
| Miss0 | Handle 1 |
|
||||
| Miss1 | Handle 2 |
|
||||
| HitGroup0 | Handle 3 </br>-Empty- |
|
||||
| HitGroup1 | Handle 4 </br> Data 0 |
|
||||
| HitGroup1 | Handle 4 </br> Data 1 |
|
||||
|
||||
### `main.cpp`
|
||||
|
||||
|
|
@ -378,19 +334,26 @@ In the description of the scene in `main`, we will tell the `wuson` models to us
|
|||
helloVk.m_hitShaderRecord.resize(2);
|
||||
helloVk.m_hitShaderRecord[0].color = nvmath::vec4f(0, 1, 0, 0); // Green
|
||||
helloVk.m_hitShaderRecord[1].color = nvmath::vec4f(0, 1, 1, 0); // Cyan
|
||||
helloVk.m_objInstance[0].hitgroup = 1; // wuson 0
|
||||
helloVk.m_objInstance[1].hitgroup = 2; // wuson 1
|
||||
helloVk.m_instances[0].hitgroup = 1; // wuson 0
|
||||
helloVk.m_instances[1].hitgroup = 2; // wuson 1
|
||||
~~~~
|
||||
|
||||
### `createRtShaderBindingTable`
|
||||
|
||||
The size of the SBT will now account for its 3 hit groups:
|
||||
**:star:NEW:star:**
|
||||
|
||||
If you are using the SBT wrapper, this part is automatically handled.
|
||||
|
||||
**OLD**
|
||||
|
||||
|
||||
~~The size of the SBT will now account for its 3 hit groups:~~
|
||||
|
||||
~~~~ C++
|
||||
uint32_t newSbtSize = rayGenSize + 2 * missSize + 3 * hitSize;
|
||||
~~~~
|
||||
|
||||
Finally, we need to add the new entry as well at the end of the buffer, reusing the handle of the second Hit Group and setting a different color.
|
||||
~~Finally, we need to add the new entry as well at the end of the buffer, reusing the handle of the second Hit Group and setting a different color.~~
|
||||
|
||||
~~~~ C++
|
||||
pHitBuffer = pBuffer;
|
||||
|
|
@ -400,7 +363,7 @@ Finally, we need to add the new entry as well at the end of the buffer, reusing
|
|||
pBuffer += hitSize;
|
||||
~~~~
|
||||
|
||||
**Note:**
|
||||
Adding entries like this can be error-prone and inconvenient for decent
|
||||
~~**Note:**
|
||||
Adding entries like this can be error-prone and inconvenient for decent
|
||||
scene sizes. Instead, it is recommended to wrap the storage of handles, data,
|
||||
and size per group in a SBT utility to handle this automatically.
|
||||
and size per group in a SBT utility to handle this automatically.~~
|
||||
|
|
|
|||
|
|
@ -40,17 +40,6 @@
|
|||
extern std::vector<std::string> defaultSearchPaths;
|
||||
|
||||
|
||||
// Holding the camera matrices
|
||||
struct CameraMatrices
|
||||
{
|
||||
nvmath::mat4f view;
|
||||
nvmath::mat4f proj;
|
||||
nvmath::mat4f viewInverse;
|
||||
// #VKRay
|
||||
nvmath::mat4f projInverse;
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Keep the handle on the device
|
||||
// Initialize the tool to do all our allocations: buffers, images
|
||||
|
|
@ -70,16 +59,17 @@ void HelloVulkan::updateUniformBuffer(const VkCommandBuffer& cmdBuf)
|
|||
{
|
||||
// Prepare new UBO contents on host.
|
||||
const float aspectRatio = m_size.width / static_cast<float>(m_size.height);
|
||||
CameraMatrices hostUBO = {};
|
||||
hostUBO.view = CameraManip.getMatrix();
|
||||
hostUBO.proj = nvmath::perspectiveVK(CameraManip.getFov(), aspectRatio, 0.1f, 1000.0f);
|
||||
// hostUBO.proj[1][1] *= -1; // Inverting Y for Vulkan (not needed with perspectiveVK).
|
||||
hostUBO.viewInverse = nvmath::invert(hostUBO.view);
|
||||
// #VKRay
|
||||
hostUBO.projInverse = nvmath::invert(hostUBO.proj);
|
||||
GlobalUniforms hostUBO = {};
|
||||
const auto& view = CameraManip.getMatrix();
|
||||
const auto& proj = nvmath::perspectiveVK(CameraManip.getFov(), aspectRatio, 0.1f, 1000.0f);
|
||||
// proj[1][1] *= -1; // Inverting Y for Vulkan (not needed with perspectiveVK).
|
||||
|
||||
hostUBO.viewProj = proj * view;
|
||||
hostUBO.viewInverse = nvmath::invert(view);
|
||||
hostUBO.projInverse = nvmath::invert(proj);
|
||||
|
||||
// UBO on the device, and what stages access it.
|
||||
VkBuffer deviceUBO = m_cameraMat.buffer;
|
||||
VkBuffer deviceUBO = m_bGlobals.buffer;
|
||||
auto uboUsageStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
|
||||
|
||||
// Ensure that the modified UBO is not visible to previous frames.
|
||||
|
|
@ -95,7 +85,7 @@ void HelloVulkan::updateUniformBuffer(const VkCommandBuffer& cmdBuf)
|
|||
|
||||
// Schedule the host-to-device upload. (hostUBO is copied into the cmd
|
||||
// buffer so it is okay to deallocate when the function returns).
|
||||
vkCmdUpdateBuffer(cmdBuf, m_cameraMat.buffer, 0, sizeof(CameraMatrices), &hostUBO);
|
||||
vkCmdUpdateBuffer(cmdBuf, m_bGlobals.buffer, 0, sizeof(GlobalUniforms), &hostUBO);
|
||||
|
||||
// Making sure the updated UBO will be visible.
|
||||
VkBufferMemoryBarrier afterBarrier{VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER};
|
||||
|
|
@ -115,13 +105,14 @@ void HelloVulkan::createDescriptorSetLayout()
|
|||
{
|
||||
auto nbTxt = static_cast<uint32_t>(m_textures.size());
|
||||
|
||||
// Camera matrices (binding = 0)
|
||||
m_descSetLayoutBind.addBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
||||
// Scene description (binding = 1)
|
||||
m_descSetLayoutBind.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
|
||||
// Camera matrices
|
||||
m_descSetLayoutBind.addBinding(SceneBindings::eGlobals, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1,
|
||||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
||||
// Obj descriptions
|
||||
m_descSetLayoutBind.addBinding(SceneBindings::eObjDescs, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
|
||||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
// Textures (binding = 2)
|
||||
m_descSetLayoutBind.addBinding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTxt,
|
||||
// Textures
|
||||
m_descSetLayoutBind.addBinding(SceneBindings::eTextures, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTxt,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
|
||||
|
||||
|
|
@ -138,11 +129,11 @@ void HelloVulkan::updateDescriptorSet()
|
|||
std::vector<VkWriteDescriptorSet> writes;
|
||||
|
||||
// Camera matrices and scene description
|
||||
VkDescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||
VkDescriptorBufferInfo dbiUnif{m_bGlobals.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, SceneBindings::eGlobals, &dbiUnif));
|
||||
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 1, &dbiSceneDesc));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_bObjDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, SceneBindings::eObjDescs, &dbiSceneDesc));
|
||||
|
||||
// All texture samplers
|
||||
std::vector<VkDescriptorImageInfo> diit;
|
||||
|
|
@ -150,7 +141,7 @@ void HelloVulkan::updateDescriptorSet()
|
|||
{
|
||||
diit.emplace_back(texture.descriptor);
|
||||
}
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 2, diit.data()));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, SceneBindings::eTextures, diit.data()));
|
||||
|
||||
// Writing the information
|
||||
vkUpdateDescriptorSets(m_device, static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||
|
|
@ -162,7 +153,7 @@ void HelloVulkan::updateDescriptorSet()
|
|||
//
|
||||
void HelloVulkan::createGraphicsPipeline()
|
||||
{
|
||||
VkPushConstantRange pushConstantRanges = {VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ObjPushConstant)};
|
||||
VkPushConstantRange pushConstantRanges = {VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstantRaster)};
|
||||
|
||||
// Creating the Pipeline Layout
|
||||
VkPipelineLayoutCreateInfo createInfo{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO};
|
||||
|
|
@ -222,30 +213,35 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
model.indexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_indices, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | rayTracingFlags);
|
||||
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | flag);
|
||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | flag);
|
||||
// Creates all textures found
|
||||
uint32_t txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
// Creates all textures found and find the offset for this model
|
||||
auto txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
createTextureImages(cmdBuf, loader.m_textures);
|
||||
cmdBufGet.submitAndWait(cmdBuf);
|
||||
m_alloc.finalizeAndReleaseStaging();
|
||||
|
||||
std::string objNb = std::to_string(m_objModel.size());
|
||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.indexBuffer.buffer, (std::string("index_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matColorBuffer.buffer, (std::string("mat_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matIndexBuffer.buffer, (std::string("matIdx_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb)));
|
||||
m_debug.setObjectName(model.indexBuffer.buffer, (std::string("index_" + objNb)));
|
||||
m_debug.setObjectName(model.matColorBuffer.buffer, (std::string("mat_" + objNb)));
|
||||
m_debug.setObjectName(model.matIndexBuffer.buffer, (std::string("matIdx_" + objNb)));
|
||||
|
||||
// Keeping transformation matrix of the instance
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = txtOffset;
|
||||
instance.vertices = nvvk::getBufferDeviceAddress(m_device, model.vertexBuffer.buffer);
|
||||
instance.indices = nvvk::getBufferDeviceAddress(m_device, model.indexBuffer.buffer);
|
||||
instance.materials = nvvk::getBufferDeviceAddress(m_device, model.matColorBuffer.buffer);
|
||||
instance.materialIndices = nvvk::getBufferDeviceAddress(m_device, model.matIndexBuffer.buffer);
|
||||
instance.transform = transform;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
m_instances.push_back(instance);
|
||||
|
||||
// Creating information for device access
|
||||
ObjDesc desc;
|
||||
desc.txtOffset = txtOffset;
|
||||
desc.vertexAddress = nvvk::getBufferDeviceAddress(m_device, model.vertexBuffer.buffer);
|
||||
desc.indexAddress = nvvk::getBufferDeviceAddress(m_device, model.indexBuffer.buffer);
|
||||
desc.materialAddress = nvvk::getBufferDeviceAddress(m_device, model.matColorBuffer.buffer);
|
||||
desc.materialIndexAddress = nvvk::getBufferDeviceAddress(m_device, model.matIndexBuffer.buffer);
|
||||
|
||||
// Keeping the obj host model and device description
|
||||
m_objModel.emplace_back(model);
|
||||
m_objInstance.emplace_back(instance);
|
||||
m_objDesc.emplace_back(desc);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -255,9 +251,9 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
//
|
||||
void HelloVulkan::createUniformBuffer()
|
||||
{
|
||||
m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
m_debug.setObjectName(m_cameraMat.buffer, "cameraMat");
|
||||
m_bGlobals = m_alloc.createBuffer(sizeof(GlobalUniforms), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
m_debug.setObjectName(m_bGlobals.buffer, "Globals");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
|
@ -266,15 +262,15 @@ void HelloVulkan::createUniformBuffer()
|
|||
// - Transformation
|
||||
// - Offset for texture
|
||||
//
|
||||
void HelloVulkan::createSceneDescriptionBuffer()
|
||||
void HelloVulkan::createObjDescriptionBuffer()
|
||||
{
|
||||
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
|
||||
|
||||
auto cmdBuf = cmdGen.createCommandBuffer();
|
||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
m_bObjDesc = m_alloc.createBuffer(cmdBuf, m_objDesc, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
cmdGen.submitAndWait(cmdBuf);
|
||||
m_alloc.finalizeAndReleaseStaging();
|
||||
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
||||
m_debug.setObjectName(m_bObjDesc.buffer, "ObjDescs");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
|
@ -360,8 +356,8 @@ void HelloVulkan::destroyResources()
|
|||
vkDestroyDescriptorPool(m_device, m_descPool, nullptr);
|
||||
vkDestroyDescriptorSetLayout(m_device, m_descSetLayout, nullptr);
|
||||
|
||||
m_alloc.destroy(m_cameraMat);
|
||||
m_alloc.destroy(m_sceneDesc);
|
||||
m_alloc.destroy(m_bGlobals);
|
||||
m_alloc.destroy(m_bObjDesc);
|
||||
|
||||
for(auto& m : m_objModel)
|
||||
{
|
||||
|
|
@ -416,14 +412,14 @@ void HelloVulkan::rasterize(const VkCommandBuffer& cmdBuf)
|
|||
vkCmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, &m_descSet, 0, nullptr);
|
||||
|
||||
|
||||
for(int i = 0; i < m_objInstance.size(); ++i)
|
||||
for(const HelloVulkan::ObjInstance& inst : m_instances)
|
||||
{
|
||||
auto& inst = m_objInstance[i];
|
||||
auto& model = m_objModel[inst.objIndex];
|
||||
m_pushConstant.instanceId = i; // Telling which instance is drawn
|
||||
auto& model = m_objModel[inst.objIndex];
|
||||
m_pcRaster.objIndex = inst.objIndex; // Telling which object is drawn
|
||||
m_pcRaster.modelMatrix = inst.transform;
|
||||
|
||||
vkCmdPushConstants(cmdBuf, m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0,
|
||||
sizeof(ObjPushConstant), &m_pushConstant);
|
||||
sizeof(PushConstantRaster), &m_pcRaster);
|
||||
vkCmdBindVertexBuffers(cmdBuf, 0, 1, &model.vertexBuffer.buffer, &offset);
|
||||
vkCmdBindIndexBuffer(cmdBuf, model.indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
vkCmdDrawIndexed(cmdBuf, model.nbIndices, 1, 0, 0, 0);
|
||||
|
|
@ -615,7 +611,7 @@ auto HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
|||
|
||||
// Describe buffer as array of VertexObj.
|
||||
VkAccelerationStructureGeometryTrianglesDataKHR triangles{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR};
|
||||
triangles.vertexFormat = VK_FORMAT_R32G32B32A32_SFLOAT; // vec3 vertex position data.
|
||||
triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; // vec3 vertex position data.
|
||||
triangles.vertexData.deviceAddress = vertexAddress;
|
||||
triangles.vertexStride = sizeof(VertexObj);
|
||||
// Describe index data (32-bit unsigned int)
|
||||
|
|
@ -664,19 +660,22 @@ void HelloVulkan::createBottomLevelAS()
|
|||
m_rtBuilder.buildBlas(allBlas, VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
void HelloVulkan::createTopLevelAS()
|
||||
{
|
||||
std::vector<VkAccelerationStructureInstanceKHR> tlas;
|
||||
tlas.reserve(m_objInstance.size());
|
||||
for(uint32_t i = 0; i < static_cast<uint32_t>(m_objInstance.size()); i++)
|
||||
tlas.reserve(m_instances.size());
|
||||
for(const HelloVulkan::ObjInstance& inst : m_instances)
|
||||
{
|
||||
VkAccelerationStructureInstanceKHR rayInst;
|
||||
rayInst.transform = nvvk::toTransformMatrixKHR(m_objInstance[i].transform); // Position of the instance
|
||||
rayInst.instanceCustomIndex = i; // gl_InstanceCustomIndexEXT
|
||||
rayInst.accelerationStructureReference = m_rtBuilder.getBlasDeviceAddress(m_objInstance[i].objIndex);
|
||||
rayInst.instanceShaderBindingTableRecordOffset = m_objInstance[i].hitgroup; // Using the hit group set in main
|
||||
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||
rayInst.mask = 0xFF;
|
||||
VkAccelerationStructureInstanceKHR rayInst{};
|
||||
rayInst.transform = nvvk::toTransformMatrixKHR(inst.transform); // Position of the instance
|
||||
rayInst.instanceCustomIndex = inst.objIndex; // gl_InstanceCustomIndexEXT
|
||||
rayInst.accelerationStructureReference = m_rtBuilder.getBlasDeviceAddress(inst.objIndex);
|
||||
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||
rayInst.mask = 0xFF; // Only be hit if rayMask & instance.mask != 0
|
||||
rayInst.instanceShaderBindingTableRecordOffset = inst.hitgroup; // Using the hit group set in main
|
||||
tlas.emplace_back(rayInst);
|
||||
}
|
||||
m_rtBuilder.buildTlas(tlas, VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR);
|
||||
|
|
@ -689,9 +688,9 @@ void HelloVulkan::createRtDescriptorSet()
|
|||
{
|
||||
// Top-level acceleration structure, usable by both the ray generation and the closest hit (to
|
||||
// shoot shadow rays)
|
||||
m_rtDescSetLayoutBind.addBinding(0, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1,
|
||||
m_rtDescSetLayoutBind.addBinding(RtxBindings::eTlas, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1,
|
||||
VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR); // TLAS
|
||||
m_rtDescSetLayoutBind.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1,
|
||||
m_rtDescSetLayoutBind.addBinding(RtxBindings::eOutImage, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1,
|
||||
VK_SHADER_STAGE_RAYGEN_BIT_KHR); // Output image
|
||||
|
||||
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
|
||||
|
|
@ -711,8 +710,8 @@ void HelloVulkan::createRtDescriptorSet()
|
|||
VkDescriptorImageInfo imageInfo{{}, m_offscreenColor.descriptor.imageView, VK_IMAGE_LAYOUT_GENERAL};
|
||||
|
||||
std::vector<VkWriteDescriptorSet> writes;
|
||||
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
|
||||
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
|
||||
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, RtxBindings::eTlas, &descASInfo));
|
||||
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, RtxBindings::eOutImage, &imageInfo));
|
||||
vkUpdateDescriptorSets(m_device, static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||
}
|
||||
|
||||
|
|
@ -725,7 +724,7 @@ void HelloVulkan::updateRtDescriptorSet()
|
|||
{
|
||||
// (1) Output buffer
|
||||
VkDescriptorImageInfo imageInfo{{}, m_offscreenColor.descriptor.imageView, VK_IMAGE_LAYOUT_GENERAL};
|
||||
VkWriteDescriptorSet wds = m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo);
|
||||
VkWriteDescriptorSet wds = m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, RtxBindings::eOutImage, &imageInfo);
|
||||
vkUpdateDescriptorSets(m_device, 1, &wds, 0, nullptr);
|
||||
}
|
||||
|
||||
|
|
@ -814,7 +813,7 @@ void HelloVulkan::createRtPipeline()
|
|||
|
||||
// Push constant: we want to be able to update constants used by the shaders
|
||||
VkPushConstantRange pushConstant{VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR,
|
||||
0, sizeof(RtPushConstant)};
|
||||
0, sizeof(PushConstantRay)};
|
||||
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO};
|
||||
|
|
@ -945,10 +944,10 @@ void HelloVulkan::raytrace(const VkCommandBuffer& cmdBuf, const nvmath::vec4f& c
|
|||
{
|
||||
m_debug.beginLabel(cmdBuf, "Ray trace");
|
||||
// Initializing push constant values
|
||||
m_rtPushConstants.clearColor = clearColor;
|
||||
m_rtPushConstants.lightPosition = m_pushConstant.lightPosition;
|
||||
m_rtPushConstants.lightIntensity = m_pushConstant.lightIntensity;
|
||||
m_rtPushConstants.lightType = m_pushConstant.lightType;
|
||||
m_pcRay.clearColor = clearColor;
|
||||
m_pcRay.lightPosition = m_pcRaster.lightPosition;
|
||||
m_pcRay.lightIntensity = m_pcRaster.lightIntensity;
|
||||
m_pcRay.lightType = m_pcRaster.lightType;
|
||||
|
||||
|
||||
std::vector<VkDescriptorSet> descSets{m_rtDescSet, m_descSet};
|
||||
|
|
@ -957,7 +956,7 @@ void HelloVulkan::raytrace(const VkCommandBuffer& cmdBuf, const nvmath::vec4f& c
|
|||
(uint32_t)descSets.size(), descSets.data(), 0, nullptr);
|
||||
vkCmdPushConstants(cmdBuf, m_rtPipelineLayout,
|
||||
VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR,
|
||||
0, sizeof(RtPushConstant), &m_rtPushConstants);
|
||||
0, sizeof(PushConstantRay), &m_pcRay);
|
||||
|
||||
|
||||
//// Size of a program identifier
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "nvvk/descriptorsets_vk.hpp"
|
||||
#include "nvvk/memallocator_dma_vk.hpp"
|
||||
#include "nvvk/resourceallocator_vk.hpp"
|
||||
#include "shaders/host_device.h"
|
||||
|
||||
// #VKRay
|
||||
#include "nvvk/raytraceKHR_vk.hpp"
|
||||
|
|
@ -46,7 +47,7 @@ public:
|
|||
void loadModel(const std::string& filename, nvmath::mat4f transform = nvmath::mat4f(1));
|
||||
void updateDescriptorSet();
|
||||
void createUniformBuffer();
|
||||
void createSceneDescriptionBuffer();
|
||||
void createObjDescriptionBuffer();
|
||||
void createTextureImages(const VkCommandBuffer& cmdBuf, const std::vector<std::string>& textures);
|
||||
void updateUniformBuffer(const VkCommandBuffer& cmdBuf);
|
||||
void onResize(int /*w*/, int /*h*/) override;
|
||||
|
|
@ -64,33 +65,28 @@ public:
|
|||
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
||||
};
|
||||
|
||||
// Instance of the OBJ
|
||||
struct ObjInstance
|
||||
{
|
||||
nvmath::mat4f transform{1}; // Position of the instance
|
||||
nvmath::mat4f transformIT{1}; // Inverse transpose
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
VkDeviceAddress vertices;
|
||||
VkDeviceAddress indices;
|
||||
VkDeviceAddress materials;
|
||||
VkDeviceAddress materialIndices;
|
||||
uint32_t hitgroup{0}; // Hit group of the instance
|
||||
nvmath::mat4f transform; // Matrix of the instance
|
||||
uint32_t objIndex{0}; // Model index reference
|
||||
int hitgroup{0}; // Hit group of the instance
|
||||
};
|
||||
|
||||
|
||||
// Information pushed at each draw call
|
||||
struct ObjPushConstant
|
||||
{
|
||||
nvmath::vec3f lightPosition{10.f, 15.f, 8.f};
|
||||
int instanceId{0}; // To retrieve the transformation matrix
|
||||
float lightIntensity{100.f};
|
||||
int lightType{0}; // 0: point, 1: infinite
|
||||
PushConstantRaster m_pcRaster{
|
||||
{1}, // Identity matrix
|
||||
{10.f, 15.f, 8.f}, // light position
|
||||
0, // instance Id
|
||||
100.f, // light intensity
|
||||
0 // light type
|
||||
};
|
||||
ObjPushConstant m_pushConstant;
|
||||
|
||||
// Array of objects and instances in the scene
|
||||
std::vector<ObjModel> m_objModel;
|
||||
std::vector<ObjInstance> m_objInstance;
|
||||
std::vector<ObjModel> m_objModel; // Model on host
|
||||
std::vector<ObjDesc> m_objDesc; // Model description for device access
|
||||
std::vector<ObjInstance> m_instances; // Scene model instances
|
||||
|
||||
|
||||
// Graphic pipeline
|
||||
VkPipelineLayout m_pipelineLayout;
|
||||
|
|
@ -100,8 +96,8 @@ public:
|
|||
VkDescriptorSetLayout m_descSetLayout;
|
||||
VkDescriptorSet m_descSet;
|
||||
|
||||
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||
nvvk::Buffer m_bGlobals; // Device-Host of the camera matrices
|
||||
nvvk::Buffer m_bObjDesc; // Device buffer of the OBJ descriptions
|
||||
|
||||
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||
|
||||
|
|
@ -110,7 +106,7 @@ public:
|
|||
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||
|
||||
|
||||
// #Post
|
||||
// #Post - Draw the rendered image on a quad using a tonemapper
|
||||
void createOffscreenRender();
|
||||
void createPostPipeline();
|
||||
void createPostDescriptor();
|
||||
|
|
@ -153,13 +149,8 @@ public:
|
|||
VkPipeline m_rtPipeline;
|
||||
nvvk::Buffer m_rtSBTBuffer;
|
||||
|
||||
struct RtPushConstant
|
||||
{
|
||||
nvmath::vec4f clearColor;
|
||||
nvmath::vec3f lightPosition;
|
||||
float lightIntensity{100.0f};
|
||||
int lightType{0};
|
||||
} m_rtPushConstants;
|
||||
// Push constant for ray tracer
|
||||
PushConstantRay m_pcRay{};
|
||||
|
||||
struct HitRecordBuffer
|
||||
{
|
||||
|
|
|
|||
|
|
@ -56,12 +56,12 @@ void renderUI(HelloVulkan& helloVk)
|
|||
ImGuiH::CameraWidget();
|
||||
if(ImGui::CollapsingHeader("Light"))
|
||||
{
|
||||
ImGui::RadioButton("Point", &helloVk.m_pushConstant.lightType, 0);
|
||||
ImGui::RadioButton("Point", &helloVk.m_pcRaster.lightType, 0);
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("Infinite", &helloVk.m_pushConstant.lightType, 1);
|
||||
ImGui::RadioButton("Infinite", &helloVk.m_pcRaster.lightType, 1);
|
||||
|
||||
ImGui::SliderFloat3("Position", &helloVk.m_pushConstant.lightPosition.x, -20.f, 20.f);
|
||||
ImGui::SliderFloat("Intensity", &helloVk.m_pushConstant.lightIntensity, 0.f, 150.f);
|
||||
ImGui::SliderFloat3("Position", &helloVk.m_pcRaster.lightPosition.x, -20.f, 20.f);
|
||||
ImGui::SliderFloat("Intensity", &helloVk.m_pcRaster.lightIntensity, 0.f, 150.f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -159,10 +159,8 @@ int main(int argc, char** argv)
|
|||
helloVk.loadModel(nvh::findFile("media/scenes/wuson.obj", defaultSearchPaths, true),
|
||||
nvmath::translation_mat4(nvmath::vec3f(-1, 0, 0)));
|
||||
|
||||
HelloVulkan::ObjInstance inst = helloVk.m_objInstance[0]; // Instance the Wuson object
|
||||
inst.transform = nvmath::translation_mat4(nvmath::vec3f(1, 0, 0));
|
||||
inst.transformIT = nvmath::transpose(nvmath::invert(inst.transform));
|
||||
helloVk.m_objInstance.push_back(inst); // Adding an instance of the Wuson
|
||||
helloVk.m_instances.push_back({nvmath::translation_mat4(nvmath::vec3f(1, 0, 0)), 0}); // Adding an instance of the Wuson
|
||||
|
||||
|
||||
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths, true));
|
||||
|
||||
|
|
@ -170,14 +168,15 @@ int main(int argc, char** argv)
|
|||
helloVk.m_hitShaderRecord.resize(2);
|
||||
helloVk.m_hitShaderRecord[0].color = nvmath::vec4f(0, 1, 0, 0); // Green
|
||||
helloVk.m_hitShaderRecord[1].color = nvmath::vec4f(0, 1, 1, 0); // Cyan
|
||||
helloVk.m_objInstance[0].hitgroup = 1; // Wuson 0
|
||||
helloVk.m_objInstance[1].hitgroup = 2; // Wuson 1
|
||||
helloVk.m_instances[0].hitgroup = 1; // Wuson 0
|
||||
helloVk.m_instances[1].hitgroup = 2; // Wuson 1
|
||||
helloVk.m_instances[2].hitgroup = 0; // Plane
|
||||
|
||||
helloVk.createOffscreenRender();
|
||||
helloVk.createDescriptorSetLayout();
|
||||
helloVk.createGraphicsPipeline();
|
||||
helloVk.createUniformBuffer();
|
||||
helloVk.createSceneDescriptionBuffer();
|
||||
helloVk.createObjDescriptionBuffer();
|
||||
helloVk.updateDescriptorSet();
|
||||
|
||||
// #VKRay
|
||||
|
|
|
|||
|
|
@ -29,59 +29,55 @@
|
|||
#include "wavefront.glsl"
|
||||
|
||||
|
||||
layout(push_constant) uniform shaderInformation
|
||||
layout(push_constant) uniform _PushConstantRaster
|
||||
{
|
||||
vec3 lightPosition;
|
||||
uint instanceId;
|
||||
float lightIntensity;
|
||||
int lightType;
|
||||
}
|
||||
pushC;
|
||||
PushConstantRaster pcRaster;
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
// Incoming
|
||||
layout(location = 1) in vec2 fragTexCoord;
|
||||
layout(location = 2) in vec3 fragNormal;
|
||||
layout(location = 3) in vec3 viewDir;
|
||||
layout(location = 4) in vec3 worldPos;
|
||||
layout(location = 1) in vec3 i_worldPos;
|
||||
layout(location = 2) in vec3 i_worldNrm;
|
||||
layout(location = 3) in vec3 i_viewDir;
|
||||
layout(location = 4) in vec2 i_texCoord;
|
||||
// Outgoing
|
||||
layout(location = 0) out vec4 outColor;
|
||||
layout(location = 0) out vec4 o_color;
|
||||
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint i[]; }; // Triangle indices
|
||||
layout(buffer_reference, scalar) buffer Materials {WaveFrontMaterial m[]; }; // Array of all materials on an object
|
||||
layout(buffer_reference, scalar) buffer MatIndices {int i[]; }; // Material ID for each triangle
|
||||
|
||||
layout(binding = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2) uniform sampler2D[] textureSamplers;
|
||||
layout(binding = eObjDescs, scalar) buffer ObjDesc_ { ObjDesc i[]; } objDesc;
|
||||
layout(binding = eTextures) uniform sampler2D[] textureSamplers;
|
||||
// clang-format on
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// Material of the object
|
||||
SceneDesc objResource = sceneDesc.i[pushC.instanceId];
|
||||
ObjDesc objResource = objDesc.i[pcRaster.objIndex];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
int matIndex = matIndices.i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials.m[matIndex];
|
||||
|
||||
vec3 N = normalize(fragNormal);
|
||||
vec3 N = normalize(i_worldNrm);
|
||||
|
||||
// Vector toward light
|
||||
vec3 L;
|
||||
float lightIntensity = pushC.lightIntensity;
|
||||
if(pushC.lightType == 0)
|
||||
float lightIntensity = pcRaster.lightIntensity;
|
||||
if(pcRaster.lightType == 0)
|
||||
{
|
||||
vec3 lDir = pushC.lightPosition - worldPos;
|
||||
vec3 lDir = pcRaster.lightPosition - i_worldPos;
|
||||
float d = length(lDir);
|
||||
lightIntensity = pushC.lightIntensity / (d * d);
|
||||
lightIntensity = pcRaster.lightIntensity / (d * d);
|
||||
L = normalize(lDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
L = normalize(pushC.lightPosition - vec3(0));
|
||||
L = normalize(pcRaster.lightPosition);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -89,15 +85,15 @@ void main()
|
|||
vec3 diffuse = computeDiffuse(mat, L, N);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
int txtOffset = sceneDesc.i[pushC.instanceId].txtOffset;
|
||||
int txtOffset = objDesc.i[pcRaster.objIndex].txtOffset;
|
||||
uint txtId = txtOffset + mat.textureId;
|
||||
vec3 diffuseTxt = texture(textureSamplers[nonuniformEXT(txtId)], fragTexCoord).xyz;
|
||||
vec3 diffuseTxt = texture(textureSamplers[nonuniformEXT(txtId)], i_texCoord).xyz;
|
||||
diffuse *= diffuseTxt;
|
||||
}
|
||||
|
||||
// Specular
|
||||
vec3 specular = computeSpecular(mat, viewDir, L, N);
|
||||
vec3 specular = computeSpecular(mat, i_viewDir, L, N);
|
||||
|
||||
// Result
|
||||
outColor = vec4(lightIntensity * (diffuse + specular), 1);
|
||||
o_color = vec4(lightIntensity * (diffuse + specular), 1);
|
||||
}
|
||||
|
|
|
|||
117
ray_tracing_manyhits/shaders/host_device.h
Normal file
117
ray_tracing_manyhits/shaders/host_device.h
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2019-2021 NVIDIA CORPORATION
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
#ifndef COMMON_HOST_DEVICE
|
||||
#define COMMON_HOST_DEVICE
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "nvmath/nvmath.h"
|
||||
// GLSL Type
|
||||
using vec2 = nvmath::vec2f;
|
||||
using vec3 = nvmath::vec3f;
|
||||
using vec4 = nvmath::vec4f;
|
||||
using mat4 = nvmath::mat4f;
|
||||
using uint = unsigned int;
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
#ifdef __cplusplus // Descriptor binding helper for C++ and GLSL
|
||||
#define START_BINDING(a) enum a {
|
||||
#define END_BINDING() }
|
||||
#else
|
||||
#define START_BINDING(a) const uint
|
||||
#define END_BINDING()
|
||||
#endif
|
||||
|
||||
START_BINDING(SceneBindings)
|
||||
eGlobals = 0, // Global uniform containing camera matrices
|
||||
eObjDescs = 1, // Access to the object descriptions
|
||||
eTextures = 2 // Access to textures
|
||||
END_BINDING();
|
||||
|
||||
START_BINDING(RtxBindings)
|
||||
eTlas = 0, // Top-level acceleration structure
|
||||
eOutImage = 1 // Ray tracer output image
|
||||
END_BINDING();
|
||||
// clang-format on
|
||||
|
||||
|
||||
// Information of a obj model when referenced in a shader
|
||||
struct ObjDesc
|
||||
{
|
||||
int txtOffset; // Texture index offset in the array of textures
|
||||
uint64_t vertexAddress; // Address of the Vertex buffer
|
||||
uint64_t indexAddress; // Address of the index buffer
|
||||
uint64_t materialAddress; // Address of the material buffer
|
||||
uint64_t materialIndexAddress; // Address of the triangle material index buffer
|
||||
};
|
||||
|
||||
// Uniform buffer set at each frame
|
||||
struct GlobalUniforms
|
||||
{
|
||||
mat4 viewProj; // Camera view * projection
|
||||
mat4 viewInverse; // Camera inverse view matrix
|
||||
mat4 projInverse; // Camera inverse projection matrix
|
||||
};
|
||||
|
||||
// Push constant structure for the raster
|
||||
struct PushConstantRaster
|
||||
{
|
||||
mat4 modelMatrix; // matrix of the instance
|
||||
vec3 lightPosition;
|
||||
uint objIndex;
|
||||
float lightIntensity;
|
||||
int lightType;
|
||||
};
|
||||
|
||||
|
||||
// Push constant structure for the ray tracer
|
||||
struct PushConstantRay
|
||||
{
|
||||
vec4 clearColor;
|
||||
vec3 lightPosition;
|
||||
float lightIntensity;
|
||||
int lightType;
|
||||
};
|
||||
|
||||
struct Vertex // See ObjLoader, copy of VertexObj, could be compressed for device
|
||||
{
|
||||
vec3 pos;
|
||||
vec3 nrm;
|
||||
vec3 color;
|
||||
vec2 texCoord;
|
||||
};
|
||||
|
||||
struct WaveFrontMaterial // See ObjLoader, copy of MaterialObj, could be compressed for device
|
||||
{
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
vec3 transmittance;
|
||||
vec3 emission;
|
||||
float shininess;
|
||||
float ior; // index of refraction
|
||||
float dissolve; // 1 == opaque; 0 == fully transparent
|
||||
int illum; // illumination model (see http://www.fileformat.info/format/material/)
|
||||
int textureId;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -39,25 +39,18 @@ layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of
|
|||
layout(buffer_reference, scalar) buffer Indices {ivec3 i[]; }; // Triangle indices
|
||||
layout(buffer_reference, scalar) buffer Materials {WaveFrontMaterial m[]; }; // Array of all materials on an object
|
||||
layout(buffer_reference, scalar) buffer MatIndices {int i[]; }; // Material ID for each triangle
|
||||
layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS;
|
||||
layout(binding = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2, set = 1) uniform sampler2D textureSamplers[];
|
||||
// clang-format on
|
||||
layout(set = 0, binding = eTlas) uniform accelerationStructureEXT topLevelAS;
|
||||
layout(set = 1, binding = eObjDescs, scalar) buffer ObjDesc_ { ObjDesc i[]; } objDesc;
|
||||
layout(set = 1, binding = eTextures) uniform sampler2D textureSamplers[];
|
||||
|
||||
layout(push_constant) uniform Constants
|
||||
{
|
||||
vec4 clearColor;
|
||||
vec3 lightPosition;
|
||||
float lightIntensity;
|
||||
int lightType;
|
||||
}
|
||||
pushC;
|
||||
layout(push_constant) uniform _PushConstantRay { PushConstantRay pcRay; };
|
||||
// clang-format on
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object data
|
||||
SceneDesc objResource = sceneDesc.i[gl_InstanceCustomIndexEXT];
|
||||
ObjDesc objResource = objDesc.i[gl_InstanceCustomIndexEXT];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
Indices indices = Indices(objResource.indexAddress);
|
||||
|
|
@ -73,32 +66,29 @@ void main()
|
|||
|
||||
const vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y);
|
||||
|
||||
// Computing the normal at hit position
|
||||
vec3 normal = v0.nrm * barycentrics.x + v1.nrm * barycentrics.y + v2.nrm * barycentrics.z;
|
||||
// Transforming the normal to world space
|
||||
normal = normalize(vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
|
||||
|
||||
// Computing the coordinates of the hit position
|
||||
vec3 worldPos = v0.pos * barycentrics.x + v1.pos * barycentrics.y + v2.pos * barycentrics.z;
|
||||
// Transforming the position to world space
|
||||
worldPos = vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
const vec3 pos = v0.pos * barycentrics.x + v1.pos * barycentrics.y + v2.pos * barycentrics.z;
|
||||
const vec3 worldPos = vec3(gl_ObjectToWorldEXT * vec4(pos, 1.0)); // Transforming the position to world space
|
||||
|
||||
// Computing the normal at hit position
|
||||
const vec3 nrm = v0.nrm * barycentrics.x + v1.nrm * barycentrics.y + v2.nrm * barycentrics.z;
|
||||
const vec3 worldNrm = normalize(vec3(nrm * gl_WorldToObjectEXT)); // Transforming the normal to world space
|
||||
|
||||
// Vector toward the light
|
||||
vec3 L;
|
||||
float lightIntensity = pushC.lightIntensity;
|
||||
float lightIntensity = pcRay.lightIntensity;
|
||||
float lightDistance = 100000.0;
|
||||
// Point light
|
||||
if(pushC.lightType == 0)
|
||||
if(pcRay.lightType == 0)
|
||||
{
|
||||
vec3 lDir = pushC.lightPosition - worldPos;
|
||||
vec3 lDir = pcRay.lightPosition - worldPos;
|
||||
lightDistance = length(lDir);
|
||||
lightIntensity = pushC.lightIntensity / (lightDistance * lightDistance);
|
||||
lightIntensity = pcRay.lightIntensity / (lightDistance * lightDistance);
|
||||
L = normalize(lDir);
|
||||
}
|
||||
else // Directional light
|
||||
{
|
||||
L = normalize(pushC.lightPosition - vec3(0));
|
||||
L = normalize(pcRay.lightPosition);
|
||||
}
|
||||
|
||||
// Material of the object
|
||||
|
|
@ -107,10 +97,10 @@ void main()
|
|||
|
||||
|
||||
// Diffuse
|
||||
vec3 diffuse = computeDiffuse(mat, L, normal);
|
||||
vec3 diffuse = computeDiffuse(mat, L, worldNrm);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
uint txtId = mat.textureId + sceneDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
uint txtId = mat.textureId + objDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord = v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y + v2.texCoord * barycentrics.z;
|
||||
diffuse *= texture(textureSamplers[nonuniformEXT(txtId)], texCoord).xyz;
|
||||
}
|
||||
|
|
@ -119,7 +109,7 @@ void main()
|
|||
float attenuation = 1;
|
||||
|
||||
// Tracing shadow ray only if the light is visible from the surface
|
||||
if(dot(normal, L) > 0)
|
||||
if(dot(worldNrm, L) > 0)
|
||||
{
|
||||
float tMin = 0.001;
|
||||
float tMax = lightDistance;
|
||||
|
|
@ -147,7 +137,7 @@ void main()
|
|||
else
|
||||
{
|
||||
// Specular
|
||||
specular = computeSpecular(mat, gl_WorldRayDirectionEXT, L, normal);
|
||||
specular = computeSpecular(mat, gl_WorldRayDirectionEXT, L, worldNrm);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,21 +20,21 @@
|
|||
#version 460
|
||||
#extension GL_EXT_ray_tracing : require
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
|
||||
|
||||
#include "raycommon.glsl"
|
||||
#include "wavefront.glsl"
|
||||
|
||||
layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS;
|
||||
layout(binding = 1, set = 0, rgba32f) uniform image2D image;
|
||||
|
||||
// clang-format off
|
||||
layout(location = 0) rayPayloadEXT hitPayload prd;
|
||||
|
||||
layout(binding = 0, set = 1) uniform CameraProperties
|
||||
{
|
||||
mat4 view;
|
||||
mat4 proj;
|
||||
mat4 viewInverse;
|
||||
mat4 projInverse;
|
||||
}
|
||||
cam;
|
||||
layout(set = 0, binding = eTlas) uniform accelerationStructureEXT topLevelAS;
|
||||
layout(set = 0, binding = eOutImage, rgba32f) uniform image2D image;
|
||||
layout(set = 1, binding = eGlobals) uniform _GlobalUniforms { GlobalUniforms uni; };
|
||||
layout(push_constant) uniform _PushConstantRay { PushConstantRay pcRay; };
|
||||
// clang-format on
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
@ -42,9 +42,9 @@ void main()
|
|||
const vec2 inUV = pixelCenter / vec2(gl_LaunchSizeEXT.xy);
|
||||
vec2 d = inUV * 2.0 - 1.0;
|
||||
|
||||
vec4 origin = cam.viewInverse * vec4(0, 0, 0, 1);
|
||||
vec4 target = cam.projInverse * vec4(d.x, d.y, 1, 1);
|
||||
vec4 direction = cam.viewInverse * vec4(normalize(target.xyz), 0);
|
||||
vec4 origin = uni.viewInverse * vec4(0, 0, 0, 1);
|
||||
vec4 target = uni.projInverse * vec4(d.x, d.y, 1, 1);
|
||||
vec4 direction = uni.viewInverse * vec4(normalize(target.xyz), 0);
|
||||
|
||||
uint rayFlags = gl_RayFlagsOpaqueEXT;
|
||||
float tMin = 0.001;
|
||||
|
|
|
|||
|
|
@ -20,16 +20,19 @@
|
|||
#version 460
|
||||
#extension GL_EXT_ray_tracing : require
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
|
||||
#include "raycommon.glsl"
|
||||
#include "wavefront.glsl"
|
||||
|
||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||
|
||||
layout(push_constant) uniform Constants
|
||||
layout(push_constant) uniform _PushConstantRay
|
||||
{
|
||||
vec4 clearColor;
|
||||
PushConstantRay pcRay;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
prd.hitValue = clearColor.xyz * 0.8;
|
||||
prd.hitValue = pcRay.clearColor.xyz * 0.8;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,14 +23,12 @@
|
|||
|
||||
#include "raycommon.glsl"
|
||||
|
||||
// clang-format off
|
||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||
layout(shaderRecordEXT) buffer sr_
|
||||
{
|
||||
vec4 c;
|
||||
}
|
||||
shaderRec;
|
||||
layout(shaderRecordEXT) buffer sr_ { vec4 shaderRec; };
|
||||
// clang-format on
|
||||
|
||||
void main()
|
||||
{
|
||||
prd.hitValue = shaderRec.c.rgb;
|
||||
prd.hitValue = shaderRec.rgb;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,38 +26,26 @@
|
|||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
// clang-format off
|
||||
layout(binding = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
// clang-format on
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject
|
||||
layout(binding = 0) uniform _GlobalUniforms
|
||||
{
|
||||
mat4 view;
|
||||
mat4 proj;
|
||||
mat4 viewI;
|
||||
}
|
||||
ubo;
|
||||
GlobalUniforms uni;
|
||||
};
|
||||
|
||||
layout(push_constant) uniform shaderInformation
|
||||
layout(push_constant) uniform _PushConstantRaster
|
||||
{
|
||||
vec3 lightPosition;
|
||||
uint instanceId;
|
||||
float lightIntensity;
|
||||
int lightType;
|
||||
}
|
||||
pushC;
|
||||
PushConstantRaster pcRaster;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec3 inPosition;
|
||||
layout(location = 1) in vec3 inNormal;
|
||||
layout(location = 2) in vec3 inColor;
|
||||
layout(location = 3) in vec2 inTexCoord;
|
||||
layout(location = 0) in vec3 i_position;
|
||||
layout(location = 1) in vec3 i_normal;
|
||||
layout(location = 2) in vec3 i_color;
|
||||
layout(location = 3) in vec2 i_texCoord;
|
||||
|
||||
|
||||
//layout(location = 0) flat out int matIndex;
|
||||
layout(location = 1) out vec2 fragTexCoord;
|
||||
layout(location = 2) out vec3 fragNormal;
|
||||
layout(location = 3) out vec3 viewDir;
|
||||
layout(location = 4) out vec3 worldPos;
|
||||
layout(location = 1) out vec3 o_worldPos;
|
||||
layout(location = 2) out vec3 o_worldNrm;
|
||||
layout(location = 3) out vec3 o_viewDir;
|
||||
layout(location = 4) out vec2 o_texCoord;
|
||||
|
||||
out gl_PerVertex
|
||||
{
|
||||
|
|
@ -67,16 +55,12 @@ out gl_PerVertex
|
|||
|
||||
void main()
|
||||
{
|
||||
mat4 objMatrix = sceneDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = sceneDesc.i[pushC.instanceId].transfoIT;
|
||||
vec3 origin = vec3(uni.viewInverse * vec4(0, 0, 0, 1));
|
||||
|
||||
vec3 origin = vec3(ubo.viewI * vec4(0, 0, 0, 1));
|
||||
o_worldPos = vec3(pcRaster.modelMatrix * vec4(i_position, 1.0));
|
||||
o_viewDir = vec3(o_worldPos - origin);
|
||||
o_texCoord = i_texCoord;
|
||||
o_worldNrm = mat3(pcRaster.modelMatrix) * i_normal;
|
||||
|
||||
worldPos = vec3(objMatrix * vec4(inPosition, 1.0));
|
||||
viewDir = vec3(worldPos - origin);
|
||||
fragTexCoord = inTexCoord;
|
||||
fragNormal = vec3(objMatrixIT * vec4(inNormal, 0.0));
|
||||
// matIndex = inMatID;
|
||||
|
||||
gl_Position = ubo.proj * ubo.view * vec4(worldPos, 1.0);
|
||||
gl_Position = uni.viewProj * vec4(o_worldPos, 1.0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,41 +17,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
vec3 pos;
|
||||
vec3 nrm;
|
||||
vec3 color;
|
||||
vec2 texCoord;
|
||||
};
|
||||
|
||||
struct WaveFrontMaterial
|
||||
{
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
vec3 transmittance;
|
||||
vec3 emission;
|
||||
float shininess;
|
||||
float ior; // index of refraction
|
||||
float dissolve; // 1 == opaque; 0 == fully transparent
|
||||
int illum; // illumination model (see http://www.fileformat.info/format/material/)
|
||||
int textureId;
|
||||
};
|
||||
|
||||
struct SceneDesc
|
||||
{
|
||||
mat4 transfo;
|
||||
mat4 transfoIT;
|
||||
int objId;
|
||||
int txtOffset;
|
||||
uint64_t vertexAddress;
|
||||
uint64_t indexAddress;
|
||||
uint64_t materialAddress;
|
||||
uint64_t materialIndexAddress;
|
||||
int hitGroup;
|
||||
};
|
||||
|
||||
#include "host_device.h"
|
||||
|
||||
vec3 computeDiffuse(WaveFrontMaterial mat, vec3 lightDir, vec3 normal)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue