commit 9f505552613ea999b476483243fc33387428a84c
parent 3facd56ef07381a0465c81deeef11e5ee083b61f
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 6 Mar 2017 16:39:22 +0100
Move the path-tracing rendering code into a specific file
Diffstat:
5 files changed, 346 insertions(+), 167 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -57,6 +57,7 @@ set(SSOL_FILES_SRC
ssol_camera.c
ssol_device.c
ssol_draw.c
+ ssol_draw_pt.c
ssol_estimator.c
ssol_image.c
ssol_material.c
@@ -80,6 +81,7 @@ set(SSOL_FILES_INC
ssol_c.h
ssol_camera.h
ssol_device_c.h
+ ssol_draw_pt.h
ssol_estimator_c.h
ssol_image_c.h
ssol_material_c.h
diff --git a/src/ssol_draw.c b/src/ssol_draw.c
@@ -17,10 +17,12 @@
#include "ssol_c.h"
#include "ssol_camera.h"
#include "ssol_device_c.h"
+#include "ssol_draw_pt.h"
#include "ssol_material_c.h"
#include "ssol_object_c.h"
#include "ssol_scene_c.h"
#include "ssol_shape_c.h"
+#include "ssol_sun_c.h"
#include <rsys/double2.h>
#include <rsys/double3.h>
@@ -35,53 +37,6 @@
STATIC_ASSERT(IS_POW2(TILE_SIZE), TILE_SIZE_must_be_a_power_of_2);
/*******************************************************************************
- * Thread context
- ******************************************************************************/
-struct thread_context {
- struct ssp_rng* rng;
- struct ssf_bsdf* bsdf;
-};
-
-static void
-thread_context_release(struct thread_context* ctx)
-{
- ASSERT(ctx);
- if(ctx->rng) SSP(rng_ref_put(ctx->rng));
- if(ctx->bsdf) SSF(bsdf_ref_put(ctx->bsdf));
-}
-
-static res_T
-thread_context_init(struct mem_allocator* allocator, struct thread_context* ctx)
-{
- res_T res = RES_OK;
- ASSERT(ctx);
- memset(ctx, 0, sizeof(ctx[0]));
- res = ssf_bsdf_create(allocator, &ctx->bsdf);
- if(res != RES_OK) goto error;
-exit:
- return res;
-error:
- thread_context_release(ctx);
- goto exit;
-}
-
-static void
-thread_context_setup(struct thread_context* ctx, struct ssp_rng* rng)
-{
- ASSERT(ctx && rng);
- if(ctx->rng) SSP(rng_ref_put(ctx->rng));
- SSP(rng_ref_get(rng));
- ctx->rng = rng;
-}
-
-/* Declare the container of the per thread contexts */
-#define DARRAY_NAME thread_ctx
-#define DARRAY_DATA struct thread_context
-#define DARRAY_FUNCTOR_INIT thread_context_init
-#define DARRAY_FUNCTOR_RELEASE thread_context_release
-#include <rsys/dynamic_array.h>
-
-/*******************************************************************************
* Helper function
******************************************************************************/
static FINLINE uint16_t
@@ -98,7 +53,6 @@ morton2D_decode(const uint32_t u32)
static void
Li_basic
(struct ssol_scene* scn,
- struct thread_context* ctx,
struct s3d_scene_view* view,
const float org[3],
const float dir[3],
@@ -108,7 +62,6 @@ Li_basic
struct ray_data ray_data = RAY_DATA_NULL;
struct s3d_hit hit;
ASSERT(scn && view && org && dir && val);
- (void)ctx;
ray_data.scn = scn;
ray_data.discard_virtual_materials = 1;
@@ -140,101 +93,9 @@ Li_basic
}
static void
-Li_pt
- (struct ssol_scene* scn,
- struct thread_context* ctx,
- struct s3d_scene_view* view,
- const float org[3],
- const float dir[3],
- double val[3])
-{
- struct s3d_hit hit;
- struct ray_data ray_data = RAY_DATA_NULL;
- struct ssol_instance* inst;
- struct ssol_material* mtl;
- const struct shaded_shape* sshape;
- struct surface_fragment frag;
- size_t idepth;
- size_t isshape;
- double throughput = 1.0;
- double cos_wi_N;
- double wi[3], o[3], uv[3];
- double N[3];
- double L = 0;
- double r;
- double pdf;
- const float ray_range[2] = {0, FLT_MAX};
- float ray_org[3];
- float ray_dir[3];
- enum ssol_side_flag side;
- ASSERT(scn && view && org && dir && val);
-
- ray_data.scn = scn;
- ray_data.discard_virtual_materials = 1;
-
- f3_set(ray_org, org);
- f3_set(ray_dir, dir);
-
- FOR_EACH(idepth, 0, 32) {
-
- S3D(scene_view_trace_ray
- (view, ray_org, ray_dir, ray_range, &ray_data, &hit));
- if(S3D_HIT_NONE(&hit)) {
- /* TODO background lighting */
- if(ray_dir[2] > 0) L += throughput;
- break;
- }
-
- /* Retrieve the hit shaded shape */
- inst = *htable_instance_find(&scn->instances_rt, &hit.prim.inst_id);
- isshape = *htable_shaded_shape_find
- (&inst->object->shaded_shapes_rt, &hit.prim.geom_id);
- sshape = darray_shaded_shape_cdata_get(&inst->object->shaded_shapes)+isshape;
-
- d3_set_f3(o, ray_org);
- d3_set_f3(wi, ray_dir);
- d2_set_f2(uv, hit.uv);
- d3_set_f3(N, hit.normal);
- d3_normalize(N, N);
- d3_normalize(wi, wi);
-
- if(f3_dot(hit.normal, ray_dir) < 0) {
- mtl = sshape->mtl_front;
- side = SSOL_FRONT;
- } else {
- mtl = sshape->mtl_back;
- side = SSOL_BACK;
- d3_minus(N, N);
- }
-
- surface_fragment_setup(&frag, o, wi, N, &hit.prim, hit.uv);
- SSF(bsdf_clear(ctx->bsdf));
- CHECK(material_shade(mtl, &frag, 1/*TODO wavelength*/, ctx->bsdf), RES_OK);
-
- d3_minus(wi, wi);
- cos_wi_N = d3_dot(wi, N);
-
- /*L += throughput * direct_lighting(); *//* TODO */
-
- /* Update the ray */
- ray_data.prim_from = hit.prim;
- ray_data.inst_from = inst;
- ray_data.side_from = side;
- f3_mulf(ray_dir, ray_dir, hit.distance);
- f3_add(ray_org, ray_org, ray_dir);
- r = ssf_bsdf_sample(ctx->bsdf, ctx->rng, wi, frag.Ns, wi, &pdf);
- ASSERT(0 <= r && r <= 1);
- f3_set_d3(ray_dir, wi);
-
- throughput *= r * cos_wi_N;
- }
- d3_splat(val, L);
-}
-
-static void
draw_tile
(struct ssol_scene* scn,
- struct thread_context* ctx,
+ struct draw_pt_thread_context* ctx,
struct s3d_scene_view* view,
const struct ssol_camera* cam,
const size_t origin[2], /* Tile origin */
@@ -251,10 +112,7 @@ draw_tile
npixels *= npixels;
FOR_EACH(mcode, 0, npixels) {
- const size_t NSAMPS = 1;
- size_t isamp;
size_t ipix[2];
- float org[3], dir[3], samp[2];
double* pixel;
ipix[0] = morton2D_decode((uint32_t)(mcode>>0));
@@ -263,20 +121,23 @@ draw_tile
if(ipix[1] >= size[1]) continue;
pixel = pixels + (ipix[1]*size[0] + ipix[0])*3/*#channels*/;
-
ipix[0] = ipix[0] + origin[0];
ipix[1] = ipix[1] + origin[1];
- d3_splat(pixel, 0);
- FOR_EACH(isamp, 0, NSAMPS) {
- double L[3];
- samp[0] = ((float)ipix[0]+ssp_rng_canonical_float(ctx->rng))*pix_sz[0];
- samp[1] = ((float)ipix[1]+ssp_rng_canonical_float(ctx->rng))*pix_sz[1];
- camera_ray(cam, samp, org, dir);
- Li_basic(scn, ctx, view, org, dir, L);
- d3_add(pixel, pixel, L);
+#if 0
+ draw_pt(scn, cam, view, ipix, pix_sz, 64, ctx, pixel);
+#else
+ {
+ float samp[2];
+ float ray_org[3], ray_dir[3];
+
+ samp[0] = ((float)ipix[0] + 0.5f) * pix_sz[0];
+ samp[1] = ((float)ipix[1] + 0.5f) * pix_sz[1];
+ camera_ray(cam, samp, ray_org, ray_dir);
+
+ Li_basic(scn, view, ray_org, ray_dir, pixel);
}
- d3_divd(pixel, pixel, (double)NSAMPS);
+#endif
}
}
@@ -292,7 +153,7 @@ ssol_draw
ssol_write_pixels_T writer,
void* data)
{
- struct darray_thread_ctx thread_ctxs;
+ struct darray_draw_pt_thread_context thread_ctxs;
struct ssp_rng_proxy* rng_proxy = NULL;
struct s3d_scene_view* view = NULL;
struct darray_byte* tiles = NULL;
@@ -305,23 +166,26 @@ ssol_draw
if(!scn || !cam || !width || !height || !writer)
return RES_BAD_ARG;
+ darray_draw_pt_thread_context_init(scn->dev->allocator, &thread_ctxs);
+
/* Create a RNG proxy */
res = ssp_rng_proxy_create
(scn->dev->allocator, &ssp_rng_threefry, scn->dev->nthreads, &rng_proxy);
if(res != RES_OK) goto error;
/* Create the thread contexts */
- darray_thread_ctx_init(scn->dev->allocator, &thread_ctxs);
- res = darray_thread_ctx_resize(&thread_ctxs, scn->dev->nthreads);
+ res = darray_draw_pt_thread_context_resize(&thread_ctxs, scn->dev->nthreads);
if(res != RES_OK) goto error;
FOR_EACH(i, 0, scn->dev->nthreads) {
- struct thread_context* ctx = darray_thread_ctx_data_get(&thread_ctxs)+i;
+ struct draw_pt_thread_context* ctx;
struct ssp_rng* rng;
+ ctx = darray_draw_pt_thread_context_data_get(&thread_ctxs)+i;
+
res = ssp_rng_proxy_create_rng(rng_proxy, i, &rng);
if(res != RES_OK) goto error;
- thread_context_setup(ctx, rng);
+ draw_pt_thread_context_setup(ctx, rng);
SSP(rng_ref_put(rng));
}
@@ -346,7 +210,7 @@ ssol_draw
#pragma omp parallel for schedule(dynamic, 1/*chunck size*/)
for(mcode=0; mcode<(int64_t)ntiles; ++mcode) {
- struct thread_context* ctx;
+ struct draw_pt_thread_context* ctx;
size_t tile_org[2];
size_t tile_sz[2];
const int ithread = omp_get_thread_num();
@@ -355,7 +219,7 @@ ssol_draw
if(ATOMIC_GET(&res) != RES_OK) continue;
- ctx = darray_thread_ctx_data_get(&thread_ctxs) + ithread;
+ ctx = darray_draw_pt_thread_context_data_get(&thread_ctxs) + ithread;
tile_org[0] = morton2D_decode((uint32_t)(mcode>>0));
if(tile_org[0] >= ntiles_x) continue;
@@ -379,7 +243,7 @@ ssol_draw
}
exit:
- darray_thread_ctx_release(&thread_ctxs);
+ darray_draw_pt_thread_context_release(&thread_ctxs);
if(rng_proxy) SSP(rng_proxy_ref_put(rng_proxy));
if(view) S3D(scene_view_ref_put(view));
return (res_T)res;
diff --git a/src/ssol_draw_pt.c b/src/ssol_draw_pt.c
@@ -0,0 +1,237 @@
+/* Copyright (C) CNRS 2016-2017
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * 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/>. */
+
+#include "ssol_c.h"
+#include "ssol_camera.h"
+#include "ssol_draw_pt.h"
+#include "ssol_material_c.h"
+#include "ssol_object_c.h"
+#include "ssol_scene_c.h"
+#include "ssol_sun_c.h"
+
+#include <rsys/double2.h>
+#include <rsys/double3.h>
+#include <rsys/float3.h>
+
+#include <star/s3d.h>
+#include <star/ssf.h>
+#include <star/ssp.h>
+
+/*******************************************************************************
+ * Per thread draw_pt context
+ ******************************************************************************/
+res_T
+draw_pt_thread_context_init
+ (struct mem_allocator* allocator,
+ struct draw_pt_thread_context* ctx)
+{
+ res_T res = RES_OK;
+ ASSERT(ctx);
+ memset(ctx, 0, sizeof(ctx[0]));
+ res = ssf_bsdf_create(allocator, &ctx->bsdf);
+ if(res != RES_OK) goto error;
+exit:
+ return res;
+error:
+ draw_pt_thread_context_release(ctx);
+ goto exit;
+}
+
+void
+draw_pt_thread_context_release(struct draw_pt_thread_context* ctx)
+{
+ ASSERT(ctx);
+ if(ctx->rng) SSP(rng_ref_put(ctx->rng));
+ if(ctx->bsdf) SSF(bsdf_ref_put(ctx->bsdf));
+}
+
+
+void
+draw_pt_thread_context_setup
+ (struct draw_pt_thread_context* ctx,
+ struct ssp_rng* rng)
+{
+ ASSERT(ctx && rng);
+ if(ctx->rng) SSP(rng_ref_put(ctx->rng));
+ SSP(rng_ref_get(rng));
+ ctx->rng = rng;
+}
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static INLINE double
+sun_lighting
+ (struct ssol_sun* sun,
+ struct s3d_scene_view* view,
+ struct ray_data* ray_data,
+ struct ssf_bsdf* bsdf,
+ const double wo[3],
+ const double N[3],
+ const float ray_org[3])
+{
+ struct s3d_hit hit;
+ const float ray_range[2] = {0, FLT_MAX};
+ double wi[3];
+ float ray_dir[3];
+ double cos_wi_N;
+ double R;
+ ASSERT(sun && view && ray_data && bsdf && wo && N && ray_org);
+ ASSERT(d3_dot(wo, N) >= 0); /* Assume that wo point outward the surface */
+
+ d3_minus(wi, sun->direction);
+ R = ssf_bsdf_eval(bsdf, wo, N, wi);
+ if(R <= 0) return 0.0;
+
+ cos_wi_N = d3_dot(wi, N);
+
+ f3_set_d3(ray_dir, wi);
+ S3D(scene_view_trace_ray(view, ray_org, ray_dir, ray_range, ray_data, &hit));
+ if(S3D_HIT_NONE(&hit)) return R * cos_wi_N;
+ return 0;
+}
+
+static void
+Li
+ (struct ssol_scene* scn,
+ struct draw_pt_thread_context* ctx,
+ struct s3d_scene_view* view,
+ const float org[3],
+ const float dir[3],
+ double val[3])
+{
+ struct s3d_hit hit;
+ struct ray_data ray_data = RAY_DATA_NULL;
+ struct ssol_instance* inst;
+ struct ssol_material* mtl;
+ const struct shaded_shape* sshape;
+ struct surface_fragment frag;
+ size_t idepth;
+ size_t isshape;
+ double throughput = 1.0;
+ double wi[3], o[3], uv[3];
+ double wo[3];
+ double N[3];
+ double L = 0;
+ double R;
+ double pdf;
+ const float ray_range[2] = {0, FLT_MAX};
+ float ray_org[3];
+ float ray_dir[3];
+ enum ssol_side_flag side;
+ ASSERT(scn && view && org && dir && val);
+
+ ray_data.scn = scn;
+ ray_data.discard_virtual_materials = 1;
+
+ f3_set(ray_org, org);
+ f3_set(ray_dir, dir);
+
+ FOR_EACH(idepth, 0, 4) {
+
+ S3D(scene_view_trace_ray
+ (view, ray_org, ray_dir, ray_range, &ray_data, &hit));
+ if(S3D_HIT_NONE(&hit)) {
+ /* TODO background lighting */
+ if(ray_dir[2] > 0) L += throughput;
+ break;
+ }
+
+ /* Retrieve the hit shaded shape */
+ inst = *htable_instance_find(&scn->instances_rt, &hit.prim.inst_id);
+ isshape = *htable_shaded_shape_find
+ (&inst->object->shaded_shapes_rt, &hit.prim.geom_id);
+ sshape = darray_shaded_shape_cdata_get(&inst->object->shaded_shapes)+isshape;
+
+ d3_set_f3(o, ray_org);
+ d3_set_f3(wo, ray_dir);
+ d2_set_f2(uv, hit.uv);
+ d3_set_f3(N, hit.normal);
+ d3_normalize(N, N);
+ d3_normalize(wo, wo);
+
+ if(f3_dot(hit.normal, ray_dir) < 0) {
+ mtl = sshape->mtl_front;
+ side = SSOL_FRONT;
+ } else {
+ mtl = sshape->mtl_back;
+ side = SSOL_BACK;
+ d3_minus(N, N);
+ }
+
+ surface_fragment_setup(&frag, o, wi, N, &hit.prim, hit.uv);
+ SSF(bsdf_clear(ctx->bsdf));
+ CHECK(material_shade(mtl, &frag, 1/*TODO wavelength*/, ctx->bsdf), RES_OK);
+
+ /* Update the ray */
+ ray_data.prim_from = hit.prim;
+ ray_data.inst_from = inst;
+ ray_data.side_from = side;
+ f3_mulf(ray_dir, ray_dir, hit.distance);
+ f3_add(ray_org, ray_org, ray_dir);
+
+ if(scn->sun) {
+ L += throughput * sun_lighting
+ (scn->sun, view, &ray_data, ctx->bsdf, wo, N, ray_org);
+ }
+
+ d3_minus(wo, wo);
+ R = ssf_bsdf_sample(ctx->bsdf, ctx->rng, wo, frag.Ns, wi, &pdf);
+ ASSERT(0 <= R && R <= 1);
+ f3_set_d3(ray_dir, wi);
+
+ throughput *= R * d3_dot(wi, N);
+ }
+ d3_splat(val, L);
+}
+
+/*******************************************************************************
+ * Local function
+ ******************************************************************************/
+void
+draw_pt
+ (struct ssol_scene* scn,
+ const struct ssol_camera* cam,
+ struct s3d_scene_view* view,
+ const size_t pix_coords[2], /* Image space pixel coordinates */
+ const float pix_sz[2], /* Normalized pixel size */
+ const size_t nsamples,
+ struct draw_pt_thread_context* ctx,
+ double pixel[3])
+{
+ double L[3];
+ size_t isample;
+ ASSERT(scn && cam && pix_coords && pix_sz && nsamples && ctx && pixel);
+
+ d3_splat(pixel, 0);
+ FOR_EACH(isample, 0, nsamples) {
+ float samp[2]; /* Pixel sample */
+ float ray_org[3], ray_dir[3];
+
+ /* Generate a sample into the pixel */
+ samp[0] = ((float)pix_coords[0]+ssp_rng_canonical_float(ctx->rng))*pix_sz[0];
+ samp[1] = ((float)pix_coords[1]+ssp_rng_canonical_float(ctx->rng))*pix_sz[1];
+
+ /* 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, ctx, view, ray_org, ray_dir, L);
+ d3_add(pixel, pixel, L);
+ }
+
+ d3_divd(pixel, pixel, (double)nsamples);
+}
diff --git a/src/ssol_draw_pt.h b/src/ssol_draw_pt.h
@@ -0,0 +1,66 @@
+/* Copyright (C) CNRS 2016-2017
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * 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/>. */
+
+#ifndef SSOL_DRAW_PT_H
+#define SSOL_DRAW_PT_H
+
+#include <rsys/dynamic_array.h>
+
+/* Forward declarations */
+struct s3d_scene_view;
+struct ssol_camera;
+struct ssol_scene;
+struct ssf_bsdf;
+struct ssp_rng;
+
+struct draw_pt_thread_context {
+ struct ssp_rng* rng;
+ struct ssf_bsdf* bsdf;
+};
+
+extern LOCAL_SYM res_T
+draw_pt_thread_context_init
+ (struct mem_allocator* allocator,
+ struct draw_pt_thread_context* ctx);
+
+extern LOCAL_SYM void
+draw_pt_thread_context_release
+ (struct draw_pt_thread_context* ctx);
+
+extern LOCAL_SYM void
+draw_pt_thread_context_setup
+ (struct draw_pt_thread_context* ctx,
+ struct ssp_rng* rng);
+
+/* Declare the container of the per thread contexts */
+#define DARRAY_NAME draw_pt_thread_context
+#define DARRAY_DATA struct draw_pt_thread_context
+#define DARRAY_FUNCTOR_INIT draw_pt_thread_context_init
+#define DARRAY_FUNCTOR_RELEASE draw_pt_thread_context_release
+#include <rsys/dynamic_array.h>
+
+extern LOCAL_SYM void
+draw_pt
+ (struct ssol_scene* scn,
+ const struct ssol_camera* cam,
+ struct s3d_scene_view* view,
+ const size_t pix_coords[2],
+ const float pix_sz[2],
+ const size_t nsamples,
+ struct draw_pt_thread_context* ctx,
+ double radiance[3]);
+
+#endif /* SSOL_DRAW_PT_H */
+
diff --git a/src/test_ssol_draw.c b/src/test_ssol_draw.c
@@ -18,6 +18,7 @@
#include "test_ssol_geometries.h"
#include "test_ssol_materials.h"
+#include <rsys/double3.h>
#include <rsys/float3.h>
#include <rsys/image.h>
#include <rsys/math.h>
@@ -114,7 +115,7 @@ setup_cornell_box(struct ssol_device* dev, struct ssol_scene* scn)
struct ssol_object* obj;
struct ssol_instance* inst;
struct ssol_material* mtl;
- struct ssol_mirror_shader shader = SSOL_MIRROR_SHADER_NULL;
+ struct ssol_matte_shader shader = SSOL_MATTE_SHADER_NULL;
struct ssol_vertex_data vdata;
struct desc desc;
float lower[3], upper[3];
@@ -122,9 +123,8 @@ setup_cornell_box(struct ssol_device* dev, struct ssol_scene* scn)
shader.normal = get_shader_normal;
shader.reflectivity = get_shader_reflectivity;
- shader.roughness = get_shader_roughness;
- CHECK(ssol_material_create_mirror(dev, &mtl), RES_OK);
- CHECK(ssol_mirror_set_shader(mtl, &shader), RES_OK);
+ CHECK(ssol_material_create_matte(dev, &mtl), RES_OK);
+ CHECK(ssol_matte_set_shader(mtl, &shader), RES_OK);
vdata.usage = SSOL_POSITION;
vdata.get = get_position;
@@ -180,10 +180,12 @@ main(int argc, char** argv)
struct ssol_device* dev;
struct ssol_camera* cam;
struct ssol_scene* scn;
+ struct ssol_sun* sun;
unsigned char* pixels = NULL;
const double pos[3] = {278.0, -1000.0, 273.0};
const double tgt[3] = {278.0, 0.0, 273.0};
const double up[3] = {0.0, 0.0, 1.0};
+ double dir[3];
(void)argc, (void)argv;
CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK);
@@ -200,6 +202,13 @@ main(int argc, char** argv)
CHECK(ssol_camera_set_fov(cam, PI/4.0), RES_OK);
CHECK(ssol_camera_look_at(cam, pos, tgt, up), RES_OK);
+ d3(dir, 1, 1, -1);
+ d3_normalize(dir, dir);
+ CHECK(ssol_sun_create_directional(dev, &sun), RES_OK);
+ CHECK(ssol_sun_set_direction(sun, dir), RES_OK);
+ CHECK(ssol_sun_set_dni(sun, 1000), RES_OK);
+ CHECK(ssol_scene_attach_sun(scn, sun), RES_OK);
+
pixels = MEM_CALLOC(&allocator, HEIGHT, PITCH);
NCHECK(pixels, NULL);
@@ -242,6 +251,7 @@ main(int argc, char** argv)
CHECK(ssol_device_ref_put(dev), RES_OK);
CHECK(ssol_camera_ref_put(cam), RES_OK);
CHECK(ssol_scene_ref_put(scn), RES_OK);
+ CHECK(ssol_sun_ref_put(sun), RES_OK);
check_memory_allocator(&allocator);
mem_shutdown_proxy_allocator(&allocator);