Skip to content
Snippets Groups Projects
Commit 1a2f45bc authored by Alexander Gauggel's avatar Alexander Gauggel
Browse files

[#94] Intersection now returns closest hit, removed unnecessary extra material...

[#94] Intersection now returns closest hit, removed unnecessary extra material buffer in shader and refactored entire raytracing compute shader
parent 31fb4cf7
No related branches found
No related tags found
1 merge request!77Resolve "SAF-R Module"
#version 450 core #version 450 core
#extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_separate_shader_objects : enable
#define M_PI 3.1415926535897932384626433832795 const float pi = 3.1415926535897932384626433832795;
const float hitBias = 0.0001; // used to offset hits to avoid self intersection
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
...@@ -26,15 +27,11 @@ layout(std430, binding = 0) coherent buffer lights{ ...@@ -26,15 +27,11 @@ layout(std430, binding = 0) coherent buffer lights{
Light inLights[]; Light inLights[];
}; };
layout(std430, binding = 1) coherent buffer materials{ layout(std430, binding = 1) coherent buffer spheres{
Material inMaterials[];
};
layout(std430, binding = 2) coherent buffer spheres{
Sphere inSpheres[]; Sphere inSpheres[];
}; };
layout(set=0, binding=3, rgba8) uniform image2D outImage; layout(set=0, binding = 2, rgba8) uniform image2D outImage;
layout( push_constant ) uniform constants{ layout( push_constant ) uniform constants{
float lightCount; float lightCount;
...@@ -42,116 +39,141 @@ layout( push_constant ) uniform constants{ ...@@ -42,116 +39,141 @@ layout( push_constant ) uniform constants{
float sphereCount; float sphereCount;
}; };
vec3 safr_reflect(const vec3 dir, const vec3 hit_center) {
return dir - hit_center * 2.f * (dot(dir, hit_center));
}
bool ray_intersect(const vec3 origin, const vec3 dir, out float t0, const int id){ bool ray_intersect(const vec3 origin, const vec3 dir, out float t0, const int id){
vec3 L = inSpheres[id].center - origin; vec3 L = inSpheres[id].center - origin;
float tca = dot(L, dir); float tca = dot(L, dir);
float d2 = dot(L, L) - tca * tca; float d2 = dot(L, L) - tca * tca;
if (d2 > inSpheres[id].radius * inSpheres[id].radius){ if (d2 > inSpheres[id].radius * inSpheres[id].radius){
return false; return false;
} }
float thc = float(sqrt(inSpheres[id].radius * inSpheres[id].radius - d2)); float thc = float(sqrt(inSpheres[id].radius * inSpheres[id].radius - d2));
t0 = tca - thc; t0 = tca - thc;
float t1 = tca + thc; float t1 = tca + thc;
if (t0 < 0) { if (t0 < 0) {
t0 = t1; t0 = t1;
} }
if (t0 < 0){ if (t0 < 0){
return false; return false;
} }
return true; return true;
} }
bool sceneIntersect(const vec3 orig, const vec3 dir, out vec3 hit, out vec3 hit_center, out Material material) { struct Intersection{
float spheres_dist = 1.0 / 0.0; bool hit;
vec3 pos;
vec3 N;
Material material;
};
Intersection sceneIntersect(const vec3 rayOrigin, const vec3 rayDirection) {
float min_d = 100000; // lets start with something big
Intersection intersection;
intersection.hit = false;
for (int i = 0; i < sphereCount; i++) { for (int i = 0; i < sphereCount; i++) {
float dist_i; float d;
if (ray_intersect(orig, dir, dist_i, i) && dist_i < spheres_dist) { if (ray_intersect(rayOrigin, rayDirection, d, i)) {
spheres_dist = dist_i;
hit = orig + dir * dist_i; intersection.hit = true;
hit_center = normalize(hit - inSpheres[i].center);
material = inSpheres[i].material; if(d < min_d){
break; min_d = d;
intersection.pos = rayOrigin + rayDirection * d;
intersection.N = normalize(intersection.pos - inSpheres[i].center);
intersection.material = inSpheres[i].material;
}
} }
} }
return spheres_dist < 1000; return intersection;
} }
vec3 biasHitPosition(vec3 hitPos, vec3 rayDirection, vec3 N){
// return hitPos + N * hitBias; // works as long as no refraction/transmission is used and camera is outside sphere
return hitPos + sign(dot(rayDirection, N)) * N * hitBias;
}
vec3 castRay(const vec3 orig, const vec3 dir, int max_depth) { vec3 computeHitLighting(Intersection intersection, vec3 V, out float outReflectionThroughput){
float lightIntensityDiffuse = 0;
float lightIntensitySpecular = 0;
for (int i = 0; i < lightCount; i++) {
vec3 L = normalize(inLights[i].position - intersection.pos);
float d = distance(inLights[i].position, intersection.pos);
vec3 shadowOrigin = biasHitPosition(intersection.pos, L, intersection.N);
Intersection shadowIntersection = sceneIntersect(shadowOrigin, L);
bool isShadowed = false;
if(shadowIntersection.hit)
isShadowed = distance(shadowIntersection.pos, shadowOrigin) < d;
if(isShadowed)
continue;
lightIntensityDiffuse += inLights[i].intensity * max(0.f, dot(L, intersection.N));
lightIntensitySpecular += pow(max(0.f, dot(reflect(V, intersection.N), L)), intersection.material.specular_exponent) * inLights[i].intensity;
}
int depth = 0; outReflectionThroughput = intersection.material.albedo[2];
vec3 point, hit_center; return intersection.material.diffuse_color * lightIntensityDiffuse * intersection.material.albedo[0] + lightIntensitySpecular * intersection.material.albedo[1];
Material material; }
vec3 result = vec3(0.2, 0.7, 0.8);
bool intersect; vec3 castRay(const vec3 initialOrigin, const vec3 initialDirection, int max_depth) {
vec3 direction = dir;
vec3 reflect_dir = direction; vec3 skyColor = vec3(0.2, 0.7, 0.8);
vec3 reflect_orig = orig;
vec3 rayOrigin = initialOrigin;
vec3 rayDirection = initialDirection;
float reflectionThroughput = 1;
vec3 color = vec3(0);
for(int i = 0; i < max_depth; i++){ for(int i = 0; i < max_depth; i++){
depth++;
intersect = sceneIntersect(reflect_orig, reflect_dir, point, hit_center, material); Intersection intersection = sceneIntersect(rayOrigin, rayDirection);
if(!intersect){
break; vec3 hitColor;
float hitReflectionThroughput;
if(intersection.hit){
hitColor = computeHitLighting(intersection, rayDirection, hitReflectionThroughput);
} }
//compute recursive directions and origins of rays and then call the function else{
reflect_dir = normalize(safr_reflect(direction, hit_center)); hitColor = skyColor;
reflect_orig = (dot(reflect_dir, hit_center) < 0) ? point - hit_center * float(1e-3) : point + hit_center * float(1e-3);// offset the original point to avoid occlusion by the object itself }
direction = reflect_dir;
} color += hitColor * reflectionThroughput;
if (depth == 1){ reflectionThroughput *= hitReflectionThroughput;
return result;
} if(!intersection.hit)
break;
vec3 reflect_color = result; rayDirection = normalize(reflect(rayDirection, intersection.N));
for(int i = 0; i < depth; i++){ rayOrigin = biasHitPosition(intersection.pos, rayDirection, intersection.N);
//compute shadows and other light properties for the returned ray color
float diffuse_light_intensity = 0, specular_light_intensity = 0;
for (int i = 0; i < lightCount; i++) {
vec3 light_dir = normalize(inLights[i].position - point);
float light_distance = distance(inLights[i].position, point);
vec3 shadow_orig = (dot(light_dir, hit_center) < 0) ? point - hit_center * float(1e-3) :
point + hit_center * float(1e-3);// checking if the point lies in the shadow of the lights[i]
vec3 shadow_pt, shadow_hit_center;
Material tmpmaterial;
if (sceneIntersect(shadow_orig, light_dir, shadow_pt, shadow_hit_center, tmpmaterial)
&& distance(shadow_pt, shadow_orig) < light_distance){
continue;
}
diffuse_light_intensity += inLights[i].intensity * max(0.f, dot(light_dir, hit_center));
specular_light_intensity += pow(max(0.f, dot(safr_reflect(light_dir, hit_center), dir)), material.specular_exponent) * inLights[i].intensity;
}
return result = material.diffuse_color * diffuse_light_intensity * material.albedo[0] +
vec3(1., 1., 1.) * specular_light_intensity * material.albedo[1] + reflect_color * material.albedo[2];
} }
return result;
return color;
} }
vec3 computeDirection(ivec2 coord){ vec3 computeDirection(ivec2 coord){
ivec2 outImageRes = imageSize(outImage); ivec2 outImageRes = imageSize(outImage);
float fov = M_PI / 2.f; float fov = pi / 2.f;
//float x = (2 * (i + 0.5f) / (float)width - 1) * tan(fov / 2.f) * width / (float)height; float x = (2 * (float(coord.x) + 0.5f) / float(outImageRes.x) - 1) * tan(fov / 2.f) * outImageRes.x / float(outImageRes.y);
float x = (2 * (float(coord.x) + 0.5f) / float(outImageRes.x) - 1) * tan(fov / 2.f) * outImageRes.x / float(outImageRes.y); float y = -(2 * (float(coord.y) + 0.5f) / float(outImageRes.y) - 1) * tan(fov / 2.f);
//float y = -(2 * (j + 0.5f) / (float)height - 1) * tan(fov / 2.f); return normalize(vec3(x, y, -1));
float y = -(2 * (float(coord.y) + 0.5f) / float(outImageRes.y) - 1) * tan(fov / 2.f);
vec3 dir = normalize(vec3(x, y, -1));
return dir;
} }
void main(){ void main(){
ivec2 coord = ivec2(gl_GlobalInvocationID.xy); ivec2 coord = ivec2(gl_GlobalInvocationID.xy);
int max_depth = 4; int max_depth = 4;
vec3 direction = computeDirection(coord); vec3 direction = computeDirection(coord);
vec3 color = castRay(vec3(0,0,0), direction, max_depth); vec3 color = castRay(vec3(0,0,0), direction, max_depth);
imageStore(outImage, coord, vec4(color, 0.f)); imageStore(outImage, coord, vec4(color, 0.f));
} }
\ No newline at end of file
...@@ -133,12 +133,6 @@ int main(int argc, const char** argv) { ...@@ -133,12 +133,6 @@ int main(int argc, const char** argv) {
); );
sphereBuffer.fill(spheres); sphereBuffer.fill(spheres);
vkcv::Buffer<safrScene::Material> materialBuffer = core.createBuffer<safrScene::Material>(
vkcv::BufferType::STORAGE,
materials.size()
);
materialBuffer.fill(materials);
glm::vec3 pushData = glm::vec3((lights.size()), (materials.size()), (spheres.size())); glm::vec3 pushData = glm::vec3((lights.size()), (materials.size()), (spheres.size()));
vkcv::PushConstants pushConstantsCompute(sizeof(glm::vec3)); vkcv::PushConstants pushConstantsCompute(sizeof(glm::vec3));
pushConstantsCompute.appendDrawcall(pushData); pushConstantsCompute.appendDrawcall(pushData);
...@@ -150,8 +144,7 @@ int main(int argc, const char** argv) { ...@@ -150,8 +144,7 @@ int main(int argc, const char** argv) {
vkcv::DescriptorWrites computeWrites; vkcv::DescriptorWrites computeWrites;
computeWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0,lightsBuffer.getHandle()), computeWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0,lightsBuffer.getHandle()),
vkcv::BufferDescriptorWrite(1,materialBuffer.getHandle()), vkcv::BufferDescriptorWrite(1,sphereBuffer.getHandle())};
vkcv::BufferDescriptorWrite(2,sphereBuffer.getHandle())};
core.writeDescriptorSet(computeDescriptorSet, computeWrites); core.writeDescriptorSet(computeDescriptorSet, computeWrites);
const auto& context = core.getContext(); const auto& context = core.getContext();
...@@ -222,7 +215,6 @@ int main(int argc, const char** argv) { ...@@ -222,7 +215,6 @@ int main(int argc, const char** argv) {
continue; continue;
} }
auto end = std::chrono::system_clock::now(); auto end = std::chrono::system_clock::now();
auto deltatime = std::chrono::duration_cast<std::chrono::microseconds>(end - start); auto deltatime = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
start = end; start = end;
...@@ -236,7 +228,7 @@ int main(int argc, const char** argv) { ...@@ -236,7 +228,7 @@ int main(int argc, const char** argv) {
auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
computeWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(3, swapchainInput)}; computeWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, swapchainInput)};
core.writeDescriptorSet(computeDescriptorSet, computeWrites); core.writeDescriptorSet(computeDescriptorSet, computeWrites);
core.prepareImageForStorage (cmdStream, swapchainInput); core.prepareImageForStorage (cmdStream, swapchainInput);
...@@ -252,14 +244,6 @@ int main(int argc, const char** argv) { ...@@ -252,14 +244,6 @@ int main(int argc, const char** argv) {
core.recordBufferMemoryBarrier(cmdStream, lightsBuffer.getHandle()); core.recordBufferMemoryBarrier(cmdStream, lightsBuffer.getHandle());
/*core.recordDrawcallsToCmdStream(
cmdStream,
safrPass,
safrPipeline,
pushConstants,
{ drawcall },
{ swapchainInput });*/
core.prepareSwapchainImageForPresent(cmdStream); core.prepareSwapchainImageForPresent(cmdStream);
core.submitCommandStream(cmdStream); core.submitCommandStream(cmdStream);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment