101 lines
2.7 KiB
Text
101 lines
2.7 KiB
Text
/*
|
|
* Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* SPDX-FileCopyrightText: Copyright (c) 2019-2021 NVIDIA CORPORATION
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#version 460
|
|
#extension GL_EXT_ray_tracing : require
|
|
#extension GL_EXT_nonuniform_qualifier : enable
|
|
#extension GL_EXT_scalar_block_layout : enable
|
|
#extension GL_GOOGLE_include_directive : enable
|
|
#include "raycommon.glsl"
|
|
#include "wavefront.glsl"
|
|
|
|
|
|
layout(binding = 7, set = 1, scalar) buffer allSpheres_
|
|
{
|
|
Sphere allSpheres[];
|
|
};
|
|
|
|
|
|
struct Ray
|
|
{
|
|
vec3 origin;
|
|
vec3 direction;
|
|
};
|
|
|
|
// Ray-Sphere intersection
|
|
// http://viclw17.github.io/2018/07/16/raytracing-ray-sphere-intersection/
|
|
float hitSphere(const Sphere s, const Ray r)
|
|
{
|
|
vec3 oc = r.origin - s.center;
|
|
float a = dot(r.direction, r.direction);
|
|
float b = 2.0 * dot(oc, r.direction);
|
|
float c = dot(oc, oc) - s.radius * s.radius;
|
|
float discriminant = b * b - 4 * a * c;
|
|
if(discriminant < 0)
|
|
{
|
|
return -1.0;
|
|
}
|
|
else
|
|
{
|
|
return (-b - sqrt(discriminant)) / (2.0 * a);
|
|
}
|
|
}
|
|
|
|
// Ray-AABB intersection
|
|
float hitAabb(const Aabb aabb, const Ray r)
|
|
{
|
|
vec3 invDir = 1.0 / r.direction;
|
|
vec3 tbot = invDir * (aabb.minimum - r.origin);
|
|
vec3 ttop = invDir * (aabb.maximum - r.origin);
|
|
vec3 tmin = min(ttop, tbot);
|
|
vec3 tmax = max(ttop, tbot);
|
|
float t0 = max(tmin.x, max(tmin.y, tmin.z));
|
|
float t1 = min(tmax.x, min(tmax.y, tmax.z));
|
|
return t1 > max(t0, 0.0) ? t0 : -1.0;
|
|
}
|
|
|
|
void main()
|
|
{
|
|
Ray ray;
|
|
ray.origin = gl_WorldRayOriginEXT;
|
|
ray.direction = gl_WorldRayDirectionEXT;
|
|
|
|
// Sphere data
|
|
Sphere sphere = allSpheres[gl_PrimitiveID];
|
|
|
|
float tHit = -1;
|
|
int hitKind = gl_PrimitiveID % 2 == 0 ? KIND_SPHERE : KIND_CUBE;
|
|
if(hitKind == KIND_SPHERE)
|
|
{
|
|
// Sphere intersection
|
|
tHit = hitSphere(sphere, ray);
|
|
}
|
|
else
|
|
{
|
|
// AABB intersection
|
|
Aabb aabb;
|
|
aabb.minimum = sphere.center - vec3(sphere.radius);
|
|
aabb.maximum = sphere.center + vec3(sphere.radius);
|
|
tHit = hitAabb(aabb, ray);
|
|
}
|
|
|
|
// Report hit point
|
|
if(tHit > 0)
|
|
reportIntersectionEXT(tHit, hitKind);
|
|
}
|