Commit 1d34724f authored by Lukas Tietze's avatar Lukas Tietze

Weiche Schatten

parent 4cb6604b
......@@ -4,8 +4,14 @@
#extension GL_EXT_nonuniform_qualifier : require
#include "raycommon.glsl"
#include "random.glsl"
#include "lighting.glsl"
layout(push_constant) uniform Constants
{
uint rngSeed;
};
layout(location = 0) rayPayloadInNV HitPayload payload;
hitAttributeNV vec3 attribs;
......@@ -53,9 +59,11 @@ void main()
vec3 res = vec3(0);
uint seed = tea(gl_LaunchIDNV.y * gl_LaunchSizeNV.x + gl_LaunchIDNV.x, rngSeed);
for(int i = 0; i < 1; i++)
{
res += CalcLight(lightSources.l[i], mat, N, worldPos, SceneCamPos(scene.s));
res += CalcLight(lightSources.l[i], mat, N, worldPos, SceneCamPos(scene.s), seed);
}
float reflectivity = MaterialRefractionIndex(mat) - 1;
......
#include "raycommon.glsl"
#define Softness (0.2)
#define NShadowSamples (4)
layout(location = 1) rayPayloadInNV bool isShadowed;
layout(binding = 0, set = 0) uniform accelerationStructureNV topLevelAS;
vec3 CalcLight(LightSource light, Material mat, vec3 N, vec3 worldPos, vec3 camPos)
vec3 CalcLight(LightSource light, Material mat, vec3 N, vec3 worldPos, vec3 camPos, uint seed)
{
vec3 L;
float a;
......@@ -27,13 +30,25 @@ vec3 CalcLight(LightSource light, Material mat, vec3 N, vec3 worldPos, vec3 camP
return vec3(0);
}
isShadowed = true;
traceNV(topLevelAS,
gl_RayFlagsTerminateOnFirstHitNV | gl_RayFlagsOpaqueNV | gl_RayFlagsSkipClosestHitShaderNV,
0xFF, 0, 0, 1,
gl_WorldRayOriginNV + gl_WorldRayDirectionNV * gl_HitTNV, // ray origin
RayTMin, L, tMax, 1
);
int nHits = 0;
for(int i = 0; i < NShadowSamples; i++) {
vec2 offset = vec2(rnd(seed), rnd(seed)) * Softness;
isShadowed = true;
traceNV(topLevelAS,
gl_RayFlagsTerminateOnFirstHitNV | gl_RayFlagsOpaqueNV | gl_RayFlagsSkipClosestHitShaderNV,
0xFF, 0, 0, 1,
gl_WorldRayOriginNV + gl_WorldRayDirectionNV * gl_HitTNV, // ray origin
RayTMin, L + vec3(offset.x, 0, offset.y), tMax, 1
);
if(!isShadowed) {
nHits++;
}
}
float hitRate = float(nHits) / float(NShadowSamples);
const vec3 ambient = LightColor(light) * MaterialAmbient(mat) * LightAmbientFactor(light);
vec3 diffuse = vec3(0);
......@@ -41,14 +56,14 @@ vec3 CalcLight(LightSource light, Material mat, vec3 N, vec3 worldPos, vec3 camP
float NDotL = max(dot(N, L), 0.0);
if(NDotL > 0 && !isShadowed)
if(NDotL > 0 && nHits > 0)
{
diffuse = a * NDotL * LightColor(light) * MaterialDiffuse(mat);
diffuse = a * NDotL * LightColor(light) * MaterialDiffuse(mat) * hitRate;
vec3 viewDir = normalize(camPos - worldPos);
vec3 reflectDir = reflect(-L, N);
specular = LightColor(light) * MaterialSpecular(mat) * a * pow(max(dot(viewDir, reflectDir), 0.0), MaterialSpecularExponent(mat));
specular = LightColor(light) * MaterialSpecular(mat) * a * pow(max(dot(viewDir, reflectDir), 0.0), MaterialSpecularExponent(mat)) * hitRate;
}
return ambient + diffuse + specular;
......
// Quelle: https://github.com/nvpro-samples/vk_raytracing_tutorial/blob/master/ray_tracing_jitter_cam/shaders/random.glsl
// Generate a random unsigned int from two unsigned int values, using 16 pairs
// of rounds of the Tiny Encryption Algorithm. See Zafar, Olano, and Curtis,
// "GPU Random Numbers via the Tiny Encryption Algorithm"
uint tea(uint val0, uint val1)
{
uint v0 = val0;
uint v1 = val1;
uint s0 = 0;
for(uint n = 0; n < 16; n++)
{
s0 += 0x9e3779b9;
v0 += ((v1 << 4) + 0xa341316c) ^ (v1 + s0) ^ ((v1 >> 5) + 0xc8013ea4);
v1 += ((v0 << 4) + 0xad90777d) ^ (v0 + s0) ^ ((v0 >> 5) + 0x7e95761e);
}
return v0;
}
// Generate a random unsigned int in [0, 2^24) given the previous RNG state
// using the Numerical Recipes linear congruential generator
uint lcg(inout uint prev)
{
uint LCG_A = 1664525u;
uint LCG_C = 1013904223u;
prev = (LCG_A * prev + LCG_C);
return prev & 0x00FFFFFF;
}
// Generate a random float in [0, 1) given the previous RNG state
float rnd(inout uint prev)
{
return (float(lcg(prev)) / float(0x01000000));
}
\ No newline at end of file
......@@ -67,9 +67,11 @@ struct LightSource
vec4 position;
vec4 color;
vec4 ambientFactor_enabled_type_effectiveRange;
vec4 size;
};
#define LightPosition(obj) (obj.position.xyz)
#define LightDimension(obj) (obj.size.xy)
#define LightColor(obj) (obj.color.rgb)
#define LightAmbientFactor(obj) (obj.ambientFactor_enabled_type_effectiveRange.x)
#define LightEnabled(obj) (obj.ambientFactor_enabled_type_effectiveRange.y)
......
......@@ -3,6 +3,12 @@
#extension GL_EXT_scalar_block_layout : enable
#extension GL_GOOGLE_include_directive : enable
#include "raycommon.glsl"
#include "random.glsl"
layout(push_constant) uniform Constants
{
uint rngSeed;
};
layout(binding = 0, set = 0) uniform accelerationStructureNV topLevelAS;
layout(binding = 1, set = 0, rgba8) uniform image2D image;
......@@ -16,33 +22,21 @@ void main()
{
uint rayFlags = gl_RayFlagsOpaqueNV;
uint cullMask = 0xff;
float tMin = 0.001;
float tMax = 10000.0;
vec2 offsets[] = {
vec2(0, 0),
vec2(1, 0),
vec2(0, 1),
vec2(1, 1),
vec2(0.5, 0.5),
};
vec3 res = vec3(0);
int nSamples = 1;
for(int i = 0; i < nSamples; i++) {
const vec2 inUv = (vec2(gl_LaunchIDNV) + offsets[i]) / vec2(gl_LaunchSizeNV.xy);
vec4 origin = scene.s.camera.viewInverse * vec4(0, 0, 0, 1);
vec4 target = scene.s.camera.projectionInverse * vec4(inUv * 2.0 - 1.0, 1, 1);
vec4 direction = scene.s.camera.viewInverse * vec4(normalize(target.xyz), 0);
uint seed = tea(gl_LaunchIDNV.y * gl_LaunchSizeNV.x + gl_LaunchIDNV.x, rngSeed);
vec2 offset = vec2(rnd(seed), rnd(seed));
const vec2 inUv = (vec2(gl_LaunchIDNV.xy) + offset) / vec2(gl_LaunchSizeNV.xy);
const vec4 origin = scene.s.camera.viewInverse * vec4(0, 0, 0, 1);
const vec4 target = scene.s.camera.projectionInverse * vec4(inUv * 2.0 - 1.0, 1, 1);
const vec4 direction = scene.s.camera.viewInverse * vec4(normalize(target.xyz), 0);
traceNV(topLevelAS, rayFlags, cullMask,
0, 0, 0,
origin.xyz, tMin,
direction.xyz, tMax, 0);
traceNV(topLevelAS, rayFlags, cullMask,
0, 0, 0,
origin.xyz, RayTMin,
direction.xyz, RayTMax, 0);
res += payload.value;
}
imageStore(image, ivec2(gl_LaunchIDNV.xy), vec4(res / nSamples, 0));
imageStore(image, ivec2(gl_LaunchIDNV.xy), vec4( payload.value, 0));
}
\ No newline at end of file
......@@ -191,7 +191,8 @@ struct ModelInfo
* @brief Die Standard-Lichtquelle.
*/
std::vector<LightSource> lightSources = {
LightSource(glm::vec3(0.f, 2.f, 0.f),
LightSource({0.f, 2.f, 0.f},
{1.f, 1.f},
glm::vec3(1.f),
LightSourceType::Point,
0.15f)};
......
......@@ -5,6 +5,7 @@
#include <chrono>
#include <memory>
#include <tuple>
#include <random>
#include "Config.hpp"
#include "Core/AppCreateInfo.hpp"
......@@ -151,6 +152,16 @@ namespace lib
std::unique_ptr<Buffer> objectInstancesBuffer;
std::unique_ptr<Buffer> lightSourcesBuffer;
struct PushConstants
{
uint32_t rngSeed;
};
PushConstants pushConstant;
std::default_random_engine randomEngine;
std::uniform_int_distribution<uint32_t> randomDistribution;
//raytracing
std::vector<GeometryInstance> geometryInstances;
std::unique_ptr<TopLevelAccelerationStructure> topLevelAS;
......@@ -199,6 +210,7 @@ namespace lib
bool show = false;
} imGui;
void InitRandomGenerators();
void CreateInstance();
void SetupDebugCallbacks();
void FindPhysicalDevice();
......
......@@ -8,48 +8,53 @@
namespace lib
{
enum class LightSourceType
{
Point = 0,
Directional = 1,
};
enum class LightSourceType
{
Point = 0,
Directional = 1,
};
#pragma pack(push, 1)
class LightSource
{
private:
glm::vec4 position = glm::vec4(0);
glm::vec4 color = glm::vec4(0);
glm::vec4 ambientFactor_enabled_type_effectiveRange = glm::vec4(0.f, 1.f, 0.f, 0.f);
public:
LightSource() = default;
// TODO:? Lichtquelle ist nicht kompatibel zum Licht-format von assimp
// LightSource(const aiLight *light);
LightSource(const glm::vec3 &position,
const glm::vec3 &color,
LightSourceType type = LightSourceType::Point,
float ambientFactor = 0.f,
bool enabled = 1.f,
float effectiveRange = std::numeric_limits<float>::max());
glm::vec3 GetPosition() const;
void SetPosition(const glm::vec3 &value);
glm::vec3 GetColor() const;
void SetColor(const glm::vec3 &value);
float GetAmbientFactor() const;
void SetAmbientFactor(float value);
bool IsEnabled() const;
void SetEnabled(bool value);
LightSourceType GetType() const;
void SetType(LightSourceType value);
float GetEffectiveRange() const;
void SetEffectiveRange(float value);
};
class LightSource
{
private:
glm::vec4 position{};
glm::vec4 color{};
glm::vec4 ambientFactor_enabled_type_effectiveRange{0.f, 1.f, 0.f, 0.f};
glm::vec4 size{1, 1, 0, 0};
public:
LightSource() = default;
// TODO:? Lichtquelle ist nicht kompatibel zum Licht-format von assimp
// LightSource(const aiLight *light);
LightSource(const glm::vec3 &position,
const glm::vec2 &size,
const glm::vec3 &color,
LightSourceType type = LightSourceType::Point,
float ambientFactor = 0.f,
bool enabled = 1.f,
float effectiveRange = std::numeric_limits<float>::max());
glm::vec3 GetPosition() const;
void SetPosition(const glm::vec3 &value);
glm::vec2 GetSize() const;
void SetSize(const glm::vec2 &value);
glm::vec3 GetColor() const;
void SetColor(const glm::vec3 &value);
float GetAmbientFactor() const;
void SetAmbientFactor(float value);
bool IsEnabled() const;
void SetEnabled(bool value);
LightSourceType GetType() const;
void SetType(LightSourceType value);
float GetEffectiveRange() const;
void SetEffectiveRange(float value);
};
#pragma pack(pop)
} // namespace lib
......@@ -7,6 +7,7 @@
#include <iterator>
#include <limits>
#include <set>
#include <random>
#include "Config.hpp"
#include "Core/CameraModel.hpp"
......@@ -95,6 +96,7 @@ lib::CgContext::CgContext(const AppCreateInfo &info, GLFWwindow *window) : windo
try
{
this->InitRandomGenerators();
this->CreateInstance();
this->CreateSurface();
this->FindPhysicalDevice();
......@@ -344,6 +346,22 @@ void lib::CgContext::RecreateSwapChain()
this->swapChainDirty = false;
}
void lib::CgContext::InitRandomGenerators()
{
std::random_device rd{};
if (rd.entropy())
{
this->randomEngine.seed(rd());
}
else
{
this->randomEngine.seed(static_cast<uint32_t>(
std::chrono::system_clock::now().time_since_epoch().count() %
std::numeric_limits<uint32_t>::max()));
}
}
void lib::CgContext::CreateInstance()
{
NameList usedExtensions;
......@@ -686,6 +704,7 @@ void lib::CgContext::UpdateCommandBuffer(uint32_t imageIndex)
auto &commandPool = this->drawingCommandPools[imageIndex];
auto &commandBuffer = this->commandBuffers[imageIndex];
this->logicalDevice.resetCommandPool(commandPool, vk::CommandPoolResetFlagBits::eReleaseResources);
this->pushConstant.rngSeed = this->randomDistribution(this->randomEngine);
vk::CommandBufferBeginInfo beginInfo;
......@@ -724,6 +743,11 @@ void lib::CgContext::UpdateCommandBuffer(uint32_t imageIndex)
vk::DependencyFlagBits::eByRegion,
{}, {}, transitionToGeneralLayout);
commandBuffer.pushConstants(this->pipelineLayout,
vk::ShaderStageFlagBits::eRaygenNV | vk::ShaderStageFlagBits::eClosestHitNV,
0, sizeof(this->pushConstant),
&this->pushConstant);
if (this->IsOk())
{
commandBuffer.copyBuffer(this->uniformStagingBuffers[imageIndex].GetBufferHandle(),
......@@ -1464,9 +1488,16 @@ bool lib::CgContext::TryCreatePipeline()
closestHitGroupInfo.intersectionShader = VK_SHADER_UNUSED_NV;
closestHitGroupInfo.generalShader = VK_SHADER_UNUSED_NV;
vk::PushConstantRange pushConstantRange;
pushConstantRange.offset = 0;
pushConstantRange.size = sizeof(this->pushConstant);
pushConstantRange.stageFlags = vk::ShaderStageFlagBits::eRaygenNV | vk::ShaderStageFlagBits::eClosestHitNV;
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
pipelineLayoutCreateInfo.setLayoutCount = 1;
pipelineLayoutCreateInfo.pSetLayouts = &this->descriptorSetLayout;
pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange;
this->pipelineLayout = this->logicalDevice.createPipelineLayout(pipelineLayoutCreateInfo);
......
......@@ -5,6 +5,7 @@
lib::LightSource::LightSource(
const glm::vec3 &position,
const glm::vec2 &size,
const glm::vec3 &color,
LightSourceType type,
float ambientFactor,
......@@ -12,6 +13,7 @@ lib::LightSource::LightSource(
float effectiveRange)
{
this->SetPosition(position);
this->SetSize(size);
this->SetColor(color);
this->SetType(type);
this->SetAmbientFactor(ambientFactor);
......@@ -31,6 +33,20 @@ void lib::LightSource::SetPosition(const glm::vec3 &value)
this->position.z = value.z;
}
glm::vec2 lib::LightSource::GetSize() const
{
return {
this->size.x,
this->size.y,
};
}
void lib::LightSource::SetSize(const glm::vec2 &value)
{
this->size.x = value.x;
this->size.y = value.y;
}
glm::vec3 lib::LightSource::GetColor() const
{
return glm::vec3(this->color.r, this->color.g, this->color.b);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment