Page MenuHome

ibl06.txt

File Metadata

Author
Matt Ebb (broken)
Created
Nov 13 2013, 1:18 PM

ibl06.txt

Index: source/blender/render/intern/source/occlusion.c
===================================================================
--- source/blender/render/intern/source/occlusion.c (revision 14978)
+++ source/blender/render/intern/source/occlusion.c (working copy)
@@ -1341,7 +1341,7 @@
skycol[2]= (1.0f-fac)*re->wrld.horb + fac*re->wrld.zenb;
}
#if 0
- else { /* WO_AOSKYTEX */
+ else if (aocolor == WO_AOSKYTEX) {
float dxyview[3];
bn[0]= -bn[0];
bn[1]= -bn[1];
@@ -1350,8 +1350,15 @@
dxyview[1]= 1.0f;
dxyview[2]= 0.0f;
shadeSkyView(skycol, co, bn, dxyview);
+#endif
+ else { /* WO_AODIFFUSESH */
+ float bentnor[3];
+
+ VECCOPY(bentnor, bn);
+ Mat4Mul3Vecfl(re->viewinv, bentnor);
+
+ IBL_diffusesh_getcolor(skycol, (float *)re->ibl_sh_coeffs, bentnor);
}
-#endif
VecMulf(skycol, occlusion);
}
Index: source/blender/render/intern/source/rayshade.c
===================================================================
--- source/blender/render/intern/source/rayshade.c (revision 14978)
+++ source/blender/render/intern/source/rayshade.c (working copy)
@@ -1536,6 +1536,9 @@
float dxyview[3], skyadded=0, div;
int aocolor;
+ float bentnor[3];
+ int noradded=0;
+
isec.faceorig= (RayFace*)shi->vlr;
isec.oborig= RAY_OBJECT_SET(&R, shi->obi);
isec.face_last= NULL;
@@ -1544,6 +1547,7 @@
isec.lay= -1;
shadfac[0]= shadfac[1]= shadfac[2]= 0.0f;
+ bentnor[0]= bentnor[1]= bentnor[2]= 0.0f;
/* prevent sky colors to be added for only shadow (shadow becomes alpha) */
aocolor= R.wrld.aocolor;
@@ -1604,29 +1608,35 @@
if(RE_ray_tree_intersect(R.raytree, &isec)) {
if (R.wrld.aomode & WO_AODIST) fac+= exp(-isec.labda*R.wrld.aodistfac);
else fac+= 1.0f;
- }
- else if(aocolor!=WO_AOPLAIN) {
- float skycol[4];
- float skyfac, view[3];
+ } else {
- view[0]= -dir[0];
- view[1]= -dir[1];
- view[2]= -dir[2];
- Normalize(view);
-
- if(aocolor==WO_AOSKYCOL) {
- skyfac= 0.5*(1.0f+view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2]);
- shadfac[0]+= (1.0f-skyfac)*R.wrld.horr + skyfac*R.wrld.zenr;
- shadfac[1]+= (1.0f-skyfac)*R.wrld.horg + skyfac*R.wrld.zeng;
- shadfac[2]+= (1.0f-skyfac)*R.wrld.horb + skyfac*R.wrld.zenb;
+
+ if(aocolor!=WO_AOPLAIN) {
+ float skycol[4];
+ float skyfac, view[3];
+
+ view[0]= -dir[0];
+ view[1]= -dir[1];
+ view[2]= -dir[2];
+ Normalize(view);
+
+ VecAddf(bentnor, bentnor, view);
+ noradded++;
+
+ if(aocolor==WO_AOSKYCOL) {
+ skyfac= 0.5*(1.0f+view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2]);
+ shadfac[0]+= (1.0f-skyfac)*R.wrld.horr + skyfac*R.wrld.zenr;
+ shadfac[1]+= (1.0f-skyfac)*R.wrld.horg + skyfac*R.wrld.zeng;
+ shadfac[2]+= (1.0f-skyfac)*R.wrld.horb + skyfac*R.wrld.zenb;
+ }
+ else if (aocolor==WO_AOSKYTEX) {
+ shadeSkyView(skycol, isec.start, view, dxyview);
+ shadfac[0]+= skycol[0];
+ shadfac[1]+= skycol[1];
+ shadfac[2]+= skycol[2];
+ }
+ skyadded++;
}
- else { /* WO_AOSKYTEX */
- shadeSkyView(skycol, isec.start, view, dxyview);
- shadfac[0]+= skycol[0];
- shadfac[1]+= skycol[1];
- shadfac[2]+= skycol[2];
- }
- skyadded++;
}
samples++;
@@ -1642,9 +1652,22 @@
}
}
- if(aocolor!=WO_AOPLAIN && skyadded) {
- div= (1.0f - fac/(float)samples)/((float)skyadded);
+ if (aocolor == WO_AODIFFUSESH && G.rt!=1 && noradded > 0) {
+ VecMulf(bentnor, (1.0f / (float)noradded));
+ Mat4Mul3Vecfl(R.viewinv, bentnor);
+
+ IBL_diffusesh_getcolor(shadfac, (float *)R.ibl_sh_coeffs, bentnor);
+
+ /* multiply by inverse proportion of geom hits, so rays that hit more other faces are darker */
+ div = (float)noradded / (float)samples * exp(R.wrld.aodistfac);
+
+ VecMulf(shadfac, div);
+
+ }
+ else if(aocolor!=WO_AOPLAIN && skyadded) {
+ div= (1.0f - fac/(float)noradded)/(float)samples;
+
shadfac[0]*= div; // average color times distances/hits formula
shadfac[1]*= div; // average color times distances/hits formula
shadfac[2]*= div; // average color times distances/hits formula
Index: source/blender/render/intern/source/texture.c
===================================================================
--- source/blender/render/intern/source/texture.c (revision 14978)
+++ source/blender/render/intern/source/texture.c (working copy)
@@ -1862,6 +1862,11 @@
shi->vn[0]+= dot*nor[0];
shi->vn[1]+= dot*nor[1];
shi->vn[2]+= dot*nor[2];
+
+ /* make worldspace copy */
+ VECCOPY(nor, shi->vn);
+ Mat4Mul3Vecfl(R.viewinv, nor);
+ VECCOPY(shi->worldnor, nor);
}
Normalize(shi->vn);
Index: source/blender/render/intern/source/shadeinput.c
===================================================================
--- source/blender/render/intern/source/shadeinput.c (revision 14978)
+++ source/blender/render/intern/source/shadeinput.c (working copy)
@@ -764,6 +764,11 @@
else
VECCOPY(shi->vn, shi->facenor);
+ /* normal in worldspace, used in Diffuse SH IBL, and nodes */
+ VECCOPY(shi->worldnor, shi->vn);
+ Mat4Mul3Vecfl(R.viewinv, shi->worldnor);
+ VecMulf(shi->worldnor, -1.0f);
+
/* used in nodes */
VECCOPY(shi->vno, shi->vn);
Index: source/blender/render/intern/source/shadeoutput.c
===================================================================
--- source/blender/render/intern/source/shadeoutput.c (revision 14978)
+++ source/blender/render/intern/source/shadeoutput.c (working copy)
@@ -1004,6 +1004,29 @@
}
}
+
+void image_based_lighting(ShadeInput *shi, ShadeResult *shr)
+{
+ float iblcol[3], worldnor[3];
+
+ VECCOPY(worldnor, shi->vn);
+ Mat4Mul3Vecfl(R.viewinv, worldnor);
+ VecMulf(worldnor, -1.0f);
+
+
+ if (R.wrld.ibl_method == WO_IBL_DIFFUSESH) {
+ IBL_diffusesh_getcolor(iblcol, (float *)R.ibl_sh_coeffs, worldnor);
+ }
+ else if (R.wrld.ibl_method == WO_IBL_IMPORTANCE) {
+ IBL_getcolor_importance(iblcol, &R, worldnor);
+ }
+
+ VecMulf(iblcol, R.wrld.ibl_multiplier);
+
+ add_to_diffuse(shr->shad, shi, 1.0f, iblcol[0], iblcol[1], iblcol[2]);
+}
+
+
/* pure AO, check for raytrace and world should have been done */
void ambient_occlusion(ShadeInput *shi)
{
@@ -1607,6 +1630,9 @@
}
}
+ if(R.wrld.mode & WO_IMAGE_BASED_LIGHTING)
+ image_based_lighting(shi, shr);
+
/* lighting pass */
if(passflag & (SCE_PASS_COMBINED|SCE_PASS_DIFFUSE|SCE_PASS_SPEC|SCE_PASS_SHADOW)) {
GroupObject *go;
Index: source/blender/render/intern/source/ibl.c
===================================================================
--- source/blender/render/intern/source/ibl.c (revision 0)
+++ source/blender/render/intern/source/ibl.c (revision 0)
@@ -0,0 +1,444 @@
+/**
+* $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Matt Ebb
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "DNA_image_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_image.h"
+#include "BKE_global.h"
+
+/* local include */
+#include "render_types.h"
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
+/* only to be used here in this file, it's for speed */
+extern struct Render R;
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+float sinc(float x) {
+ if (fabs(x) < 1.0e-4) return 1.0 ;
+ else return(sin(x)/x) ;
+}
+
+
+/* Converts UV coordinates from an environment map to the equivalent 3D vector
+ * Incoming UV coordinates are considered to be in [-1,1]
+ * domega = the solid angle that pixel represents in the unit sphere
+ * returns 1 if the pixel actually represents anything in the env map
+ * eg. pixels within the unit circle of an angmap */
+static int uv_to_xyz(int mapping, float *uv, float *xyz, float dtheta_dphi, float *domega)
+{
+ float phi, theta, sinphi, sintheta;
+ float radius_sq=1.0f;
+
+ float u = uv[0];
+ float v = uv[1];
+
+ switch(mapping)
+ {
+ case WO_IBL_MAP_SPHERE:
+ phi = (v*0.5f+0.5f)*M_PI; // pi < phi < 0
+ theta = -u*M_PI; // pi < theta < -pi
+
+ /* transform u,v to cartesian components */
+ sinphi = sin(phi);
+ xyz[0] = -sinphi * sin(theta);
+ xyz[1] = sinphi * cos(theta);
+ xyz[2] = -cos(phi);
+
+ /* solid angle */
+ if (domega) *domega = sinphi*dtheta_dphi;
+ break;
+
+ case WO_IBL_MAP_ANGMAP:
+ default:
+ /* for angmap, only consider points inside the unit circle */
+ radius_sq = u*u + v*v;
+ if(radius_sq>1.0f) return 0;
+
+ theta = M_PI*sqrt(radius_sq);
+ phi = atan2(v,u);
+
+ /* transform u,v to cartesian components */
+ sintheta = sin(theta);
+ xyz[0] = sintheta*cos(phi);
+ xyz[1] = cos(theta);
+ xyz[2] = sintheta*sin(phi);
+
+ /* solid angle */
+ if (domega) *domega = sinc(theta)*dtheta_dphi;
+ break;
+ }
+
+ return 1;
+}
+
+typedef struct ImpHistogram
+{
+ float dir[3];
+ float col[3];
+ double sumintensity;
+ float domega;
+} ImpHistogram;
+
+/* RGB -> YCbCr(use Y only) */
+static double rgb_to_intensity(float r, float g, float b)
+{
+ return (0.2989 * r + 0.5866 * g + 0.1145 * b);
+}
+
+void free_ibl_importance(Render *re)
+{
+ if (re->wrld.importance_col) MEM_freeN(re->wrld.importance_col);
+ if (re->wrld.importance_vec) MEM_freeN(re->wrld.importance_vec);
+}
+
+static void importance_get_sample(float *vec, float *col, double *importance_vec, float *importance_col, int num)
+{
+ vec[0] = (float)importance_vec[3*num+0];
+ vec[1] = (float)importance_vec[3*num+1];
+ vec[2] = (float)importance_vec[3*num+2];
+
+ col[0] = importance_col[3*num+0];
+ col[1] = importance_col[3*num+1];
+ col[2] = importance_col[3*num+2];
+}
+
+static void importance_print_samples(Render *re)
+{
+ int i;
+
+ float vec[3], col[3];
+
+ for (i=0; i < re->wrld.ibl_importance_samples; i++) {
+ importance_get_sample(vec, col, re->wrld.importance_vec, re->wrld.importance_col, i);
+
+ printf("col %d - [%f,%f,%f] , ", i, col[0], col[1], col[2]);
+ printf("vec %d - [%f,%f,%f] , ", i, vec[0], vec[1], vec[2]);
+ }
+}
+
+
+void init_ibl_importance(Render *re)
+{
+ ImBuf *ibuf;
+ Image *ima;
+ ImpHistogram *hist;
+ float *rect_float;
+ float col[4], rnd;
+ int w, h, i, j;
+ double sumintensity=0.0, maxintensity, intensity, highest_intensity=0.0;
+ int index;
+ float dtheta_dphi, domega=0.f;
+
+
+ double *vec_table;
+ float *col_table;
+
+ float uv[2], xyz[3];
+
+ float falloff;
+
+ int nsamples = re->wrld.ibl_importance_samples;
+
+ ima = re->wrld.ibl_image;
+ if (!ima) return;
+ ibuf = BKE_image_get_ibuf(ima, NULL);
+
+ w = ibuf->x;
+ h = ibuf->y;
+ rect_float = ibuf->rect_float;
+ if (!rect_float) return;
+
+ dtheta_dphi= (M_PI/(float)h) * (M_PI_2/(float)w);
+ if (re->wrld.ibl_mapping == WO_IBL_MAP_SPHERE) dtheta_dphi /= 2.0f;
+
+ hist = (ImpHistogram *)MEM_mallocN(sizeof(ImpHistogram)*w*h, "importance sampling histogram");
+ re->wrld.importance_vec = MEM_mallocN(3*sizeof(double)*nsamples, "importance sampling vectors");
+ re->wrld.importance_col = MEM_mallocN(3*sizeof(float)*nsamples, "importance sampling colours");
+
+ vec_table = re->wrld.importance_vec;
+ col_table = re->wrld.importance_col;
+
+ re->i.infostr= "Calculating Importance Histogram";
+
+ /* build a histogram with summed pixel intensities */
+ for(j=0;j<h;j++)
+ {
+ uv[1] = 2.0f*((float)j/(float)h) - 1.0f; /* coord in [-1,1] */
+
+ for(i=0;i<w;i++)
+ {
+ uv[0] = 2.0f*((float)i/(float)w) - 1.0f; /* coord in [-1,1] */
+
+ index = j*w+i;
+
+ uv_to_xyz(re->wrld.ibl_mapping, uv, hist[index].dir, dtheta_dphi, &domega);
+
+ falloff = cos(M_PI * ((float)j/(float)h));
+
+ hist[index].col[0] = rect_float[4 * index + 0];
+ hist[index].col[1] = rect_float[4 * index + 1];
+ hist[index].col[2] = rect_float[4 * index + 2];
+
+ hist[index].domega = domega;
+
+ // printf("col - [%f,%f,%f] , ", j, hist[i].col[0], hist[i].col[1], hist[i].col[2]);
+
+ intensity = rgb_to_intensity(hist[index].col[0], hist[index].col[1], hist[index].col[2]);
+ sumintensity += intensity;
+ hist[index].sumintensity = sumintensity;
+
+ }
+ }
+
+/* for (j = 0; j < h; j++) {
+ for (i = 0; i < w; i++) {
+
+ if (!inunitsphere(i, j, w, h)) continue;
+
+ index = j * w + i;
+
+ xy_to_vec(hist[index].dir, i, j, w, h);
+
+ hist[index].col[0] = rect_float[4 * index + 0];
+ hist[index].col[1] = rect_float[4 * index + 1];
+ hist[index].col[2] = rect_float[4 * index + 2];
+ hist[index].col[3] = 1.0;
+
+ hist[index].xy[0] = i;
+ hist[index].xy[1] = j;
+ intensity = rgb_to_intensity(hist[index].col[0], hist[index].col[1], hist[index].col[2]);
+
+ sumintensity += intensity;
+ hist[index].sumintensity = sumintensity;
+ }
+ }
+*/
+
+ printf("IBL:importance: sumintensity = %f\n", sumintensity);
+
+ maxintensity = sumintensity;
+
+ R.i.infostr= "Generating Importance Sampling Points";
+ printf("colours [");
+ for (j = 0; j < nsamples; j++) {
+ // printf("col %d - [%f,%f,%f] , ", j, hist[i].col[0], hist[i].col[1], hist[i].col[2]);
+ // printf("dir %d - [%f,%f,%f] , ", j, hist[i].dir[0], hist[i].dir[1], hist[i].dir[2]);
+
+ /* generate random number in [0, maxintensity) */
+ rnd = BLI_frand() * maxintensity;
+
+ /*
+ if (samp_type == SAMP_TYPE_IMPORTANCE) {
+ rnd = BLI_frand() * maxintensity; // no thread_frand, since we're calculating in a non-threaded prepass
+ } else if (samp_type == SAMP_TYPE_IMPORTANCESTRATIFIED) {
+ // stratified
+ // printf("stratified \n");
+ rnd = (((double)j + BLI_frand()) / (double)nsamples) * maxintensity;
+ }
+ */
+
+ for (i = 0; i < w*h; i++) {
+ if (rnd < hist[i].sumintensity) {
+ break;
+ }
+ }
+
+ vec_table[3*j + 0] = hist[i].dir[0];
+ vec_table[3*j + 1] = hist[i].dir[1];
+ vec_table[3*j + 2] = hist[i].dir[2];
+
+ col_table[3*j + 0] = hist[i].col[0];
+ col_table[3*j + 1] = hist[i].col[1];
+ col_table[3*j + 2] = hist[i].col[2];
+
+ printf("[%f,%f, %f] , ", col_table[3*j + 0], col_table[3*j + 1], col_table[3*j + 2]);
+ }
+ printf("]\n");
+ MEM_freeN(hist);
+
+ importance_print_samples(re);
+}
+
+
+
+/* expects normal in world space */
+void IBL_getcolor_importance(float *col, Render *re, float *n)
+{
+ int s, nsamples = re->wrld.ibl_importance_samples;
+ float vec[3], dot, sampcol[3], accumcol[3];
+ int samplesadded=0;
+
+ for (s=0; s<nsamples; s++) {
+
+ importance_get_sample(vec, sampcol, re->wrld.importance_vec, re->wrld.importance_col, s);
+
+ /* only use samples in same hemisphere */
+ dot = Inpf(n, vec);
+ if (dot > 0.0f) {
+
+ VecMulf(sampcol, dot);
+ VecAddf(accumcol, accumcol, sampcol);
+
+ }
+ samplesadded++;
+ }
+
+ VecMulf(accumcol, 1.0f/(float)samplesadded);
+ VECCOPY(col, accumcol);
+}
+
+
+
+/* *** Diffuse irradiance: Spherical Harmonics *** */
+/*
+* Based on the paper and sample code of:
+* "An Efficient Representation for Irradiance Environment Maps"
+* by Ravi Ramamoorthi and Pat Hanrahan
+* http://graphics.stanford.edu/papers/envmap/
+*
+* Also thanks to some example code by Francesco Banterle
+* http://www.banterle.com/francesco/
+*
+* This calculates RGB values for lighting coefficients L_{lm} with
+* 0 <= l <= 2 and -l <= m <= l. There are 9 coefficients in all.
+*/
+
+
+void init_ibl_diffusesh(struct Render *re)
+{
+ ImBuf *ibuf;
+ Image *ima;
+ float uv[2], xyz[3], x, y, z;
+ float dtheta_dphi, c, domega=0.f;
+ int w, h, i, j, k;
+ float *rect_float, pix[3];
+ int index, col;
+
+ ima = re->wrld.ibl_image;
+ if (!ima) return;
+ ibuf = BKE_image_get_ibuf(ima, NULL);
+
+ w = ibuf->x;
+ h = ibuf->y;
+ rect_float = ibuf->rect_float;
+ if (!rect_float) return;
+
+ dtheta_dphi= (M_PI/(float)h) * (M_PI_2/(float)w);
+ if (re->wrld.ibl_mapping == WO_IBL_MAP_SPHERE) dtheta_dphi /= 2.0f;
+
+ memset(re->ibl_sh_coeffs, 0, sizeof(re->ibl_sh_coeffs));
+
+ for(j=0;j<h;j++)
+ {
+ uv[1] = 2.0f*((float)j/(float)h) - 1.0f; /* coord in [-1,1] */
+
+ for(i=0;i<w;i++)
+ {
+ uv[0] = 2.0f*((float)i/(float)w) - 1.0f; /* coord in [-1,1] */
+
+ uv_to_xyz(re->wrld.ibl_mapping, uv, xyz, dtheta_dphi, &domega);
+
+ x = xyz[0]; y = xyz[1]; z = xyz[2];
+ index = j*w+i;
+
+ pix[0] = rect_float[4 * index + 0];
+ pix[1] = rect_float[4 * index + 1];
+ pix[2] = rect_float[4 * index + 2];
+
+ /* add the light per pixel to the coefficients per term,
+ * based on a constant, the differential solid angle and
+ * cartesian components of surface normal x,y,z */
+ for (col = 0 ; col < 3 ; col++) {
+
+ /* L_{00}. Note that Y_{00} = 0.282095 */
+ c=0.282095f*domega;
+ re->ibl_sh_coeffs[0][col] += pix[col]*c;
+
+ /* L_{1m}. -1 <= m <= 1. The linear terms */
+ c=0.488603f*domega;
+ re->ibl_sh_coeffs[1][col]+=pix[col]*c*y;
+ re->ibl_sh_coeffs[2][col]+=pix[col]*c*z;
+ re->ibl_sh_coeffs[3][col]+=pix[col]*c*x;
+
+ /* The Quadratic terms, L_{2m} -2 <= m <= 2 */
+ /* First, L_{2-2}, L_{2-1}, L_{21} corresponding to xy,yz,xz */
+ c=1.092548f*domega;
+ re->ibl_sh_coeffs[4][col]+=pix[col]*c*x*y;
+ re->ibl_sh_coeffs[5][col]+=pix[col]*c*y*z;
+ re->ibl_sh_coeffs[7][col]+=pix[col]*c*x*z;
+
+ /* L_{20}. Note that Y_{20} = 0.315392 (3z^2 - 1) */
+ c=0.315392f*domega*(3.0f*z*z-1.0f);
+ re->ibl_sh_coeffs[6][col]+=pix[col]*c;
+
+ c=0.546274f*domega*(x*x-y*y);
+ re->ibl_sh_coeffs[8][col]+=pix[col]*c;
+ }
+ }
+ }
+};
+
+
+/* expects normal in world space */
+void IBL_diffusesh_getcolor( float *col, float *coeffs, float *n)
+{
+ float x, y, z;
+ static const float c1 = 0.429043, c2 = 0.511664, c3 = 0.743125, c4 = 0.886227, c5 = 0.247708;
+ int rgb;
+ float *L00, *L1_1, *L10, *L11, *L2_2, *L2_1, *L20, *L21, *L22;
+
+ L00 = coeffs + 0*3;
+ L1_1 = coeffs + 1*3;
+ L10 = coeffs + 2*3;
+ L11 = coeffs + 3*3;
+ L2_2 = coeffs + 4*3;
+ L2_1 = coeffs + 5*3;
+ L20 = coeffs + 6*3;
+ L21 = coeffs + 7*3;
+ L22 = coeffs + 8*3;
+
+ x = n[0] ; y = n[1] ; z = n[2];
+
+ for (rgb = 0; rgb < 3; rgb++) {
+ col[rgb] = c1*L22[rgb]*(x*x - y*y);
+ col[rgb] += c3*L20[rgb]*z*z;
+ col[rgb] += c4*L00[rgb];
+ col[rgb] += -c5*L20[rgb];
+ col[rgb] += 2.0f*c1*(L2_2[rgb]*x*y + L21[rgb]*x*z + L2_1[rgb]*y*z);
+ col[rgb] += 2.0f*c2*(L11[rgb]*x + L1_1[rgb]*y + L10[rgb]*z);
+ }
+}
\ No newline at end of file
Index: source/blender/render/intern/source/convertblender.c
===================================================================
--- source/blender/render/intern/source/convertblender.c (revision 14978)
+++ source/blender/render/intern/source/convertblender.c (working copy)
@@ -4429,6 +4429,11 @@
if(re->r.mode & R_RAYTRACE)
free_render_qmcsampler(re);
+ if (re->wrld.mode & WO_IMAGE_BASED_LIGHTING) {
+ if (re->wrld.ibl_method == WO_IBL_IMPORTANCE)
+ free_ibl_importance(re);
+ }
+
if(re->r.mode & R_RAYTRACE) freeraytree(re);
free_sss(re);
@@ -4807,8 +4812,19 @@
if(re->wrld.mode & WO_AMB_OCC)
if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT)
init_ao_sphere(&re->wrld);
+
+ if (re->wrld.aocolor == WO_AODIFFUSESH)
+ init_ibl_diffusesh(re);
}
+ if(re->wrld.mode & WO_IMAGE_BASED_LIGHTING) {
+ if (re->wrld.ibl_method == WO_IBL_DIFFUSESH) {
+ init_ibl_diffusesh(re);
+ } else if (re->wrld.ibl_method == WO_IBL_IMPORTANCE) {
+ init_ibl_importance(re);
+ }
+ }
+
/* still bad... doing all */
init_render_textures(re);
init_render_materials(re->r.mode, &re->wrld.ambr);
Index: source/blender/render/intern/include/render_types.h
===================================================================
--- source/blender/render/intern/include/render_types.h (revision 14978)
+++ source/blender/render/intern/include/render_types.h (working copy)
@@ -33,6 +33,7 @@
/* ------------------------------------------------------------------------- */
#include "DNA_color_types.h"
+#include "DNA_image_types.h"
#include "DNA_scene_types.h"
#include "DNA_world_types.h"
#include "DNA_object_types.h"
@@ -199,6 +200,14 @@
struct Object *excludeob;
+ /* Image Based Lighting */
+ /* spherical harmonics coefficients diffuse prefiltered */
+ float ibl_sh_coeffs[9][3];
+ /* importance sampling directions and colours */
+ float *importance_col;
+ double *importance_vec;
+
+
/* arena for allocating data for use during render, for
* example dynamic TFaces to go in the VlakRen structure.
*/
Index: source/blender/render/intern/include/rendercore.h
===================================================================
--- source/blender/render/intern/include/rendercore.h (revision 14978)
+++ source/blender/render/intern/include/rendercore.h (working copy)
@@ -104,5 +104,13 @@
extern void init_render_qmcsampler(Render *re);
extern void free_render_qmcsampler(Render *re);
+/* -------- ibl.c ------- */
+
+void init_ibl_diffusesh(Render *re);
+void init_ibl_importance(Render *re);
+void free_ibl_importance(Render *re);
+
+void image_based_lighting(struct ShadeInput *shi, struct ShadeResult *shr);
+void IBL_diffusesh_getcolor( float *col, float *coeffs, float *n);
#endif /* RENDER_EXT_H */
Index: source/blender/render/extern/include/RE_shader_ext.h
===================================================================
--- source/blender/render/extern/include/RE_shader_ext.h (revision 14978)
+++ source/blender/render/extern/include/RE_shader_ext.h (working copy)
@@ -136,6 +136,7 @@
float refcol[4], displace[3];
float strandco, tang[3], nmaptang[3], stress, winspeed[4];
float duplilo[3], dupliuv[3];
+ float worldnor[3];
ShadeInputUV uv[8]; /* 8 = MAX_MTFACE */
ShadeInputCol col[8]; /* 8 = MAX_MCOL */
Index: source/blender/python/api2_2x/World.h
===================================================================
--- source/blender/python/api2_2x/World.h (revision 14978)
+++ source/blender/python/api2_2x/World.h (working copy)
@@ -31,6 +31,7 @@
#define EXPP_WORLD_H
#include <Python.h>
+#include "DNA_image_types.h"
#include "DNA_world_types.h"
#define BPy_World_Check(v) ((v)->ob_type==&World_Type)
Index: source/blender/blenkernel/intern/world.c
===================================================================
--- source/blender/blenkernel/intern/world.c (revision 14978)
+++ source/blender/blenkernel/intern/world.c (working copy)
@@ -34,6 +34,7 @@
#include <math.h>
#include "MEM_guardedalloc.h"
+#include "DNA_image_types.h"
#include "DNA_world_types.h"
#include "DNA_texture_types.h"
#include "DNA_scriptlink_types.h"
@@ -83,6 +84,7 @@
World *add_world(char *name)
{
World *wrld;
+ ImageUser *iuser;
wrld= alloc_libblock(&G.main->world, ID_WO, name);
@@ -104,6 +106,14 @@
wrld->physicsEngine= WOPHY_BULLET;//WOPHY_SUMO; Bullet by default
wrld->preview = NULL;
+
+ iuser = &(wrld->ibl_iuser);
+
+ iuser->sfra= 1;
+ iuser->fie_ima= 2;
+ iuser->ok= 1;
+
+ wrld->ibl_multiplier = 1.0;
return wrld;
}
Index: source/blender/makesdna/DNA_world_types.h
===================================================================
--- source/blender/makesdna/DNA_world_types.h (revision 14978)
+++ source/blender/makesdna/DNA_world_types.h (working copy)
@@ -36,12 +36,18 @@
struct Ipo;
struct MTex;
+struct Image;
+struct ImageUser;
#ifndef MAX_MTEX
#define MAX_MTEX 10
#endif
+typedef struct Ibl {
+ float dsh_coeffs[9][3];
+} Ibl;
+
/**
* World defines general modeling data such as a background fill,
* gravity, color model, stars, etc. It mixes game-data, rendering
@@ -106,13 +112,21 @@
float *aosphere, *aotables;
+ short ibl_method, ibl_mapping;
+ short ibl_importance_samples, pad5[3];
+ float ibl_multiplier;
+ struct Image *ibl_image;
+ struct ImageUser ibl_iuser;
+ float *importance_col;
+ double *importance_vec;
+
struct Ipo *ipo;
struct MTex *mtex[10];
/* previews */
struct PreviewImage *preview;
-
+
ScriptLink scriptlink;
} World;
@@ -133,6 +147,7 @@
#define WO_DOF 4
#define WO_ACTIVITY_CULLING 8
#define WO_AMB_OCC 16
+#define WO_IMAGE_BASED_LIGHTING 32
/* aomix */
#define WO_AOADD 0
@@ -153,7 +168,16 @@
#define WO_AOPLAIN 0
#define WO_AOSKYCOL 1
#define WO_AOSKYTEX 2
+#define WO_AODIFFUSESH 3
+/* ibl_method */
+#define WO_IBL_DIFFUSESH 0
+#define WO_IBL_IMPORTANCE 1
+
+/* ibl_mapping */
+#define WO_IBL_MAP_ANGMAP 0
+#define WO_IBL_MAP_SPHERE 1
+
/* ao_gather_method */
#define WO_AOGATHER_RAYTRACE 0
#define WO_AOGATHER_APPROX 1
Index: source/blender/src/buttons_shading.c
===================================================================
--- source/blender/src/buttons_shading.c (revision 14978)
+++ source/blender/src/buttons_shading.c (working copy)
@@ -2163,13 +2163,98 @@
}
+static void world_panel_ibl(World *wrld)
+{
+ uiBlock *block;
+ short yco=PANEL_YMAX;
+ char *strp;
+ struct ImageUser *iuser= &(wrld->ibl_iuser);
+ uiBut *but;
+
+ block= uiNewBlock(&curarea->uiblocks, "world_panel_ibl", UI_EMBOSS, UI_HELV, curarea->win);
+ uiNewPanelTabbed("Amb Occ", "World");
+ if(uiNewPanel(curarea, block, "Image Based Lighting", "World", PANELX, PANELY, PANELW, PANELH)==0) return;
+
+ uiDefButBitS(block, TOG, WO_IMAGE_BASED_LIGHTING, B_REDR, "Image Based Lighting",
+ X2CLM1, yco-=BUTH, BUTW1, BUTH, &wrld->mode, 0, 0, 0, 0, "Enables lighting from an environment image (light probe)");
+
+ yco -= YSPACE;
+
+// uiDefButS(block, MENU, B_REDR, "Calculation Method %t|Diffuse Prefiltered %x0|Importance Sampled %x1",
+// X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->ibl_method, 0, 0, 0, 0, "");
+ uiDefButS(block, MENU, B_REDR, "Calculation Method %t|Diffuse Prefiltered %x0",
+ X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->ibl_method, 0, 0, 0, 0, "");
+
+ if (wrld->ibl_method == WO_IBL_IMPORTANCE) {
+ uiDefButS(block, NUM, B_REDR, "Samples:",
+ X2CLM2, yco, BUTW2, BUTH, &wrld->ibl_importance_samples, 0.0, 512.0, 1.0, 0, "Number of times to sample the environment map");
+ }
+
+ yco -= YSPACE;
+
+ /* Browse */
+ IMAnames_to_pupstring(&strp, NULL, NULL, &(G.main->image), NULL, &iuser->menunr);
+
+ uiBlockBeginAlign(block);
+ but= uiDefButS(block, MENU, B_REDR, strp,
+ X2CLM1, yco-=BUTH, ICONBUTW, BUTH, &iuser->menunr, 0, 0, 0, 0, "Selects an existing Image or Movie");
+ uiButSetFunc(but, image_browse_cb, &(wrld->ibl_image), iuser);
+
+ MEM_freeN(strp);
+
+ if (wrld->ibl_image != NULL) {
+ char str[128];
+
+ if (wrld->ibl_image->source != IMA_SRC_FILE) {
+ uiDefBut(block, LABEL, 0, "Still images only",
+ X2CLM1, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, ""); /* for align in panel */
+ return;
+ }
+ uiSetButLock(wrld->ibl_image->id.lib!=NULL, ERROR_LIBDATA_MESSAGE);
+ but= uiDefIconBut(block, BUT, B_REDR, ICON_FILESEL,
+ X2CLM1+ICONBUTW, yco, X2CLM1+ICONBUTW, BUTH, 0, 0, 0, 0, 0, "Open Fileselect to load new Image");
+ uiButSetFunc(but, image_load_fs_cb, &(wrld->ibl_image), iuser);
+
+ but= uiDefBut(block, TEX, B_IDNAME, "IM:",
+ X2CLM1+2*ICONBUTW, yco, PANEL_XMAX-4*ICONBUTW-BUTW4, BUTH, wrld->ibl_image->id.name+2, 0.0, 21.0, 0, 0, "Current Image Datablock name.");
+ uiButSetFunc(but, test_idbutton_cb, wrld->ibl_image->id.name, NULL);
+
+ but= uiDefBut(block, BUT, B_REDR, "Reload",
+ PANEL_XMAX-2*ICONBUTW-BUTW4, yco, BUTW4, BUTH, NULL, 0, 0, 0, 0, "Reloads Image or Movie");
+ uiButSetFunc(but, image_reload_cb, &(wrld->ibl_image), iuser);
+
+ but= uiDefIconBut(block, BUT, B_REDR, ICON_X,
+ PANEL_XMAX-2*ICONBUTW, yco, ICONBUTW, BUTH, 0, 0, 0, 0, 0, "Unlink Image block");
+ uiButSetFunc(but, image_unlink_cb, &(wrld->ibl_image), NULL);
+
+ sprintf(str, "%d", wrld->ibl_image->id.us);
+ uiDefBut(block, BUT, B_NOP, str,
+ PANEL_XMAX-ICONBUTW, yco, ICONBUTW, BUTH, 0, 0, 0, 0, 0, "Only displays number of users of Image block");
+
+ } else {
+ but= uiDefBut(block, BUT, B_REDR, "Load",
+ X2CLM1+ICONBUTW, yco, BUTW2-ICONBUTW, BUTH, NULL, 0, 0, 0, 0, "Load new Image");
+ uiButSetFunc(but, image_load_fs_cb, &(wrld->ibl_image), iuser);
+ }
+
+ uiBlockEndAlign(block);
+
+ yco-= YSPACE;
+
+ uiDefButF(block, NUM, B_REDR, "Multiplier:",
+ X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->ibl_multiplier, 0.0, 100.0, 1.0, 0, "Multiply the final result to brighten or darken the lighting");
+
+ uiDefButS(block, MENU, B_REDR, "Image Format %t|Angular Map %x0|Sphere (LatLong) %x1",
+ X2CLM2, yco, BUTW2, BUTH, &wrld->ibl_mapping, 0, 0, 0, 0, "");
+}
+
static void world_panel_amb_occ(World *wrld)
{
uiBlock *block;
short yco=PANEL_YMAX;
+ char *str;
block= uiNewBlock(&curarea->uiblocks, "world_panel_amb_oc", UI_EMBOSS, UI_HELV, curarea->win);
- uiNewPanelTabbed("Mist / Stars / Physics", "World");
if(uiNewPanel(curarea, block, "Amb Occ", "World", PANELX, PANELY, PANELW, PANELH)==0) return;
uiSetButLock(wrld->id.lib!=0, ERROR_LIBDATA_MESSAGE);
@@ -2262,19 +2347,19 @@
/* color treatment */
uiBlockBeginAlign(block);
- uiDefButS(block, ROW, B_REDR, "Plain",
- X3CLM1, yco-=BUTH, BUTW3, BUTH, &wrld->aocolor, 2.0, (float)WO_AOPLAIN, 0, 0, "Plain diffuse energy (white)");
- uiDefButS(block, ROW, B_REDR, "Sky Color",
- X3CLM2, yco, BUTW3, BUTH, &wrld->aocolor, 2.0, (float)WO_AOSKYCOL, 0, 0, "Use horizon and zenith color for diffuse energy");
- if(wrld->ao_gather_method == WO_AOGATHER_RAYTRACE)
- uiDefButS(block, ROW, B_REDR, "Sky Texture",
- X3CLM3, yco, BUTW3, BUTH, &wrld->aocolor, 2.0, (float)WO_AOSKYTEX, 0, 0, "Does full Sky texture render for diffuse energy");
- uiBlockEndAlign(block);
+
+ if(wrld->ao_gather_method == WO_AOGATHER_RAYTRACE) {
+ uiDefButS(block, MENU, B_REDR, "Plain %x0|Sky Color %x1|Sky Texture %x2|IBL: Diffuse Prefiltered %x3",
+ X3CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->aocolor, 0.0, (float)WO_AOPLAIN, 0, 0, "");
+ } else {
+ uiDefButS(block, MENU, B_REDR, "Plain %x0|Sky Color %x1|IBL: Diffuse Prefiltered %x3",
+ X3CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->aocolor, 0.0, (float)WO_AOPLAIN, 0, 0, "");
+ }
yco -= YSPACE;
- uiDefButF(block, NUMSLI, B_REDR, "Energy:",
- X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->aoenergy, 0.01, 3.0, 100, 0, "Sets global energy scale for AO");
+ uiDefButF(block, NUM, B_REDR, "Energy:",
+ X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->aoenergy, 0.01, 10.0, 100, 0, "Sets global energy scale for AO");
}
static void world_panel_world(World *wrld)
@@ -4371,6 +4456,7 @@
if(wrld) {
world_panel_mistaph(wrld);
world_panel_amb_occ(wrld);
+ world_panel_ibl(wrld);
world_panel_texture(wrld);
world_panel_mapto(wrld);
}
Index: source/blender/blenloader/intern/readfile.c
===================================================================
--- source/blender/blenloader/intern/readfile.c (revision 14978)
+++ source/blender/blenloader/intern/readfile.c (working copy)
@@ -2138,6 +2138,8 @@
}
}
+ wrld->ibl_image= newlibadr_us(fd, wrld->id.lib, wrld->ibl_image);
+
lib_link_scriptlink(fd, &wrld->id, &wrld->scriptlink);
wrld->id.flag -= LIB_NEEDLINK;
@@ -2155,6 +2157,9 @@
for(a=0; a<MAX_MTEX; a++) {
wrld->mtex[a]= newdataadr(fd, wrld->mtex[a]);
}
+
+ wrld->ibl_iuser.ok= 1;
+
wrld->preview = direct_link_preview_image(fd, wrld->preview);
}
@@ -7530,6 +7535,8 @@
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 11)) {
Object *ob;
bActionStrip *strip;
+ World *wrld;
+ ImageUser *iuser;
/* nla-strips - scale */
for (ob= main->object.first; ob; ob= ob->id.next) {
@@ -7553,6 +7560,16 @@
ob->soft->shearstiff = 1.0f;
}
}
+
+ for(wrld=main->world.first; wrld; wrld= wrld->id.next) {
+ iuser = &(wrld->ibl_iuser);
+
+ iuser->sfra= 1;
+ iuser->fie_ima= 2;
+ iuser->ok= 1;
+ wrld->ibl_multiplier = 1.0;
+ }
+
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 14)) {
Index: source/blender/nodes/intern/SHD_util.h
===================================================================
--- source/blender/nodes/intern/SHD_util.h (revision 14978)
+++ source/blender/nodes/intern/SHD_util.h (working copy)
@@ -109,6 +109,7 @@
#define GEOM_OUT_NORMAL 5
#define GEOM_OUT_VCOL 6
#define GEOM_OUT_FRONTBACK 7
+#define GEOM_OUT_WORLDNORMAL 8
/* input socket defines */
Index: source/blender/nodes/intern/SHD_nodes/SHD_geom.c
===================================================================
--- source/blender/nodes/intern/SHD_nodes/SHD_geom.c (revision 14978)
+++ source/blender/nodes/intern/SHD_nodes/SHD_geom.c (working copy)
@@ -39,9 +39,10 @@
{ SOCK_VECTOR, 0, "View", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
{ SOCK_VECTOR, 0, "Orco", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
{ SOCK_VECTOR, 0, "UV", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
- { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
+ { SOCK_VECTOR, 0, "View Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
{ SOCK_RGBA, 0, "Vertex Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 0, "Front/Back", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 0, "World Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
{ -1, 0, "" }
};
@@ -73,6 +74,7 @@
VECCOPY(out[GEOM_OUT_ORCO]->vec, shi->lo);
VECCOPY(out[GEOM_OUT_UV]->vec, suv->uv);
VECCOPY(out[GEOM_OUT_NORMAL]->vec, shi->vno);
+ VECCOPY(out[GEOM_OUT_WORLDNORMAL]->vec, shi->worldnor);
if (shi->totcol) {
/* find vertex color layer by name */

Event Timeline