1
//---------------------------------------------------------------------------------------
2
// Handles image based textures, including environment & shadow maps
3
//---------------------------------------------------------------------------------------
4
// (environmentmaps not yet TODO)
6
#include "ImageTextures.h"
18
//---------------------------------------------------------------------------------------
20
void getTextureColor(RtColor col, const char* texname, float st[8], float A)
22
const TextureCache* const texcache = State::Instance()->getTextureCache();
23
const EXRbuf_t* const texinfo = texcache->getTextureInfo(texname);
24
if (texinfo == NULL) {
25
// texture could not be opened or possibly some other error occured
26
col[0] = col[1] = col[2] = 0.f;
29
// convert to color if texture is actually single channel
30
if (texinfo->numChannels() == 1) {
31
getTextureFloat(col[0], texname, st, A);
32
col[1] = col[2] = col[0];
36
const float cs = (st[0] + st[2] + st[4] + st[6])*0.25f, ct = (st[1] + st[3] + st[5] + st[7])*0.25f;
37
const int wd = texinfo->getWidth(0), ht = texinfo->getHeight(0);
39
float levf = MAX2(0.5f*logf(wd*ht*A)*(float)M_LOG2E, 0.f); // includes sqrt
40
const int maxlevel = texinfo->getLevels() - 2; // -2 to account for trilerp
41
int level = MIN2(FLOORI(levf), maxlevel);
43
// color at current level
44
int wdl = texinfo->getWidth(level), htl = texinfo->getHeight(level);
45
float u0 = wdl*(cs - FLOORF(cs))-0.5f, v0 = htl*(ct - FLOORF(ct))-0.5f;
46
// x0/y0 coords change here depending on wrap type, currently wrap for now
47
int x0 = int(u0) % wdl, y0 = int(v0) % htl;
48
if (x0 < 0) x0 += wdl;
49
if (y0 < 0) y0 += htl;
50
RtColor c00, c10, c01, c11;
51
texcache->getColor(texinfo, x0, y0, level, c00);
52
texcache->getColor(texinfo, x0+1, y0, level, c10);
53
texcache->getColor(texinfo, x0+1, y0+1, level, c11);
54
texcache->getColor(texinfo, x0, y0+1, level, c01);
55
bilerp(col1, u0-x0, v0-y0, c00, c10, c01, c11);
56
// color at next level
58
wdl = texinfo->getWidth(level), htl = texinfo->getHeight(level);
59
u0 = wdl*(cs - FLOORF(cs))-0.5f, v0 = htl*(ct - FLOORF(ct))-0.5f;
60
x0 = int(u0) % wdl, y0 = int(v0) % htl;
61
if (x0 < 0) x0 += wdl;
62
if (y0 < 0) y0 += htl;
63
texcache->getColor(texinfo, x0, y0, level, c00);
64
texcache->getColor(texinfo, x0+1, y0, level, c10);
65
texcache->getColor(texinfo, x0+1, y0+1, level, c11);
66
texcache->getColor(texinfo, x0, y0+1, level, c01);
67
bilerp(col2, u0-x0, v0-y0, c00, c10, c01, c11);
70
col[0] = col1[0] + levf*(col2[0] - col1[0]);
71
col[1] = col1[1] + levf*(col2[1] - col1[1]);
72
col[2] = col1[2] + levf*(col2[2] - col1[2]);
75
// test, samples actual st area at level 0
76
const int wd = texinfo->getWidth(0), ht = texinfo->getHeight(0);
77
const float fxmin = wd*MIN4(st[0], st[2], st[4], st[6]);
78
const float fymin = ht*MIN4(st[1], st[3], st[5], st[7]);
79
const float fxmax = wd*MAX4(st[0], st[2], st[4], st[6]);
80
const float fymax = ht*MAX4(st[1], st[3], st[5], st[7]);
81
const float fw = (fxmax - fxmin), fh = (fymax - fymin);
82
const int xmin = FLOORI(fxmin), ymin = FLOORI(fymin);
83
const int xmax = CEILI(fxmax), ymax = CEILI(fymax);
84
col[0] = col[1] = col[2] = 0.f;
86
for (int y=ymin; y<=ymax; ++y)
87
for (int x=xmin; x<=xmax; ++x) {
88
const float fx = (x - cs*wd), fy = (y - ct*ht);
89
const float wt = RiGaussianFilter(fx, fy, fw, fh);
92
texcache->getColor(texinfo, x, y, 0, tc);
93
col[0] += wt*tc[0], col[1] += wt*tc[1], col[2] += wt*tc[2];
95
const float sd = (wts==0.f) ? 1.f : (1.f/wts);
96
col[0] *= sd, col[1] *= sd, col[2] *= sd;
101
void getTextureFloat(RtFloat& fval, const char* texname, float st[8], float A)
103
const TextureCache* const texcache = State::Instance()->getTextureCache();
104
const EXRbuf_t* const texinfo = texcache->getTextureInfo(texname);
105
if (texinfo == NULL) {
106
// texture could not be opened or possibly some other error occured
110
if (!texinfo->numChannels() == 1) {
111
// actually a color image, return red channel only (could also average or weight channels)
113
getTextureColor(col, texname, st, A);
118
const float cs = (st[0] + st[2] + st[4] + st[6])*0.25f, ct = (st[1] + st[3] + st[5] + st[7])*0.25f;
119
const int wd = texinfo->getWidth(0), ht = texinfo->getHeight(0);
121
float levf = MAX2(0.5f*logf(wd*ht*A)*(float)M_LOG2E, 0.f); // includes sqrt
122
const int maxlevel = texinfo->getLevels() - 2;
123
int level = MIN2(FLOORI(levf), maxlevel);
125
RtFloat fval1, fval2;
126
// value at current level
127
int wdl = texinfo->getWidth(level), htl = texinfo->getHeight(level);
128
float u0 = wdl*(cs - FLOORF(cs))-0.5f, v0 = htl*(ct - FLOORF(ct))-0.5f;
130
int x0 = int(u0) % wdl, y0 = int(v0) % htl;
131
if (x0 < 0) x0 += wdl;
132
if (y0 < 0) y0 += htl;
133
float f00 = texcache->getFloat(texinfo, x0, y0, level);
134
float f10 = texcache->getFloat(texinfo, x0+1, y0, level);
135
float f11 = texcache->getFloat(texinfo, x0+1, y0+1, level);
136
float f01 = texcache->getFloat(texinfo, x0, y0+1, level);
137
bilerpF(fval1, u0-x0, v0-y0, f00, f10, f01, f11);
138
// value at next level
140
wdl = texinfo->getWidth(level), htl = texinfo->getHeight(level);
141
u0 = wdl*(cs - FLOORF(cs))-0.5f, v0 = htl*(ct - FLOORF(ct))-0.5f;
142
x0 = int(u0) % wdl, y0 = int(v0) % htl;
143
if (x0 < 0) x0 += wdl;
144
if (y0 < 0) y0 += htl;
145
f00 = texcache->getFloat(texinfo, x0, y0, level);
146
f10 = texcache->getFloat(texinfo, x0+1, y0, level);
147
f11 = texcache->getFloat(texinfo, x0+1, y0+1, level);
148
f01 = texcache->getFloat(texinfo, x0, y0+1, level);
149
bilerpF(fval2, u0-x0, v0-y0, f00, f10, f01, f11);
151
levf -= FLOORF(levf);
152
fval = fval1 + levf*(fval2 - fval1);
156
float getShadowFactor(const char* texname, float st[8], const RtPoint& wldP, float* samples, float* blur, float* bias)
158
const TextureCache* const texcache = State::Instance()->getTextureCache();
159
const EXRbuf_t* const texinfo = texcache->getTextureInfo(texname);
160
if (texinfo == NULL) return 0.f; // texture could not be opened or possibly some other error occured
162
mulPMP(ltP, texinfo->get_w2c(), wldP);
163
const float wz = bias ? (ltP[2] - *bias) : (ltP[2] - 0.01f); // 0.01 default bias
164
const RtMatrix& c2r = texinfo->get_c2r();
165
if (texinfo->isOrtho()) {
166
ltP[0] = c2r[0][0]*ltP[0] + c2r[0][1]*ltP[1] + c2r[0][2]*ltP[2] + c2r[0][3];
167
ltP[1] = c2r[1][0]*ltP[0] + c2r[1][1]*ltP[1] + c2r[1][2]*ltP[2] + c2r[1][3];
170
ltP[0] = c2r[0][0]*ltP[0] + c2r[0][1]*ltP[1] + c2r[0][2]*ltP[2];
171
ltP[1] = c2r[1][0]*ltP[0] + c2r[1][1]*ltP[1] + c2r[1][2]*ltP[2];
172
if (ltP[2] != 0.f) { ltP[2] = 1.f/ltP[2]; ltP[0] *= ltP[2]; ltP[1] *= ltP[2]; }
174
const float blur_rad = blur ? (*blur)*0.5f : 0;
175
const float maxwd = float(texinfo->getWidth() - 1), maxht = float(texinfo->getHeight() - 1);
176
const float xmin = MIN2(MAX2(ltP[0] - blur_rad, 0.f), maxwd);
177
const float xmax = MIN2(MAX2(ltP[0] + blur_rad, 0.f), maxwd);
178
const float ymin = MIN2(MAX2(ltP[1] - blur_rad, 0.f), maxht);
179
const float ymax = MIN2(MAX2(ltP[1] + blur_rad, 0.f), maxht);
180
const float dx = xmax - xmin, dy = ymax - ymin;
181
if ((dx < 0.f) || (dy < 0.f)) return 0.f;
182
const int numsam = samples ? int(*samples) : 1; // single sample default
183
const float sdiv = 1.f/(float)numsam;
185
//static unsigned int VDCC = 0, SBC = 0;
186
static Halton H2(2), H3(3);
187
for (int sm=0; sm<numsam; ++sm) {
189
if (ts == 16) return 0.f;
190
if (ts == 0) return 1.f;
192
const float zval = texcache->getDepth(texinfo, int(xmin + H2.getNext()*dx), int(ymin + H3.getNext()*dy));
193
//const float zval = texcache->getDepth(texinfo, int(xmin + RI_vdC(++VDCC)*dx), int(ymin + RI_Sb(++SBC)*dy));
194
//const float zval = texcache->getDepth(texinfo, int(xmin + RI_vdC(++VDCC)*dx), int(ymin + (sm + 0.5f)*sdiv*dy));
195
//const float zval = texcache->getDepth(texinfo, int(xmin + frand()*dx), int(ymin + frand()*dy));
196
// zval <= 0.f is invalid access return value of getFloat()
197
ts += (zval > 0.f) ? ((zval < wz) ? 0 : 1) : 0;
199
return 1.f - ts*sdiv;