ssol_draw_draft.c (5494B)
1 /* Copyright (C) 2018-2026 |Meso|Star> (contact@meso-star.com) 2 * Copyright (C) 2016, 2018 CNRS 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17 #include "ssol_c.h" 18 #include "ssol_camera.h" 19 #include "ssol_device_c.h" 20 #include "ssol_draw.h" 21 #include "ssol_material_c.h" 22 #include "ssol_object_c.h" 23 #include "ssol_scene_c.h" 24 #include "ssol_shape_c.h" 25 26 #include <rsys/double3.h> 27 #include <rsys/dynamic_array_float.h> 28 #include <rsys/float3.h> 29 30 #include <star/ssp.h> 31 32 #include <float.h> 33 34 /******************************************************************************* 35 * Helper functions 36 ******************************************************************************/ 37 static void 38 Li 39 (struct ssol_scene* scn, 40 struct s3d_scene_view* view, 41 const float org[3], 42 const float dir[3], 43 double val[3]) 44 { 45 const float range[2] = {0, FLT_MAX}; 46 struct ssol_surface_fragment frag; 47 struct ray_data ray_data = RAY_DATA_NULL; 48 struct s3d_hit hit; 49 ASSERT(scn && view && org && dir && val); 50 51 ray_data.scn = scn; 52 ray_data.discard_virtual_materials = 1; 53 S3D(scene_view_trace_ray(view, org, dir, range, &ray_data, &hit)); 54 if(S3D_HIT_NONE(&hit)) { 55 d3_splat(val, 0); 56 } else { 57 struct ssol_instance* inst; 58 struct ssol_material* mtl; 59 const struct shaded_shape* sshape; 60 size_t isshape; 61 double o[3], wi[3]; 62 double N[3]={0}; 63 double cos_N_wi; 64 65 /* Retrieve the hit shaded shape */ 66 inst = *htable_instance_find(&scn->instances_rt, &hit.prim.inst_id); 67 isshape = *htable_shaded_shape_find 68 (&inst->object->shaded_shapes_rt, &hit.prim.geom_id); 69 sshape = darray_shaded_shape_cdata_get 70 (&inst->object->shaded_shapes) + isshape; 71 72 /* Retrieve and normalized the hit normal */ 73 switch(sshape->shape->type) { 74 case SHAPE_MESH: d3_normalize(N, d3_set_f3(N, hit.normal)); break; 75 case SHAPE_PUNCHED: d3_normalize(N, ray_data.N); break; 76 break; 77 default: FATAL("Unreachable code"); break; 78 } 79 80 d3_set_f3(o, org); 81 d3_set_f3(wi, dir); 82 d3_normalize(wi, wi); 83 if(d3_dot(N, wi) < 0) { 84 mtl = sshape->mtl_front; 85 } else { 86 mtl = sshape->mtl_back; 87 d3_minus(N, N); 88 } 89 90 surface_fragment_setup(&frag, o, wi, N, &hit.prim, hit.uv); 91 material_shade_normal(mtl, &frag, 1/*TODO wavelength*/, N); 92 93 ASSERT(d3_is_normalized(N)); 94 cos_N_wi = d3_dot(N, d3_minus(wi, wi)); 95 d3_splat(val, MMAX(cos_N_wi, 0)); 96 } 97 } 98 99 static void 100 draw_pixel 101 (struct ssol_scene* scn, 102 const struct ssol_camera* cam, 103 struct s3d_scene_view* view, 104 const int ithread, 105 const size_t pix_coords[2], /* Image space pixel coordinates */ 106 const float pix_sz[2], /* Normalized pixel size */ 107 const size_t nsamples, 108 double pixel[3], 109 void* data) 110 { 111 struct darray_float* samples = data; 112 float samp[2]; 113 float ray_org[3], ray_dir[3]; 114 double sum[3] = {0, 0, 0}; 115 size_t i; 116 ASSERT(scn && cam && view && pix_coords && pix_sz && nsamples && pixel && data); 117 (void)ithread; 118 119 FOR_EACH(i, 0, nsamples) { 120 double weight[3]; 121 const float* r = darray_float_cdata_get(samples) + i*2; 122 123 /* Generate a sample into the pixel */ 124 samp[0] = ((float)pix_coords[0] + r[0]) * pix_sz[0]; 125 samp[1] = ((float)pix_coords[1] + r[1]) * pix_sz[1]; 126 127 /* Generate a ray starting from the pinhole camera and passing through the 128 * pixel sample */ 129 camera_ray(cam, samp, ray_org, ray_dir); 130 131 /* Compute the radiance arriving through the sampled camera ray */ 132 Li(scn, view, ray_org, ray_dir, weight); 133 d3_add(sum, sum, weight); 134 } 135 d3_divd(pixel, sum, (double)nsamples); 136 } 137 138 139 /******************************************************************************* 140 * Exported function 141 ******************************************************************************/ 142 res_T 143 ssol_draw_draft 144 (struct ssol_scene* scn, 145 struct ssol_camera* cam, 146 const size_t width, 147 const size_t height, 148 const size_t spp, 149 ssol_write_pixels_T writer, 150 void* data) 151 { 152 struct darray_float samples; 153 struct ssp_rng* rng = NULL; 154 size_t i; 155 res_T res = RES_OK; 156 157 if(!scn || !spp) return RES_BAD_ARG; 158 159 darray_float_init(scn->dev->allocator, &samples); 160 161 res = scene_check(scn, FUNC_NAME); 162 if(res != RES_OK) goto error; 163 164 res = darray_float_reserve(&samples, spp * 2/*#dimensions*/); 165 if(res != RES_OK) goto error; 166 167 res = ssp_rng_create(scn->dev->allocator, SSP_RNG_THREEFRY, &rng); 168 if(res != RES_OK) goto error; 169 170 /* Generate the pixel samples */ 171 FOR_EACH(i, 0, spp) { 172 const float x = ssp_rng_canonical_float(rng); 173 const float y = ssp_rng_canonical_float(rng); 174 darray_float_push_back(&samples, &x); 175 darray_float_push_back(&samples, &y); 176 } 177 178 res = draw(scn, cam, width, height, spp, writer, data, draw_pixel, &samples); 179 if(res != RES_OK) goto error; 180 181 exit: 182 darray_float_release(&samples); 183 if(rng) SSP(rng_ref_put(rng)); 184 return res; 185 error: 186 goto exit; 187 } 188