commit b3e48bafd23ff9eef9e329e4eb87a51b54358031
parent c628c73deac8ebecdb3f3a3322d903c08113af1c
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 8 Mar 2017 15:56:58 +0100
Update the API of the ssol_draw_<draft|pt> functions
Add the number of samples per pixel to the function arguments.
Diffstat:
5 files changed, 139 insertions(+), 48 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -172,6 +172,7 @@ if(NOT NO_TEST)
build_test(test_ssol_draw)
register_test(test_ssol_draw_draft test_ssol_draw draft)
+ register_test(test_ssol_draw_pt test_ssol_draw pt)
endif()
diff --git a/src/ssol.h b/src/ssol.h
@@ -956,6 +956,7 @@ ssol_draw_draft
struct ssol_camera* cam,
const size_t width, /* #pixels in X */
const size_t height, /* #pixels in Y */
+ const size_t spp, /* #samples per pixel */
ssol_write_pixels_T writer,
void* writer_data);
@@ -965,6 +966,7 @@ ssol_draw_pt
struct ssol_camera* cam,
const size_t width, /* #pixels in X */
const size_t height, /* #pixels in Y */
+ const size_t spp,
ssol_write_pixels_T writer,
void* writer_data);
diff --git a/src/ssol_draw_draft.c b/src/ssol_draw_draft.c
@@ -15,14 +15,18 @@
#include "ssol_c.h"
#include "ssol_camera.h"
+#include "ssol_device_c.h"
#include "ssol_draw.h"
#include "ssol_object_c.h"
#include "ssol_scene_c.h"
#include "ssol_shape_c.h"
#include <rsys/double3.h>
+#include <rsys/dynamic_array_float.h>
#include <rsys/float3.h>
+#include <star/ssp.h>
+
#include <float.h>
/*******************************************************************************
@@ -82,15 +86,31 @@ draw_pixel
double pixel[3],
void* ctx)
{
+ struct darray_float* samples = ctx;
float samp[2];
float ray_org[3], ray_dir[3];
- ASSERT(scn && cam && view && pix_coords && pix_sz && nsamples && pixel);
- (void)ithread, (void)ctx, (void)nsamples;
+ double sum[3] = {0, 0, 0};
+ size_t i;
+ ASSERT(scn && cam && view && pix_coords && pix_sz && nsamples && pixel && ctx);
+ (void)ithread;
+
+ FOR_EACH(i, 0, nsamples) {
+ double weight[3];
+ const float* r = darray_float_cdata_get(samples) + i*2;
+
+ /* Generate a sample into the pixel */
+ samp[0] = ((float)pix_coords[0] + r[0]) * pix_sz[0];
+ samp[1] = ((float)pix_coords[1] + r[1]) * pix_sz[1];
- samp[0] = ((float)pix_coords[0] + 0.5f) * pix_sz[0];
- samp[1] = ((float)pix_coords[1] + 0.5f) * pix_sz[1];
- camera_ray(cam, samp, ray_org, ray_dir);
- Li(scn, view, ray_org, ray_dir, pixel);
+ /* Generate a ray starting from the pinhole camera and passing through the
+ * pixel sample */
+ camera_ray(cam, samp, ray_org, ray_dir);
+
+ /* Compute the radiance arriving through the sampled camera ray */
+ Li(scn, view, ray_org, ray_dir, weight);
+ d3_add(sum, sum, weight);
+ }
+ d3_divd(pixel, sum, (double)nsamples);
}
@@ -103,9 +123,40 @@ ssol_draw_draft
struct ssol_camera* cam,
const size_t width,
const size_t height,
+ const size_t spp,
ssol_write_pixels_T writer,
void* data)
{
- return draw(scn, cam, width, height, 1, writer, data, draw_pixel, NULL);
+ struct darray_float samples;
+ struct ssp_rng* rng = NULL;
+ size_t i;
+ res_T res = RES_OK;
+
+ if(!scn || !spp) return RES_BAD_ARG;
+
+ darray_float_init(scn->dev->allocator, &samples);
+ res = darray_float_reserve(&samples, spp * 2/*#dimensions*/);
+ if(res != RES_OK) goto error;
+
+ res = ssp_rng_create(scn->dev->allocator, &ssp_rng_threefry, &rng);
+ if(res != RES_OK) goto error;
+
+ /* Generate the pixel samples */
+ FOR_EACH(i, 0, spp) {
+ const float x = ssp_rng_canonical_float(rng);
+ const float y = ssp_rng_canonical_float(rng);
+ darray_float_push_back(&samples, &x);
+ darray_float_push_back(&samples, &y);
+ }
+
+ res = draw(scn, cam, width, height, spp, writer, data, draw_pixel, &samples);
+ if(res != RES_OK) goto error;
+
+exit:
+ darray_float_release(&samples);
+ if(rng) SSP(rng_ref_put(rng));
+ return res;
+error:
+ goto exit;
}
diff --git a/src/ssol_draw_pt.c b/src/ssol_draw_pt.c
@@ -238,15 +238,15 @@ draw_pixel
{
struct darray_thread_context* thread_ctxs = data;
struct thread_context* ctx;
- double L[3];
+ double sum[3] = {0, 0, 0};
size_t isample;
- ASSERT(scn && cam && pix_coords && pix_sz && nsamples && pixel && ctx);
+ ASSERT(scn && cam && pix_coords && pix_sz && nsamples && pixel && data);
ASSERT((size_t)ithread < darray_thread_context_size_get(thread_ctxs));
ctx = darray_thread_context_data_get(thread_ctxs) + ithread;
- d3_splat(pixel, 0);
FOR_EACH(isample, 0, nsamples) {
+ double weight[3];
float samp[2]; /* Pixel sample */
float ray_org[3], ray_dir[3];
@@ -259,11 +259,11 @@ draw_pixel
camera_ray(cam, samp, ray_org, ray_dir);
/* Compute the radiance arriving through the sampled camera ray */
- Li(scn, ctx, view, ray_org, ray_dir, L);
- d3_add(pixel, pixel, L);
+ Li(scn, ctx, view, ray_org, ray_dir, weight);
+ d3_add(sum, sum, weight);
}
- d3_divd(pixel, pixel, (double)nsamples); /* Expected value */
+ d3_divd(pixel, sum, (double)nsamples);
}
/*******************************************************************************
@@ -275,6 +275,7 @@ ssol_draw_pt
struct ssol_camera* cam,
const size_t width,
const size_t height,
+ const size_t spp,
ssol_write_pixels_T writer,
void* data)
{
@@ -310,7 +311,7 @@ ssol_draw_pt
}
/* Invoke the draw process */
- res = draw(scn, cam, width, height, 4, writer, data, draw_pixel, &thread_ctxs);
+ res = draw(scn, cam, width, height, spp, writer, data, draw_pixel, &thread_ctxs);
if(res != RES_OK) goto error;
exit:
diff --git a/src/test_ssol_draw.c b/src/test_ssol_draw.c
@@ -25,8 +25,8 @@
#include <string.h>
-#define WIDTH 800
-#define HEIGHT 600
+#define WIDTH 256
+#define HEIGHT 256
#define PITCH (WIDTH*sizeof(unsigned char[3]))
#define PROJ_RATIO ((double)WIDTH/(double)HEIGHT)
@@ -193,6 +193,7 @@ main(int argc, char** argv)
struct ssol_camera* cam,
const size_t width,
const size_t height,
+ const size_t spp,
ssol_write_pixels_T writer,
void* data);
(void)argc, (void)argv;
@@ -206,6 +207,9 @@ main(int argc, char** argv)
draw_func = ssol_draw_draft;
} else if(!strcmp(argv[1], "pt")) {
draw_func = ssol_draw_pt;
+ } else {
+ fprintf(stderr, "Usage: %s <draft|pt>\n", argv[0]);
+ return -1;
}
CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK);
@@ -232,38 +236,70 @@ main(int argc, char** argv)
pixels = MEM_CALLOC(&allocator, HEIGHT, PITCH);
NCHECK(pixels, NULL);
- CHECK(draw_func(NULL, NULL, 0, 0, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, NULL, 0, 0, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, cam, 0, 0, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, cam, 0, 0, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, NULL, WIDTH, 0, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, NULL, WIDTH, 0, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, cam, WIDTH, 0, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, cam, WIDTH, 0, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, NULL, 0, HEIGHT, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, NULL, 0, HEIGHT, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, cam, 0, HEIGHT, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, cam, 0, HEIGHT, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, NULL, WIDTH, HEIGHT, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, NULL, WIDTH, HEIGHT, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, cam, WIDTH, WIDTH, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, cam, WIDTH, HEIGHT, NULL, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, NULL, 0, 0, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, NULL, 0, 0, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, cam, 0, 0, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, cam, 0, 0, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, NULL, WIDTH, 0, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, NULL, WIDTH, 0, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, cam, WIDTH, 0, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, cam, WIDTH, 0, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, NULL, 0, HEIGHT, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, NULL, 0, HEIGHT, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, cam, 0, HEIGHT, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, cam, 0, HEIGHT, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, NULL, WIDTH, HEIGHT, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, NULL, WIDTH, HEIGHT, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(NULL, cam, WIDTH, WIDTH, write_RGB8, pixels), RES_BAD_ARG);
- CHECK(draw_func(scn, cam, WIDTH, HEIGHT, write_RGB8, pixels), RES_OK);
+ CHECK(draw_func(NULL, NULL, 0, 0, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, 0, 0, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, 0, 0, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, 0, 0, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, WIDTH, 0, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, WIDTH, 0, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, WIDTH, 0, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, WIDTH, 0, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, 0, HEIGHT, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, 0, HEIGHT, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, 0, HEIGHT, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, 0, HEIGHT, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, WIDTH, HEIGHT, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, WIDTH, HEIGHT, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, WIDTH, WIDTH, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, WIDTH, HEIGHT, 0, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, 0, 0, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, 0, 0, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, 0, 0, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, 0, 0, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, WIDTH, 0, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, WIDTH, 0, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, WIDTH, 0, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, WIDTH, 0, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, 0, HEIGHT, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, 0, HEIGHT, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, 0, HEIGHT, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, 0, HEIGHT, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, WIDTH, HEIGHT, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, WIDTH, HEIGHT, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, WIDTH, WIDTH, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, WIDTH, HEIGHT, 0, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, 0, 0, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, 0, 0, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, 0, 0, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, 0, 0, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, WIDTH, 0, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, WIDTH, 0, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, WIDTH, 0, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, WIDTH, 0, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, 0, HEIGHT, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, 0, HEIGHT, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, 0, HEIGHT, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, 0, HEIGHT, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, WIDTH, HEIGHT, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, WIDTH, HEIGHT, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, WIDTH, WIDTH, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, WIDTH, HEIGHT, 4, NULL, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, 0, 0, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, 0, 0, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, 0, 0, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, 0, 0, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, WIDTH, 0, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, WIDTH, 0, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, WIDTH, 0, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, WIDTH, 0, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, 0, HEIGHT, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, 0, HEIGHT, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, 0, HEIGHT, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, 0, HEIGHT, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, NULL, WIDTH, HEIGHT, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, NULL, WIDTH, HEIGHT, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(NULL, cam, WIDTH, WIDTH, 4, write_RGB8, pixels), RES_BAD_ARG);
+ CHECK(draw_func(scn, cam, WIDTH, HEIGHT, 4, write_RGB8, pixels), RES_OK);
CHECK(image_ppm_write_stream(stdout, WIDTH, HEIGHT, 3, pixels), RES_OK);