summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAiden Gall <aiden@aidengall.xyz>2024-02-04 21:50:16 +0000
committerAiden Gall <aiden@aidengall.xyz>2024-02-04 22:20:33 +0000
commitc0fb8bf2d8e25308eadff659564ad9600e5cb369 (patch)
treed4d33f069bc93dd01ea1912be4fc682be16f742a
parentc44d2805ba480fc7c2faf8ae07f2c1c9febf7e34 (diff)
raytraced background gradient
-rw-r--r--src/cl/spirt.cl46
-rw-r--r--src/spirt.c105
2 files changed, 127 insertions, 24 deletions
diff --git a/src/cl/spirt.cl b/src/cl/spirt.cl
index 12022bb..26bdf00 100644
--- a/src/cl/spirt.cl
+++ b/src/cl/spirt.cl
@@ -13,21 +13,51 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
+#define RAY_ORIG(RAYS, INDEX) (RAYS[INDEX])
+#define RAY_DIR(RAYS, INDEX) (RAYS[INDEX + 1])
+
+__kernel void
+gen_rays(__global float3 *const rays, float3 camera_centre,
+ float3 pixel_delta_u, float3 pixel_delta_v, float3 corner00)
+{
+ size_t idx, w, i, j;
+
+ w = get_global_size(0);
+
+ i = get_global_id(0);
+ j = get_global_id(1);
+
+ idx = (w * j + i) * 2;
+
+ RAY_ORIG(rays, idx) = camera_centre;
+ RAY_DIR(rays, idx) = corner00 +
+ ((i * pixel_delta_u) + (j * pixel_delta_v)) -
+ camera_centre;
+}
+
__kernel void
-hello(__global unsigned char *const canvas)
+ray_colour(__global uchar *const canvas, __global float3 *const rays)
{
- size_t idx, w, h, i, j;
+ size_t canvas_idx, ray_idx, w, i, j;
+ float3 unit_direction, colour;
+ float a;
w = get_global_size(0);
- h = get_global_size(1);
i = get_global_id(0);
j = get_global_id(1);
- idx = (w * j + i) * 4;
+ canvas_idx = (w * j + i) * 4;
+ ray_idx = (w * j + i) * 2;
+
+ unit_direction = normalize(RAY_DIR(rays, ray_idx));
+ a = 0.5f * (unit_direction.y + 1.0f);
+
+ colour = (1.0f - a) * (float3)(1.0f) + a * (float3)(0.5f, 0.7f, 1.0f);
+ colour = 256.0f * clamp(sqrt(colour), 0.0f, 0.999f);
- canvas[idx] = (unsigned char)((255 * i) / (w - 1));
- canvas[idx + 1] = (unsigned char)((255 * j) / (h - 1));
- canvas[idx + 2] = 63;
- canvas[idx + 3] = 255;
+ canvas[canvas_idx] = colour.x;
+ canvas[canvas_idx + 1] = colour.y;
+ canvas[canvas_idx + 2] = colour.z;
+ canvas[canvas_idx + 3] = 255;
}
diff --git a/src/spirt.c b/src/spirt.c
index fd6457b..527981f 100644
--- a/src/spirt.c
+++ b/src/spirt.c
@@ -33,7 +33,8 @@ struct kernel_context {
cl_context context;
cl_command_queue command_queue;
cl_program program;
- cl_kernel k_hello;
+ cl_kernel k_gen_rays;
+ cl_kernel k_ray_colour;
};
struct opts {
@@ -43,8 +44,16 @@ struct opts {
long devidx;
};
-static unsigned char *kernel_hello(struct kernel_context *runtime,
- size_t image_width, size_t image_height);
+struct camera {
+ cl_float3 centre;
+ cl_float3 pixel_delta_u;
+ cl_float3 pixel_delta_v;
+ cl_float3 corner00;
+};
+
+static unsigned char *kernel_render(struct kernel_context *runtime,
+ size_t image_width, size_t image_height,
+ struct camera cam);
static struct kernel_context kernel_context_init(size_t platidx, size_t devidx);
static void kernel_context_clean(struct kernel_context *runtime);
@@ -55,18 +64,24 @@ extern const char *SPIRV_START[];
extern const char *SPIRV_END[];
static unsigned char *
-kernel_hello(struct kernel_context *const runtime, const size_t image_width,
- const size_t image_height)
+kernel_render(struct kernel_context *const runtime, const size_t image_width,
+ const size_t image_height, const struct camera cam)
{
cl_int err;
size_t global_item_size[2];
unsigned char *h_canvas;
- cl_mem d_canvas;
- size_t canvas_size;
+ cl_mem d_canvas, d_rays;
+ size_t rays_size, canvas_size;
canvas_size = (sizeof("RGBA") - 1) * image_width * image_height;
+ rays_size = 2 * image_width * image_height;
+
+ d_rays = clCreateBuffer(runtime->context, CL_MEM_READ_WRITE,
+ sizeof(cl_float3) * rays_size, NULL, &err);
+ if (err != CL_SUCCESS)
+ die("clCreateBuffer: %s\n", cl_strerror(err));
h_canvas = calloc(canvas_size, sizeof(*h_canvas));
if (!h_canvas)
@@ -77,15 +92,38 @@ kernel_hello(struct kernel_context *const runtime, const size_t image_width,
if (err != CL_SUCCESS)
die("clCreateBuffer: %s\n", cl_strerror(err));
- err = clSetKernelArg(runtime->k_hello, 0, sizeof(d_canvas), &d_canvas);
+ err = clSetKernelArg(runtime->k_gen_rays, 0, sizeof(d_rays), &d_rays);
+ err |= clSetKernelArg(runtime->k_gen_rays, 1, sizeof(cl_float3),
+ &cam.centre);
+ err |= clSetKernelArg(runtime->k_gen_rays, 2, sizeof(cl_float3),
+ &cam.pixel_delta_u);
+ err |= clSetKernelArg(runtime->k_gen_rays, 3, sizeof(cl_float3),
+ &cam.pixel_delta_v);
+ err |= clSetKernelArg(runtime->k_gen_rays, 4, sizeof(cl_float3),
+ &cam.corner00);
if (err != CL_SUCCESS)
die("clSetKernelArg: %s\n", cl_strerror(err));
global_item_size[0] = image_width;
global_item_size[1] = image_height;
- err = clEnqueueNDRangeKernel(runtime->command_queue, runtime->k_hello,
- 2, NULL, global_item_size, NULL, 0, NULL,
- NULL);
+ err = clEnqueueNDRangeKernel(runtime->command_queue,
+ runtime->k_gen_rays, 2, NULL,
+ global_item_size, NULL, 0, NULL, NULL);
+ if (err != CL_SUCCESS)
+ die("clEnqueueNDRangeKernel: %s\n", cl_strerror(err));
+
+ err = clSetKernelArg(runtime->k_ray_colour, 0, sizeof(d_canvas),
+ &d_canvas);
+ err |= clSetKernelArg(runtime->k_ray_colour, 1, sizeof(d_rays),
+ &d_rays);
+ if (err != CL_SUCCESS)
+ die("clSetKernelArg: %s\n", cl_strerror(err));
+
+ global_item_size[0] = image_width;
+ global_item_size[1] = image_height;
+ err = clEnqueueNDRangeKernel(runtime->command_queue,
+ runtime->k_ray_colour, 2, NULL,
+ global_item_size, NULL, 0, NULL, NULL);
if (err != CL_SUCCESS)
die("clEnqueueNDRangeKernel: %s\n", cl_strerror(err));
@@ -95,6 +133,7 @@ kernel_hello(struct kernel_context *const runtime, const size_t image_width,
if (err != CL_SUCCESS)
die("clEnqueueReadBuffer: %s\n", cl_strerror(err));
+ clReleaseMemObject(d_rays);
clReleaseMemObject(d_canvas);
return h_canvas;
@@ -138,7 +177,11 @@ kernel_context_init(const size_t platidx, const size_t devidx)
runtime.program = compile_spirv_program(runtime.context, runtime.device,
SPIRV_START, SPIRV_SIZE);
- runtime.k_hello = clCreateKernel(runtime.program, "hello", &err);
+ runtime.k_gen_rays = clCreateKernel(runtime.program, "gen_rays", &err);
+ if (err != CL_SUCCESS)
+ die("clCreateKernel: %s\n", cl_strerror(err));
+ runtime.k_ray_colour =
+ clCreateKernel(runtime.program, "ray_colour", &err);
if (err != CL_SUCCESS)
die("clCreateKernel: %s\n", cl_strerror(err));
@@ -151,7 +194,8 @@ kernel_context_clean(struct kernel_context *const runtime)
clFlush(runtime->command_queue);
clFinish(runtime->command_queue);
- clReleaseKernel(runtime->k_hello);
+ clReleaseKernel(runtime->k_gen_rays);
+ clReleaseKernel(runtime->k_ray_colour);
clReleaseProgram(runtime->program);
clReleaseCommandQueue(runtime->command_queue);
clReleaseContext(runtime->context);
@@ -164,8 +208,8 @@ get_args(int argc, char *argv[])
opts.platidx = 0;
opts.devidx = 0;
- opts.width = 256;
- opts.height = 256;
+ opts.width = 1024;
+ opts.height = 576;
if (argv[0])
argv++, argc--;
@@ -213,6 +257,8 @@ main(int argc, char *argv[])
struct kernel_context runtime;
unsigned char *h_canvas;
+ struct camera cam;
+ float focal_length, viewport_width, viewport_height;
Image img;
Texture2D texture;
@@ -221,7 +267,34 @@ main(int argc, char *argv[])
runtime = kernel_context_init(opts.platidx, opts.devidx);
- h_canvas = kernel_hello(&runtime, opts.width, opts.height);
+ focal_length = 1.0f;
+ viewport_height = 2.0f;
+ viewport_width =
+ viewport_height * ((float)opts.width / (float)opts.height);
+
+ cam.centre.s[0] = 0.0f;
+ cam.centre.s[1] = 0.0f;
+ cam.centre.s[2] = 0.0f;
+
+ cam.pixel_delta_u.s[0] = viewport_width / (float)opts.width;
+ cam.pixel_delta_u.s[1] = 0.0f;
+ cam.pixel_delta_u.s[2] = 0.0f;
+
+ cam.pixel_delta_v.s[0] = 0.0f;
+ cam.pixel_delta_v.s[1] = -viewport_height / (float)opts.height;
+ cam.pixel_delta_v.s[2] = 0.0f;
+
+ cam.corner00.s[0] =
+ cam.centre.s[0] - viewport_width / 2.0f +
+ 0.5f * (cam.pixel_delta_u.s[0] + cam.pixel_delta_v.s[0]);
+ cam.corner00.s[1] =
+ cam.centre.s[1] + viewport_height / 2.0f +
+ 0.5f * (cam.pixel_delta_u.s[1] + cam.pixel_delta_v.s[1]);
+ cam.corner00.s[2] =
+ cam.centre.s[2] - focal_length +
+ 0.5f * (cam.pixel_delta_u.s[2] + cam.pixel_delta_v.s[2]);
+
+ h_canvas = kernel_render(&runtime, opts.width, opts.height, cam);
img.data = h_canvas;
img.width = opts.width;