Merge pull request #1186 from SaschaWillems/slang_shaders
[WIP] Add Slang shaders
This commit is contained in:
commit
0951c1d362
518 changed files with 12348 additions and 27 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -240,4 +240,6 @@ android/.idea/**
|
|||
|
||||
libs/vulkan/*.so
|
||||
|
||||
.vscode/*
|
||||
.vscode/*
|
||||
|
||||
__pycache__**
|
||||
|
|
@ -68,7 +68,7 @@ Once built, examples can be run from the bin directory. The list of available co
|
|||
-vs, --vsync: Enable V-Sync
|
||||
-f, --fullscreen: Start in fullscreen mode
|
||||
-w, --width: Set window width
|
||||
-s, --shaders: Select shader type to use (glsl or hlsl)
|
||||
-s, --shaders: Select shader type to use (glsl, slang, hlsl)
|
||||
-g, --gpu: Select GPU to run on
|
||||
-gl, --listgpus: Display a list of available Vulkan devices
|
||||
-b, --benchmark: Run example in benchmark mode
|
||||
|
|
@ -83,7 +83,7 @@ Note that some examples require specific device features, and if you are on a mu
|
|||
|
||||
## Shaders
|
||||
|
||||
Vulkan consumes shaders in an intermediate representation called SPIR-V. This makes it possible to use different shader languages by compiling them to that bytecode format. The primary shader language used here is [GLSL](shaders/glsl) but most samples also come with [HLSL](shaders/hlsl) shader sources.
|
||||
Vulkan consumes shaders in an intermediate representation called SPIR-V. This makes it possible to use different shader languages by compiling them to that bytecode format. The primary shader language used here is [GLSL](shaders/glsl), most samples also come with [slang](shaders/slang/) and [HLSL](shaders/hlsl) shader sources, making it easy to compare the differences between those shading languages.
|
||||
|
||||
## A note on synchronization
|
||||
|
||||
|
|
|
|||
|
|
@ -89,6 +89,15 @@ VkResult VulkanExampleBase::createInstance()
|
|||
}
|
||||
}
|
||||
|
||||
// Shaders generated by Slang require a certain SPIR-V environment that can't be satisfied by Vulkan 1.0, so we need to expliclity up that to at least 1.1 and enable some required extensions
|
||||
if (shaderDir == "slang") {
|
||||
if (apiVersion < VK_API_VERSION_1_1) {
|
||||
apiVersion = VK_API_VERSION_1_1;
|
||||
}
|
||||
enabledDeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
VkApplicationInfo appInfo{};
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo.pApplicationName = name.c_str();
|
||||
|
|
|
|||
|
|
@ -391,8 +391,8 @@ public:
|
|||
vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(vkglTF::Vertex, color)), // Location 2: Texture coordinates
|
||||
// Per-Instance attributes
|
||||
// These are fetched for each instance rendered
|
||||
vks::initializers::vertexInputAttributeDescription(1, 4, VK_FORMAT_R32G32B32_SFLOAT, offsetof(InstanceData, pos)), // Location 4: Position
|
||||
vks::initializers::vertexInputAttributeDescription(1, 5, VK_FORMAT_R32_SFLOAT, offsetof(InstanceData, scale)), // Location 5: Scale
|
||||
vks::initializers::vertexInputAttributeDescription(1, 3, VK_FORMAT_R32G32B32_SFLOAT, offsetof(InstanceData, pos)), // Location 4: Position
|
||||
vks::initializers::vertexInputAttributeDescription(1, 4, VK_FORMAT_R32_SFLOAT, offsetof(InstanceData, scale)), // Location 5: Scale
|
||||
};
|
||||
inputState.pVertexBindingDescriptions = bindingDescriptions.data();
|
||||
inputState.pVertexAttributeDescriptions = attributeDescriptions.data();
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ public:
|
|||
|
||||
VkDebugReportCallbackEXT debugReportCallback{};
|
||||
|
||||
std::string shaderDir = "glsl";
|
||||
|
||||
VkResult createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, VkBuffer *buffer, VkDeviceMemory *memory, VkDeviceSize size, void *data = nullptr)
|
||||
{
|
||||
// Create the buffer handle
|
||||
|
|
@ -132,11 +134,19 @@ public:
|
|||
vks::android::loadVulkanLibrary();
|
||||
#endif
|
||||
|
||||
if (commandLineParser.isSet("shaders")) {
|
||||
shaderDir = commandLineParser.getValueAsString("shaders", "glsl");
|
||||
}
|
||||
|
||||
VkApplicationInfo appInfo = {};
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo.pApplicationName = "Vulkan headless example";
|
||||
appInfo.pEngineName = "VulkanExample";
|
||||
appInfo.apiVersion = VK_API_VERSION_1_0;
|
||||
// Shaders generated by Slang require a certain SPIR-V environment that can't be satisfied by Vulkan 1.0, so we need to expliclity up that to at least 1.1 and enable some required extensions
|
||||
if (shaderDir == "slang") {
|
||||
appInfo.apiVersion = VK_API_VERSION_1_1;
|
||||
}
|
||||
|
||||
/*
|
||||
Vulkan instance creation (without surface extensions)
|
||||
|
|
@ -159,7 +169,7 @@ public:
|
|||
bool layersAvailable = true;
|
||||
for (auto layerName : validationLayers) {
|
||||
bool layerAvailable = false;
|
||||
for (auto instanceLayer : instanceLayers) {
|
||||
for (auto& instanceLayer : instanceLayers) {
|
||||
if (strcmp(instanceLayer.layerName, layerName) == 0) {
|
||||
layerAvailable = true;
|
||||
break;
|
||||
|
|
@ -260,8 +270,15 @@ public:
|
|||
deviceCreateInfo.queueCreateInfoCount = 1;
|
||||
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
|
||||
std::vector<const char*> deviceExtensions = {};
|
||||
|
||||
// Shaders generated by Slang require a certain SPIR-V environment that can't be satisfied by Vulkan 1.0, so we need to expliclity up that to at least 1.1 and enable some required extensions
|
||||
if (shaderDir == "slang") {
|
||||
deviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME);
|
||||
deviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_KHR_portability_subset)
|
||||
// SRS - When running on macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension
|
||||
// When running on macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension
|
||||
uint32_t deviceExtCount = 0;
|
||||
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtCount, nullptr);
|
||||
if (deviceExtCount > 0)
|
||||
|
|
@ -410,10 +427,6 @@ public:
|
|||
VkSpecializationMapEntry specializationMapEntry = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t));
|
||||
VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(1, &specializationMapEntry, sizeof(SpecializationData), &specializationData);
|
||||
|
||||
std::string shaderDir = "glsl";
|
||||
if (commandLineParser.isSet("shaders")) {
|
||||
shaderDir = commandLineParser.getValueAsString("shaders", "glsl");
|
||||
}
|
||||
const std::string shadersPath = getShaderBasePath() + shaderDir + "/computeheadless/";
|
||||
|
||||
VkPipelineShaderStageCreateInfo shaderStage = {};
|
||||
|
|
|
|||
|
|
@ -97,6 +97,8 @@ public:
|
|||
|
||||
VkDebugReportCallbackEXT debugReportCallback{};
|
||||
|
||||
std::string shaderDir = "glsl";
|
||||
|
||||
uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties) {
|
||||
VkPhysicalDeviceMemoryProperties deviceMemoryProperties;
|
||||
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties);
|
||||
|
|
@ -163,11 +165,19 @@ public:
|
|||
vks::android::loadVulkanLibrary();
|
||||
#endif
|
||||
|
||||
if (commandLineParser.isSet("shaders")) {
|
||||
shaderDir = commandLineParser.getValueAsString("shaders", "glsl");
|
||||
}
|
||||
|
||||
VkApplicationInfo appInfo = {};
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo.pApplicationName = "Vulkan headless example";
|
||||
appInfo.pEngineName = "VulkanExample";
|
||||
appInfo.apiVersion = VK_API_VERSION_1_0;
|
||||
// Shaders generated by Slang require a certain SPIR-V environment that can't be satisfied by Vulkan 1.0, so we need to expliclity up that to at least 1.1 and enable some required extensions
|
||||
if (shaderDir == "slang") {
|
||||
appInfo.apiVersion = VK_API_VERSION_1_1;
|
||||
}
|
||||
|
||||
/*
|
||||
Vulkan instance creation (without surface extensions)
|
||||
|
|
@ -190,7 +200,7 @@ public:
|
|||
bool layersAvailable = true;
|
||||
for (auto layerName : validationLayers) {
|
||||
bool layerAvailable = false;
|
||||
for (auto instanceLayer : instanceLayers) {
|
||||
for (auto& instanceLayer : instanceLayers) {
|
||||
if (strcmp(instanceLayer.layerName, layerName) == 0) {
|
||||
layerAvailable = true;
|
||||
break;
|
||||
|
|
@ -290,8 +300,15 @@ public:
|
|||
deviceCreateInfo.queueCreateInfoCount = 1;
|
||||
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
|
||||
std::vector<const char*> deviceExtensions = {};
|
||||
|
||||
// Shaders generated by Slang require a certain SPIR-V environment that can't be satisfied by Vulkan 1.0, so we need to expliclity up that to at least 1.1 and enable some required extensions
|
||||
if (shaderDir == "slang") {
|
||||
deviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME);
|
||||
deviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_KHR_portability_subset)
|
||||
// SRS - When running on macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension
|
||||
// When running on macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension
|
||||
uint32_t deviceExtCount = 0;
|
||||
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtCount, nullptr);
|
||||
if (deviceExtCount > 0)
|
||||
|
|
@ -643,7 +660,6 @@ public:
|
|||
|
||||
pipelineCreateInfo.pVertexInputState = &vertexInputState;
|
||||
|
||||
std::string shaderDir = "glsl";
|
||||
if (commandLineParser.isSet("shaders")) {
|
||||
shaderDir = commandLineParser.getValueAsString("shaders", "glsl");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
/*
|
||||
Vulkan Example - Cascaded shadow mapping for directional light sources
|
||||
Copyright by Sascha Willems - www.saschawillems.de
|
||||
Copyright (c) 2016-2025 by Sascha Willems - www.saschawillems.de
|
||||
This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||
*/
|
||||
|
||||
/*
|
||||
This example implements projective cascaded shadow mapping. This technique splits up the camera frustum into
|
||||
multiple frustums with each getting its own full-res shadow map, implemented as a layered depth-only image.
|
||||
The shader then selects the proper shadow map layer depending on what split of the frustum the depth value
|
||||
|
|
@ -175,7 +173,7 @@ public:
|
|||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
|
||||
|
||||
// Floor
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstBlock), &pushConstBlock);
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstBlock), &pushConstBlock);
|
||||
models.terrain.draw(commandBuffer, vkglTF::RenderFlags::BindImages, pipelineLayout);
|
||||
|
||||
// Trees
|
||||
|
|
@ -189,7 +187,7 @@ public:
|
|||
|
||||
for (auto& position : positions) {
|
||||
pushConstBlock.position = glm::vec4(position, 0.0f);
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstBlock), &pushConstBlock);
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstBlock), &pushConstBlock);
|
||||
// This will also bind the texture images to set 1
|
||||
models.tree.draw(commandBuffer, vkglTF::RenderFlags::BindImages, pipelineLayout);
|
||||
}
|
||||
|
|
@ -413,7 +411,7 @@ public:
|
|||
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.debugShadowMap);
|
||||
PushConstBlock pushConstBlock = {};
|
||||
pushConstBlock.cascadeIndex = displayDepthMapCascadeIndex;
|
||||
vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstBlock), &pushConstBlock);
|
||||
vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstBlock), &pushConstBlock);
|
||||
vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0);
|
||||
}
|
||||
|
||||
|
|
@ -490,7 +488,7 @@ public:
|
|||
|
||||
// Shared pipeline layout (scene and depth map debug display)
|
||||
{
|
||||
VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstBlock), 0);
|
||||
VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PushConstBlock), 0);
|
||||
std::array<VkDescriptorSetLayout, 2> setLayouts = { descriptorSetLayout, vkglTF::descriptorSetLayoutImage };
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast<uint32_t>(setLayouts.size()));
|
||||
pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
|
||||
|
|
@ -500,7 +498,7 @@ public:
|
|||
|
||||
// Depth pass pipeline layout
|
||||
{
|
||||
VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstBlock), 0);
|
||||
VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PushConstBlock), 0);
|
||||
std::array<VkDescriptorSetLayout, 2> setLayouts = { descriptorSetLayout, vkglTF::descriptorSetLayoutImage };
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast<uint32_t>(setLayouts.size()));
|
||||
pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
# Shaders
|
||||
|
||||
This folder contains the shaders used by the samples. Source files are available as GLSL and HLSL and also come with precompiled SPIR-V files that are consumed by the samples. To recompile shaders you can use the `compileshaders.py` scripts in the respective folders or any other means that can generate Vulkan SPIR-V from GLSL or HLSL. One such option is [this extension for Visual Studio](https://github.com/SaschaWillems/SPIRV-VSExtension).
|
||||
This folder contains the shaders used by the samples. Source files are available in GLSL, HLSL and [slang](https://shader-slang.org/) and also come with precompiled SPIR-V files that are consumed by the samples. To recompile shaders you can use the `compileshaders.py` scripts in the respective folders or any other means that can generate Vulkan SPIR-V from GLSL, HLSL or slang. One such option is [this extension for Visual Studio](https://github.com/SaschaWillems/SPIRV-VSExtension).
|
||||
|
||||
Note that not all samples may come with all shading language variants. So some samples that have GLSL source files might not come with HLSL and/or slang source files.
|
||||
|
||||
A note for using **slang** shaders: These require a different SPIR-V environment than glsl/hlsl. When selecting slang shaders, the base requirement for all samples is raised to at least Vulkan 1.1 with the SPIRV 1.4 extension.
|
||||
|
||||
If you want to compile **slang** shaders to SPIR-V, please use the latest release from [here](https://github.com/shader-slang/slang/releases) to get the latest bug fixes and features required for some of the samples.
|
||||
Binary file not shown.
|
|
@ -6,8 +6,8 @@ layout (location = 1) in vec3 inNormal;
|
|||
layout (location = 2) in vec3 inColor;
|
||||
|
||||
// Instanced attributes
|
||||
layout (location = 4) in vec3 instancePos;
|
||||
layout (location = 5) in float instanceScale;
|
||||
layout (location = 3) in vec3 instancePos;
|
||||
layout (location = 4) in float instanceScale;
|
||||
|
||||
layout (binding = 0) uniform UBO
|
||||
{
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -6,8 +6,8 @@ struct VSInput
|
|||
[[vk::location(1)]] float3 Normal : NORMAL0;
|
||||
[[vk::location(2)]] float3 Color : COLOR0;
|
||||
// Instanced attributes
|
||||
[[vk::location(4)]] float3 instancePos : TEXCOORD0;
|
||||
[[vk::location(5)]] float instanceScale : TEXCOORD1;
|
||||
[[vk::location(3)]] float3 instancePos : TEXCOORD0;
|
||||
[[vk::location(4)]] float instanceScale : TEXCOORD1;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
|
|
|
|||
Binary file not shown.
86
shaders/slang/_rename.py
Normal file
86
shaders/slang/_rename.py
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# Copyright (C) 2025 by Sascha Willems - www.saschawillems.de
|
||||
# This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||
|
||||
from shutil import move
|
||||
|
||||
# To match required file names to fother shading languages that don't support multiple entry points, shader files may need to be renamed for some samples
|
||||
def checkRenameFiles(samplename):
|
||||
mappings = {}
|
||||
match samplename:
|
||||
case "displacement":
|
||||
mappings = {
|
||||
"displacement.vert.spv": "base.vert.spv",
|
||||
"displacement.frag.spv": "base.frag.spv",
|
||||
}
|
||||
case "geometryshader":
|
||||
mappings = {
|
||||
"normaldebug.vert.spv": "base.vert.spv",
|
||||
"normaldebug.frag.spv": "base.frag.spv",
|
||||
}
|
||||
case "graphicspipelinelibrary":
|
||||
mappings = {
|
||||
"uber.vert.spv": "shared.vert.spv",
|
||||
}
|
||||
case "raytracingbasic":
|
||||
mappings = {
|
||||
"raytracingbasic.rchit.spv": "closesthit.rchit.spv",
|
||||
"raytracingbasic.rmiss.spv": "miss.rmiss.spv",
|
||||
"raytracingbasic.rgen.spv": "raygen.rgen.spv",
|
||||
}
|
||||
case "raytracingcallable":
|
||||
mappings = {
|
||||
"raytracingcallable.rchit.spv": "closesthit.rchit.spv",
|
||||
"raytracingcallable.rmiss.spv": "miss.rmiss.spv",
|
||||
"raytracingcallable.rgen.spv": "raygen.rgen.spv",
|
||||
}
|
||||
case "raytracinggltf":
|
||||
mappings = {
|
||||
"raytracinggltf.rchit.spv": "closesthit.rchit.spv",
|
||||
"raytracinggltf.rmiss.spv": "miss.rmiss.spv",
|
||||
"raytracinggltf.rgen.spv": "raygen.rgen.spv",
|
||||
"raytracinggltf.rahit.spv": "anyhit.rahit.spv",
|
||||
}
|
||||
case "raytracingpositionfetch":
|
||||
mappings = {
|
||||
"raytracingpositionfetch.rchit.spv": "closesthit.rchit.spv",
|
||||
"raytracingpositionfetch.rmiss.spv": "miss.rmiss.spv",
|
||||
"raytracingpositionfetch.rgen.spv": "raygen.rgen.spv",
|
||||
}
|
||||
case "raytracingreflections":
|
||||
mappings = {
|
||||
"raytracingreflections.rchit.spv": "closesthit.rchit.spv",
|
||||
"raytracingreflections.rmiss.spv": "miss.rmiss.spv",
|
||||
"raytracingreflections.rgen.spv": "raygen.rgen.spv",
|
||||
}
|
||||
case "raytracingsbtdata":
|
||||
mappings = {
|
||||
"raytracingsbtdata.rchit.spv": "closesthit.rchit.spv",
|
||||
"raytracingsbtdata.rmiss.spv": "miss.rmiss.spv",
|
||||
"raytracingsbtdata.rgen.spv": "raygen.rgen.spv",
|
||||
}
|
||||
case "raytracingshadows":
|
||||
mappings = {
|
||||
"raytracingshadows.rchit.spv": "closesthit.rchit.spv",
|
||||
"raytracingshadows.rmiss.spv": "miss.rmiss.spv",
|
||||
"raytracingshadows.rgen.spv": "raygen.rgen.spv",
|
||||
}
|
||||
case "raytracingtextures":
|
||||
mappings = {
|
||||
"raytracingtextures.rchit.spv": "closesthit.rchit.spv",
|
||||
"raytracingtextures.rmiss.spv": "miss.rmiss.spv",
|
||||
"raytracingtextures.rgen.spv": "raygen.rgen.spv",
|
||||
"raytracingtextures.rahit.spv": "anyhit.rahit.spv",
|
||||
}
|
||||
case "raytracingintersection":
|
||||
mappings = {
|
||||
"raytracingintersection.rchit.spv": "closesthit.rchit.spv",
|
||||
"raytracingintersection.rmiss.spv": "miss.rmiss.spv",
|
||||
"raytracingintersection.rgen.spv": "raygen.rgen.spv",
|
||||
"raytracingintersection.rint.spv": "intersection.rint.spv",
|
||||
}
|
||||
case "viewportarray":
|
||||
mappings = {
|
||||
"scene.geom.spv": "multiview.geom.spv",
|
||||
}
|
||||
for x, y in mappings.items():
|
||||
move(samplename + "\\" + x, samplename + "\\" + y)
|
||||
BIN
shaders/slang/base/uioverlay.frag.spv
Normal file
BIN
shaders/slang/base/uioverlay.frag.spv
Normal file
Binary file not shown.
43
shaders/slang/base/uioverlay.slang
Normal file
43
shaders/slang/base/uioverlay.slang
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
Sampler2D fontTexture;
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float2 Pos : POSITION0;
|
||||
float2 UV;
|
||||
float4 Color;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float2 UV;
|
||||
float4 Color;
|
||||
};
|
||||
|
||||
struct PushConstants
|
||||
{
|
||||
float2 scale;
|
||||
float2 translate;
|
||||
};
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input, uniform PushConstants pushConstants)
|
||||
{
|
||||
VSOutput output;
|
||||
output.Pos = float4(input.Pos * pushConstants.scale + pushConstants.translate, 0.0, 1.0);
|
||||
output.UV = input.UV;
|
||||
output.Color = input.Color;
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
return input.Color * fontTexture.Sample(input.UV);
|
||||
}
|
||||
BIN
shaders/slang/base/uioverlay.vert.spv
Normal file
BIN
shaders/slang/base/uioverlay.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/bloom/colorpass.frag.spv
Normal file
BIN
shaders/slang/bloom/colorpass.frag.spv
Normal file
Binary file not shown.
45
shaders/slang/bloom/colorpass.slang
Normal file
45
shaders/slang/bloom/colorpass.slang
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float4 Pos;
|
||||
float2 UV;
|
||||
float3 Color;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float3 Color;
|
||||
float2 UV;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 projection;
|
||||
float4x4 view;
|
||||
float4x4 model;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
Sampler2D colorMapSampler;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input)
|
||||
{
|
||||
VSOutput output;
|
||||
output.UV = input.UV;
|
||||
output.Color = input.Color;
|
||||
output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, input.Pos)));
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
return float4(input.Color, 1);
|
||||
}
|
||||
BIN
shaders/slang/bloom/colorpass.vert.spv
Normal file
BIN
shaders/slang/bloom/colorpass.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/bloom/gaussblur.frag.spv
Normal file
BIN
shaders/slang/bloom/gaussblur.frag.spv
Normal file
Binary file not shown.
63
shaders/slang/bloom/gaussblur.slang
Normal file
63
shaders/slang/bloom/gaussblur.slang
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float2 UV;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float blurScale;
|
||||
float blurStrength;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
Sampler2D samplerColor;
|
||||
|
||||
[[SpecializationConstant]] const int blurdirection = 0;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(uint VertexIndex: SV_VertexID)
|
||||
{
|
||||
VSOutput output;
|
||||
output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2);
|
||||
output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f);
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
float weight[5];
|
||||
weight[0] = 0.227027;
|
||||
weight[1] = 0.1945946;
|
||||
weight[2] = 0.1216216;
|
||||
weight[3] = 0.054054;
|
||||
weight[4] = 0.016216;
|
||||
|
||||
float2 textureSize;
|
||||
samplerColor.GetDimensions(textureSize.x, textureSize.y);
|
||||
float2 tex_offset = 1.0 / textureSize * ubo.blurScale; // gets size of single texel
|
||||
float3 result = samplerColor.Sample(input.UV).rgb * weight[0]; // current fragment's contribution
|
||||
for(int i = 1; i < 5; ++i)
|
||||
{
|
||||
if (blurdirection == 1)
|
||||
{
|
||||
// H
|
||||
result += samplerColor.Sample(input.UV + float2(tex_offset.x * i, 0.0)).rgb * weight[i] * ubo.blurScale;
|
||||
result += samplerColor.Sample(input.UV - float2(tex_offset.x * i, 0.0)).rgb * weight[i] * ubo.blurScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
// V
|
||||
result += samplerColor.Sample(input.UV + float2(0.0, tex_offset.y * i)).rgb * weight[i] * ubo.blurScale;
|
||||
result += samplerColor.Sample(input.UV - float2(0.0, tex_offset.y * i)).rgb * weight[i] * ubo.blurScale;
|
||||
}
|
||||
}
|
||||
return float4(result, 1.0);
|
||||
}
|
||||
BIN
shaders/slang/bloom/gaussblur.vert.spv
Normal file
BIN
shaders/slang/bloom/gaussblur.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/bloom/phongpass.frag.spv
Normal file
BIN
shaders/slang/bloom/phongpass.frag.spv
Normal file
Binary file not shown.
70
shaders/slang/bloom/phongpass.slang
Normal file
70
shaders/slang/bloom/phongpass.slang
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float4 Pos;
|
||||
float2 UV;
|
||||
float3 Color;
|
||||
float3 Normal;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float3 Normal;
|
||||
float2 UV;
|
||||
float3 Color;
|
||||
float3 ViewVec;
|
||||
float3 LightVec;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 projection;
|
||||
float4x4 view;
|
||||
float4x4 model;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
Sampler2D colorMapSampler;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input)
|
||||
{
|
||||
VSOutput output;
|
||||
output.Normal = input.Normal;
|
||||
output.Color = input.Color;
|
||||
output.UV = input.UV;
|
||||
output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, input.Pos)));
|
||||
|
||||
float3 lightPos = float3(-5.0, -5.0, 0.0);
|
||||
float4 pos = mul(ubo.view, mul(ubo.model, input.Pos));
|
||||
output.Normal = mul((float4x3)mul(ubo.view, ubo.model), input.Normal).xyz;
|
||||
output.LightVec = lightPos - pos.xyz;
|
||||
output.ViewVec = -pos.xyz;
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
float3 ambient = float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
// Adjust light calculations for glow color
|
||||
if ((input.Color.r >= 0.9) || (input.Color.g >= 0.9) || (input.Color.b >= 0.9))
|
||||
{
|
||||
ambient = input.Color * 0.25;
|
||||
}
|
||||
|
||||
float3 N = normalize(input.Normal);
|
||||
float3 L = normalize(input.LightVec);
|
||||
float3 V = normalize(input.ViewVec);
|
||||
float3 R = reflect(-L, N);
|
||||
float3 diffuse = max(dot(N, L), 0.0) * input.Color;
|
||||
float3 specular = pow(max(dot(R, V), 0.0), 8.0) * float3(0.75f, 0.75f, 0.75f);
|
||||
return float4(ambient + diffuse + specular, 1.0);
|
||||
}
|
||||
BIN
shaders/slang/bloom/phongpass.vert.spv
Normal file
BIN
shaders/slang/bloom/phongpass.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/bloom/skybox.frag.spv
Normal file
BIN
shaders/slang/bloom/skybox.frag.spv
Normal file
Binary file not shown.
41
shaders/slang/bloom/skybox.slang
Normal file
41
shaders/slang/bloom/skybox.slang
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float3 Pos;
|
||||
}
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float3 UVW;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 projection;
|
||||
float4x4 view;
|
||||
float4x4 model;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
SamplerCube samplerCubeMap;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input)
|
||||
{
|
||||
VSOutput output;
|
||||
output.UVW = input.Pos;
|
||||
output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0))));
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
return samplerCubeMap.Sample(input.UVW);
|
||||
}
|
||||
BIN
shaders/slang/bloom/skybox.vert.spv
Normal file
BIN
shaders/slang/bloom/skybox.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/bufferdeviceaddress/cube.frag.spv
Normal file
BIN
shaders/slang/bufferdeviceaddress/cube.frag.spv
Normal file
Binary file not shown.
54
shaders/slang/bufferdeviceaddress/cube.slang
Normal file
54
shaders/slang/bufferdeviceaddress/cube.slang
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
Sampler2D samplerColorMap;
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float3 Pos;
|
||||
float3 Normal;
|
||||
float2 UV;
|
||||
float3 Color;
|
||||
};
|
||||
|
||||
struct MatrixReference {
|
||||
float4x4 matrix;
|
||||
};
|
||||
|
||||
struct PushConsts {
|
||||
// Pointer to the buffer with the scene's MVP matrix
|
||||
ConstBufferPointer<MatrixReference> sceneDataReference;
|
||||
// Pointer to the buffer for the data for each model
|
||||
ConstBufferPointer<MatrixReference> modelDataReference;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float3 Normal;
|
||||
float3 Color;
|
||||
float2 UV;
|
||||
};
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input, uniform PushConsts pushConstants)
|
||||
{
|
||||
MatrixReference sceneData = pushConstants.sceneDataReference.get();
|
||||
MatrixReference modelData = pushConstants.modelDataReference.get();
|
||||
|
||||
VSOutput output;
|
||||
output.Normal = input.Normal;
|
||||
output.Color = input.Color;
|
||||
output.UV = input.UV;
|
||||
output.Pos = mul(sceneData.matrix, mul(modelData.matrix, float4(input.Pos.xyz, 1.0)));
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
return samplerColorMap.Sample(input.UV) * float4(input.Color, 1.0);
|
||||
}
|
||||
BIN
shaders/slang/bufferdeviceaddress/cube.vert.spv
Normal file
BIN
shaders/slang/bufferdeviceaddress/cube.vert.spv
Normal file
Binary file not shown.
132
shaders/slang/compileshaders.py
Normal file
132
shaders/slang/compileshaders.py
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
# Copyright (C) 2025 by Sascha Willems - www.saschawillems.de
|
||||
# This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||
|
||||
import argparse
|
||||
import fileinput
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from _rename import *
|
||||
|
||||
parser = argparse.ArgumentParser(description='Compile all slang shaders')
|
||||
parser.add_argument('--slangc', type=str, help='path to slangc executable')
|
||||
parser.add_argument('--sample', type=str, help='can be used to compile shaders for a single sample only')
|
||||
args = parser.parse_args()
|
||||
|
||||
def findCompiler():
|
||||
def isExe(path):
|
||||
return os.path.isfile(path) and os.access(path, os.X_OK)
|
||||
|
||||
if args.slangc != None and isExe(args.slangc):
|
||||
return args.slangc
|
||||
|
||||
exe_name = "slangc"
|
||||
if os.name == "nt":
|
||||
exe_name += ".exe"
|
||||
|
||||
for exe_dir in os.environ["PATH"].split(os.pathsep):
|
||||
full_path = os.path.join(exe_dir, exe_name)
|
||||
if isExe(full_path):
|
||||
return full_path
|
||||
|
||||
sys.exit("Could not find slangc executable on PATH, and was not specified with --slangc")
|
||||
|
||||
def getShaderStages(filename):
|
||||
stages = []
|
||||
with open(filename) as f:
|
||||
filecontent = f.read()
|
||||
if '[shader("vertex")]' in filecontent:
|
||||
stages.append("vertex")
|
||||
if '[shader("fragment")]' in filecontent:
|
||||
stages.append("fragment")
|
||||
if '[shader("raygeneration")]' in filecontent:
|
||||
stages.append("raygeneration")
|
||||
if '[shader("miss")]' in filecontent:
|
||||
stages.append("miss")
|
||||
if '[shader("closesthit")]' in filecontent:
|
||||
stages.append("closesthit")
|
||||
if '[shader("callable")]' in filecontent:
|
||||
stages.append("callable")
|
||||
if '[shader("intersection")]' in filecontent:
|
||||
stages.append("intersection")
|
||||
if '[shader("anyhit")]' in filecontent:
|
||||
stages.append("anyhit")
|
||||
if '[shader("compute")]' in filecontent:
|
||||
stages.append("compute")
|
||||
if '[shader("amplification")]' in filecontent:
|
||||
stages.append("amplification")
|
||||
if '[shader("mesh")]' in filecontent:
|
||||
stages.append("mesh")
|
||||
if '[shader("geometry")]' in filecontent:
|
||||
stages.append("geometry")
|
||||
if '[shader("hull")]' in filecontent:
|
||||
stages.append("hull")
|
||||
if '[shader("domain")]' in filecontent:
|
||||
stages.append("domain")
|
||||
f.close()
|
||||
return stages
|
||||
|
||||
compiler_path = findCompiler()
|
||||
|
||||
print("Found slang compiler at %s", compiler_path)
|
||||
|
||||
compile_single_sample = ""
|
||||
if args.sample != None:
|
||||
compile_single_sample = args.sample
|
||||
if (not os.path.isdir(compile_single_sample)):
|
||||
print("ERROR: No directory found with name %s" % compile_single_sample)
|
||||
exit(-1)
|
||||
|
||||
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||
dir_path = dir_path.replace('\\', '/')
|
||||
for root, dirs, files in os.walk(dir_path):
|
||||
folder_name = os.path.basename(root)
|
||||
if (compile_single_sample != "" and folder_name != compile_single_sample):
|
||||
continue
|
||||
for file in files:
|
||||
if file.endswith(".slang"):
|
||||
input_file = os.path.join(root, file)
|
||||
# Slang can store multiple shader stages in a single file, we need to split into separate SPIR-V files for the sample framework
|
||||
stages = getShaderStages(input_file)
|
||||
print("Compiling %s" % input_file)
|
||||
output_base_file_name = input_file
|
||||
for stage in stages:
|
||||
entry_point = stage + "Main"
|
||||
output_ext = ""
|
||||
match stage:
|
||||
case "vertex":
|
||||
output_ext = ".vert"
|
||||
case "fragment":
|
||||
output_ext = ".frag"
|
||||
case "raygeneration":
|
||||
output_ext = ".rgen"
|
||||
case "miss":
|
||||
output_ext = ".rmiss"
|
||||
case "closesthit":
|
||||
output_ext = ".rchit"
|
||||
case "callable":
|
||||
output_ext = ".rcall"
|
||||
case "intersection":
|
||||
output_ext = ".rint"
|
||||
case "anyhit":
|
||||
output_ext = ".rahit"
|
||||
case "compute":
|
||||
output_ext = ".comp"
|
||||
case "mesh":
|
||||
output_ext = ".mesh"
|
||||
case "amplification":
|
||||
output_ext = ".task"
|
||||
case "geometry":
|
||||
output_ext = ".geom"
|
||||
case "hull":
|
||||
output_ext = ".tesc"
|
||||
case "domain":
|
||||
output_ext = ".tese"
|
||||
output_file = output_base_file_name + output_ext + ".spv"
|
||||
output_file = output_file.replace(".slang", "")
|
||||
print(output_file)
|
||||
res = subprocess.call("%s %s -profile spirv_1_4 -matrix-layout-column-major -target spirv -o %s -entry %s -stage %s -warnings-disable 39001" % (compiler_path, input_file, output_file, entry_point, stage), shell=True)
|
||||
if res != 0:
|
||||
print("Error %s", res)
|
||||
sys.exit(res)
|
||||
checkRenameFiles(folder_name)
|
||||
BIN
shaders/slang/computecloth/cloth.comp.spv
Normal file
BIN
shaders/slang/computecloth/cloth.comp.spv
Normal file
Binary file not shown.
BIN
shaders/slang/computecloth/cloth.frag.spv
Normal file
BIN
shaders/slang/computecloth/cloth.frag.spv
Normal file
Binary file not shown.
190
shaders/slang/computecloth/cloth.slang
Normal file
190
shaders/slang/computecloth/cloth.slang
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float3 Pos;
|
||||
float2 UV;
|
||||
float3 Normal;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float2 UV;
|
||||
float3 Normal;
|
||||
float3 ViewVec;
|
||||
float3 LightVec;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 projection;
|
||||
float4x4 modelview;
|
||||
float4 lightPos;
|
||||
};
|
||||
[[vk::binding(0,0)]] ConstantBuffer<UBO> ubo;
|
||||
[[vk::binding(1,0)]] Sampler2D samplerColor;
|
||||
|
||||
struct Particle {
|
||||
float4 pos;
|
||||
float4 vel;
|
||||
float4 uv;
|
||||
float4 normal;
|
||||
};
|
||||
|
||||
[[vk::binding(0,0)]] StructuredBuffer<Particle> particleIn;
|
||||
[[vk::binding(1,0)]] RWStructuredBuffer<Particle> particleOut;
|
||||
|
||||
struct UBOCompute
|
||||
{
|
||||
float deltaT;
|
||||
float particleMass;
|
||||
float springStiffness;
|
||||
float damping;
|
||||
float restDistH;
|
||||
float restDistV;
|
||||
float restDistD;
|
||||
float sphereRadius;
|
||||
float4 spherePos;
|
||||
float4 gravity;
|
||||
int2 particleCount;
|
||||
};
|
||||
[[vk::binding(2, 0)]] ConstantBuffer<UBOCompute> params;
|
||||
|
||||
float3 springForce(float3 p0, float3 p1, float restDist)
|
||||
{
|
||||
float3 dist = p0 - p1;
|
||||
return normalize(dist) * params.springStiffness * (length(dist) - restDist);
|
||||
}
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input)
|
||||
{
|
||||
VSOutput output;
|
||||
output.UV = input.UV;
|
||||
output.Normal = input.Normal.xyz;
|
||||
float4 eyePos = mul(ubo.modelview, float4(input.Pos.x, input.Pos.y, input.Pos.z, 1.0));
|
||||
output.Pos = mul(ubo.projection, eyePos);
|
||||
float4 pos = float4(input.Pos, 1.0);
|
||||
float3 lPos = ubo.lightPos.xyz;
|
||||
output.LightVec = lPos - pos.xyz;
|
||||
output.ViewVec = -pos.xyz;
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
float3 color = samplerColor.Sample(input.UV).rgb;
|
||||
float3 N = normalize(input.Normal);
|
||||
float3 L = normalize(input.LightVec);
|
||||
float3 V = normalize(input.ViewVec);
|
||||
float3 R = reflect(-L, N);
|
||||
float3 diffuse = max(dot(N, L), 0.15) * float3(1, 1, 1);
|
||||
float3 specular = pow(max(dot(R, V), 0.0), 8.0) * float3(0.2, 0.2, 0.2);
|
||||
return float4(diffuse * color.rgb + specular, 1.0);
|
||||
}
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(10, 10, 1)]
|
||||
void computeMain(uint3 id: SV_DispatchThreadID, uniform uint calculateNormals)
|
||||
{
|
||||
uint index = id.y * params.particleCount.x + id.x;
|
||||
if (index > params.particleCount.x * params.particleCount.y)
|
||||
return;
|
||||
|
||||
// Initial force from gravity
|
||||
float3 force = params.gravity.xyz * params.particleMass;
|
||||
|
||||
float3 pos = particleIn[index].pos.xyz;
|
||||
float3 vel = particleIn[index].vel.xyz;
|
||||
|
||||
// Spring forces from neighboring particles
|
||||
// left
|
||||
if (id.x > 0) {
|
||||
force += springForce(particleIn[index-1].pos.xyz, pos, params.restDistH);
|
||||
}
|
||||
// right
|
||||
if (id.x < params.particleCount.x - 1) {
|
||||
force += springForce(particleIn[index + 1].pos.xyz, pos, params.restDistH);
|
||||
}
|
||||
// upper
|
||||
if (id.y < params.particleCount.y - 1) {
|
||||
force += springForce(particleIn[index + params.particleCount.x].pos.xyz, pos, params.restDistV);
|
||||
}
|
||||
// lower
|
||||
if (id.y > 0) {
|
||||
force += springForce(particleIn[index - params.particleCount.x].pos.xyz, pos, params.restDistV);
|
||||
}
|
||||
// upper-left
|
||||
if ((id.x > 0) && (id.y < params.particleCount.y - 1)) {
|
||||
force += springForce(particleIn[index + params.particleCount.x - 1].pos.xyz, pos, params.restDistD);
|
||||
}
|
||||
// lower-left
|
||||
if ((id.x > 0) && (id.y > 0)) {
|
||||
force += springForce(particleIn[index - params.particleCount.x - 1].pos.xyz, pos, params.restDistD);
|
||||
}
|
||||
// upper-right
|
||||
if ((id.x < params.particleCount.x - 1) && (id.y < params.particleCount.y - 1)) {
|
||||
force += springForce(particleIn[index + params.particleCount.x + 1].pos.xyz, pos, params.restDistD);
|
||||
}
|
||||
// lower-right
|
||||
if ((id.x < params.particleCount.x - 1) && (id.y > 0)) {
|
||||
force += springForce(particleIn[index - params.particleCount.x + 1].pos.xyz, pos, params.restDistD);
|
||||
}
|
||||
|
||||
force += (-params.damping * vel);
|
||||
|
||||
// Integrate
|
||||
float3 f = force * (1.0 / params.particleMass);
|
||||
particleOut[index].pos = float4(pos + vel * params.deltaT + 0.5 * f * params.deltaT * params.deltaT, 1.0);
|
||||
particleOut[index].vel = float4(vel + f * params.deltaT, 0.0);
|
||||
|
||||
// Sphere collision
|
||||
float3 sphereDist = particleOut[index].pos.xyz - params.spherePos.xyz;
|
||||
if (length(sphereDist) < params.sphereRadius + 0.01) {
|
||||
// If the particle is inside the sphere, push it to the outer radius
|
||||
particleOut[index].pos.xyz = params.spherePos.xyz + normalize(sphereDist) * (params.sphereRadius + 0.01);
|
||||
// Cancel out velocity
|
||||
particleOut[index].vel = float4(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Normals
|
||||
if (calculateNormals == 1) {
|
||||
float3 normal = float3(0, 0, 0);
|
||||
float3 a, b, c;
|
||||
if (id.y > 0) {
|
||||
if (id.x > 0) {
|
||||
a = particleIn[index - 1].pos.xyz - pos;
|
||||
b = particleIn[index - params.particleCount.x - 1].pos.xyz - pos;
|
||||
c = particleIn[index - params.particleCount.x].pos.xyz - pos;
|
||||
normal += cross(a,b) + cross(b,c);
|
||||
}
|
||||
if (id.x < params.particleCount.x - 1) {
|
||||
a = particleIn[index - params.particleCount.x].pos.xyz - pos;
|
||||
b = particleIn[index - params.particleCount.x + 1].pos.xyz - pos;
|
||||
c = particleIn[index + 1].pos.xyz - pos;
|
||||
normal += cross(a,b) + cross(b,c);
|
||||
}
|
||||
}
|
||||
if (id.y < params.particleCount.y - 1) {
|
||||
if (id.x > 0) {
|
||||
a = particleIn[index + params.particleCount.x].pos.xyz - pos;
|
||||
b = particleIn[index + params.particleCount.x - 1].pos.xyz - pos;
|
||||
c = particleIn[index - 1].pos.xyz - pos;
|
||||
normal += cross(a,b) + cross(b,c);
|
||||
}
|
||||
if (id.x < params.particleCount.x - 1) {
|
||||
a = particleIn[index + 1].pos.xyz - pos;
|
||||
b = particleIn[index + params.particleCount.x + 1].pos.xyz - pos;
|
||||
c = particleIn[index + params.particleCount.x].pos.xyz - pos;
|
||||
normal += cross(a,b) + cross(b,c);
|
||||
}
|
||||
}
|
||||
particleOut[index].normal = float4(normalize(normal), 0.0f);
|
||||
}
|
||||
}
|
||||
BIN
shaders/slang/computecloth/cloth.vert.spv
Normal file
BIN
shaders/slang/computecloth/cloth.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/computecloth/sphere.frag.spv
Normal file
BIN
shaders/slang/computecloth/sphere.frag.spv
Normal file
Binary file not shown.
55
shaders/slang/computecloth/sphere.slang
Normal file
55
shaders/slang/computecloth/sphere.slang
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float3 Pos;
|
||||
float2 UV;
|
||||
float3 Normal;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float3 Normal;
|
||||
float3 ViewVec;
|
||||
float3 LightVec;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 projection;
|
||||
float4x4 modelview;
|
||||
float4 lightPos;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input)
|
||||
{
|
||||
VSOutput output;
|
||||
float4 eyePos = mul(ubo.modelview, float4(input.Pos.x, input.Pos.y, input.Pos.z, 1.0));
|
||||
output.Pos = mul(ubo.projection, eyePos);
|
||||
float4 pos = float4(input.Pos, 1.0);
|
||||
float3 lPos = ubo.lightPos.xyz;
|
||||
output.LightVec = lPos - pos.xyz;
|
||||
output.ViewVec = -pos.xyz;
|
||||
output.Normal = input.Normal;
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
float3 color = float3(0.5, 0.5, 0.5);
|
||||
float3 N = normalize(input.Normal);
|
||||
float3 L = normalize(input.LightVec);
|
||||
float3 V = normalize(input.ViewVec);
|
||||
float3 R = reflect(-L, N);
|
||||
float3 diffuse = max(dot(N, L), 0.15);
|
||||
float3 specular = pow(max(dot(R, V), 0.0), 32.0);
|
||||
return float4(diffuse * color.rgb + specular, 1.0);
|
||||
}
|
||||
BIN
shaders/slang/computecloth/sphere.vert.spv
Normal file
BIN
shaders/slang/computecloth/sphere.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/computecullandlod/cull.comp.spv
Normal file
BIN
shaders/slang/computecullandlod/cull.comp.spv
Normal file
Binary file not shown.
115
shaders/slang/computecullandlod/cull.slang
Normal file
115
shaders/slang/computecullandlod/cull.slang
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#define MAX_LOD_LEVEL_COUNT 6
|
||||
[[SpecializationConstant]] const int MAX_LOD_LEVEL = 5;
|
||||
|
||||
struct InstanceData
|
||||
{
|
||||
float3 pos;
|
||||
float scale;
|
||||
};
|
||||
StructuredBuffer<InstanceData> instances;
|
||||
|
||||
// Same layout as VkDrawIndexedIndirectCommand
|
||||
struct IndexedIndirectCommand
|
||||
{
|
||||
uint indexCount;
|
||||
uint instanceCount;
|
||||
uint firstIndex;
|
||||
uint vertexOffset;
|
||||
uint firstInstance;
|
||||
};
|
||||
RWStructuredBuffer<IndexedIndirectCommand> indirectDraws;
|
||||
|
||||
// Binding 2: Uniform block object with matrices
|
||||
struct UBO
|
||||
{
|
||||
float4x4 projection;
|
||||
float4x4 modelview;
|
||||
float4 cameraPos;
|
||||
float4 frustumPlanes[6];
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
// Binding 3: Indirect draw stats
|
||||
struct UBOOut
|
||||
{
|
||||
uint drawCount;
|
||||
uint lodCount[MAX_LOD_LEVEL_COUNT];
|
||||
};
|
||||
RWStructuredBuffer<UBOOut> uboOut;
|
||||
|
||||
// Binding 4: level-of-detail information
|
||||
struct LOD
|
||||
{
|
||||
uint firstIndex;
|
||||
uint indexCount;
|
||||
float distance;
|
||||
float _pad0;
|
||||
};
|
||||
StructuredBuffer<LOD> lods;
|
||||
|
||||
bool frustumCheck(float4 pos, float radius)
|
||||
{
|
||||
// Check sphere against frustum planes
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (dot(pos, ubo.frustumPlanes[i]) + radius < 0.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(16, 1, 1)]
|
||||
void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID)
|
||||
{
|
||||
uint idx = GlobalInvocationID.x;
|
||||
uint temp;
|
||||
|
||||
// Clear stats on first invocation
|
||||
if (idx == 0)
|
||||
{
|
||||
InterlockedExchange(uboOut[0].drawCount, 0, temp);
|
||||
for (uint i = 0; i < MAX_LOD_LEVEL + 1; i++)
|
||||
{
|
||||
InterlockedExchange(uboOut[0].lodCount[i], 0, temp);
|
||||
}
|
||||
}
|
||||
|
||||
float4 pos = float4(instances[idx].pos.xyz, 1.0);
|
||||
|
||||
// Check if object is within current viewing frustum
|
||||
if (frustumCheck(pos, 1.0))
|
||||
{
|
||||
indirectDraws[idx].instanceCount = 1;
|
||||
|
||||
// Increase number of indirect draw counts
|
||||
InterlockedAdd(uboOut[0].drawCount, 1, temp);
|
||||
|
||||
// Select appropriate LOD level based on distance to camera
|
||||
uint lodLevel = MAX_LOD_LEVEL;
|
||||
for (uint i = 0; i < MAX_LOD_LEVEL; i++)
|
||||
{
|
||||
if (distance(instances[idx].pos.xyz, ubo.cameraPos.xyz) < lods[i].distance)
|
||||
{
|
||||
lodLevel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
indirectDraws[idx].firstIndex = lods[lodLevel].firstIndex;
|
||||
indirectDraws[idx].indexCount = lods[lodLevel].indexCount;
|
||||
// Update stats
|
||||
InterlockedAdd(uboOut[0].lodCount[lodLevel], 1, temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
indirectDraws[idx].instanceCount = 0;
|
||||
}
|
||||
}
|
||||
BIN
shaders/slang/computecullandlod/indirectdraw.frag.spv
Normal file
BIN
shaders/slang/computecullandlod/indirectdraw.frag.spv
Normal file
Binary file not shown.
56
shaders/slang/computecullandlod/indirectdraw.slang
Normal file
56
shaders/slang/computecullandlod/indirectdraw.slang
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float4 Pos : POSITION0;
|
||||
float3 Normal;
|
||||
float3 Color;
|
||||
// Instanced attributes
|
||||
float3 instancePos;
|
||||
float instanceScale;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float3 Normal;
|
||||
float3 Color;
|
||||
float3 ViewVec;
|
||||
float3 LightVec;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 projection;
|
||||
float4x4 modelview;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input)
|
||||
{
|
||||
VSOutput output;
|
||||
output.Color = input.Color;
|
||||
output.Normal = input.Normal;
|
||||
float4 pos = float4((input.Pos.xyz * input.instanceScale) + input.instancePos, 1.0);
|
||||
output.Pos = mul(ubo.projection, mul(ubo.modelview, pos));
|
||||
float4 wPos = mul(ubo.modelview, float4(pos.xyz, 1.0));
|
||||
float4 lPos = float4(0.0, 10.0, 50.0, 1.0);
|
||||
output.LightVec = lPos.xyz - pos.xyz;
|
||||
output.ViewVec = -pos.xyz;
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
float3 N = normalize(input.Normal);
|
||||
float3 L = normalize(input.LightVec);
|
||||
float3 ambient = float3(0.25, 0.25, 0.25);
|
||||
float3 diffuse = max(dot(N, L), 0.0).xxx;
|
||||
return float4((ambient + diffuse) * input.Color, 1.0);
|
||||
}
|
||||
BIN
shaders/slang/computecullandlod/indirectdraw.vert.spv
Normal file
BIN
shaders/slang/computecullandlod/indirectdraw.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/computeheadless/headless.comp.spv
Normal file
BIN
shaders/slang/computeheadless/headless.comp.spv
Normal file
Binary file not shown.
34
shaders/slang/computeheadless/headless.slang
Normal file
34
shaders/slang/computeheadless/headless.slang
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
RWStructuredBuffer<uint> values;
|
||||
|
||||
[[SpecializationConstant]] const uint BUFFER_ELEMENTS = 32;
|
||||
|
||||
uint fibonacci(uint n) {
|
||||
if(n <= 1){
|
||||
return n;
|
||||
}
|
||||
uint curr = 1;
|
||||
uint prev = 1;
|
||||
for(uint i = 2; i < n; ++i) {
|
||||
uint temp = curr;
|
||||
curr += prev;
|
||||
prev = temp;
|
||||
}
|
||||
return curr;
|
||||
}
|
||||
|
||||
[numthreads(1, 1, 1)]
|
||||
[shader("compute")]
|
||||
void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID)
|
||||
{
|
||||
uint index = GlobalInvocationID.x;
|
||||
if (index >= BUFFER_ELEMENTS)
|
||||
return;
|
||||
values[index] = fibonacci(values[index]);
|
||||
}
|
||||
|
||||
BIN
shaders/slang/computenbody/particle.frag.spv
Normal file
BIN
shaders/slang/computenbody/particle.frag.spv
Normal file
Binary file not shown.
56
shaders/slang/computenbody/particle.slang
Normal file
56
shaders/slang/computenbody/particle.slang
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float4 Pos;
|
||||
float4 Vel;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float PSize : SV_PointSize;
|
||||
float GradientPos;
|
||||
float2 CenterPos;
|
||||
float PointSize;
|
||||
};
|
||||
|
||||
Sampler2D samplerColorMap;
|
||||
Sampler2D samplerGradientRamp;
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 projection;
|
||||
float4x4 modelview;
|
||||
float2 screendim;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input)
|
||||
{
|
||||
VSOutput output;
|
||||
const float spriteSize = 0.005 * input.Pos.w; // Point size influenced by mass (stored in input.Pos.w);
|
||||
|
||||
float4 eyePos = mul(ubo.modelview, float4(input.Pos.x, input.Pos.y, input.Pos.z, 1.0));
|
||||
float4 projectedCorner = mul(ubo.projection, float4(0.5 * spriteSize, 0.5 * spriteSize, eyePos.z, eyePos.w));
|
||||
output.PSize = output.PointSize = clamp(ubo.screendim.x * projectedCorner.x / projectedCorner.w, 1.0, 128.0);
|
||||
|
||||
output.Pos = mul(ubo.projection, eyePos);
|
||||
output.CenterPos = ((output.Pos.xy / output.Pos.w) + 1.0) * 0.5 * ubo.screendim;
|
||||
|
||||
output.GradientPos = input.Vel.w;
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
float3 color = samplerGradientRamp.Sample(float2(input.GradientPos, 0.0)).rgb;
|
||||
float2 PointCoord = (input.Pos.xy - input.CenterPos.xy) / input.PointSize + 0.5;
|
||||
return float4(samplerColorMap.Sample(PointCoord).rgb * color, 1);
|
||||
}
|
||||
BIN
shaders/slang/computenbody/particle.vert.spv
Normal file
BIN
shaders/slang/computenbody/particle.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/computenbody/particle_calculate.comp.spv
Normal file
BIN
shaders/slang/computenbody/particle_calculate.comp.spv
Normal file
Binary file not shown.
77
shaders/slang/computenbody/particle_calculate.slang
Normal file
77
shaders/slang/computenbody/particle_calculate.slang
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct Particle
|
||||
{
|
||||
float4 pos;
|
||||
float4 vel;
|
||||
};
|
||||
// Binding 0 : Position storage buffer
|
||||
RWStructuredBuffer<Particle> particles;
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float deltaT;
|
||||
int particleCount;
|
||||
float gravity;
|
||||
float power;
|
||||
float soften;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
#define MAX_SHARED_DATA_SIZE 1024
|
||||
[[SpecializationConstant]] const int SHARED_DATA_SIZE = 512;
|
||||
[[SpecializationConstant]] const float GRAVITY = 0.002;
|
||||
[[SpecializationConstant]] const float POWER = 0.75;
|
||||
[[SpecializationConstant]] const float SOFTEN = 0.0075;
|
||||
|
||||
// Share data between computer shader invocations to speed up caluclations
|
||||
groupshared float4 sharedData[MAX_SHARED_DATA_SIZE];
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(256, 1, 1)]
|
||||
void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID, uint3 LocalInvocationID : SV_GroupThreadID)
|
||||
{
|
||||
// Current SSBO index
|
||||
uint index = GlobalInvocationID.x;
|
||||
if (index >= ubo.particleCount)
|
||||
return;
|
||||
|
||||
float4 position = particles[index].pos;
|
||||
float4 velocity = particles[index].vel;
|
||||
float4 acceleration = float4(0, 0, 0, 0);
|
||||
|
||||
for (int i = 0; i < ubo.particleCount; i += SHARED_DATA_SIZE)
|
||||
{
|
||||
if (i + LocalInvocationID.x < ubo.particleCount)
|
||||
{
|
||||
sharedData[LocalInvocationID.x] = particles[i + LocalInvocationID.x].pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
sharedData[LocalInvocationID.x] = float4(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
|
||||
for (int j = 0; j < 256; j++)
|
||||
{
|
||||
float4 other = sharedData[j];
|
||||
float3 len = other.xyz - position.xyz;
|
||||
acceleration.xyz += ubo.gravity * len * other.w / pow(dot(len, len) + ubo.soften, ubo.power);
|
||||
}
|
||||
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
}
|
||||
|
||||
particles[index].vel.xyz += ubo.deltaT * acceleration.xyz;
|
||||
|
||||
// Gradient texture position
|
||||
particles[index].vel.w += 0.1 * ubo.deltaT;
|
||||
if (particles[index].vel.w > 1.0) {
|
||||
particles[index].vel.w -= 1.0;
|
||||
}
|
||||
}
|
||||
BIN
shaders/slang/computenbody/particle_integrate.comp.spv
Normal file
BIN
shaders/slang/computenbody/particle_integrate.comp.spv
Normal file
Binary file not shown.
31
shaders/slang/computenbody/particle_integrate.slang
Normal file
31
shaders/slang/computenbody/particle_integrate.slang
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct Particle
|
||||
{
|
||||
float4 pos;
|
||||
float4 vel;
|
||||
};
|
||||
// Binding 0 : Position storage buffer
|
||||
RWStructuredBuffer<Particle> particles;
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float deltaT;
|
||||
int particleCount;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(256, 1, 1)]
|
||||
void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID)
|
||||
{
|
||||
int index = int(GlobalInvocationID.x);
|
||||
float4 position = particles[index].pos;
|
||||
float4 velocity = particles[index].vel;
|
||||
position += ubo.deltaT * velocity;
|
||||
particles[index].pos = position;
|
||||
}
|
||||
BIN
shaders/slang/computeparticles/particle.comp.spv
Normal file
BIN
shaders/slang/computeparticles/particle.comp.spv
Normal file
Binary file not shown.
BIN
shaders/slang/computeparticles/particle.frag.spv
Normal file
BIN
shaders/slang/computeparticles/particle.frag.spv
Normal file
Binary file not shown.
120
shaders/slang/computeparticles/particle.slang
Normal file
120
shaders/slang/computeparticles/particle.slang
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
[[vk::binding(0, 0)]] Sampler2D samplerColorMap;
|
||||
[[vk::binding(1, 0)]] Sampler2D samplerGradientRamp;
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float2 Pos : POSITION0;
|
||||
float4 GradientPos : POSITION1;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float PointSize : SV_PointSize;
|
||||
float4 Color : COLOR0;
|
||||
float GradientPos : POSITION0;
|
||||
};
|
||||
|
||||
struct Particle
|
||||
{
|
||||
float2 pos;
|
||||
float2 vel;
|
||||
float4 gradientPos;
|
||||
};
|
||||
// Binding 0 : Position storage buffer
|
||||
[[vk::binding(0, 0)]] RWStructuredBuffer<Particle> particles;
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float deltaT;
|
||||
float destX;
|
||||
float destY;
|
||||
int particleCount;
|
||||
};
|
||||
[[vk::binding(1, 0)]] ConstantBuffer<UBO> ubo;
|
||||
|
||||
struct PushConsts
|
||||
{
|
||||
float2 screendim;
|
||||
};
|
||||
|
||||
float2 attraction(float2 pos, float2 attractPos)
|
||||
{
|
||||
float2 delta = attractPos - pos;
|
||||
const float damp = 0.5;
|
||||
float dDampedDot = dot(delta, delta) + damp;
|
||||
float invDist = 1.0f / sqrt(dDampedDot);
|
||||
float invDistCubed = invDist*invDist*invDist;
|
||||
return delta * invDistCubed * 0.0035;
|
||||
}
|
||||
|
||||
float2 repulsion(float2 pos, float2 attractPos)
|
||||
{
|
||||
float2 delta = attractPos - pos;
|
||||
float targetDistance = sqrt(dot(delta, delta));
|
||||
return delta * (1.0 / (targetDistance * targetDistance * targetDistance)) * -0.000035;
|
||||
}
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input)
|
||||
{
|
||||
VSOutput output;
|
||||
output.PointSize = 8.0;
|
||||
output.Color = float4(0.035, 0.035, 0.035, 0.035);
|
||||
output.GradientPos = input.GradientPos.x;
|
||||
output.Pos = float4(input.Pos.xy, 1.0, 1.0);
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input, float2 pointCoord: SV_PointCoord)
|
||||
{
|
||||
float3 color = samplerGradientRamp.Sample(float2(input.GradientPos, 0.0)).rgb;
|
||||
return float4(samplerColorMap.Sample(pointCoord).rgb * color, 1.0);
|
||||
}
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(256, 1, 1)]
|
||||
void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID)
|
||||
{
|
||||
// Current SSBO index
|
||||
uint index = GlobalInvocationID.x;
|
||||
// Don't try to write beyond particle count
|
||||
if (index >= ubo.particleCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Read position and velocity
|
||||
float2 vVel = particles[index].vel.xy;
|
||||
float2 vPos = particles[index].pos.xy;
|
||||
|
||||
float2 destPos = float2(ubo.destX, ubo.destY);
|
||||
|
||||
float2 delta = destPos - vPos;
|
||||
float targetDistance = sqrt(dot(delta, delta));
|
||||
vVel += repulsion(vPos, destPos.xy) * 0.05;
|
||||
|
||||
// Move by velocity
|
||||
vPos += vVel * ubo.deltaT;
|
||||
|
||||
// collide with boundary
|
||||
if ((vPos.x < -1.0) || (vPos.x > 1.0) || (vPos.y < -1.0) || (vPos.y > 1.0)) {
|
||||
vVel = (-vVel * 0.1) + attraction(vPos, destPos) * 12;
|
||||
} else {
|
||||
particles[index].pos.xy = vPos;
|
||||
}
|
||||
|
||||
// Write back
|
||||
particles[index].vel.xy = vVel;
|
||||
particles[index].gradientPos.x += 0.02 * ubo.deltaT;
|
||||
if (particles[index].gradientPos.x > 1.0) {
|
||||
particles[index].gradientPos.x -= 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
BIN
shaders/slang/computeparticles/particle.vert.spv
Normal file
BIN
shaders/slang/computeparticles/particle.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/computeraytracing/raytracing.comp.spv
Normal file
BIN
shaders/slang/computeraytracing/raytracing.comp.spv
Normal file
Binary file not shown.
258
shaders/slang/computeraytracing/raytracing.slang
Normal file
258
shaders/slang/computeraytracing/raytracing.slang
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
// Shader is looseley based on the ray tracing coding session by Inigo Quilez (www.iquilezles.org)
|
||||
|
||||
#define EPSILON 0.0001
|
||||
#define MAXLEN 1000.0
|
||||
#define SHADOW 0.5
|
||||
#define RAYBOUNCES 2
|
||||
#define REFLECTIONS true
|
||||
#define REFLECTIONSTRENGTH 0.4
|
||||
#define REFLECTIONFALLOFF 0.5
|
||||
|
||||
#define SceneObjectTypeSphere 0
|
||||
#define SceneObjectTypePlane 1
|
||||
|
||||
RWTexture2D<float4> resultImage;
|
||||
|
||||
struct Camera
|
||||
{
|
||||
float3 pos;
|
||||
float3 lookat;
|
||||
float fov;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float3 lightPos;
|
||||
float aspectRatio;
|
||||
float4 fogColor;
|
||||
Camera camera;
|
||||
float4x4 rotMat;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
struct SceneObject
|
||||
{
|
||||
float4 objectProperties;
|
||||
float3 diffuse;
|
||||
float specular;
|
||||
int id;
|
||||
int objectType;
|
||||
};
|
||||
StructuredBuffer<SceneObject> sceneObjects;
|
||||
|
||||
void reflectRay(inout float3 rayD, in float3 mormal)
|
||||
{
|
||||
rayD = rayD + 2.0 * -dot(mormal, rayD) * mormal;
|
||||
}
|
||||
|
||||
// Lighting =========================================================
|
||||
|
||||
float lightDiffuse(float3 normal, float3 lightDir)
|
||||
{
|
||||
return clamp(dot(normal, lightDir), 0.1, 1.0);
|
||||
}
|
||||
|
||||
float lightSpecular(float3 normal, float3 lightDir, float specularFactor)
|
||||
{
|
||||
float3 viewVec = normalize(ubo.camera.pos);
|
||||
float3 halfVec = normalize(lightDir + viewVec);
|
||||
return pow(clamp(dot(normal, halfVec), 0.0, 1.0), specularFactor);
|
||||
}
|
||||
|
||||
// Sphere ===========================================================
|
||||
|
||||
float sphereIntersect(in float3 rayO, in float3 rayD, in SceneObject sphere)
|
||||
{
|
||||
float3 oc = rayO - sphere.objectProperties.xyz;
|
||||
float b = 2.0 * dot(oc, rayD);
|
||||
float c = dot(oc, oc) - sphere.objectProperties.w * sphere.objectProperties.w;
|
||||
float h = b*b - 4.0*c;
|
||||
if (h < 0.0)
|
||||
{
|
||||
return -1.0;
|
||||
}
|
||||
float t = (-b - sqrt(h)) / 2.0;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
float3 sphereNormal(in float3 pos, in SceneObject sphere)
|
||||
{
|
||||
return (pos - sphere.objectProperties.xyz) / sphere.objectProperties.w;
|
||||
}
|
||||
|
||||
// Plane ===========================================================
|
||||
|
||||
float planeIntersect(float3 rayO, float3 rayD, SceneObject plane)
|
||||
{
|
||||
float d = dot(rayD, plane.objectProperties.xyz);
|
||||
|
||||
if (d == 0.0)
|
||||
return 0.0;
|
||||
|
||||
float t = -(plane.objectProperties.w + dot(rayO, plane.objectProperties.xyz)) / d;
|
||||
|
||||
if (t < 0.0)
|
||||
return 0.0;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
int intersect(in float3 rayO, in float3 rayD, inout float resT)
|
||||
{
|
||||
int id = -1;
|
||||
float t = MAXLEN;
|
||||
|
||||
uint sceneObjectsLength;
|
||||
uint sceneObjectsStride;
|
||||
sceneObjects.GetDimensions(sceneObjectsLength, sceneObjectsStride);
|
||||
|
||||
for (int i = 0; i < sceneObjectsLength; i++) {
|
||||
// Sphere
|
||||
if (sceneObjects[i].objectType == SceneObjectTypeSphere) {
|
||||
t = sphereIntersect(rayO, rayD, sceneObjects[i]);
|
||||
}
|
||||
// Plane
|
||||
if (sceneObjects[i].objectType == SceneObjectTypePlane) {
|
||||
t = planeIntersect(rayO, rayD, sceneObjects[i]);
|
||||
}
|
||||
if ((t > EPSILON) && (t < resT))
|
||||
{
|
||||
id = sceneObjects[i].id;
|
||||
resT = t;
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
float calcShadow(in float3 rayO, in float3 rayD, in int objectId, inout float t)
|
||||
{
|
||||
uint sceneObjectsLength;
|
||||
uint sceneObjectsStride;
|
||||
sceneObjects.GetDimensions(sceneObjectsLength, sceneObjectsStride);
|
||||
|
||||
for (int i = 0; i < sceneObjectsLength; i++) {
|
||||
if (sceneObjects[i].id == objectId)
|
||||
continue;
|
||||
|
||||
float tLoc = MAXLEN;
|
||||
|
||||
// Sphere
|
||||
if (sceneObjects[i].objectType == SceneObjectTypeSphere)
|
||||
{
|
||||
tLoc = sphereIntersect(rayO, rayD, sceneObjects[i]);
|
||||
}
|
||||
// Plane
|
||||
if (sceneObjects[i].objectType == SceneObjectTypePlane)
|
||||
{
|
||||
tLoc = planeIntersect(rayO, rayD, sceneObjects[i]);
|
||||
}
|
||||
if ((tLoc > EPSILON) && (tLoc < t))
|
||||
{
|
||||
t = tLoc;
|
||||
return SHADOW;
|
||||
}
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
float3 fog(in float t, in float3 color)
|
||||
{
|
||||
return lerp(color, ubo.fogColor.rgb, clamp(sqrt(t*t)/20.0, 0.0, 1.0));
|
||||
}
|
||||
|
||||
float3 renderScene(inout float3 rayO, inout float3 rayD, inout int id)
|
||||
{
|
||||
float3 color = float3(0, 0, 0);
|
||||
float t = MAXLEN;
|
||||
|
||||
// Get intersected object ID
|
||||
int objectID = intersect(rayO, rayD, t);
|
||||
|
||||
if (objectID == -1)
|
||||
{
|
||||
return color;
|
||||
}
|
||||
|
||||
float3 pos = rayO + t * rayD;
|
||||
float3 lightVec = normalize(ubo.lightPos - pos);
|
||||
float3 normal;
|
||||
|
||||
uint sceneObjectsLength;
|
||||
uint sceneObjectsStride;
|
||||
sceneObjects.GetDimensions(sceneObjectsLength, sceneObjectsStride);
|
||||
|
||||
for (int i = 0; i < sceneObjectsLength; i++) {
|
||||
if (objectID == sceneObjects[i].id)
|
||||
{
|
||||
// Sphere
|
||||
if (sceneObjects[i].objectType == SceneObjectTypeSphere) {
|
||||
normal = sphereNormal(pos, sceneObjects[i]);
|
||||
}
|
||||
// Plane
|
||||
if (sceneObjects[i].objectType == SceneObjectTypePlane) {
|
||||
normal = sceneObjects[i].objectProperties.xyz;
|
||||
}
|
||||
// Lighting
|
||||
float diffuse = lightDiffuse(normal, lightVec);
|
||||
float specular = lightSpecular(normal, lightVec, sceneObjects[i].specular);
|
||||
color = diffuse * sceneObjects[i].diffuse + specular;
|
||||
}
|
||||
}
|
||||
|
||||
if (id == -1)
|
||||
return color;
|
||||
|
||||
id = objectID;
|
||||
|
||||
// Shadows
|
||||
t = length(ubo.lightPos - pos);
|
||||
color *= calcShadow(pos, lightVec, id, t);
|
||||
|
||||
// Fog
|
||||
color = fog(t, color);
|
||||
|
||||
// Reflect ray for next render pass
|
||||
reflectRay(rayD, normal);
|
||||
rayO = pos;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(16, 16, 1)]
|
||||
void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID)
|
||||
{
|
||||
int2 dim;
|
||||
resultImage.GetDimensions(dim.x, dim.y);
|
||||
float2 uv = float2(GlobalInvocationID.xy) / dim;
|
||||
|
||||
float3 rayO = ubo.camera.pos;
|
||||
float3 rayD = normalize(float3((-1.0 + 2.0 * uv) * float2(ubo.aspectRatio, 1.0), -1.0));
|
||||
|
||||
// Basic color path
|
||||
int id = 0;
|
||||
float3 finalColor = renderScene(rayO, rayD, id);
|
||||
|
||||
// Reflection
|
||||
if (REFLECTIONS)
|
||||
{
|
||||
float reflectionStrength = REFLECTIONSTRENGTH;
|
||||
for (int i = 0; i < RAYBOUNCES; i++)
|
||||
{
|
||||
float3 reflectionColor = renderScene(rayO, rayD, id);
|
||||
finalColor = (1.0 - reflectionStrength) * finalColor + reflectionStrength * lerp(reflectionColor, finalColor, 1.0 - reflectionStrength);
|
||||
reflectionStrength *= REFLECTIONFALLOFF;
|
||||
}
|
||||
}
|
||||
|
||||
resultImage[int2(GlobalInvocationID.xy)] = float4(finalColor, 0.0);
|
||||
}
|
||||
BIN
shaders/slang/computeraytracing/texture.frag.spv
Normal file
BIN
shaders/slang/computeraytracing/texture.frag.spv
Normal file
Binary file not shown.
28
shaders/slang/computeraytracing/texture.slang
Normal file
28
shaders/slang/computeraytracing/texture.slang
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float2 UV;
|
||||
};
|
||||
|
||||
Sampler2D samplerColor;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(uint VertexIndex: SV_VertexID)
|
||||
{
|
||||
VSOutput output;
|
||||
output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2);
|
||||
output.Pos = float4(output.UV * 2.0f + -1.0f, 0.0f, 1.0f);
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
return samplerColor.Sample(float2(input.UV.x, 1.0 - input.UV.y));
|
||||
}
|
||||
BIN
shaders/slang/computeraytracing/texture.vert.spv
Normal file
BIN
shaders/slang/computeraytracing/texture.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/computeshader/edgedetect.comp.spv
Normal file
BIN
shaders/slang/computeshader/edgedetect.comp.spv
Normal file
Binary file not shown.
34
shaders/slang/computeshader/edgedetect.slang
Normal file
34
shaders/slang/computeshader/edgedetect.slang
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
import shared;
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(16, 16, 1)]
|
||||
void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID)
|
||||
{
|
||||
float imageData[9];
|
||||
// Fetch neighbouring texels
|
||||
int n = -1;
|
||||
for (int i=-1; i<2; ++i)
|
||||
{
|
||||
for(int j=-1; j<2; ++j)
|
||||
{
|
||||
n++;
|
||||
float3 rgb = inputImage[uint2(GlobalInvocationID.x + i, GlobalInvocationID.y + j)].rgb;
|
||||
imageData[n] = (rgb.r + rgb.g + rgb.b) / 3.0;
|
||||
}
|
||||
}
|
||||
|
||||
float kernel[9];
|
||||
kernel[0] = -1.0/8.0; kernel[1] = -1.0/8.0; kernel[2] = -1.0/8.0;
|
||||
kernel[3] = -1.0/8.0; kernel[4] = 1.0; kernel[5] = -1.0/8.0;
|
||||
kernel[6] = -1.0/8.0; kernel[7] = -1.0/8.0; kernel[8] = -1.0/8.0;
|
||||
|
||||
float4 res = float4(conv(kernel, imageData, 0.1, 0.0).xxx, 1.0);
|
||||
|
||||
resultImage[int2(GlobalInvocationID.xy)] = res;
|
||||
}
|
||||
BIN
shaders/slang/computeshader/emboss.comp.spv
Normal file
BIN
shaders/slang/computeshader/emboss.comp.spv
Normal file
Binary file not shown.
34
shaders/slang/computeshader/emboss.slang
Normal file
34
shaders/slang/computeshader/emboss.slang
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
import shared;
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(16, 16, 1)]
|
||||
void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID)
|
||||
{
|
||||
float imageData[9];
|
||||
// Fetch neighbouring texels
|
||||
int n = -1;
|
||||
for (int i=-1; i<2; ++i)
|
||||
{
|
||||
for(int j=-1; j<2; ++j)
|
||||
{
|
||||
n++;
|
||||
float3 rgb = inputImage[uint2(GlobalInvocationID.x + i, GlobalInvocationID.y + j)].rgb;
|
||||
imageData[n] = (rgb.r + rgb.g + rgb.b) / 3.0;
|
||||
}
|
||||
}
|
||||
|
||||
float kernel[9];
|
||||
kernel[0] = -1.0; kernel[1] = 0.0; kernel[2] = 0.0;
|
||||
kernel[3] = 0.0; kernel[4] = -1.0; kernel[5] = 0.0;
|
||||
kernel[6] = 0.0; kernel[7] = 0.0; kernel[8] = 2.0;
|
||||
|
||||
float4 res = float4(conv(kernel, imageData, 1.0, 0.50).xxx, 1.0);
|
||||
|
||||
resultImage[int2(GlobalInvocationID.xy)] = res;
|
||||
}
|
||||
20
shaders/slang/computeshader/shared.slang
Normal file
20
shaders/slang/computeshader/shared.slang
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
module shared;
|
||||
|
||||
public Texture2D inputImage;
|
||||
public RWTexture2D<float4> resultImage;
|
||||
|
||||
public float conv(in float kernel[9], in float data[9], in float denom, in float offset)
|
||||
{
|
||||
float res = 0.0;
|
||||
for (int i=0; i<9; ++i)
|
||||
{
|
||||
res += kernel[i] * data[i];
|
||||
}
|
||||
return saturate(res/denom + offset);
|
||||
}
|
||||
BIN
shaders/slang/computeshader/sharpen.comp.spv
Normal file
BIN
shaders/slang/computeshader/sharpen.comp.spv
Normal file
Binary file not shown.
43
shaders/slang/computeshader/sharpen.slang
Normal file
43
shaders/slang/computeshader/sharpen.slang
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
import shared;
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(16, 16, 1)]
|
||||
void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID)
|
||||
{
|
||||
float r[9];
|
||||
float g[9];
|
||||
float b[9];
|
||||
|
||||
// Fetch neighbouring texels
|
||||
int n = -1;
|
||||
for (int i=-1; i<2; ++i)
|
||||
{
|
||||
for(int j=-1; j<2; ++j)
|
||||
{
|
||||
n++;
|
||||
float3 rgb = inputImage[uint2(GlobalInvocationID.x + i, GlobalInvocationID.y + j)].rgb;
|
||||
r[n] = rgb.r;
|
||||
g[n] = rgb.g;
|
||||
b[n] = rgb.b;
|
||||
}
|
||||
}
|
||||
|
||||
float kernel[9];
|
||||
kernel[0] = -1.0; kernel[1] = -1.0; kernel[2] = -1.0;
|
||||
kernel[3] = -1.0; kernel[4] = 9.0; kernel[5] = -1.0;
|
||||
kernel[6] = -1.0; kernel[7] = -1.0; kernel[8] = -1.0;
|
||||
|
||||
float4 res = float4(
|
||||
conv(kernel, r, 1.0, 0.0),
|
||||
conv(kernel, g, 1.0, 0.0),
|
||||
conv(kernel, b, 1.0, 0.0),
|
||||
1.0);
|
||||
|
||||
resultImage[int2(GlobalInvocationID.xy)] = res;
|
||||
}
|
||||
BIN
shaders/slang/computeshader/texture.frag.spv
Normal file
BIN
shaders/slang/computeshader/texture.frag.spv
Normal file
Binary file not shown.
41
shaders/slang/computeshader/texture.slang
Normal file
41
shaders/slang/computeshader/texture.slang
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float3 Pos;
|
||||
float2 UV;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float2 UV;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 projection;
|
||||
float4x4 model;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
Sampler2D samplerColor;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input)
|
||||
{
|
||||
VSOutput output;
|
||||
output.UV = input.UV;
|
||||
output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0)));
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
return samplerColor.Sample(input.UV);
|
||||
}
|
||||
BIN
shaders/slang/computeshader/texture.vert.spv
Normal file
BIN
shaders/slang/computeshader/texture.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/conditionalrender/model.frag.spv
Normal file
BIN
shaders/slang/conditionalrender/model.frag.spv
Normal file
Binary file not shown.
66
shaders/slang/conditionalrender/model.slang
Normal file
66
shaders/slang/conditionalrender/model.slang
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float3 Pos;
|
||||
float3 Normal;
|
||||
float3 Color;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float3 Normal;
|
||||
float3 Color;
|
||||
float3 ViewVec;
|
||||
float3 LightVec;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 projection;
|
||||
float4x4 view;
|
||||
float4x4 model;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
struct Node
|
||||
{
|
||||
float4x4 transform;
|
||||
};
|
||||
[[vk::binding(0,1)]] ConstantBuffer<Node> node;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input, uniform float4 baseColorFactor)
|
||||
{
|
||||
VSOutput output;
|
||||
output.Normal = input.Normal;
|
||||
output.Color = baseColorFactor.rgb;
|
||||
float4 pos = float4(input.Pos, 1.0);
|
||||
output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, mul(node.transform, pos))));
|
||||
|
||||
output.Normal = mul((float4x3)mul(ubo.view, mul(ubo.model, node.transform)), input.Normal).xyz;
|
||||
|
||||
float4 localpos = mul(ubo.view, mul(ubo.model, mul(node.transform, pos)));
|
||||
float3 lightPos = float3(10.0f, -10.0f, 10.0f);
|
||||
output.LightVec = lightPos.xyz - localpos.xyz;
|
||||
output.ViewVec = -localpos.xyz;
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
float3 N = normalize(input.Normal);
|
||||
float3 L = normalize(input.LightVec);
|
||||
float3 V = normalize(input.ViewVec);
|
||||
float3 R = reflect(-L, N);
|
||||
float3 ambient = float3(0.1, 0.1, 0.1);
|
||||
float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0);
|
||||
float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75);
|
||||
return float4((ambient + diffuse) * input.Color.rgb + specular, 1.0);
|
||||
}
|
||||
BIN
shaders/slang/conditionalrender/model.vert.spv
Normal file
BIN
shaders/slang/conditionalrender/model.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/conservativeraster/fullscreen.frag.spv
Normal file
BIN
shaders/slang/conservativeraster/fullscreen.frag.spv
Normal file
Binary file not shown.
28
shaders/slang/conservativeraster/fullscreen.slang
Normal file
28
shaders/slang/conservativeraster/fullscreen.slang
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float2 UV;
|
||||
};
|
||||
|
||||
Sampler2D samplerColor;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(uint VertexIndex: SV_VertexID)
|
||||
{
|
||||
VSOutput output;
|
||||
output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2);
|
||||
output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f);
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
return samplerColor.Sample(input.UV);
|
||||
}
|
||||
BIN
shaders/slang/conservativeraster/fullscreen.vert.spv
Normal file
BIN
shaders/slang/conservativeraster/fullscreen.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/conservativeraster/triangle.frag.spv
Normal file
BIN
shaders/slang/conservativeraster/triangle.frag.spv
Normal file
Binary file not shown.
38
shaders/slang/conservativeraster/triangle.slang
Normal file
38
shaders/slang/conservativeraster/triangle.slang
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
struct VSInput
|
||||
{
|
||||
float3 Pos;
|
||||
float3 Color;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float3 Color;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 projection;
|
||||
float4x4 model;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input)
|
||||
{
|
||||
VSOutput output;
|
||||
output.Color = input.Color;
|
||||
output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos, 1.0)));
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
return float4(input.Color, 1);
|
||||
}
|
||||
BIN
shaders/slang/conservativeraster/triangle.vert.spv
Normal file
BIN
shaders/slang/conservativeraster/triangle.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/conservativeraster/triangleoverlay.frag.spv
Normal file
BIN
shaders/slang/conservativeraster/triangleoverlay.frag.spv
Normal file
Binary file not shown.
11
shaders/slang/conservativeraster/triangleoverlay.slang
Normal file
11
shaders/slang/conservativeraster/triangleoverlay.slang
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain()
|
||||
{
|
||||
return float4(1.0, 1.0, 1.0, 1.0);
|
||||
}
|
||||
BIN
shaders/slang/debugprintf/toon.frag.spv
Normal file
BIN
shaders/slang/debugprintf/toon.frag.spv
Normal file
Binary file not shown.
73
shaders/slang/debugprintf/toon.slang
Normal file
73
shaders/slang/debugprintf/toon.slang
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float3 Pos;
|
||||
float3 Normal;
|
||||
float3 Color;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float3 Normal;
|
||||
float3 Color;
|
||||
float3 ViewVec;
|
||||
float3 LightVec;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 projection;
|
||||
float4x4 model;
|
||||
float4 lightPos;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input)
|
||||
{
|
||||
VSOutput output;
|
||||
output.Normal = input.Normal;
|
||||
output.Color = input.Color;
|
||||
output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0)));
|
||||
|
||||
float4 pos = mul(ubo.model, float4(input.Pos, 1.0));
|
||||
// Output the vertex position using debug printf
|
||||
printf("Position = %v4f", pos);
|
||||
|
||||
output.Normal = mul((float4x3)ubo.model, input.Normal).xyz;
|
||||
float3 lPos = mul((float4x3)ubo.model, ubo.lightPos.xyz).xyz;
|
||||
output.LightVec = lPos - pos.xyz;
|
||||
output.ViewVec = -pos.xyz;
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
// Desaturate color
|
||||
float3 color = float3(lerp(input.Color, dot(float3(0.2126, 0.7152, 0.0722), input.Color).xxx, 0.65));
|
||||
|
||||
// High ambient colors because mesh materials are pretty dark
|
||||
float3 ambient = color * float3(1.0, 1.0, 1.0);
|
||||
float3 N = normalize(input.Normal);
|
||||
float3 L = normalize(input.LightVec);
|
||||
float3 V = normalize(input.ViewVec);
|
||||
float3 R = reflect(-L, N);
|
||||
float3 diffuse = max(dot(N, L), 0.0) * color;
|
||||
float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75);
|
||||
|
||||
float intensity = dot(N, L);
|
||||
float shade = 1.0;
|
||||
shade = intensity < 0.5 ? 0.75 : shade;
|
||||
shade = intensity < 0.35 ? 0.6 : shade;
|
||||
shade = intensity < 0.25 ? 0.5 : shade;
|
||||
shade = intensity < 0.1 ? 0.25 : shade;
|
||||
|
||||
return float4(input.Color * 3.0 * shade, 1);
|
||||
}
|
||||
BIN
shaders/slang/debugprintf/toon.vert.spv
Normal file
BIN
shaders/slang/debugprintf/toon.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/debugutils/colorpass.frag.spv
Normal file
BIN
shaders/slang/debugutils/colorpass.frag.spv
Normal file
Binary file not shown.
41
shaders/slang/debugutils/colorpass.slang
Normal file
41
shaders/slang/debugutils/colorpass.slang
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float4 Pos;
|
||||
float3 Normal;
|
||||
float2 UV;
|
||||
float3 Color;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float3 Color;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 projection;
|
||||
float4x4 model;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input)
|
||||
{
|
||||
VSOutput output;
|
||||
output.Color = input.Color;
|
||||
output.Pos = mul(ubo.projection, mul(ubo.model, input.Pos));
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
return float4(input.Color, 1.0);
|
||||
}
|
||||
BIN
shaders/slang/debugutils/colorpass.vert.spv
Normal file
BIN
shaders/slang/debugutils/colorpass.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/debugutils/postprocess.frag.spv
Normal file
BIN
shaders/slang/debugutils/postprocess.frag.spv
Normal file
Binary file not shown.
55
shaders/slang/debugutils/postprocess.slang
Normal file
55
shaders/slang/debugutils/postprocess.slang
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float2 UV;
|
||||
};
|
||||
|
||||
[[vk::binding(1, 0)]] Sampler2D samplerColor;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(uint VertexIndex: SV_VertexID)
|
||||
{
|
||||
VSOutput output;
|
||||
output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2);
|
||||
output.Pos = float4(output.UV * float2(2.0f, 2.0f) + float2(-1.0f, -1.0f), 0.0f, 1.0f);
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
// Single pass gauss blur
|
||||
|
||||
const float2 texOffset = float2(0.01, 0.01);
|
||||
|
||||
float2 tc0 = input.UV + float2(-texOffset.x, -texOffset.y);
|
||||
float2 tc1 = input.UV + float2( 0.0, -texOffset.y);
|
||||
float2 tc2 = input.UV + float2(+texOffset.x, -texOffset.y);
|
||||
float2 tc3 = input.UV + float2(-texOffset.x, 0.0);
|
||||
float2 tc4 = input.UV + float2( 0.0, 0.0);
|
||||
float2 tc5 = input.UV + float2(+texOffset.x, 0.0);
|
||||
float2 tc6 = input.UV + float2(-texOffset.x, +texOffset.y);
|
||||
float2 tc7 = input.UV + float2( 0.0, +texOffset.y);
|
||||
float2 tc8 = input.UV + float2(+texOffset.x, +texOffset.y);
|
||||
|
||||
float4 col0 = samplerColor.Sample(tc0);
|
||||
float4 col1 = samplerColor.Sample(tc1);
|
||||
float4 col2 = samplerColor.Sample(tc2);
|
||||
float4 col3 = samplerColor.Sample(tc3);
|
||||
float4 col4 = samplerColor.Sample(tc4);
|
||||
float4 col5 = samplerColor.Sample(tc5);
|
||||
float4 col6 = samplerColor.Sample(tc6);
|
||||
float4 col7 = samplerColor.Sample(tc7);
|
||||
float4 col8 = samplerColor.Sample(tc8);
|
||||
|
||||
float4 sum = (1.0 * col0 + 2.0 * col1 + 1.0 * col2 +
|
||||
2.0 * col3 + 4.0 * col4 + 2.0 * col5 +
|
||||
1.0 * col6 + 2.0 * col7 + 1.0 * col8) / 16.0;
|
||||
return float4(sum.rgb, 1.0);
|
||||
}
|
||||
BIN
shaders/slang/debugutils/postprocess.vert.spv
Normal file
BIN
shaders/slang/debugutils/postprocess.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/debugutils/toon.frag.spv
Normal file
BIN
shaders/slang/debugutils/toon.frag.spv
Normal file
Binary file not shown.
71
shaders/slang/debugutils/toon.slang
Normal file
71
shaders/slang/debugutils/toon.slang
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float3 Pos;
|
||||
float3 Normal;
|
||||
float2 UV;
|
||||
float3 Color;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float3 Normal;
|
||||
float3 Color;
|
||||
float2 UV;
|
||||
float3 ViewVec;
|
||||
float3 LightVec;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 projection;
|
||||
float4x4 model;
|
||||
float4 lightPos;
|
||||
};
|
||||
ConstantBuffer<UBO> ubo;
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(VSInput input)
|
||||
{
|
||||
VSOutput output;
|
||||
output.Color = input.Color;
|
||||
output.UV = input.UV;
|
||||
output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0)));
|
||||
float4 pos = mul(ubo.model, float4(input.Pos, 1.0));
|
||||
output.Normal = mul((float4x3)ubo.model, input.Normal).xyz;
|
||||
float3 lPos = mul((float4x3)ubo.model, ubo.lightPos.xyz).xyz;
|
||||
output.LightVec = lPos - pos.xyz;
|
||||
output.ViewVec = -pos.xyz;
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
// Desaturate color
|
||||
float3 color = float3(lerp(input.Color, dot(float3(0.2126,0.7152,0.0722), input.Color).xxx, 0.65));
|
||||
|
||||
// High ambient colors because mesh materials are pretty dark
|
||||
float3 ambient = color * float3(1.0, 1.0, 1.0);
|
||||
float3 N = normalize(input.Normal);
|
||||
float3 L = normalize(input.LightVec);
|
||||
float3 V = normalize(input.ViewVec);
|
||||
float3 R = reflect(-L, N);
|
||||
float3 diffuse = max(dot(N, L), 0.0) * color;
|
||||
float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75);
|
||||
|
||||
float intensity = dot(N,L);
|
||||
float shade = 1.0;
|
||||
shade = intensity < 0.5 ? 0.75 : shade;
|
||||
shade = intensity < 0.35 ? 0.6 : shade;
|
||||
shade = intensity < 0.25 ? 0.5 : shade;
|
||||
shade = intensity < 0.1 ? 0.25 : shade;
|
||||
|
||||
return float4(input.Color * 3.0 * shade, 1);
|
||||
}
|
||||
BIN
shaders/slang/debugutils/toon.vert.spv
Normal file
BIN
shaders/slang/debugutils/toon.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/deferred/deferred.frag.spv
Normal file
BIN
shaders/slang/deferred/deferred.frag.spv
Normal file
Binary file not shown.
110
shaders/slang/deferred/deferred.slang
Normal file
110
shaders/slang/deferred/deferred.slang
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/* Copyright (c) 2025, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
[[vk::binding(1, 0)]] Sampler2D samplerposition;
|
||||
[[vk::binding(2, 0)]] Sampler2D samplerNormal;
|
||||
[[vk::binding(3, 0)]] Sampler2D samplerAlbedo;
|
||||
|
||||
struct Light {
|
||||
float4 position;
|
||||
float3 color;
|
||||
float radius;
|
||||
};
|
||||
|
||||
struct UBO
|
||||
{
|
||||
Light lights[6];
|
||||
float4 viewPos;
|
||||
int displayDebugTarget;
|
||||
};
|
||||
[[vk::binding(4, 0)]] ConstantBuffer<UBO> ubo;
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
float2 UV;
|
||||
};
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput vertexMain(uint VertexIndex: SV_VertexID)
|
||||
{
|
||||
VSOutput output;
|
||||
output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2);
|
||||
output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f);
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(VSOutput input)
|
||||
{
|
||||
// Get G-Buffer values
|
||||
float3 fragPos = samplerposition.Sample(input.UV).rgb;
|
||||
float3 normal = samplerNormal.Sample(input.UV).rgb;
|
||||
float4 albedo = samplerAlbedo.Sample(input.UV);
|
||||
|
||||
float3 fragcolor;
|
||||
|
||||
// Debug display
|
||||
if (ubo.displayDebugTarget > 0) {
|
||||
switch (ubo.displayDebugTarget) {
|
||||
case 1:
|
||||
fragcolor.rgb = fragPos;
|
||||
break;
|
||||
case 2:
|
||||
fragcolor.rgb = normal;
|
||||
break;
|
||||
case 3:
|
||||
fragcolor.rgb = albedo.rgb;
|
||||
break;
|
||||
case 4:
|
||||
fragcolor.rgb = albedo.aaa;
|
||||
break;
|
||||
}
|
||||
return float4(fragcolor, 1.0);
|
||||
}
|
||||
|
||||
#define lightCount 6
|
||||
#define ambient 0.0
|
||||
|
||||
// Ambient part
|
||||
fragcolor = albedo.rgb * ambient;
|
||||
|
||||
for(int i = 0; i < lightCount; ++i)
|
||||
{
|
||||
// Vector to light
|
||||
float3 L = ubo.lights[i].position.xyz - fragPos;
|
||||
// Distance from light to fragment position
|
||||
float dist = length(L);
|
||||
|
||||
// Viewer to fragment
|
||||
float3 V = ubo.viewPos.xyz - fragPos;
|
||||
V = normalize(V);
|
||||
|
||||
//if(dist < ubo.lights[i].radius)
|
||||
{
|
||||
// Light to fragment
|
||||
L = normalize(L);
|
||||
|
||||
// Attenuation
|
||||
float atten = ubo.lights[i].radius / (pow(dist, 2.0) + 1.0);
|
||||
|
||||
// Diffuse part
|
||||
float3 N = normalize(normal);
|
||||
float NdotL = max(0.0, dot(N, L));
|
||||
float3 diff = ubo.lights[i].color * albedo.rgb * NdotL * atten;
|
||||
|
||||
// Specular part
|
||||
// Specular map values are stored in alpha of albedo mrt
|
||||
float3 R = reflect(-L, N);
|
||||
float NdotR = max(0.0, dot(R, V));
|
||||
float3 spec = ubo.lights[i].color * albedo.a * pow(NdotR, 16.0) * atten;
|
||||
|
||||
fragcolor += diff + spec;
|
||||
}
|
||||
}
|
||||
|
||||
return float4(fragcolor, 1.0);
|
||||
}
|
||||
BIN
shaders/slang/deferred/deferred.vert.spv
Normal file
BIN
shaders/slang/deferred/deferred.vert.spv
Normal file
Binary file not shown.
BIN
shaders/slang/deferred/mrt.frag.spv
Normal file
BIN
shaders/slang/deferred/mrt.frag.spv
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue