-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Raytracing pipeline demo #173
base: master
Are you sure you want to change the base?
Raytracing pipeline demo #173
Conversation
9e2eb0f
to
bcbd729
Compare
void mouseProcess(const nbl::ui::IMouseEventChannel::range_t& events) | ||
// return whether camera is moved by mouse | ||
bool mouseProcess(const nbl::ui::IMouseEventChannel::range_t& events) | ||
{ | ||
bool cameraMoved = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are these your changes?
coordinate with @AnastaZIuk
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is my changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this bool
is not a reliable way to find out if the camera moved during a frame (nor is the keyboard one)
I'd perform any such checks in endInputProcessing
by comparing matrices (or pos and target) before and after setting position and target
8f16aad
to
34a3fa9
Compare
Signed-off-by: kevyuu <[email protected]>
- Multiple HitGroup. Each with closesthit and anythit shader - Multiple Miss Shader Group. Signed-off-by: kevyuu <[email protected]>
Signed-off-by: kevyuu <[email protected]>
Signed-off-by: kevyuu <[email protected]>
Signed-off-by: kevyuu <[email protected]>
Signed-off-by: kevyuu <[email protected]>
Signed-off-by: kevyuu <[email protected]>
Signed-off-by: kevyuu <[email protected]>
Signed-off-by: kevyuu <[email protected]>
Signed-off-by: kevyuu <[email protected]>
Signed-off-by: kevyuu <[email protected]>
Signed-off-by: kevyuu <[email protected]>
Signed-off-by: Ali Cheraghi <[email protected]> Signed-off-by: kevyuu <[email protected]>
Signed-off-by: kevyuu <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
main.cpp
I'll review later
enum E_LIGHT_TYPE : uint16_t | ||
{ | ||
ELT_DIRECTIONAL, | ||
ELT_POINT, | ||
ELT_SPOT, | ||
ELT_COUNT | ||
}; | ||
|
||
struct Light | ||
{ | ||
float32_t3 direction; | ||
float32_t3 position; | ||
float32_t outerCutoff; | ||
uint16_t type; | ||
|
||
|
||
#ifndef __HLSL_VERSION | ||
bool operator==(const Light&) const = default; | ||
#endif | ||
|
||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keep example simple, do just directional light
// 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" | ||
uint32_t tea(uint32_t val0, uint32_t val1) | ||
{ | ||
uint32_t v0 = val0; | ||
uint32_t v1 = val1; | ||
uint32_t s0 = 0; | ||
|
||
for(uint32_t 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 | ||
uint32_t lcg(inout uint32_t prev) | ||
{ | ||
uint32_t LCG_A = 1664525u; | ||
uint32_t LCG_C = 1013904223u; | ||
prev = (LCG_A * prev + LCG_C); | ||
return prev & 0x00FFFFFF; | ||
} | ||
|
||
// Generate a random float32_t in [0, 1) given the previous RNG state | ||
float32_t rnd(inout uint32_t prev) | ||
{ | ||
return (float32_t(lcg(prev)) / float32_t(0x01000000)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you may want to rework them into something resembling xoroshiro.hlsl
in the Nabla repo and pcg.hlsl
from the HLSL BxDF PR https://github.com/Devsh-Graphics-Programming/Nabla/pull/811/files#diff-717f65cfd315d91ced5e7da9f817f786fb1f8c1b1c06a570df4f61be3660a643
uint32_t seed = p.seed; | ||
if (geom.material.dissolve == 0.0) | ||
IgnoreHit(); | ||
else if (rnd(seed) > geom.material.dissolve) | ||
IgnoreHit(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok so you stochastically do alpha, btw for this to add up, you'd need to "boost" the color (throughput in the color payload) by the probability of the path taken, so:
if you ignore the hit, you mul by1.f/(1.f-dissolve)
if you don't ignore the hit, you mul by1.f/dissolve
basically same as importance sampling. Nvm they cancel out and you never multiplied them into the throughput.
For the shadow ray there is a more performant way actually, instead of importance sampling the mix
this*alpha+next*(1-alpha)
you can recognise that the shadow ray doesn't have to be a boolean and you can multiply the dissolve into it same you would an alpha value (you do need to create the BLAS with the no-duplicate hit flag though).
Also at this point you can make two separate anyhit HLSL shader sources.
if (geom.material.illum != 4) | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can build your TLAS with instance flags that prevent ANY_HIT being called on them (or what it only BLAS?).
This is useful because you don't end up executing the vk::RawBufferLoad
for the things that are not transparent to check if they are transparent (saving Bandwidth in the meantime).
|
||
struct [raypayload] ShadowPayload | ||
{ | ||
bool isShadowed : read(caller) : write(caller,miss); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as I've mentioned in the comment in your anyhit shader, its better to have a float32_t opacity
and have the anyhit multiply into it, which allows for transparent shadows, you have to use the 4 bytes in your payload anyway.
struct Attrib | ||
{ | ||
float3 HitAttribute; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you never fill this out?
[[vk::binding(0, 0)]] RaytracingAccelerationStructure topLevelAS; | ||
|
||
[shader("closesthit")] | ||
void main(inout ColorPayload p, in BuiltInTriangleIntersectionAttributes attribs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BuiltInTriangleIntersectionAttributes
? but its not a triangle?
SProceduralGeomInfo sphere = vk::RawBufferLoad < SProceduralGeomInfo > (pc.proceduralGeomInfoBuffer + primID * sizeof(SProceduralGeomInfo)); | ||
|
||
// Computing the normal at hit position | ||
float32_t3 worldNormal = normalize(worldPosition - sphere.center); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you already had to load and compute some of this in the intersection shader, is it not possible to pass it in the payload/custom attribs to the closest hit shader?
uint flags = | ||
RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH | RAY_FLAG_FORCE_OPAQUE | | ||
RAY_FLAG_SKIP_CLOSEST_HIT_SHADER; | ||
|
||
ShadowPayload shadowPayload; | ||
shadowPayload.isShadowed = true; | ||
shadowPayload.seed = p.seed; | ||
TraceRay(topLevelAS, flags, 0xFF, ERT_OCCLUSION, 0, EMT_OCCLUSION, rayDesc, shadowPayload); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw if you follow my advice on transparent shadows, the flags will have to change
P.S. do IgnoreHit()
and modifying the payload mix? (Idea is that accepted hit will not cause the invocation of a miss shader or any more anyhits).
rayDesc.TMin = 0.01; | ||
rayDesc.TMax = cLight.outLightDistance; | ||
|
||
uint flags = RAY_FLAG_SKIP_CLOSEST_HIT_SHADER; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the reason for not having RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH
here?
float32_t3 direction; | ||
float32_t3 position; | ||
float32_t outerCutoff; | ||
uint16_t type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use 16-bit types in PushConstants. they require a feature to be enabled and no AMD GPU supports them afaik
Signed-off-by: kevyuu <[email protected]>
Signed-off-by: kevyuu <[email protected]>
Signed-off-by: kevyuu <[email protected]>
Signed-off-by: kevyuu <[email protected]>
Implement a demo to cover various ray tracing pipeline use cases.