mirror of
https://github.com/ZDoom/ZDRay.git
synced 2025-02-03 13:11:04 +00:00
Implement bounces and emissive surfaces
This commit is contained in:
parent
8df36944eb
commit
0c4199b281
12 changed files with 377 additions and 248 deletions
|
@ -5,7 +5,9 @@ static const char* glsl_rchit_bounce = R"glsl(
|
||||||
|
|
||||||
struct hitPayload
|
struct hitPayload
|
||||||
{
|
{
|
||||||
|
vec3 hitPosition;
|
||||||
float hitAttenuation;
|
float hitAttenuation;
|
||||||
|
int hitSurfaceIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SurfaceInfo
|
struct SurfaceInfo
|
||||||
|
@ -25,9 +27,10 @@ layout(set = 0, binding = 6) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// SurfaceInfo surface = surfaces[surfaceIndices[gl_PrimitiveID]];
|
int surfaceIndex = surfaceIndices[gl_PrimitiveID];
|
||||||
|
payload.hitPosition = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT;
|
||||||
payload.hitAttenuation = 0.0;
|
payload.hitSurfaceIndex = surfaceIndex;
|
||||||
|
payload.hitAttenuation = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
)glsl";
|
)glsl";
|
||||||
|
|
|
@ -5,7 +5,9 @@ static const char* glsl_rchit_light = R"glsl(
|
||||||
|
|
||||||
struct hitPayload
|
struct hitPayload
|
||||||
{
|
{
|
||||||
|
vec3 hitPosition;
|
||||||
float hitAttenuation;
|
float hitAttenuation;
|
||||||
|
int hitSurfaceIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SurfaceInfo
|
struct SurfaceInfo
|
||||||
|
@ -20,7 +22,7 @@ struct SurfaceInfo
|
||||||
|
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload payload;
|
layout(location = 0) rayPayloadInEXT hitPayload payload;
|
||||||
|
|
||||||
layout(set = 0, binding = 5) buffer SurfaceIndexBuffer { int surfaceIndices[]; };
|
layout(set = 0, binding = 5) buffer SurfaceIndexBuffer { uint surfaceIndices[]; };
|
||||||
layout(set = 0, binding = 6) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
|
layout(set = 0, binding = 6) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
|
|
|
@ -5,7 +5,9 @@ static const char* glsl_rchit_sun = R"glsl(
|
||||||
|
|
||||||
struct hitPayload
|
struct hitPayload
|
||||||
{
|
{
|
||||||
|
vec3 hitPosition;
|
||||||
float hitAttenuation;
|
float hitAttenuation;
|
||||||
|
int hitSurfaceIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SurfaceInfo
|
struct SurfaceInfo
|
||||||
|
|
|
@ -5,30 +5,143 @@ static const char* glsl_rgen_bounce = R"glsl(
|
||||||
|
|
||||||
struct hitPayload
|
struct hitPayload
|
||||||
{
|
{
|
||||||
|
vec3 hitPosition;
|
||||||
float hitAttenuation;
|
float hitAttenuation;
|
||||||
|
int hitSurfaceIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(location = 0) rayPayloadEXT hitPayload payload;
|
layout(location = 0) rayPayloadEXT hitPayload payload;
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform accelerationStructureEXT acc;
|
layout(set = 0, binding = 0) uniform accelerationStructureEXT acc;
|
||||||
layout(set = 0, binding = 1, rgba32f) uniform image2D positions;
|
layout(set = 0, binding = 1, rgba32f) uniform image2D startpositions;
|
||||||
layout(set = 0, binding = 2, rgba32f) uniform image2D normals;
|
layout(set = 0, binding = 2, rgba32f) uniform image2D positions;
|
||||||
layout(set = 0, binding = 3, rgba32f) uniform image2D outputs;
|
layout(set = 0, binding = 3, rgba32f) uniform image2D outputs;
|
||||||
|
|
||||||
layout(set = 0, binding = 4) uniform Uniforms
|
layout(set = 0, binding = 4) uniform Uniforms
|
||||||
{
|
{
|
||||||
|
uint SampleIndex;
|
||||||
|
uint SampleCount;
|
||||||
|
uint PassType;
|
||||||
|
uint Padding2;
|
||||||
vec3 LightOrigin;
|
vec3 LightOrigin;
|
||||||
float PassType;
|
float Padding0;
|
||||||
float LightRadius;
|
float LightRadius;
|
||||||
float LightIntensity;
|
float LightIntensity;
|
||||||
float LightInnerAngleCos;
|
float LightInnerAngleCos;
|
||||||
float LightOuterAngleCos;
|
float LightOuterAngleCos;
|
||||||
vec3 LightSpotDir;
|
vec3 LightDir;
|
||||||
float SampleDistance;
|
float SampleDistance;
|
||||||
vec3 LightColor;
|
vec3 LightColor;
|
||||||
float Padding;
|
float Padding1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SurfaceInfo
|
||||||
|
{
|
||||||
|
vec3 Normal;
|
||||||
|
float EmissiveDistance;
|
||||||
|
vec3 EmissiveColor;
|
||||||
|
float EmissiveIntensity;
|
||||||
|
float Sky;
|
||||||
|
float Padding0, Padding1, Padding2;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(set = 0, binding = 6) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
|
||||||
|
|
||||||
|
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);
|
||||||
|
vec2 Hammersley(uint i, uint N);
|
||||||
|
float RadicalInverse_VdC(uint bits);
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
ivec2 texelPos = ivec2(gl_LaunchIDEXT.xy);
|
||||||
|
|
||||||
|
vec4 data0;
|
||||||
|
if (PassType == 2)
|
||||||
|
data0 = imageLoad(positions, texelPos);
|
||||||
|
else
|
||||||
|
data0 = imageLoad(startpositions, texelPos);
|
||||||
|
|
||||||
|
vec4 incoming = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
int surfaceIndex = int(data0.w);
|
||||||
|
if (surfaceIndex >= 0)
|
||||||
|
{
|
||||||
|
SurfaceInfo surface = surfaces[surfaceIndex];
|
||||||
|
|
||||||
|
vec3 origin = data0.xyz;
|
||||||
|
vec3 normal = surface.Normal;
|
||||||
|
|
||||||
|
if (PassType == 0)
|
||||||
|
{
|
||||||
|
incoming.rgb = surface.EmissiveColor * surface.EmissiveIntensity;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
incoming = imageLoad(outputs, texelPos);
|
||||||
|
|
||||||
|
if (PassType == 1)
|
||||||
|
incoming.w = 1.0f / float(SampleCount);
|
||||||
|
|
||||||
|
vec2 Xi = Hammersley(SampleIndex, SampleCount);
|
||||||
|
vec3 H = ImportanceSampleGGX(Xi, normal, 1.0f);
|
||||||
|
vec3 L = normalize(H * (2.0f * dot(normal, H)) - normal);
|
||||||
|
|
||||||
|
float NdotL = max(dot(normal, L), 0.0);
|
||||||
|
|
||||||
|
const float p = 1 / (2 * 3.14159265359);
|
||||||
|
incoming.w *= NdotL / p;
|
||||||
|
|
||||||
|
if (NdotL > 0.0f)
|
||||||
|
{
|
||||||
|
const float minDistance = 0.1;
|
||||||
|
|
||||||
|
traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, origin, minDistance, L, 2000, 0);
|
||||||
|
if (payload.hitAttenuation == 1.0)
|
||||||
|
{
|
||||||
|
float hitDistance = distance(origin, payload.hitPosition);
|
||||||
|
surfaceIndex = payload.hitSurfaceIndex;
|
||||||
|
surface = surfaces[surfaceIndex];
|
||||||
|
origin = payload.hitPosition;
|
||||||
|
|
||||||
|
if (surface.EmissiveDistance > 0.0)
|
||||||
|
{
|
||||||
|
float attenuation = max(1.0 - (hitDistance / surface.EmissiveDistance), 0.0f);
|
||||||
|
incoming.rgb += surface.EmissiveColor * (surface.EmissiveIntensity * attenuation * incoming.w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
incoming.w *= 0.25; // the amount of incoming light the surfaces emit
|
||||||
|
}
|
||||||
|
|
||||||
|
data0.xyz = origin;
|
||||||
|
data0.w = float(surfaceIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
imageStore(positions, texelPos, data0);
|
||||||
|
imageStore(outputs, texelPos, incoming);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
|
||||||
|
{
|
||||||
|
float a = roughness * roughness;
|
||||||
|
|
||||||
|
float phi = 2.0f * 3.14159265359 * Xi.x;
|
||||||
|
float cosTheta = sqrt((1.0f - Xi.y) / (1.0f + (a * a - 1.0f) * Xi.y));
|
||||||
|
float sinTheta = sqrt(1.0f - cosTheta * cosTheta);
|
||||||
|
|
||||||
|
// from spherical coordinates to cartesian coordinates
|
||||||
|
vec3 H = vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
|
||||||
|
|
||||||
|
// from tangent-space vector to world-space sample vector
|
||||||
|
vec3 up = abs(N.z) < 0.999f ? vec3(0.0f, 0.0f, 1.0f) : vec3(1.0f, 0.0f, 0.0f);
|
||||||
|
vec3 tangent = normalize(cross(up, N));
|
||||||
|
vec3 bitangent = cross(N, tangent);
|
||||||
|
|
||||||
|
vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
||||||
|
return normalize(sampleVec);
|
||||||
|
}
|
||||||
|
|
||||||
float RadicalInverse_VdC(uint bits)
|
float RadicalInverse_VdC(uint bits)
|
||||||
{
|
{
|
||||||
bits = (bits << 16u) | (bits >> 16u);
|
bits = (bits << 16u) | (bits >> 16u);
|
||||||
|
@ -44,67 +157,4 @@ vec2 Hammersley(uint i, uint N)
|
||||||
return vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
return vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
ivec2 texelPos = ivec2(gl_LaunchIDEXT.xy);
|
|
||||||
vec4 data0 = imageLoad(positions, texelPos);
|
|
||||||
vec4 data1 = imageLoad(normals, texelPos);
|
|
||||||
if (data1 == vec4(0))
|
|
||||||
return;
|
|
||||||
|
|
||||||
vec3 origin = data0.xyz;
|
|
||||||
vec3 normal = data1.xyz;
|
|
||||||
|
|
||||||
vec4 emittance = vec4(0.0);
|
|
||||||
if (PassType == 1.0)
|
|
||||||
emittance = imageLoad(outputs, texelPos);
|
|
||||||
|
|
||||||
const float minDistance = 0.01;
|
|
||||||
const uint sample_count = 1024;
|
|
||||||
|
|
||||||
float dist = distance(LightOrigin, origin);
|
|
||||||
if (dist > minDistance && dist < LightRadius)
|
|
||||||
{
|
|
||||||
vec3 dir = normalize(LightOrigin - origin);
|
|
||||||
|
|
||||||
float distAttenuation = max(1.0 - (dist / LightRadius), 0.0);
|
|
||||||
float angleAttenuation = max(dot(normal, dir), 0.0);
|
|
||||||
float spotAttenuation = 1.0;
|
|
||||||
if (LightOuterAngleCos > -1.0)
|
|
||||||
{
|
|
||||||
float cosDir = dot(dir, LightSpotDir);
|
|
||||||
spotAttenuation = smoothstep(LightOuterAngleCos, LightInnerAngleCos, cosDir);
|
|
||||||
spotAttenuation = max(spotAttenuation, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
float attenuation = distAttenuation * angleAttenuation * spotAttenuation;
|
|
||||||
if (attenuation > 0.0)
|
|
||||||
{
|
|
||||||
float shadowAttenuation = 0.0;
|
|
||||||
vec3 e0 = cross(normal, abs(normal.x) < abs(normal.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0));
|
|
||||||
vec3 e1 = cross(normal, e0);
|
|
||||||
e0 = cross(normal, e1);
|
|
||||||
for (uint i = 0; i < sample_count; i++)
|
|
||||||
{
|
|
||||||
vec2 offset = (Hammersley(i, sample_count) - 0.5) * SampleDistance;
|
|
||||||
vec3 origin2 = origin + offset.x * e0 + offset.y * e1;
|
|
||||||
|
|
||||||
float dist2 = distance(LightOrigin, origin2);
|
|
||||||
vec3 dir2 = normalize(LightOrigin - origin2);
|
|
||||||
|
|
||||||
traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, origin2, minDistance, dir2, dist2, 0);
|
|
||||||
shadowAttenuation += payload.hitAttenuation;
|
|
||||||
}
|
|
||||||
shadowAttenuation *= 1.0 / float(sample_count);
|
|
||||||
|
|
||||||
attenuation *= shadowAttenuation;
|
|
||||||
|
|
||||||
emittance.rgb += LightColor * (attenuation * LightIntensity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emittance.w += 1.0;
|
|
||||||
imageStore(outputs, texelPos, emittance);
|
|
||||||
}
|
|
||||||
|
|
||||||
)glsl";
|
)glsl";
|
||||||
|
|
|
@ -5,30 +5,119 @@ static const char* glsl_rgen_light = R"glsl(
|
||||||
|
|
||||||
struct hitPayload
|
struct hitPayload
|
||||||
{
|
{
|
||||||
|
vec3 hitPosition;
|
||||||
float hitAttenuation;
|
float hitAttenuation;
|
||||||
|
int hitSurfaceIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(location = 0) rayPayloadEXT hitPayload payload;
|
layout(location = 0) rayPayloadEXT hitPayload payload;
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform accelerationStructureEXT acc;
|
layout(set = 0, binding = 0) uniform accelerationStructureEXT acc;
|
||||||
layout(set = 0, binding = 1, rgba32f) uniform image2D positions;
|
layout(set = 0, binding = 1, rgba32f) uniform image2D startpositions;
|
||||||
layout(set = 0, binding = 2, rgba32f) uniform image2D normals;
|
layout(set = 0, binding = 2, rgba32f) uniform image2D positions;
|
||||||
layout(set = 0, binding = 3, rgba32f) uniform image2D outputs;
|
layout(set = 0, binding = 3, rgba32f) uniform image2D outputs;
|
||||||
|
|
||||||
layout(set = 0, binding = 4) uniform Uniforms
|
layout(set = 0, binding = 4) uniform Uniforms
|
||||||
{
|
{
|
||||||
|
uint SampleIndex;
|
||||||
|
uint SampleCount;
|
||||||
|
uint PassType;
|
||||||
|
uint Padding2;
|
||||||
vec3 LightOrigin;
|
vec3 LightOrigin;
|
||||||
float PassType;
|
float Padding0;
|
||||||
float LightRadius;
|
float LightRadius;
|
||||||
float LightIntensity;
|
float LightIntensity;
|
||||||
float LightInnerAngleCos;
|
float LightInnerAngleCos;
|
||||||
float LightOuterAngleCos;
|
float LightOuterAngleCos;
|
||||||
vec3 LightSpotDir;
|
vec3 LightDir;
|
||||||
float SampleDistance;
|
float SampleDistance;
|
||||||
vec3 LightColor;
|
vec3 LightColor;
|
||||||
float Padding;
|
float Padding1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SurfaceInfo
|
||||||
|
{
|
||||||
|
vec3 Normal;
|
||||||
|
float EmissiveDistance;
|
||||||
|
vec3 EmissiveColor;
|
||||||
|
float EmissiveIntensity;
|
||||||
|
float Sky;
|
||||||
|
float Padding0, Padding1, Padding2;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(set = 0, binding = 6) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
|
||||||
|
|
||||||
|
vec2 Hammersley(uint i, uint N);
|
||||||
|
float RadicalInverse_VdC(uint bits);
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
ivec2 texelPos = ivec2(gl_LaunchIDEXT.xy);
|
||||||
|
vec4 incoming = imageLoad(outputs, texelPos);
|
||||||
|
vec4 data0 = imageLoad(positions, texelPos);
|
||||||
|
int surfaceIndex = int(data0.w);
|
||||||
|
if (surfaceIndex < 0 || incoming.w <= 0.0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const float minDistance = 0.01;
|
||||||
|
|
||||||
|
vec3 origin = data0.xyz;
|
||||||
|
float dist = distance(LightOrigin, origin);
|
||||||
|
if (dist > minDistance && dist < LightRadius)
|
||||||
|
{
|
||||||
|
vec3 dir = normalize(LightOrigin - origin);
|
||||||
|
|
||||||
|
SurfaceInfo surface = surfaces[surfaceIndex];
|
||||||
|
vec3 normal = surface.Normal;
|
||||||
|
|
||||||
|
float distAttenuation = max(1.0 - (dist / LightRadius), 0.0);
|
||||||
|
float angleAttenuation = max(dot(normal, dir), 0.0);
|
||||||
|
float spotAttenuation = 1.0;
|
||||||
|
if (LightOuterAngleCos > -1.0)
|
||||||
|
{
|
||||||
|
float cosDir = dot(dir, LightDir);
|
||||||
|
spotAttenuation = smoothstep(LightOuterAngleCos, LightInnerAngleCos, cosDir);
|
||||||
|
spotAttenuation = max(spotAttenuation, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float attenuation = distAttenuation * angleAttenuation * spotAttenuation;
|
||||||
|
if (attenuation > 0.0)
|
||||||
|
{
|
||||||
|
float shadowAttenuation = 0.0;
|
||||||
|
|
||||||
|
if (PassType == 0)
|
||||||
|
{
|
||||||
|
vec3 e0 = cross(normal, abs(normal.x) < abs(normal.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0));
|
||||||
|
vec3 e1 = cross(normal, e0);
|
||||||
|
e0 = cross(normal, e1);
|
||||||
|
for (uint i = 0; i < SampleCount; i++)
|
||||||
|
{
|
||||||
|
vec2 offset = (Hammersley(i, SampleCount) - 0.5) * SampleDistance;
|
||||||
|
vec3 origin2 = origin + offset.x * e0 + offset.y * e1;
|
||||||
|
|
||||||
|
float dist2 = distance(LightOrigin, origin2);
|
||||||
|
vec3 dir2 = normalize(LightOrigin - origin2);
|
||||||
|
|
||||||
|
traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 1, 0, 1, origin2, minDistance, dir2, dist2, 0);
|
||||||
|
shadowAttenuation += payload.hitAttenuation;
|
||||||
|
}
|
||||||
|
shadowAttenuation *= 1.0 / float(SampleCount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 1, 0, 1, origin, minDistance, dir, dist, 0);
|
||||||
|
shadowAttenuation = payload.hitAttenuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
attenuation *= shadowAttenuation;
|
||||||
|
|
||||||
|
incoming.rgb += LightColor * (attenuation * LightIntensity) * incoming.w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
imageStore(outputs, texelPos, incoming);
|
||||||
|
}
|
||||||
|
|
||||||
float RadicalInverse_VdC(uint bits)
|
float RadicalInverse_VdC(uint bits)
|
||||||
{
|
{
|
||||||
bits = (bits << 16u) | (bits >> 16u);
|
bits = (bits << 16u) | (bits >> 16u);
|
||||||
|
@ -44,67 +133,4 @@ vec2 Hammersley(uint i, uint N)
|
||||||
return vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
return vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
ivec2 texelPos = ivec2(gl_LaunchIDEXT.xy);
|
|
||||||
vec4 data0 = imageLoad(positions, texelPos);
|
|
||||||
vec4 data1 = imageLoad(normals, texelPos);
|
|
||||||
if (data1 == vec4(0))
|
|
||||||
return;
|
|
||||||
|
|
||||||
vec3 origin = data0.xyz;
|
|
||||||
vec3 normal = data1.xyz;
|
|
||||||
|
|
||||||
vec4 emittance = vec4(0.0);
|
|
||||||
if (PassType == 1.0)
|
|
||||||
emittance = imageLoad(outputs, texelPos);
|
|
||||||
|
|
||||||
const float minDistance = 0.01;
|
|
||||||
const uint sample_count = 1024;
|
|
||||||
|
|
||||||
float dist = distance(LightOrigin, origin);
|
|
||||||
if (dist > minDistance && dist < LightRadius)
|
|
||||||
{
|
|
||||||
vec3 dir = normalize(LightOrigin - origin);
|
|
||||||
|
|
||||||
float distAttenuation = max(1.0 - (dist / LightRadius), 0.0);
|
|
||||||
float angleAttenuation = max(dot(normal, dir), 0.0);
|
|
||||||
float spotAttenuation = 1.0;
|
|
||||||
if (LightOuterAngleCos > -1.0)
|
|
||||||
{
|
|
||||||
float cosDir = dot(dir, LightSpotDir);
|
|
||||||
spotAttenuation = smoothstep(LightOuterAngleCos, LightInnerAngleCos, cosDir);
|
|
||||||
spotAttenuation = max(spotAttenuation, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
float attenuation = distAttenuation * angleAttenuation * spotAttenuation;
|
|
||||||
if (attenuation > 0.0)
|
|
||||||
{
|
|
||||||
float shadowAttenuation = 0.0;
|
|
||||||
vec3 e0 = cross(normal, abs(normal.x) < abs(normal.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0));
|
|
||||||
vec3 e1 = cross(normal, e0);
|
|
||||||
e0 = cross(normal, e1);
|
|
||||||
for (uint i = 0; i < sample_count; i++)
|
|
||||||
{
|
|
||||||
vec2 offset = (Hammersley(i, sample_count) - 0.5) * SampleDistance;
|
|
||||||
vec3 origin2 = origin + offset.x * e0 + offset.y * e1;
|
|
||||||
|
|
||||||
float dist2 = distance(LightOrigin, origin2);
|
|
||||||
vec3 dir2 = normalize(LightOrigin - origin2);
|
|
||||||
|
|
||||||
traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 1, 0, 1, origin2, minDistance, dir2, dist2, 0);
|
|
||||||
shadowAttenuation += payload.hitAttenuation;
|
|
||||||
}
|
|
||||||
shadowAttenuation *= 1.0 / float(sample_count);
|
|
||||||
|
|
||||||
attenuation *= shadowAttenuation;
|
|
||||||
|
|
||||||
emittance.rgb += LightColor * (attenuation * LightIntensity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emittance.w += 1.0;
|
|
||||||
imageStore(outputs, texelPos, emittance);
|
|
||||||
}
|
|
||||||
|
|
||||||
)glsl";
|
)glsl";
|
||||||
|
|
|
@ -5,30 +5,96 @@ static const char* glsl_rgen_sun = R"glsl(
|
||||||
|
|
||||||
struct hitPayload
|
struct hitPayload
|
||||||
{
|
{
|
||||||
|
vec3 hitPosition;
|
||||||
float hitAttenuation;
|
float hitAttenuation;
|
||||||
|
int hitSurfaceIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(location = 0) rayPayloadEXT hitPayload payload;
|
layout(location = 0) rayPayloadEXT hitPayload payload;
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform accelerationStructureEXT acc;
|
layout(set = 0, binding = 0) uniform accelerationStructureEXT acc;
|
||||||
layout(set = 0, binding = 1, rgba32f) uniform image2D positions;
|
layout(set = 0, binding = 1, rgba32f) uniform image2D startpositions;
|
||||||
layout(set = 0, binding = 2, rgba32f) uniform image2D normals;
|
layout(set = 0, binding = 2, rgba32f) uniform image2D positions;
|
||||||
layout(set = 0, binding = 3, rgba32f) uniform image2D outputs;
|
layout(set = 0, binding = 3, rgba32f) uniform image2D outputs;
|
||||||
|
|
||||||
layout(set = 0, binding = 4) uniform Uniforms
|
layout(set = 0, binding = 4) uniform Uniforms
|
||||||
{
|
{
|
||||||
|
uint SampleIndex;
|
||||||
|
uint SampleCount;
|
||||||
|
uint PassType;
|
||||||
|
uint Padding2;
|
||||||
vec3 LightOrigin;
|
vec3 LightOrigin;
|
||||||
float PassType;
|
float Padding0;
|
||||||
float LightRadius;
|
float LightRadius;
|
||||||
float LightIntensity;
|
float LightIntensity;
|
||||||
float LightInnerAngleCos;
|
float LightInnerAngleCos;
|
||||||
float LightOuterAngleCos;
|
float LightOuterAngleCos;
|
||||||
vec3 LightSpotDir;
|
vec3 LightDir;
|
||||||
float SampleDistance;
|
float SampleDistance;
|
||||||
vec3 LightColor;
|
vec3 LightColor;
|
||||||
float Padding;
|
float Padding1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SurfaceInfo
|
||||||
|
{
|
||||||
|
vec3 Normal;
|
||||||
|
float EmissiveDistance;
|
||||||
|
vec3 EmissiveColor;
|
||||||
|
float EmissiveIntensity;
|
||||||
|
float Sky;
|
||||||
|
float Padding0, Padding1, Padding2;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(set = 0, binding = 6) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
|
||||||
|
|
||||||
|
vec2 Hammersley(uint i, uint N);
|
||||||
|
float RadicalInverse_VdC(uint bits);
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
ivec2 texelPos = ivec2(gl_LaunchIDEXT.xy);
|
||||||
|
vec4 incoming = imageLoad(outputs, texelPos);
|
||||||
|
vec4 data0 = imageLoad(positions, texelPos);
|
||||||
|
int surfaceIndex = int(data0.w);
|
||||||
|
if (surfaceIndex < 0 || incoming.w <= 0.0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SurfaceInfo surface = surfaces[surfaceIndex];
|
||||||
|
vec3 normal = surface.Normal;
|
||||||
|
|
||||||
|
vec3 origin = data0.xyz;
|
||||||
|
origin += normal * 0.1;
|
||||||
|
|
||||||
|
const float minDistance = 0;
|
||||||
|
const float dist = 32768.0;
|
||||||
|
|
||||||
|
float attenuation = 0.0;
|
||||||
|
if (PassType == 0)
|
||||||
|
{
|
||||||
|
vec3 e0 = cross(normal, abs(normal.x) < abs(normal.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0));
|
||||||
|
vec3 e1 = cross(normal, e0);
|
||||||
|
e0 = cross(normal, e1);
|
||||||
|
|
||||||
|
for (uint i = 0; i < SampleCount; i++)
|
||||||
|
{
|
||||||
|
vec2 offset = (Hammersley(i, SampleCount) - 0.5) * SampleDistance;
|
||||||
|
vec3 origin2 = origin + offset.x * e0 + offset.y * e1;
|
||||||
|
|
||||||
|
traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 2, 0, 2, origin2, minDistance, LightDir, dist, 0);
|
||||||
|
attenuation += payload.hitAttenuation;
|
||||||
|
}
|
||||||
|
attenuation *= 1.0 / float(SampleCount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 2, 0, 2, origin, minDistance, LightDir, dist, 0);
|
||||||
|
attenuation = payload.hitAttenuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
incoming.rgb += LightColor * (attenuation * LightIntensity) * incoming.w;
|
||||||
|
imageStore(outputs, texelPos, incoming);
|
||||||
|
}
|
||||||
|
|
||||||
float RadicalInverse_VdC(uint bits)
|
float RadicalInverse_VdC(uint bits)
|
||||||
{
|
{
|
||||||
bits = (bits << 16u) | (bits >> 16u);
|
bits = (bits << 16u) | (bits >> 16u);
|
||||||
|
@ -44,47 +110,4 @@ vec2 Hammersley(uint i, uint N)
|
||||||
return vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
return vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
ivec2 texelPos = ivec2(gl_LaunchIDEXT.xy);
|
|
||||||
vec4 data0 = imageLoad(positions, texelPos);
|
|
||||||
vec4 data1 = imageLoad(normals, texelPos);
|
|
||||||
if (data1 == vec4(0))
|
|
||||||
return;
|
|
||||||
|
|
||||||
vec3 origin = data0.xyz;
|
|
||||||
vec3 normal = data1.xyz;
|
|
||||||
|
|
||||||
vec4 emittance = vec4(0.0);
|
|
||||||
if (PassType == 1.0)
|
|
||||||
emittance = imageLoad(outputs, texelPos);
|
|
||||||
|
|
||||||
const float minDistance = 0.01;
|
|
||||||
const uint sample_count = 1024;
|
|
||||||
|
|
||||||
vec3 e0 = cross(normal, abs(normal.x) < abs(normal.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0));
|
|
||||||
vec3 e1 = cross(normal, e0);
|
|
||||||
e0 = cross(normal, e1);
|
|
||||||
|
|
||||||
origin += normal * 0.1;
|
|
||||||
|
|
||||||
float attenuation = 0.0;
|
|
||||||
for (uint i = 0; i < sample_count; i++)
|
|
||||||
{
|
|
||||||
vec2 offset = (Hammersley(i, sample_count) - 0.5) * SampleDistance;
|
|
||||||
vec3 origin2 = origin + offset.x * e0 + offset.y * e1;
|
|
||||||
|
|
||||||
float dist2 = 32768.0;
|
|
||||||
vec3 dir2 = LightSpotDir;
|
|
||||||
|
|
||||||
traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 2, 0, 2, origin2, minDistance, dir2, dist2, 0);
|
|
||||||
attenuation += payload.hitAttenuation;
|
|
||||||
}
|
|
||||||
attenuation *= 1.0 / float(sample_count);
|
|
||||||
emittance.rgb += LightColor * (attenuation * LightIntensity);
|
|
||||||
|
|
||||||
emittance.w += 1.0;
|
|
||||||
imageStore(outputs, texelPos, emittance);
|
|
||||||
}
|
|
||||||
|
|
||||||
)glsl";
|
)glsl";
|
||||||
|
|
|
@ -5,7 +5,9 @@ static const char* glsl_rmiss_bounce = R"glsl(
|
||||||
|
|
||||||
struct hitPayload
|
struct hitPayload
|
||||||
{
|
{
|
||||||
|
vec3 hitPosition;
|
||||||
float hitAttenuation;
|
float hitAttenuation;
|
||||||
|
int hitSurfaceIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload payload;
|
layout(location = 0) rayPayloadInEXT hitPayload payload;
|
||||||
|
|
|
@ -5,7 +5,9 @@ static const char* glsl_rmiss_light = R"glsl(
|
||||||
|
|
||||||
struct hitPayload
|
struct hitPayload
|
||||||
{
|
{
|
||||||
|
vec3 hitPosition;
|
||||||
float hitAttenuation;
|
float hitAttenuation;
|
||||||
|
int hitSurfaceIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload payload;
|
layout(location = 0) rayPayloadInEXT hitPayload payload;
|
||||||
|
|
|
@ -5,7 +5,9 @@ static const char* glsl_rmiss_sun = R"glsl(
|
||||||
|
|
||||||
struct hitPayload
|
struct hitPayload
|
||||||
{
|
{
|
||||||
|
vec3 hitPosition;
|
||||||
float hitAttenuation;
|
float hitAttenuation;
|
||||||
|
int hitSurfaceIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload payload;
|
layout(location = 0) rayPayloadInEXT hitPayload payload;
|
||||||
|
|
|
@ -76,36 +76,62 @@ void GPURaytracer::Raytrace(LevelMesh* level)
|
||||||
|
|
||||||
UploadTasks(tasks);
|
UploadTasks(tasks);
|
||||||
|
|
||||||
// Sunlight
|
Uniforms uniforms = {};
|
||||||
{
|
uniforms.SampleDistance = (float)mesh->samples;
|
||||||
Uniforms uniforms = {};
|
uniforms.SampleCount = SAMPLE_COUNT;
|
||||||
uniforms.LightOrigin = Vec3(0.0f, 0.0f, 0.0f);
|
|
||||||
uniforms.LightRadius = -1.0f;
|
uniforms.SampleIndex = 0;
|
||||||
uniforms.LightIntensity = 1.0f;
|
uniforms.PassType = 0;
|
||||||
uniforms.LightInnerAngleCos = -1.0f;
|
RunTrace(uniforms, rgenBounceRegion);
|
||||||
uniforms.LightOuterAngleCos = -1.0f;
|
|
||||||
uniforms.LightSpotDir = mesh->map->GetSunDirection();
|
uniforms.LightDir = mesh->map->GetSunDirection();
|
||||||
uniforms.LightColor = mesh->map->GetSunColor();
|
uniforms.LightColor = mesh->map->GetSunColor();
|
||||||
uniforms.PassType = 0.0f;
|
uniforms.LightIntensity = 1.0f;
|
||||||
uniforms.SampleDistance = (float)mesh->samples;
|
RunTrace(uniforms, rgenSunRegion);
|
||||||
RunTrace(uniforms, rgenSunRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ThingLight& light : mesh->map->ThingLights)
|
for (ThingLight& light : mesh->map->ThingLights)
|
||||||
{
|
{
|
||||||
Uniforms uniforms = {};
|
|
||||||
uniforms.LightOrigin = light.LightOrigin();
|
uniforms.LightOrigin = light.LightOrigin();
|
||||||
uniforms.LightRadius = light.LightRadius();
|
uniforms.LightRadius = light.LightRadius();
|
||||||
uniforms.LightIntensity = light.intensity;
|
uniforms.LightIntensity = light.intensity;
|
||||||
uniforms.LightInnerAngleCos = light.innerAngleCos;
|
uniforms.LightInnerAngleCos = light.innerAngleCos;
|
||||||
uniforms.LightOuterAngleCos = light.outerAngleCos;
|
uniforms.LightOuterAngleCos = light.outerAngleCos;
|
||||||
uniforms.LightSpotDir = light.SpotDir();
|
uniforms.LightDir = light.SpotDir();
|
||||||
uniforms.LightColor = light.rgb;
|
uniforms.LightColor = light.rgb;
|
||||||
uniforms.PassType = 1.0f;
|
|
||||||
uniforms.SampleDistance = (float)mesh->samples;
|
|
||||||
RunTrace(uniforms, rgenLightRegion);
|
RunTrace(uniforms, rgenLightRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < uniforms.SampleCount; i++)
|
||||||
|
{
|
||||||
|
uniforms.PassType = 1;
|
||||||
|
uniforms.SampleIndex = i;
|
||||||
|
RunTrace(uniforms, rgenBounceRegion);
|
||||||
|
|
||||||
|
for (int bounce = 0; bounce < LightBounce; bounce++)
|
||||||
|
{
|
||||||
|
uniforms.LightDir = mesh->map->GetSunDirection();
|
||||||
|
uniforms.LightColor = mesh->map->GetSunColor();
|
||||||
|
uniforms.LightIntensity = 1.0f;
|
||||||
|
RunTrace(uniforms, rgenSunRegion);
|
||||||
|
|
||||||
|
for (ThingLight& light : mesh->map->ThingLights)
|
||||||
|
{
|
||||||
|
uniforms.LightOrigin = light.LightOrigin();
|
||||||
|
uniforms.LightRadius = light.LightRadius();
|
||||||
|
uniforms.LightIntensity = light.intensity;
|
||||||
|
uniforms.LightInnerAngleCos = light.innerAngleCos;
|
||||||
|
uniforms.LightOuterAngleCos = light.outerAngleCos;
|
||||||
|
uniforms.LightDir = light.SpotDir();
|
||||||
|
uniforms.LightColor = light.rgb;
|
||||||
|
RunTrace(uniforms, rgenLightRegion);
|
||||||
|
}
|
||||||
|
|
||||||
|
uniforms.PassType = 2;
|
||||||
|
uniforms.SampleIndex = (i + bounce) % uniforms.SampleCount;
|
||||||
|
RunTrace(uniforms, rgenBounceRegion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DownloadTasks(tasks);
|
DownloadTasks(tasks);
|
||||||
|
|
||||||
if (device->renderdoc)
|
if (device->renderdoc)
|
||||||
|
@ -139,9 +165,8 @@ void GPURaytracer::UploadTasks(const std::vector<SurfaceTask>& tasks)
|
||||||
throw std::runtime_error("Ray trace task count is too large");
|
throw std::runtime_error("Ray trace task count is too large");
|
||||||
|
|
||||||
size_t imageSize = sizeof(Vec4) * rayTraceImageSize * rayTraceImageSize;
|
size_t imageSize = sizeof(Vec4) * rayTraceImageSize * rayTraceImageSize;
|
||||||
uint8_t* imageData = (uint8_t*)imageTransferBuffer->Map(0, imageSize * 2);
|
uint8_t* imageData = (uint8_t*)imageTransferBuffer->Map(0, imageSize);
|
||||||
Vec4* positions = (Vec4*)imageData;
|
Vec4* startPositions = (Vec4*)imageData;
|
||||||
Vec4* normals = (Vec4*)(imageData + imageSize);
|
|
||||||
for (size_t i = 0; i < tasks.size(); i++)
|
for (size_t i = 0; i < tasks.size(); i++)
|
||||||
{
|
{
|
||||||
const SurfaceTask& task = tasks[i];
|
const SurfaceTask& task = tasks[i];
|
||||||
|
@ -150,19 +175,16 @@ void GPURaytracer::UploadTasks(const std::vector<SurfaceTask>& tasks)
|
||||||
Vec3 normal = surface->plane.Normal();
|
Vec3 normal = surface->plane.Normal();
|
||||||
Vec3 pos = surface->lightmapOrigin + normal + surface->lightmapSteps[0] * (float)task.x + surface->lightmapSteps[1] * (float)task.y;
|
Vec3 pos = surface->lightmapOrigin + normal + surface->lightmapSteps[0] * (float)task.x + surface->lightmapSteps[1] * (float)task.y;
|
||||||
|
|
||||||
positions[i] = Vec4(pos, 1.0f);
|
startPositions[i] = Vec4(pos, (float)task.surf);
|
||||||
normals[i] = Vec4(normal, 1.0f);
|
|
||||||
}
|
}
|
||||||
for (size_t i = tasks.size(); i < maxTasks; i++)
|
for (size_t i = tasks.size(); i < maxTasks; i++)
|
||||||
{
|
{
|
||||||
positions[i] = Vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
startPositions[i] = Vec4(0.0f, 0.0f, 0.0f, -1.0f);
|
||||||
normals[i] = Vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
|
||||||
}
|
}
|
||||||
imageTransferBuffer->Unmap();
|
imageTransferBuffer->Unmap();
|
||||||
|
|
||||||
PipelineBarrier barrier1;
|
PipelineBarrier barrier1;
|
||||||
barrier1.addImage(positionsImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT);
|
barrier1.addImage(startPositionsImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||||
barrier1.addImage(normalsImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT);
|
|
||||||
barrier1.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
barrier1.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||||
|
|
||||||
VkBufferImageCopy region = {};
|
VkBufferImageCopy region = {};
|
||||||
|
@ -172,21 +194,12 @@ void GPURaytracer::UploadTasks(const std::vector<SurfaceTask>& tasks)
|
||||||
region.imageExtent.depth = 1;
|
region.imageExtent.depth = 1;
|
||||||
region.imageSubresource.layerCount = 1;
|
region.imageSubresource.layerCount = 1;
|
||||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
cmdbuffer->copyBufferToImage(imageTransferBuffer->buffer, positionsImage->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
cmdbuffer->copyBufferToImage(imageTransferBuffer->buffer, startPositionsImage->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||||
|
|
||||||
region = {};
|
|
||||||
region.bufferOffset = imageSize;
|
|
||||||
region.imageExtent.width = rayTraceImageSize;
|
|
||||||
region.imageExtent.height = rayTraceImageSize;
|
|
||||||
region.imageExtent.depth = 1;
|
|
||||||
region.imageSubresource.layerCount = 1;
|
|
||||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
cmdbuffer->copyBufferToImage(imageTransferBuffer->buffer, normalsImage->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
|
||||||
|
|
||||||
PipelineBarrier barrier2;
|
PipelineBarrier barrier2;
|
||||||
barrier2.addBuffer(uniformBuffer.get(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
|
barrier2.addBuffer(uniformBuffer.get(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
|
||||||
barrier2.addImage(positionsImage.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
|
barrier2.addImage(startPositionsImage.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
|
||||||
barrier2.addImage(normalsImage.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
|
barrier2.addImage(positionsImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 0, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
|
||||||
barrier2.addImage(outputImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 0, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
|
barrier2.addImage(outputImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 0, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
|
||||||
barrier2.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
|
barrier2.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
|
||||||
}
|
}
|
||||||
|
@ -303,7 +316,7 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
|
||||||
info.Normal = surface->plane.Normal();
|
info.Normal = surface->plane.Normal();
|
||||||
if (def)
|
if (def)
|
||||||
{
|
{
|
||||||
info.EmissiveDistance = def->distance;
|
info.EmissiveDistance = def->distance + def->distance;
|
||||||
info.EmissiveIntensity = def->intensity;
|
info.EmissiveIntensity = def->intensity;
|
||||||
info.EmissiveColor = def->rgb;
|
info.EmissiveColor = def->rgb;
|
||||||
}
|
}
|
||||||
|
@ -611,7 +624,7 @@ void GPURaytracer::CreatePipeline()
|
||||||
setbuilder.addBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
setbuilder.addBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
||||||
setbuilder.addBinding(4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
setbuilder.addBinding(4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
||||||
setbuilder.addBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
setbuilder.addBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||||
setbuilder.addBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
setbuilder.addBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||||
descriptorSetLayout = setbuilder.create(device.get());
|
descriptorSetLayout = setbuilder.create(device.get());
|
||||||
descriptorSetLayout->SetDebugName("descriptorSetLayout");
|
descriptorSetLayout->SetDebugName("descriptorSetLayout");
|
||||||
|
|
||||||
|
@ -750,15 +763,15 @@ void GPURaytracer::CreateDescriptorSet()
|
||||||
imgbuilder1.setUsage(VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
imgbuilder1.setUsage(VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||||
imgbuilder1.setFormat(VK_FORMAT_R32G32B32A32_SFLOAT);
|
imgbuilder1.setFormat(VK_FORMAT_R32G32B32A32_SFLOAT);
|
||||||
imgbuilder1.setSize(rayTraceImageSize, rayTraceImageSize);
|
imgbuilder1.setSize(rayTraceImageSize, rayTraceImageSize);
|
||||||
positionsImage = imgbuilder1.create(device.get());
|
startPositionsImage = imgbuilder1.create(device.get());
|
||||||
positionsImage->SetDebugName("positionsImage");
|
startPositionsImage->SetDebugName("startPositionsImage");
|
||||||
|
|
||||||
ImageBuilder imgbuilder2;
|
ImageBuilder imgbuilder2;
|
||||||
imgbuilder2.setUsage(VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
imgbuilder2.setUsage(VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||||
imgbuilder2.setFormat(VK_FORMAT_R32G32B32A32_SFLOAT);
|
imgbuilder2.setFormat(VK_FORMAT_R32G32B32A32_SFLOAT);
|
||||||
imgbuilder2.setSize(rayTraceImageSize, rayTraceImageSize);
|
imgbuilder2.setSize(rayTraceImageSize, rayTraceImageSize);
|
||||||
normalsImage = imgbuilder2.create(device.get());
|
positionsImage = imgbuilder2.create(device.get());
|
||||||
normalsImage->SetDebugName("normalsImage");
|
positionsImage->SetDebugName("positionsImage");
|
||||||
|
|
||||||
ImageBuilder imgbuilder3;
|
ImageBuilder imgbuilder3;
|
||||||
imgbuilder3.setUsage(VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
|
imgbuilder3.setUsage(VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
|
||||||
|
@ -768,14 +781,14 @@ void GPURaytracer::CreateDescriptorSet()
|
||||||
outputImage->SetDebugName("outputImage");
|
outputImage->SetDebugName("outputImage");
|
||||||
|
|
||||||
ImageViewBuilder viewbuilder1;
|
ImageViewBuilder viewbuilder1;
|
||||||
viewbuilder1.setImage(positionsImage.get(), VK_FORMAT_R32G32B32A32_SFLOAT);
|
viewbuilder1.setImage(startPositionsImage.get(), VK_FORMAT_R32G32B32A32_SFLOAT);
|
||||||
positionsImageView = viewbuilder1.create(device.get());
|
startPositionsImageView = viewbuilder1.create(device.get());
|
||||||
positionsImageView->SetDebugName("positionsImageView");
|
startPositionsImageView->SetDebugName("startPositionsImageView");
|
||||||
|
|
||||||
ImageViewBuilder viewbuilder2;
|
ImageViewBuilder viewbuilder2;
|
||||||
viewbuilder2.setImage(normalsImage.get(), VK_FORMAT_R32G32B32A32_SFLOAT);
|
viewbuilder2.setImage(positionsImage.get(), VK_FORMAT_R32G32B32A32_SFLOAT);
|
||||||
normalsImageView = viewbuilder2.create(device.get());
|
positionsImageView = viewbuilder2.create(device.get());
|
||||||
normalsImageView->SetDebugName("normalsImageView");
|
positionsImageView->SetDebugName("positionsImageView");
|
||||||
|
|
||||||
ImageViewBuilder viewbuilder3;
|
ImageViewBuilder viewbuilder3;
|
||||||
viewbuilder3.setImage(outputImage.get(), VK_FORMAT_R32G32B32A32_SFLOAT);
|
viewbuilder3.setImage(outputImage.get(), VK_FORMAT_R32G32B32A32_SFLOAT);
|
||||||
|
@ -796,8 +809,8 @@ void GPURaytracer::CreateDescriptorSet()
|
||||||
|
|
||||||
WriteDescriptors write;
|
WriteDescriptors write;
|
||||||
write.addAccelerationStructure(descriptorSet.get(), 0, tlAccelStruct.get());
|
write.addAccelerationStructure(descriptorSet.get(), 0, tlAccelStruct.get());
|
||||||
write.addStorageImage(descriptorSet.get(), 1, positionsImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
write.addStorageImage(descriptorSet.get(), 1, startPositionsImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
||||||
write.addStorageImage(descriptorSet.get(), 2, normalsImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
write.addStorageImage(descriptorSet.get(), 2, positionsImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
||||||
write.addStorageImage(descriptorSet.get(), 3, outputImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
write.addStorageImage(descriptorSet.get(), 3, outputImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
||||||
write.addBuffer(descriptorSet.get(), 4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uniformBuffer.get());
|
write.addBuffer(descriptorSet.get(), 4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uniformBuffer.get());
|
||||||
write.addBuffer(descriptorSet.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceIndexBuffer.get());
|
write.addBuffer(descriptorSet.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceIndexBuffer.get());
|
||||||
|
@ -982,7 +995,7 @@ Vec3 GPURaytracer::TracePath(const Vec3& pos, const Vec3& dir, int sampleIndex,
|
||||||
return emittance;
|
return emittance;
|
||||||
|
|
||||||
const float p = 1 / (2 * M_PI);
|
const float p = 1 / (2 * M_PI);
|
||||||
Vec3 incoming = TracePath(hitpos, normal, (sampleIndex + depth + 1) % SAMPLE_COUNT, depth + 1);
|
Vec3 incoming = TracePath(hitpos, L, (sampleIndex + depth + 1) % SAMPLE_COUNT, depth + 1);
|
||||||
|
|
||||||
return emittance + incoming * NdotL / p;
|
return emittance + incoming * NdotL / p;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,16 +8,20 @@ class LevelMesh;
|
||||||
|
|
||||||
struct Uniforms
|
struct Uniforms
|
||||||
{
|
{
|
||||||
|
uint32_t SampleIndex;
|
||||||
|
uint32_t SampleCount;
|
||||||
|
uint32_t PassType;
|
||||||
|
uint32_t Padding2;
|
||||||
Vec3 LightOrigin;
|
Vec3 LightOrigin;
|
||||||
float PassType;
|
float Padding0;
|
||||||
float LightRadius;
|
float LightRadius;
|
||||||
float LightIntensity;
|
float LightIntensity;
|
||||||
float LightInnerAngleCos;
|
float LightInnerAngleCos;
|
||||||
float LightOuterAngleCos;
|
float LightOuterAngleCos;
|
||||||
Vec3 LightSpotDir;
|
Vec3 LightDir;
|
||||||
float SampleDistance;
|
float SampleDistance;
|
||||||
Vec3 LightColor;
|
Vec3 LightColor;
|
||||||
float Padding;
|
float Padding1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SurfaceInfo
|
struct SurfaceInfo
|
||||||
|
@ -110,8 +114,8 @@ private:
|
||||||
VkStridedDeviceAddressRegionKHR hitRegion = {};
|
VkStridedDeviceAddressRegionKHR hitRegion = {};
|
||||||
VkStridedDeviceAddressRegionKHR callRegion = {};
|
VkStridedDeviceAddressRegionKHR callRegion = {};
|
||||||
|
|
||||||
std::unique_ptr<VulkanImage> positionsImage, normalsImage, outputImage;
|
std::unique_ptr<VulkanImage> startPositionsImage, positionsImage, outputImage;
|
||||||
std::unique_ptr<VulkanImageView> positionsImageView, normalsImageView, outputImageView;
|
std::unique_ptr<VulkanImageView> startPositionsImageView, positionsImageView, outputImageView;
|
||||||
std::unique_ptr<VulkanBuffer> imageTransferBuffer;
|
std::unique_ptr<VulkanBuffer> imageTransferBuffer;
|
||||||
|
|
||||||
std::unique_ptr<VulkanBuffer> uniformBuffer;
|
std::unique_ptr<VulkanBuffer> uniformBuffer;
|
||||||
|
|
|
@ -220,7 +220,7 @@ Vec3 Raytracer::TracePath(const Vec3& pos, const Vec3& dir, int sampleIndex, int
|
||||||
return emittance;
|
return emittance;
|
||||||
|
|
||||||
const float p = 1 / (2 * M_PI);
|
const float p = 1 / (2 * M_PI);
|
||||||
Vec3 incoming = TracePath(hitpos, normal, (sampleIndex + depth + 1) % SAMPLE_COUNT, depth + 1);
|
Vec3 incoming = TracePath(hitpos, L, (sampleIndex + depth + 1) % SAMPLE_COUNT, depth + 1);
|
||||||
|
|
||||||
return emittance + incoming * NdotL / p;
|
return emittance + incoming * NdotL / p;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue