Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F86314031
aniso.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Oct 5, 18:40
Size
12 KB
Mime Type
text/x-c
Expires
Mon, Oct 7, 18:40 (2 d)
Engine
blob
Format
Raw Data
Handle
21398465
Attached To
R10977 RADIANCE Photon Map
aniso.c
View Options
#ifndef lint
static
const
char
RCSid
[]
=
"$Id: aniso.c,v 2.61 2015/09/02 18:59:01 greg Exp $"
;
#endif
/*
* Shading functions for anisotropic materials.
*/
#include "copyright.h"
#include "ray.h"
#include "ambient.h"
#include "otypes.h"
#include "rtotypes.h"
#include "source.h"
#include "func.h"
#include "random.h"
#include "pmapmat.h"
#ifndef MAXITER
#define MAXITER 10
/* maximum # specular ray attempts */
#endif
/*
* This routine implements the anisotropic Gaussian
* model described by Ward in Siggraph `92 article, updated with
* normalization and sampling adjustments due to Geisler-Moroder and Duer.
* We orient the surface towards the incoming ray, so a single
* surface can be used to represent an infinitely thin object.
*
* Arguments for MAT_PLASTIC2 and MAT_METAL2 are:
* 4+ ux uy uz funcfile [transform...]
* 0
* 6 red grn blu specular-frac. u-rough v-rough
*
* Real arguments for MAT_TRANS2 are:
* 8 red grn blu rspec u-rough v-rough trans tspec
*/
/* specularity flags */
#define SP_REFL 01
/* has reflected specular component */
#define SP_TRAN 02
/* has transmitted specular */
#define SP_FLAT 04
/* reflecting surface is flat */
#define SP_RBLT 010
/* reflection below sample threshold */
#define SP_TBLT 020
/* transmission below threshold */
typedef
struct
{
OBJREC
*
mp
;
/* material pointer */
RAY
*
rp
;
/* ray pointer */
short
specfl
;
/* specularity flags, defined above */
COLOR
mcolor
;
/* color of this material */
COLOR
scolor
;
/* color of specular component */
FVECT
vrefl
;
/* vector in reflected direction */
FVECT
prdir
;
/* vector in transmitted direction */
FVECT
u
,
v
;
/* u and v vectors orienting anisotropy */
double
u_alpha
;
/* u roughness */
double
v_alpha
;
/* v roughness */
double
rdiff
,
rspec
;
/* reflected specular, diffuse */
double
trans
;
/* transmissivity */
double
tdiff
,
tspec
;
/* transmitted specular, diffuse */
FVECT
pnorm
;
/* perturbed surface normal */
double
pdot
;
/* perturbed dot product */
}
ANISODAT
;
/* anisotropic material data */
static
void
getacoords
(
ANISODAT
*
np
);
static
void
agaussamp
(
ANISODAT
*
np
);
static
void
diraniso
(
/* compute source contribution */
COLOR
cval
,
/* returned coefficient */
void
*
nnp
,
/* material data */
FVECT
ldir
,
/* light source direction */
double
omega
/* light source size */
)
{
ANISODAT
*
np
=
nnp
;
double
ldot
;
double
dtmp
,
dtmp1
,
dtmp2
;
FVECT
h
;
double
au2
,
av2
;
COLOR
ctmp
;
setcolor
(
cval
,
0.0
,
0.0
,
0.0
);
ldot
=
DOT
(
np
->
pnorm
,
ldir
);
if
(
ldot
<
0.0
?
np
->
trans
<=
FTINY
:
np
->
trans
>=
1.0
-
FTINY
)
return
;
/* wrong side */
if
((
ldot
>
FTINY
)
&
(
np
->
rdiff
>
FTINY
))
{
/*
* Compute and add diffuse reflected component to returned
* color. The diffuse reflected component will always be
* modified by the color of the material.
*/
copycolor
(
ctmp
,
np
->
mcolor
);
dtmp
=
ldot
*
omega
*
np
->
rdiff
*
(
1.0
/
PI
);
scalecolor
(
ctmp
,
dtmp
);
addcolor
(
cval
,
ctmp
);
}
if
((
ldot
<
-
FTINY
)
&
(
np
->
tdiff
>
FTINY
))
{
/*
* Compute diffuse transmission.
*/
copycolor
(
ctmp
,
np
->
mcolor
);
dtmp
=
-
ldot
*
omega
*
np
->
tdiff
*
(
1.0
/
PI
);
scalecolor
(
ctmp
,
dtmp
);
addcolor
(
cval
,
ctmp
);
}
if
(
ambRayInPmap
(
np
->
rp
))
return
;
/* specular accounted for in photon map */
if
(
ldot
>
FTINY
&&
np
->
specfl
&
SP_REFL
)
{
/*
* Compute specular reflection coefficient using
* anisotropic Gaussian distribution model.
*/
/* add source width if flat */
if
(
np
->
specfl
&
SP_FLAT
)
au2
=
av2
=
omega
*
(
0.25
/
PI
);
else
au2
=
av2
=
0.0
;
au2
+=
np
->
u_alpha
*
np
->
u_alpha
;
av2
+=
np
->
v_alpha
*
np
->
v_alpha
;
/* half vector */
VSUB
(
h
,
ldir
,
np
->
rp
->
rdir
);
/* ellipse */
dtmp1
=
DOT
(
np
->
u
,
h
);
dtmp1
*=
dtmp1
/
au2
;
dtmp2
=
DOT
(
np
->
v
,
h
);
dtmp2
*=
dtmp2
/
av2
;
/* new W-G-M-D model */
dtmp
=
DOT
(
np
->
pnorm
,
h
);
dtmp
*=
dtmp
;
dtmp1
=
(
dtmp1
+
dtmp2
)
/
dtmp
;
dtmp
=
exp
(
-
dtmp1
)
*
DOT
(
h
,
h
)
/
(
PI
*
dtmp
*
dtmp
*
sqrt
(
au2
*
av2
));
/* worth using? */
if
(
dtmp
>
FTINY
)
{
copycolor
(
ctmp
,
np
->
scolor
);
dtmp
*=
ldot
*
omega
;
scalecolor
(
ctmp
,
dtmp
);
addcolor
(
cval
,
ctmp
);
}
}
if
(
ldot
<
-
FTINY
&&
np
->
specfl
&
SP_TRAN
)
{
/*
* Compute specular transmission. Specular transmission
* is always modified by material color.
*/
/* roughness + source */
au2
=
av2
=
omega
*
(
1.0
/
PI
);
au2
+=
np
->
u_alpha
*
np
->
u_alpha
;
av2
+=
np
->
v_alpha
*
np
->
v_alpha
;
/* "half vector" */
VSUB
(
h
,
ldir
,
np
->
prdir
);
dtmp
=
DOT
(
h
,
h
);
if
(
dtmp
>
FTINY
*
FTINY
)
{
dtmp1
=
DOT
(
h
,
np
->
pnorm
);
dtmp
=
1.0
-
dtmp1
*
dtmp1
/
dtmp
;
if
(
dtmp
>
FTINY
*
FTINY
)
{
dtmp1
=
DOT
(
h
,
np
->
u
);
dtmp1
*=
dtmp1
/
au2
;
dtmp2
=
DOT
(
h
,
np
->
v
);
dtmp2
*=
dtmp2
/
av2
;
dtmp
=
(
dtmp1
+
dtmp2
)
/
dtmp
;
}
}
else
dtmp
=
0.0
;
/* Gaussian */
dtmp
=
exp
(
-
dtmp
)
*
(
1.0
/
PI
)
*
sqrt
(
-
ldot
/
(
np
->
pdot
*
au2
*
av2
));
/* worth using? */
if
(
dtmp
>
FTINY
)
{
copycolor
(
ctmp
,
np
->
mcolor
);
dtmp
*=
np
->
tspec
*
omega
;
scalecolor
(
ctmp
,
dtmp
);
addcolor
(
cval
,
ctmp
);
}
}
}
int
m_aniso
(
/* shade ray that hit something anisotropic */
OBJREC
*
m
,
RAY
*
r
)
{
ANISODAT
nd
;
COLOR
ctmp
;
int
i
;
/* easy shadow test */
if
(
r
->
crtype
&
SHADOW
)
return
(
1
);
if
(
m
->
oargs
.
nfargs
!=
(
m
->
otype
==
MAT_TRANS2
?
8
:
6
))
objerror
(
m
,
USER
,
"bad number of real arguments"
);
/* check for back side */
if
(
r
->
rod
<
0.0
)
{
if
(
!
backvis
)
{
raytrans
(
r
);
return
(
1
);
}
raytexture
(
r
,
m
->
omod
);
flipsurface
(
r
);
/* reorient if backvis */
}
else
raytexture
(
r
,
m
->
omod
);
/* get material color */
nd
.
mp
=
m
;
nd
.
rp
=
r
;
setcolor
(
nd
.
mcolor
,
m
->
oargs
.
farg
[
0
],
m
->
oargs
.
farg
[
1
],
m
->
oargs
.
farg
[
2
]);
/* get roughness */
nd
.
specfl
=
0
;
nd
.
u_alpha
=
m
->
oargs
.
farg
[
4
];
nd
.
v_alpha
=
m
->
oargs
.
farg
[
5
];
if
((
nd
.
u_alpha
<=
FTINY
)
|
(
nd
.
v_alpha
<=
FTINY
))
objerror
(
m
,
USER
,
"roughness too small"
);
nd
.
pdot
=
raynormal
(
nd
.
pnorm
,
r
);
/* perturb normal */
if
(
nd
.
pdot
<
.001
)
nd
.
pdot
=
.001
;
/* non-zero for diraniso() */
multcolor
(
nd
.
mcolor
,
r
->
pcol
);
/* modify material color */
/* get specular component */
if
((
nd
.
rspec
=
m
->
oargs
.
farg
[
3
])
>
FTINY
)
{
nd
.
specfl
|=
SP_REFL
;
/* compute specular color */
if
(
m
->
otype
==
MAT_METAL2
)
copycolor
(
nd
.
scolor
,
nd
.
mcolor
);
else
setcolor
(
nd
.
scolor
,
1.0
,
1.0
,
1.0
);
scalecolor
(
nd
.
scolor
,
nd
.
rspec
);
/* check threshold */
if
(
specthresh
>=
nd
.
rspec
-
FTINY
)
nd
.
specfl
|=
SP_RBLT
;
/* compute refl. direction */
VSUM
(
nd
.
vrefl
,
r
->
rdir
,
nd
.
pnorm
,
2.0
*
nd
.
pdot
);
if
(
DOT
(
nd
.
vrefl
,
r
->
ron
)
<=
FTINY
)
/* penetration? */
VSUM
(
nd
.
vrefl
,
r
->
rdir
,
r
->
ron
,
2.0
*
r
->
rod
);
}
/* compute transmission */
if
(
m
->
otype
==
MAT_TRANS2
)
{
nd
.
trans
=
m
->
oargs
.
farg
[
6
]
*
(
1.0
-
nd
.
rspec
);
nd
.
tspec
=
nd
.
trans
*
m
->
oargs
.
farg
[
7
];
nd
.
tdiff
=
nd
.
trans
-
nd
.
tspec
;
if
(
nd
.
tspec
>
FTINY
)
{
nd
.
specfl
|=
SP_TRAN
;
/* check threshold */
if
(
specthresh
>=
nd
.
tspec
-
FTINY
)
nd
.
specfl
|=
SP_TBLT
;
if
(
DOT
(
r
->
pert
,
r
->
pert
)
<=
FTINY
*
FTINY
)
{
VCOPY
(
nd
.
prdir
,
r
->
rdir
);
}
else
{
for
(
i
=
0
;
i
<
3
;
i
++
)
/* perturb */
nd
.
prdir
[
i
]
=
r
->
rdir
[
i
]
-
r
->
pert
[
i
];
if
(
DOT
(
nd
.
prdir
,
r
->
ron
)
<
-
FTINY
)
normalize
(
nd
.
prdir
);
/* OK */
else
VCOPY
(
nd
.
prdir
,
r
->
rdir
);
}
}
}
else
nd
.
tdiff
=
nd
.
tspec
=
nd
.
trans
=
0.0
;
/* diffuse reflection */
nd
.
rdiff
=
1.0
-
nd
.
trans
-
nd
.
rspec
;
if
(
r
->
ro
!=
NULL
&&
isflat
(
r
->
ro
->
otype
))
nd
.
specfl
|=
SP_FLAT
;
getacoords
(
&
nd
);
/* set up coordinates */
if
(
nd
.
specfl
&
(
SP_REFL
|
SP_TRAN
))
agaussamp
(
&
nd
);
if
(
nd
.
rdiff
>
FTINY
)
{
/* ambient from this side */
copycolor
(
ctmp
,
nd
.
mcolor
);
/* modified by material color */
scalecolor
(
ctmp
,
nd
.
rdiff
);
if
(
nd
.
specfl
&
SP_RBLT
)
/* add in specular as well? */
addcolor
(
ctmp
,
nd
.
scolor
);
multambient
(
ctmp
,
r
,
nd
.
pnorm
);
addcolor
(
r
->
rcol
,
ctmp
);
/* add to returned color */
}
if
(
nd
.
tdiff
>
FTINY
)
{
/* ambient from other side */
FVECT
bnorm
;
flipsurface
(
r
);
bnorm
[
0
]
=
-
nd
.
pnorm
[
0
];
bnorm
[
1
]
=
-
nd
.
pnorm
[
1
];
bnorm
[
2
]
=
-
nd
.
pnorm
[
2
];
copycolor
(
ctmp
,
nd
.
mcolor
);
/* modified by color */
if
(
nd
.
specfl
&
SP_TBLT
)
scalecolor
(
ctmp
,
nd
.
trans
);
else
scalecolor
(
ctmp
,
nd
.
tdiff
);
multambient
(
ctmp
,
r
,
bnorm
);
addcolor
(
r
->
rcol
,
ctmp
);
flipsurface
(
r
);
}
/* add direct component */
direct
(
r
,
diraniso
,
&
nd
);
return
(
1
);
}
static
void
getacoords
(
/* set up coordinate system */
ANISODAT
*
np
)
{
MFUNC
*
mf
;
int
i
;
mf
=
getfunc
(
np
->
mp
,
3
,
0x7
,
1
);
setfunc
(
np
->
mp
,
np
->
rp
);
errno
=
0
;
for
(
i
=
0
;
i
<
3
;
i
++
)
np
->
u
[
i
]
=
evalue
(
mf
->
ep
[
i
]);
if
((
errno
==
EDOM
)
|
(
errno
==
ERANGE
))
np
->
u
[
0
]
=
np
->
u
[
1
]
=
np
->
u
[
2
]
=
0.0
;
if
(
mf
->
fxp
!=
&
unitxf
)
multv3
(
np
->
u
,
np
->
u
,
mf
->
fxp
->
xfm
);
fcross
(
np
->
v
,
np
->
pnorm
,
np
->
u
);
if
(
normalize
(
np
->
v
)
==
0.0
)
{
if
(
fabs
(
np
->
u_alpha
-
np
->
v_alpha
)
>
0.001
)
objerror
(
np
->
mp
,
WARNING
,
"illegal orientation vector"
);
getperpendicular
(
np
->
u
,
np
->
pnorm
,
1
);
/* punting */
fcross
(
np
->
v
,
np
->
pnorm
,
np
->
u
);
np
->
u_alpha
=
np
->
v_alpha
=
sqrt
(
0.5
*
(
np
->
u_alpha
*
np
->
u_alpha
+
np
->
v_alpha
*
np
->
v_alpha
)
);
}
else
fcross
(
np
->
u
,
np
->
v
,
np
->
pnorm
);
}
static
void
agaussamp
(
/* sample anisotropic Gaussian specular */
ANISODAT
*
np
)
{
RAY
sr
;
FVECT
h
;
double
rv
[
2
];
double
d
,
sinp
,
cosp
;
COLOR
scol
;
int
maxiter
,
ntrials
,
nstarget
,
nstaken
;
int
i
;
/* compute reflection */
if
((
np
->
specfl
&
(
SP_REFL
|
SP_RBLT
))
==
SP_REFL
&&
rayorigin
(
&
sr
,
SPECULAR
,
np
->
rp
,
np
->
scolor
)
==
0
)
{
nstarget
=
1
;
if
(
specjitter
>
1.5
)
{
/* multiple samples? */
nstarget
=
specjitter
*
np
->
rp
->
rweight
+
.5
;
if
(
sr
.
rweight
<=
minweight
*
nstarget
)
nstarget
=
sr
.
rweight
/
minweight
;
if
(
nstarget
>
1
)
{
d
=
1.
/
nstarget
;
scalecolor
(
sr
.
rcoef
,
d
);
sr
.
rweight
*=
d
;
}
else
nstarget
=
1
;
}
setcolor
(
scol
,
0.
,
0.
,
0.
);
dimlist
[
ndims
++
]
=
(
int
)(
size_t
)
np
->
mp
;
maxiter
=
MAXITER
*
nstarget
;
for
(
nstaken
=
ntrials
=
0
;
nstaken
<
nstarget
&&
ntrials
<
maxiter
;
ntrials
++
)
{
if
(
ntrials
)
d
=
frandom
();
else
d
=
urand
(
ilhash
(
dimlist
,
ndims
)
+
samplendx
);
multisamp
(
rv
,
2
,
d
);
d
=
2.0
*
PI
*
rv
[
0
];
cosp
=
tcos
(
d
)
*
np
->
u_alpha
;
sinp
=
tsin
(
d
)
*
np
->
v_alpha
;
d
=
1.
/
sqrt
(
cosp
*
cosp
+
sinp
*
sinp
);
cosp
*=
d
;
sinp
*=
d
;
if
((
0.
<=
specjitter
)
&
(
specjitter
<
1.
))
rv
[
1
]
=
1.0
-
specjitter
*
rv
[
1
];
if
(
rv
[
1
]
<=
FTINY
)
d
=
1.0
;
else
d
=
sqrt
(
-
log
(
rv
[
1
])
/
(
cosp
*
cosp
/
(
np
->
u_alpha
*
np
->
u_alpha
)
+
sinp
*
sinp
/
(
np
->
v_alpha
*
np
->
v_alpha
)));
for
(
i
=
0
;
i
<
3
;
i
++
)
h
[
i
]
=
np
->
pnorm
[
i
]
+
d
*
(
cosp
*
np
->
u
[
i
]
+
sinp
*
np
->
v
[
i
]);
d
=
-
2.0
*
DOT
(
h
,
np
->
rp
->
rdir
)
/
(
1.0
+
d
*
d
);
VSUM
(
sr
.
rdir
,
np
->
rp
->
rdir
,
h
,
d
);
/* sample rejection test */
if
((
d
=
DOT
(
sr
.
rdir
,
np
->
rp
->
ron
))
<=
FTINY
)
continue
;
checknorm
(
sr
.
rdir
);
if
(
nstarget
>
1
)
{
/* W-G-M-D adjustment */
if
(
nstaken
)
rayclear
(
&
sr
);
rayvalue
(
&
sr
);
d
=
2.
/
(
1.
+
np
->
rp
->
rod
/
d
);
scalecolor
(
sr
.
rcol
,
d
);
addcolor
(
scol
,
sr
.
rcol
);
}
else
{
rayvalue
(
&
sr
);
multcolor
(
sr
.
rcol
,
sr
.
rcoef
);
addcolor
(
np
->
rp
->
rcol
,
sr
.
rcol
);
}
++
nstaken
;
}
if
(
nstarget
>
1
)
{
/* final W-G-M-D weighting */
multcolor
(
scol
,
sr
.
rcoef
);
d
=
(
double
)
nstarget
/
ntrials
;
scalecolor
(
scol
,
d
);
addcolor
(
np
->
rp
->
rcol
,
scol
);
}
ndims
--
;
}
/* compute transmission */
copycolor
(
sr
.
rcoef
,
np
->
mcolor
);
/* modify by material color */
scalecolor
(
sr
.
rcoef
,
np
->
tspec
);
if
((
np
->
specfl
&
(
SP_TRAN
|
SP_TBLT
))
==
SP_TRAN
&&
rayorigin
(
&
sr
,
SPECULAR
,
np
->
rp
,
sr
.
rcoef
)
==
0
)
{
nstarget
=
1
;
if
(
specjitter
>
1.5
)
{
/* multiple samples? */
nstarget
=
specjitter
*
np
->
rp
->
rweight
+
.5
;
if
(
sr
.
rweight
<=
minweight
*
nstarget
)
nstarget
=
sr
.
rweight
/
minweight
;
if
(
nstarget
>
1
)
{
d
=
1.
/
nstarget
;
scalecolor
(
sr
.
rcoef
,
d
);
sr
.
rweight
*=
d
;
}
else
nstarget
=
1
;
}
dimlist
[
ndims
++
]
=
(
int
)(
size_t
)
np
->
mp
;
maxiter
=
MAXITER
*
nstarget
;
for
(
nstaken
=
ntrials
=
0
;
nstaken
<
nstarget
&&
ntrials
<
maxiter
;
ntrials
++
)
{
if
(
ntrials
)
d
=
frandom
();
else
d
=
urand
(
ilhash
(
dimlist
,
ndims
)
+
1823
+
samplendx
);
multisamp
(
rv
,
2
,
d
);
d
=
2.0
*
PI
*
rv
[
0
];
cosp
=
tcos
(
d
)
*
np
->
u_alpha
;
sinp
=
tsin
(
d
)
*
np
->
v_alpha
;
d
=
1.
/
sqrt
(
cosp
*
cosp
+
sinp
*
sinp
);
cosp
*=
d
;
sinp
*=
d
;
if
((
0.
<=
specjitter
)
&
(
specjitter
<
1.
))
rv
[
1
]
=
1.0
-
specjitter
*
rv
[
1
];
if
(
rv
[
1
]
<=
FTINY
)
d
=
1.0
;
else
d
=
sqrt
(
-
log
(
rv
[
1
])
/
(
cosp
*
cosp
/
(
np
->
u_alpha
*
np
->
u_alpha
)
+
sinp
*
sinp
/
(
np
->
v_alpha
*
np
->
v_alpha
)));
for
(
i
=
0
;
i
<
3
;
i
++
)
sr
.
rdir
[
i
]
=
np
->
prdir
[
i
]
+
d
*
(
cosp
*
np
->
u
[
i
]
+
sinp
*
np
->
v
[
i
]);
if
(
DOT
(
sr
.
rdir
,
np
->
rp
->
ron
)
>=
-
FTINY
)
continue
;
normalize
(
sr
.
rdir
);
/* OK, normalize */
if
(
nstaken
)
/* multi-sampling */
rayclear
(
&
sr
);
rayvalue
(
&
sr
);
multcolor
(
sr
.
rcol
,
sr
.
rcoef
);
addcolor
(
np
->
rp
->
rcol
,
sr
.
rcol
);
++
nstaken
;
}
ndims
--
;
}
}
Event Timeline
Log In to Comment