BRL-CAD
sh_brdf.c
Go to the documentation of this file.
1 /* S H _ B R D F . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1996-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @file liboptical/sh_brdf.c
21  *
22  * Simple Isotropic Gaussian model with just one parameter (RMS slope).
23  *
24  * Notes -
25  * The normals on all surfaces point OUT of the solid.
26  * The incoming light rays point IN.
27  *
28  * Implementation is based on the simple Isotropic Gaussian Model
29  * presented by Gregory Ward in "Measuring and Modeling Anisotropic
30  * Reflection" (Which also references earlier work by Beckmann,
31  * Torrance, and Cook).
32  */
33 
34 #include "common.h"
35 
36 #include <stddef.h>
37 #include <stdio.h>
38 #include <math.h>
39 
40 #include "vmath.h"
41 #include "mater.h"
42 #include "raytrace.h"
43 #include "optical.h"
44 #include "light.h"
45 
46 /* from view.c */
47 extern double AmbientIntensity;
48 
49 /* Local information */
50 struct brdf_specific {
51  uint32_t magic;
52  double specular_refl; /* specular reflectance */
53  double diffuse_refl; /* diffuse reflectance */
54  double rms_slope; /* Standard deviation (RMS) of surface slope (roughness) */
55  double rms_sq; /* square of above */
56  double denom; /* denominator for specular term */
57  double transmit; /* Moss "transparency" */
58  double reflect; /* Moss "transmission" */
59  double refrac_index;
60  double extinction;
61 };
62 #define BRDF_MAGIC 0xbeef00d
63 #define BRDF_NULL ((struct brdf_specific *)0)
64 #define BRDF_O(m) bu_offsetof(struct brdf_specific, m)
65 
67  {"%g", 1, "specular", BRDF_O(specular_refl), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
68  {"%g", 1, "sp", BRDF_O(specular_refl), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
69  {"%g", 1, "diffuse", BRDF_O(diffuse_refl), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
70  {"%g", 1, "di", BRDF_O(diffuse_refl), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
71  {"%g", 1, "rough", BRDF_O(rms_slope), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
72  {"%g", 1, "rms", BRDF_O(rms_slope), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
73  {"%g", 1, "transmit", BRDF_O(transmit), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
74  {"%g", 1, "tr", BRDF_O(transmit), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
75  {"%g", 1, "reflect", BRDF_O(reflect), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
76  {"%g", 1, "re", BRDF_O(reflect), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
77  {"%g", 1, "ri", BRDF_O(refrac_index), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
78  {"%g", 1, "extinction_per_meter", BRDF_O(extinction), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
79  {"%g", 1, "extinction", BRDF_O(extinction), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
80  {"%g", 1, "ex", BRDF_O(extinction), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
81  {"", 0, (char *)0, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
82 };
83 
84 
85 HIDDEN int brdf_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip);
86 HIDDEN int brdf_render(register struct application *ap, const struct partition *pp, struct shadework *swp, void *dp);
87 HIDDEN void brdf_print(register struct region *rp, void *dp);
88 HIDDEN void brdf_free(void *cp);
89 
90 struct mfuncs brdf_mfuncs[] = {
91  {MF_MAGIC, "brdf", 0, MFI_NORMAL|MFI_LIGHT, 0,
92  brdf_setup, brdf_render, brdf_print, brdf_free },
93 
94  {0, (char *)0, 0, 0, 0,
95  0, 0, 0, 0 }
96 };
97 
98 
99 #define RI_AIR 1.0 /* Refractive index of air. */
100 
101 HIDDEN int
102 brdf_setup(register struct region *UNUSED(rp), struct bu_vls *matparm, void **dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *UNUSED(rtip))
103 {
104  register struct brdf_specific *pp;
105 
106  BU_CK_VLS(matparm);
107  BU_GET(pp, struct brdf_specific);
108  *dpp = pp;
109 
110  pp->magic = BRDF_MAGIC;
111  pp->specular_refl = 0.7;
112  pp->diffuse_refl = 0.3;
113  pp->transmit = 0.0;
114  pp->reflect = 0.0;
115  pp->refrac_index = RI_AIR;
116  pp->extinction = 0.0;
117  pp->rms_slope = 0.05;
118 
119  if (bu_struct_parse(matparm, brdf_parse, (char *)pp, NULL) < 0) {
120  BU_PUT(pp, struct brdf_specific);
121  return -1;
122  }
123 
124  pp->rms_sq = pp->rms_slope * pp->rms_slope;
125  pp->denom = 4.0 * M_PI * pp->rms_sq;
126 
127  return 1;
128 }
129 HIDDEN void
130 brdf_print(register struct region *rp, void *dp)
131 {
132  bu_struct_print(rp->reg_name, brdf_parse, (char *)dp);
133 }
134 
135 
136 HIDDEN void
137 brdf_free(void *cp)
138 {
139  BU_PUT(cp, struct brdf_specific);
140 }
141 
142 
143 /*
144  Color pixel based on the energy of a point light source (Eps)
145  plus some diffuse illumination (Epd) reflected from the point
146  <x, y> :
147 
148  E = Epd + Eps (1)
149 
150  The energy reflected from diffuse illumination is the product
151  of the reflectance coefficient at point P (Rp) and the diffuse
152  illumination (Id) :
153 
154  Epd = Rp * Id (2)
155 
156  The energy reflected from the point light source is calculated
157  by the sum of the diffuse reflectance (Rd) and the specular
158  reflectance (Rs), multiplied by the intensity of the light
159  source (Ips) :
160 
161  Eps = (Rd + Rs) * Ips (3)
162 
163  The diffuse reflectance is calculated by the product of the
164  reflectance coefficient (Rp) and the cosine of the angle of
165  incidence (I) and normalized by PI :
166 
167  Rd = Rp * cos(I) / PI (4)
168 
169  The specular reflectance is calculated by the product of the
170  specular reflectance coefficient and a term dependent on the
171  surface roughness :
172 
173  Rs = W(I, O) * R(I, O, r) (5)
174 
175  Where,
176  I is the angle of incidence.
177  O is the angle to the observer.
178  r is the standard deviation (RMS) of the surface slope.
179  W returns the specular reflection coefficient as a function
180  of the angle of incidence, and the viewer angle.
181  R is a surface roughness term.
182 
183 */
184 HIDDEN int
185 brdf_render(register struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
186 {
187  register struct light_specific *lp;
188  register fastf_t *intensity, *to_light;
189  register int i;
190  register fastf_t cosi, cosr;
191  register fastf_t refl;
192  vect_t h_dir;
193  vect_t to_eye;
194  vect_t work;
195  vect_t cprod; /* color product */
196  point_t matcolor; /* Material color */
197  struct brdf_specific *ps =
198  (struct brdf_specific *)dp;
199 
200  if (ps->magic != BRDF_MAGIC) bu_log("brdf_render: bad magic\n");
201 
202  if (rdebug&RDEBUG_SHADE)
203  bu_struct_print("brdf_render", brdf_parse, (char *)ps);
204 
205  swp->sw_transmit = ps->transmit;
206  swp->sw_reflect = ps->reflect;
207  swp->sw_refrac_index = ps->refrac_index;
208  swp->sw_extinction = ps->extinction;
209  if (swp->sw_xmitonly) {
210  if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
211  (void)rr_render(ap, pp, swp);
212  return 1; /* done */
213  }
214 
215  VMOVE(matcolor, swp->sw_color);
216 
217  /* Diffuse reflectance from "Ambient" light source (at eye) */
218  if ((cosr = -VDOT(swp->sw_hit.hit_normal, ap->a_ray.r_dir)) > 0.0) {
219  if (cosr > 1.00001) {
220  bu_log("cosAmb=1+%g (x%d, y%d, lvl%d)\n", cosr-1,
221  ap->a_x, ap->a_y, ap->a_level);
222  cosr = 1;
223  }
224  refl = cosr * AmbientIntensity;
225  VSCALE(swp->sw_color, matcolor, refl);
226  } else {
227  VSETALL(swp->sw_color, 0);
228  }
229 
230  VREVERSE(to_eye, ap->a_ray.r_dir);
231 
232  /* Consider effects of each light source */
233  for (i=ap->a_rt_i->rti_nlights-1; i>=0; i--) {
234  fastf_t cos_tmp;
235  fastf_t tan_sq;
236  double exponent;
237 
238  if ((lp = (struct light_specific *)swp->sw_visible[i]) == LIGHT_NULL)
239  continue;
240 
241  /* Light is not shadowed -- add this contribution */
242  intensity = swp->sw_intensity+3*i;
243  to_light = swp->sw_tolight+3*i;
244 
245  if ((cosi = VDOT(swp->sw_hit.hit_normal, to_light)) > 0.0) {
246  if (cosi > 1.00001) {
247  bu_log("cosI=1+%g (x%d, y%d, lvl%d)\n", cosi-1,
248  ap->a_x, ap->a_y, ap->a_level);
249  cosi = 1;
250  }
251 
252  /* Diffuse reflectance from this light source. */
253  refl = cosi * lp->lt_fraction * ps->diffuse_refl;
254  VELMUL(work, lp->lt_color,
255  intensity);
256  VELMUL(cprod, matcolor, work);
257  VJOIN1(swp->sw_color, swp->sw_color,
258  refl, cprod);
259 
260  /* Calculate specular reflectance. */
261  if (ZERO(ps->rms_sq))
262  continue;
263  VADD2(h_dir, to_eye, to_light);
264  VUNITIZE(h_dir);
265  cos_tmp = VDOT(h_dir, swp->sw_hit.hit_normal);
266  if (cos_tmp <= 0.0)
267  continue;
268  cos_tmp *= cos_tmp;
269  if (ZERO(cos_tmp))
270  continue;
271 
272  tan_sq = (1.0-cos_tmp)/cos_tmp;
273  exponent = (-tan_sq/ps->rms_sq);
274  refl = ps->specular_refl * lp->lt_fraction * exp(exponent) /
275  sqrt(cosi * cosr) / ps->denom;
276  if (refl > 1.0)
277  refl = 1.0;
278 
279  VELMUL(work, lp->lt_color, intensity);
280  VJOIN1(swp->sw_color, swp->sw_color, refl, work);
281 
282  }
283  }
284 
285  if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
286  (void)rr_render(ap, pp, swp);
287  return 1;
288 }
289 
290 
291 /*
292  * Local Variables:
293  * mode: C
294  * tab-width: 8
295  * indent-tabs-mode: t
296  * c-file-style: "stroustrup"
297  * End:
298  * ex: shiftwidth=4 tabstop=8
299  */
#define BRDF_O(m)
Definition: sh_brdf.c:64
double transmit
Definition: sh_brdf.c:57
struct xray a_ray
Actual ray to be shot.
Definition: raytrace.h:1583
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define MF_MAGIC
Definition: magic.h:205
double extinction
Definition: sh_brdf.c:60
#define VSETALL(a, s)
Definition: color.c:54
#define M_PI
Definition: fft.h:35
struct mfuncs brdf_mfuncs[]
Definition: sh_brdf.c:90
Header file for the BRL-CAD common definitions.
double denom
Definition: sh_brdf.c:56
double refrac_index
Definition: sh_brdf.c:59
const char * reg_name
Identifying string.
Definition: raytrace.h:539
HIDDEN int brdf_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip)
Definition: sh_brdf.c:102
#define HIDDEN
Definition: common.h:86
void bu_struct_print(const char *title, const struct bu_structparse *parsetab, const char *base)
Definition: parse.c:1221
HIDDEN int brdf_render(register struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
Definition: sh_brdf.c:185
uint32_t magic
Definition: sh_brdf.c:51
struct rt_i * a_rt_i
this librt instance
Definition: raytrace.h:1588
#define BU_CK_VLS(_vp)
Definition: vls.h:69
int rti_nlights
number of light sources
Definition: raytrace.h:1760
int a_x
Screen X of ray, if applicable.
Definition: raytrace.h:1596
#define BU_GET(_ptr, _type)
Definition: malloc.h:201
HIDDEN int to_light(struct ged *gedp, int argc, const char *argv[], ged_func_ptr func, const char *usage, int maxargs)
Definition: tclcad_obj.c:6431
int a_level
recursion level (for printing)
Definition: raytrace.h:1595
double specular_refl
Definition: sh_brdf.c:52
#define UNUSED(parameter)
Definition: common.h:239
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
#define BRDF_MAGIC
Definition: sh_brdf.c:62
double rms_sq
Definition: sh_brdf.c:55
#define BU_STRUCTPARSE_FUNC_NULL
Definition: parse.h:153
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
#define ZERO(val)
Definition: units.c:38
#define RDEBUG_SHADE
Definition: optical.h:130
int bu_struct_parse(const struct bu_vls *in_vls, const struct bu_structparse *desc, const char *base, void *data)
Definition: parse.c:878
double diffuse_refl
Definition: sh_brdf.c:53
int a_y
Screen Y of ray, if applicable.
Definition: raytrace.h:1597
HIDDEN void brdf_free(void *cp)
Definition: sh_brdf.c:137
HIDDEN void brdf_print(register struct region *rp, void *dp)
Definition: sh_brdf.c:130
#define RI_AIR
Definition: sh_brdf.c:99
int rr_render(struct application *app, const struct partition *pp, struct shadework *swp)
double rms_slope
Definition: sh_brdf.c:54
Definition: vls.h:56
struct bu_structparse brdf_parse[]
Definition: sh_brdf.c:66
double fastf_t
Definition: defines.h:300
Header file for the BRL-CAD Optical Library, LIBOPTICAL.
double reflect
Definition: sh_brdf.c:58
int rdebug
Definition: init.c:39
double AmbientIntensity
Definition: init.c:40