2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2006-12-05 16:43:01 +00:00
|
|
|
* ***** 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,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2006-12-05 16:43:01 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2006 Blender Foundation
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Contributors: Hos, Robert Wenzlaff.
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
2011-02-27 19:31:27 +00:00
|
|
|
/** \file blender/render/intern/source/shadeoutput.c
|
|
|
|
* \ingroup render
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
#include <stdio.h>
|
2007-11-12 09:37:46 +00:00
|
|
|
#include <float.h>
|
2006-12-05 16:43:01 +00:00
|
|
|
#include <math.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
#include "BLI_math.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2006-12-05 16:43:01 +00:00
|
|
|
|
* Extra lamp falloff options, including custom curve!
This adds some new lamp attenuation options to the Lamp panel, replacing the old 'Quad' button. Yes, the panel layout is still nasty here, but I've ignored it for now to address properly in the panels cleanup work.
* Constant
http://mke3.net/blender/devel/rendering/falloff-constant.jpg
Lamp doesn't decay with distance
* Inverse Linear
http://mke3.net/blender/devel/rendering/falloff-invlinear.jpg
Default, and same as in older Blender without 'Quad' on. Decays linearly, with 'Dist' value as the lamp's half-energy-distance
* Inverse Square
http://mke3.net/blender/devel/rendering/falloff-invsquare.jpg
A sharper, more realistic decay, good for most electric lights (i.e. not sunlight). This is similar to the old Quad option with slight changes.
* Lin/Quad weighted
Exactly the same as in older Blenders with the old 'Quad' button enabled. When this setting is chosen, two sliders are shown, 'Linear' and 'Quad' (previously Quad1 and Quad2), which controls the 'linearness' or 'quadraticness' of the falloff curve. Lamps in old files with the 'Quad' button on will be initialised to this setting.
But much better for precise control over the lamp falloff now is:
* Custom Curve
This shows an extra 'Falloff Curve' panel, where you can use the standard Blender curve UI control to precisely control how the light falls off. The Y axis is intensity, and the X axis is distance, stretched over the length of the 'Dist' value.
Some example curves and renders:
http://mke3.net/blender/devel/rendering/falloff-curve1-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve1.jpg
http://mke3.net/blender/devel/rendering/falloff-curve2-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve2.jpg
http://mke3.net/blender/devel/rendering/falloff-curve3-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve3.jpg (whee)
2007-09-16 13:50:34 +00:00
|
|
|
#include "BKE_colortools.h"
|
2006-12-05 16:43:01 +00:00
|
|
|
#include "BKE_material.h"
|
|
|
|
#include "BKE_texture.h"
|
2011-01-07 19:18:31 +00:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
#include "DNA_group_types.h"
|
|
|
|
#include "DNA_lamp_types.h"
|
|
|
|
#include "DNA_material_types.h"
|
|
|
|
|
|
|
|
/* local include */
|
2008-01-17 19:27:16 +00:00
|
|
|
#include "occlusion.h"
|
2006-12-05 16:43:01 +00:00
|
|
|
#include "render_types.h"
|
|
|
|
#include "rendercore.h"
|
|
|
|
#include "shadbuf.h"
|
2007-05-03 21:37:52 +00:00
|
|
|
#include "sss.h"
|
2006-12-05 16:43:01 +00:00
|
|
|
#include "texture.h"
|
|
|
|
|
2011-11-14 16:05:44 +00:00
|
|
|
#include "shading.h" /* own include */
|
|
|
|
|
2015-03-17 15:20:33 +01:00
|
|
|
#include "IMB_colormanagement.h"
|
|
|
|
|
2012-11-04 07:18:29 +00:00
|
|
|
/* could enable at some point but for now there are far too many conversions */
|
2012-11-23 10:03:50 +00:00
|
|
|
#ifdef __GNUC__
|
|
|
|
# pragma GCC diagnostic ignored "-Wdouble-promotion"
|
|
|
|
#endif
|
2012-11-04 07:18:29 +00:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
/* 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;
|
|
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
|
2008-09-22 01:51:24 +00:00
|
|
|
ListBase *get_lights(ShadeInput *shi)
|
2006-12-07 14:17:38 +00:00
|
|
|
{
|
|
|
|
|
2013-05-15 17:09:45 +00:00
|
|
|
if (R.r.scemode & R_BUTS_PREVIEW)
|
2009-06-25 12:32:55 +00:00
|
|
|
return &R.lights;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (shi->mat && shi->mat->group)
|
2006-12-07 14:17:38 +00:00
|
|
|
return &shi->mat->group->gobject;
|
2009-06-25 12:32:55 +00:00
|
|
|
|
|
|
|
return &R.lights;
|
2006-12-07 14:17:38 +00:00
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
#if 0
|
2012-05-26 16:04:31 +00:00
|
|
|
static void fogcolor(const float colf[3], float *rco, float *view)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
float alpha, stepsize, startdist, dist, hor[4], zen[3], vec[3], dview[3];
|
|
|
|
float div=0.0f, distfac;
|
|
|
|
|
|
|
|
hor[0]= R.wrld.horr; hor[1]= R.wrld.horg; hor[2]= R.wrld.horb;
|
|
|
|
zen[0]= R.wrld.zenr; zen[1]= R.wrld.zeng; zen[2]= R.wrld.zenb;
|
|
|
|
|
2011-09-12 04:14:12 +00:00
|
|
|
copy_v3_v3(vec, rco);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* we loop from cur coord to mist start in steps */
|
|
|
|
stepsize= 1.0f;
|
|
|
|
|
|
|
|
div= ABS(view[2]);
|
|
|
|
dview[0]= view[0]/(stepsize*div);
|
|
|
|
dview[1]= view[1]/(stepsize*div);
|
|
|
|
dview[2]= -stepsize;
|
|
|
|
|
|
|
|
startdist= -rco[2] + BLI_frand();
|
2012-03-24 06:38:07 +00:00
|
|
|
for (dist= startdist; dist>R.wrld.miststa; dist-= stepsize) {
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
hor[0]= R.wrld.horr; hor[1]= R.wrld.horg; hor[2]= R.wrld.horb;
|
|
|
|
alpha= 1.0f;
|
|
|
|
do_sky_tex(vec, vec, NULL, hor, zen, &alpha);
|
|
|
|
|
|
|
|
distfac= (dist-R.wrld.miststa)/R.wrld.mistdist;
|
|
|
|
|
|
|
|
hor[3]= hor[0]*distfac*distfac;
|
|
|
|
|
|
|
|
/* premul! */
|
|
|
|
alpha= hor[3];
|
|
|
|
hor[0]= hor[0]*alpha;
|
|
|
|
hor[1]= hor[1]*alpha;
|
|
|
|
hor[2]= hor[2]*alpha;
|
|
|
|
addAlphaOverFloat(colf, hor);
|
|
|
|
|
2012-03-09 06:04:17 +00:00
|
|
|
sub_v3_v3(vec, dview);
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* zcor is distance, co the 3d coordinate in eye space, return alpha */
|
2011-09-24 14:34:24 +00:00
|
|
|
float mistfactor(float zcor, float const co[3])
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
float fac, hi;
|
|
|
|
|
2012-10-07 09:48:59 +00:00
|
|
|
fac = zcor - R.wrld.miststa; /* zcor is calculated per pixel */
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* fac= -co[2]-R.wrld.miststa; */
|
|
|
|
|
2012-10-07 09:48:59 +00:00
|
|
|
if (fac > 0.0f) {
|
|
|
|
if (fac < R.wrld.mistdist) {
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-10-07 09:48:59 +00:00
|
|
|
fac = (fac / R.wrld.mistdist);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-10-07 09:48:59 +00:00
|
|
|
if (R.wrld.mistype == 0) {
|
|
|
|
fac *= fac;
|
|
|
|
}
|
|
|
|
else if (R.wrld.mistype == 1) {
|
|
|
|
/* pass */
|
|
|
|
}
|
|
|
|
else {
|
2014-09-17 14:11:37 +10:00
|
|
|
fac = sqrtf(fac);
|
2012-10-07 09:48:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fac = 1.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
2012-10-07 09:48:59 +00:00
|
|
|
else {
|
|
|
|
fac = 0.0f;
|
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* height switched off mist */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (R.wrld.misthi!=0.0f && fac!=0.0f) {
|
2006-12-05 16:43:01 +00:00
|
|
|
/* at height misthi the mist is completely gone */
|
|
|
|
|
2012-10-07 09:48:59 +00:00
|
|
|
hi = R.viewinv[0][2] * co[0] +
|
|
|
|
R.viewinv[1][2] * co[1] +
|
|
|
|
R.viewinv[2][2] * co[2] +
|
|
|
|
R.viewinv[3][2];
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-10-07 09:48:59 +00:00
|
|
|
if (hi > R.wrld.misthi) {
|
|
|
|
fac = 0.0f;
|
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (hi>0.0f) {
|
2006-12-05 16:43:01 +00:00
|
|
|
hi= (R.wrld.misthi-hi)/R.wrld.misthi;
|
|
|
|
fac*= hi*hi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
return (1.0f-fac)* (1.0f-R.wrld.misi);
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens)
|
|
|
|
{
|
|
|
|
double a, b, c, disc, nray[3], npos[3];
|
2011-02-03 16:31:03 +00:00
|
|
|
double t0, t1 = 0.0f, t2= 0.0f, t3;
|
|
|
|
float p1[3], p2[3], ladist, maxz = 0.0f, maxy = 0.0f, haint;
|
2014-04-01 11:34:00 +11:00
|
|
|
int cuts;
|
|
|
|
bool do_clip = true, use_yco = false;
|
2011-09-24 14:34:24 +00:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
*intens= 0.0f;
|
|
|
|
haint= lar->haint;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (R.r.mode & R_ORTHO) {
|
2006-12-05 16:43:01 +00:00
|
|
|
/* camera pos (view vector) cannot be used... */
|
|
|
|
/* camera position (cox,coy,0) rotate around lamp */
|
|
|
|
p1[0]= shi->co[0]-lar->co[0];
|
|
|
|
p1[1]= shi->co[1]-lar->co[1];
|
|
|
|
p1[2]= -lar->co[2];
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_m3_v3(lar->imat, p1);
|
2012-07-07 22:51:57 +00:00
|
|
|
copy_v3db_v3fl(npos, p1); /* npos is double! */
|
2007-11-14 10:20:13 +00:00
|
|
|
|
|
|
|
/* pre-scale */
|
2011-11-11 12:00:08 +00:00
|
|
|
npos[2] *= (double)lar->sh_zfac;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-09 06:04:17 +00:00
|
|
|
copy_v3db_v3fl(npos, lar->sh_invcampos); /* in initlamp calculated */
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* rotate view */
|
2012-03-09 06:04:17 +00:00
|
|
|
copy_v3db_v3fl(nray, shi->view);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_m3_v3_double(lar->imat, nray);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (R.wrld.mode & WO_MIST) {
|
2006-12-05 16:43:01 +00:00
|
|
|
/* patchy... */
|
|
|
|
haint *= mistfactor(-lar->co[2], lar->co);
|
2012-03-24 06:38:07 +00:00
|
|
|
if (haint==0.0f) {
|
2006-12-05 16:43:01 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* rotate maxz */
|
2012-05-19 13:28:19 +00:00
|
|
|
if (shi->co[2]==0.0f) {
|
2014-04-01 11:34:00 +11:00
|
|
|
do_clip = false; /* for when halo at sky */
|
2012-05-19 13:28:19 +00:00
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
else {
|
|
|
|
p1[0]= shi->co[0]-lar->co[0];
|
|
|
|
p1[1]= shi->co[1]-lar->co[1];
|
|
|
|
p1[2]= shi->co[2]-lar->co[2];
|
|
|
|
|
|
|
|
maxz= lar->imat[0][2]*p1[0]+lar->imat[1][2]*p1[1]+lar->imat[2][2]*p1[2];
|
|
|
|
maxz*= lar->sh_zfac;
|
|
|
|
maxy= lar->imat[0][1]*p1[0]+lar->imat[1][1]*p1[1]+lar->imat[2][1]*p1[2];
|
|
|
|
|
2013-12-04 09:23:29 +11:00
|
|
|
if (fabs(nray[2]) < FLT_EPSILON) {
|
2014-04-01 11:34:00 +11:00
|
|
|
use_yco = true;
|
2012-05-19 13:28:19 +00:00
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
/* scale z to make sure volume is normalized */
|
2011-11-11 12:00:08 +00:00
|
|
|
nray[2] *= (double)lar->sh_zfac;
|
2006-12-05 16:43:01 +00:00
|
|
|
/* nray does not need normalization */
|
|
|
|
|
|
|
|
ladist= lar->sh_zfac*lar->dist;
|
|
|
|
|
|
|
|
/* solve */
|
|
|
|
a = nray[0] * nray[0] + nray[1] * nray[1] - nray[2]*nray[2];
|
|
|
|
b = nray[0] * npos[0] + nray[1] * npos[1] - nray[2]*npos[2];
|
|
|
|
c = npos[0] * npos[0] + npos[1] * npos[1] - npos[2]*npos[2];
|
|
|
|
|
2013-04-18 16:26:58 +00:00
|
|
|
cuts= 0;
|
2007-11-12 09:37:46 +00:00
|
|
|
if (fabs(a) < DBL_EPSILON) {
|
2006-12-05 16:43:01 +00:00
|
|
|
/*
|
|
|
|
* Only one intersection point...
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
disc = b*b - a*c;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (disc==0.0) {
|
2006-12-05 16:43:01 +00:00
|
|
|
t1=t2= (-b)/ a;
|
2013-04-18 16:26:58 +00:00
|
|
|
cuts= 2;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
else if (disc > 0.0) {
|
|
|
|
disc = sqrt(disc);
|
|
|
|
t1 = (-b + disc) / a;
|
|
|
|
t2 = (-b - disc) / a;
|
2013-04-18 16:26:58 +00:00
|
|
|
cuts= 2;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
2013-04-18 16:26:58 +00:00
|
|
|
if (cuts==2) {
|
2011-09-24 14:34:24 +00:00
|
|
|
int ok1=0, ok2=0;
|
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
/* sort */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (t1>t2) {
|
2006-12-05 16:43:01 +00:00
|
|
|
a= t1; t1= t2; t2= a;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* z of intersection points with diabolo */
|
|
|
|
p1[2]= npos[2] + t1*nray[2];
|
|
|
|
p2[2]= npos[2] + t2*nray[2];
|
|
|
|
|
|
|
|
/* evaluate both points */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (p1[2]<=0.0f) ok1= 1;
|
|
|
|
if (p2[2]<=0.0f && t1!=t2) ok2= 1;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* at least 1 point with negative z */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ok1==0 && ok2==0) return;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* intersction point with -ladist, the bottom of the cone */
|
2014-04-01 11:34:00 +11:00
|
|
|
if (use_yco == false) {
|
2011-11-11 12:00:08 +00:00
|
|
|
t3= ((double)(-ladist)-npos[2])/nray[2];
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* de we have to replace one of the intersection points? */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ok1) {
|
|
|
|
if (p1[2]<-ladist) t1= t3;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
t1= t3;
|
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ok2) {
|
|
|
|
if (p2[2]<-ladist) t2= t3;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
t2= t3;
|
|
|
|
}
|
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (ok1==0 || ok2==0) return;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* at least 1 visible interesction point */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (t1<0.0 && t2<0.0) return;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (t1<0.0) t1= 0.0;
|
|
|
|
if (t2<0.0) t2= 0.0;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (t1==t2) return;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* sort again to be sure */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (t1>t2) {
|
2006-12-05 16:43:01 +00:00
|
|
|
a= t1; t1= t2; t2= a;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* calculate t0: is the maximum visible z (when halo is intersected by face) */
|
2012-05-19 13:28:19 +00:00
|
|
|
if (do_clip) {
|
2014-04-01 11:34:00 +11:00
|
|
|
if (use_yco == false) t0 = ((double)maxz - npos[2]) / nray[2];
|
2012-11-04 07:18:29 +00:00
|
|
|
else t0 = ((double)maxy - npos[1]) / nray[1];
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-05-19 13:28:19 +00:00
|
|
|
if (t0 < t1) return;
|
|
|
|
if (t0 < t2) t2= t0;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* calc points */
|
|
|
|
p1[0]= npos[0] + t1*nray[0];
|
|
|
|
p1[1]= npos[1] + t1*nray[1];
|
|
|
|
p1[2]= npos[2] + t1*nray[2];
|
|
|
|
p2[0]= npos[0] + t2*nray[0];
|
|
|
|
p2[1]= npos[1] + t2*nray[1];
|
|
|
|
p2[2]= npos[2] + t2*nray[2];
|
|
|
|
|
|
|
|
|
|
|
|
/* now we have 2 points, make three lengths with it */
|
|
|
|
|
2014-09-17 14:11:37 +10:00
|
|
|
a = len_v3(p1);
|
|
|
|
b = len_v3(p2);
|
|
|
|
c = len_v3v3(p1, p2);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
a/= ladist;
|
|
|
|
a= sqrt(a);
|
|
|
|
b/= ladist;
|
|
|
|
b= sqrt(b);
|
|
|
|
c/= ladist;
|
|
|
|
|
|
|
|
*intens= c*( (1.0-a)+(1.0-b) );
|
|
|
|
|
|
|
|
/* WATCH IT: do not clip a,b en c at 1.0, this gives nasty little overflows
|
2012-03-09 18:28:30 +00:00
|
|
|
* at the edges (especially with narrow halos) */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (*intens<=0.0f) return;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* soft area */
|
|
|
|
/* not needed because t0 has been used for p1/p2 as well */
|
2012-03-24 07:52:14 +00:00
|
|
|
/* if (doclip && t0<t2) { */
|
2006-12-05 16:43:01 +00:00
|
|
|
/* *intens *= (t0-t1)/(t2-t1); */
|
|
|
|
/* } */
|
|
|
|
|
|
|
|
*intens *= haint;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->shb && lar->shb->shadhalostep) {
|
2006-12-05 16:43:01 +00:00
|
|
|
*intens *= shadow_halo(lar, p1, p2);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-24 14:34:24 +00:00
|
|
|
void renderspothalo(ShadeInput *shi, float col[4], float alpha)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
2006-12-08 18:37:55 +00:00
|
|
|
ListBase *lights;
|
2006-12-05 16:43:01 +00:00
|
|
|
GroupObject *go;
|
|
|
|
LampRen *lar;
|
|
|
|
float i;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (alpha==0.0f) return;
|
2006-12-07 14:17:38 +00:00
|
|
|
|
2006-12-08 18:37:55 +00:00
|
|
|
lights= get_lights(shi);
|
2012-03-24 06:38:07 +00:00
|
|
|
for (go=lights->first; go; go= go->next) {
|
2006-12-05 16:43:01 +00:00
|
|
|
lar= go->lampren;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar==NULL) continue;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->type==LA_SPOT && (lar->mode & LA_HALO) && (lar->buftype != LA_SHADBUF_DEEP) && lar->haint>0) {
|
2006-12-08 18:37:55 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->mode & LA_LAYER)
|
|
|
|
if (shi->vlr && (lar->lay & shi->obi->lay)==0)
|
2007-01-06 11:13:07 +00:00
|
|
|
continue;
|
2012-03-24 06:38:07 +00:00
|
|
|
if ((lar->lay & shi->lay)==0)
|
2007-01-06 11:13:07 +00:00
|
|
|
continue;
|
2006-12-08 18:37:55 +00:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
spothalo(lar, shi, &i);
|
2012-07-07 22:51:57 +00:00
|
|
|
if (i > 0.0f) {
|
|
|
|
const float i_alpha = i * alpha;
|
|
|
|
col[0] += i_alpha * lar->r;
|
|
|
|
col[1] += i_alpha * lar->g;
|
|
|
|
col[2] += i_alpha * lar->b;
|
|
|
|
col[3] += i_alpha; /* all premul */
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* clip alpha, is needed for unified 'alpha threshold' (vanillaRenderPipe.c) */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (col[3]>1.0f) col[3]= 1.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- shaders ----------------------- */
|
|
|
|
|
2007-04-04 13:18:41 +00:00
|
|
|
static double Normalize_d(double *n)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
double d;
|
|
|
|
|
|
|
|
d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (d>0.00000000000000001) {
|
2006-12-05 16:43:01 +00:00
|
|
|
d= sqrt(d);
|
|
|
|
|
|
|
|
n[0]/=d;
|
|
|
|
n[1]/=d;
|
|
|
|
n[2]/=d;
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
else {
|
2006-12-05 16:43:01 +00:00
|
|
|
n[0]=n[1]=n[2]= 0.0;
|
|
|
|
d= 0.0;
|
|
|
|
}
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* mix of 'real' fresnel and allowing control. grad defines blending gradient */
|
2012-05-26 16:04:31 +00:00
|
|
|
float fresnel_fac(const float view[3], const float vn[3], float grad, float fac)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
float t1, t2;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (fac==0.0f) return 1.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-05-26 16:04:31 +00:00
|
|
|
t1 = dot_v3v3(view, vn);
|
2012-03-24 06:38:07 +00:00
|
|
|
if (t1>0.0f) t2= 1.0f+t1;
|
2006-12-05 16:43:01 +00:00
|
|
|
else t2= 1.0f-t1;
|
|
|
|
|
2011-11-11 12:00:08 +00:00
|
|
|
t2= grad + (1.0f-grad)*powf(t2, fac);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (t2<0.0f) return 0.0f;
|
|
|
|
else if (t2>1.0f) return 1.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
return t2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static double saacos_d(double fac)
|
|
|
|
{
|
2012-03-24 06:38:07 +00:00
|
|
|
if (fac<= -1.0) return M_PI;
|
|
|
|
else if (fac>=1.0) return 0.0;
|
2006-12-05 16:43:01 +00:00
|
|
|
else return acos(fac);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Stoke's form factor. Need doubles here for extreme small area sizes */
|
2012-05-26 16:04:31 +00:00
|
|
|
static float area_lamp_energy(float (*area)[3], const float co[3], const float vn[3])
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
double fac;
|
|
|
|
double vec[4][3]; /* vectors of rendered co to vertices lamp */
|
|
|
|
double cross[4][3]; /* cross products of this */
|
|
|
|
double rad[4]; /* angles between vecs */
|
|
|
|
|
2007-12-01 17:55:16 +00:00
|
|
|
VECSUB(vec[0], co, area[0]);
|
|
|
|
VECSUB(vec[1], co, area[1]);
|
|
|
|
VECSUB(vec[2], co, area[2]);
|
|
|
|
VECSUB(vec[3], co, area[3]);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2007-04-04 13:18:41 +00:00
|
|
|
Normalize_d(vec[0]);
|
|
|
|
Normalize_d(vec[1]);
|
|
|
|
Normalize_d(vec[2]);
|
|
|
|
Normalize_d(vec[3]);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* cross product */
|
2012-05-27 12:21:13 +00:00
|
|
|
#define CROSS(dest, a, b) \
|
2012-10-15 04:16:34 +00:00
|
|
|
{ \
|
|
|
|
dest[0]= a[1] * b[2] - a[2] * b[1]; \
|
|
|
|
dest[1]= a[2] * b[0] - a[0] * b[2]; \
|
|
|
|
dest[2]= a[0] * b[1] - a[1] * b[0]; \
|
2012-05-27 12:21:13 +00:00
|
|
|
} (void)0
|
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
CROSS(cross[0], vec[0], vec[1]);
|
|
|
|
CROSS(cross[1], vec[1], vec[2]);
|
|
|
|
CROSS(cross[2], vec[2], vec[3]);
|
|
|
|
CROSS(cross[3], vec[3], vec[0]);
|
|
|
|
|
2012-05-27 12:21:13 +00:00
|
|
|
#undef CROSS
|
|
|
|
|
2007-04-04 13:18:41 +00:00
|
|
|
Normalize_d(cross[0]);
|
|
|
|
Normalize_d(cross[1]);
|
|
|
|
Normalize_d(cross[2]);
|
|
|
|
Normalize_d(cross[3]);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* angles */
|
|
|
|
rad[0]= vec[0][0]*vec[1][0]+ vec[0][1]*vec[1][1]+ vec[0][2]*vec[1][2];
|
|
|
|
rad[1]= vec[1][0]*vec[2][0]+ vec[1][1]*vec[2][1]+ vec[1][2]*vec[2][2];
|
|
|
|
rad[2]= vec[2][0]*vec[3][0]+ vec[2][1]*vec[3][1]+ vec[2][2]*vec[3][2];
|
|
|
|
rad[3]= vec[3][0]*vec[0][0]+ vec[3][1]*vec[0][1]+ vec[3][2]*vec[0][2];
|
|
|
|
|
|
|
|
rad[0]= saacos_d(rad[0]);
|
|
|
|
rad[1]= saacos_d(rad[1]);
|
|
|
|
rad[2]= saacos_d(rad[2]);
|
|
|
|
rad[3]= saacos_d(rad[3]);
|
|
|
|
|
|
|
|
/* Stoke formula */
|
|
|
|
fac= rad[0]*(vn[0]*cross[0][0]+ vn[1]*cross[0][1]+ vn[2]*cross[0][2]);
|
|
|
|
fac+= rad[1]*(vn[0]*cross[1][0]+ vn[1]*cross[1][1]+ vn[2]*cross[1][2]);
|
|
|
|
fac+= rad[2]*(vn[0]*cross[2][0]+ vn[1]*cross[2][1]+ vn[2]*cross[2][2]);
|
|
|
|
fac+= rad[3]*(vn[0]*cross[3][0]+ vn[1]*cross[3][1]+ vn[2]*cross[3][2]);
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (fac<=0.0) return 0.0;
|
2007-12-01 17:55:16 +00:00
|
|
|
return fac;
|
|
|
|
}
|
|
|
|
|
2012-05-26 16:04:31 +00:00
|
|
|
static float area_lamp_energy_multisample(LampRen *lar, const float co[3], float *vn)
|
2007-12-01 17:55:16 +00:00
|
|
|
{
|
|
|
|
/* corner vectors are moved around according lamp jitter */
|
|
|
|
float *jitlamp= lar->jitter, vec[3];
|
|
|
|
float area[4][3], intens= 0.0f;
|
|
|
|
int a= lar->ray_totsamp;
|
2008-05-07 20:24:06 +00:00
|
|
|
|
|
|
|
/* test if co is behind lamp */
|
2011-09-11 02:50:01 +00:00
|
|
|
sub_v3_v3v3(vec, co, lar->co);
|
2012-03-24 06:38:07 +00:00
|
|
|
if (dot_v3v3(vec, lar->vec) < 0.0f)
|
2008-05-07 20:24:06 +00:00
|
|
|
return 0.0f;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
while (a--) {
|
2007-12-01 17:55:16 +00:00
|
|
|
vec[0]= jitlamp[0];
|
|
|
|
vec[1]= jitlamp[1];
|
|
|
|
vec[2]= 0.0f;
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_m3_v3(lar->mat, vec);
|
2007-12-01 17:55:16 +00:00
|
|
|
|
2011-11-06 16:38:21 +00:00
|
|
|
add_v3_v3v3(area[0], lar->area[0], vec);
|
|
|
|
add_v3_v3v3(area[1], lar->area[1], vec);
|
|
|
|
add_v3_v3v3(area[2], lar->area[2], vec);
|
|
|
|
add_v3_v3v3(area[3], lar->area[3], vec);
|
2007-12-01 17:55:16 +00:00
|
|
|
|
|
|
|
intens+= area_lamp_energy(area, co, vn);
|
|
|
|
|
|
|
|
jitlamp+= 2;
|
|
|
|
}
|
|
|
|
intens /= (float)lar->ray_totsamp;
|
|
|
|
|
2012-07-07 22:51:57 +00:00
|
|
|
return pow(intens * lar->areasize, lar->k); /* corrected for buttons size and lar->dist^2 */
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static float spec(float inp, int hard)
|
|
|
|
{
|
|
|
|
float b1;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (inp>=1.0f) return 1.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
else if (inp<=0.0f) return 0.0f;
|
|
|
|
|
|
|
|
b1= inp*inp;
|
|
|
|
/* avoid FPE */
|
2012-10-21 05:46:41 +00:00
|
|
|
if (b1<0.01f) b1= 0.01f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if ((hard & 1)==0) inp= 1.0f;
|
|
|
|
if (hard & 2) inp*= b1;
|
2006-12-05 16:43:01 +00:00
|
|
|
b1*= b1;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (hard & 4) inp*= b1;
|
2006-12-05 16:43:01 +00:00
|
|
|
b1*= b1;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (hard & 8) inp*= b1;
|
2006-12-05 16:43:01 +00:00
|
|
|
b1*= b1;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (hard & 16) inp*= b1;
|
2006-12-05 16:43:01 +00:00
|
|
|
b1*= b1;
|
|
|
|
|
|
|
|
/* avoid FPE */
|
2012-10-21 05:46:41 +00:00
|
|
|
if (b1<0.001f) b1= 0.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (hard & 32) inp*= b1;
|
2006-12-05 16:43:01 +00:00
|
|
|
b1*= b1;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (hard & 64) inp*=b1;
|
2006-12-05 16:43:01 +00:00
|
|
|
b1*= b1;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (hard & 128) inp*=b1;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
if (b1<0.001f) b1= 0.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (hard & 256) {
|
2006-12-05 16:43:01 +00:00
|
|
|
b1*= b1;
|
|
|
|
inp*=b1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return inp;
|
|
|
|
}
|
|
|
|
|
2012-05-26 16:04:31 +00:00
|
|
|
static float Phong_Spec(const float n[3], const float l[3], const float v[3], int hard, int tangent )
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
float h[3];
|
|
|
|
float rslt;
|
|
|
|
|
|
|
|
h[0] = l[0] + v[0];
|
|
|
|
h[1] = l[1] + v[1];
|
|
|
|
h[2] = l[2] + v[2];
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(h);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2];
|
2012-03-24 06:38:07 +00:00
|
|
|
if (tangent) rslt= sasqrt(1.0f - rslt*rslt);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if ( rslt > 0.0f ) rslt= spec(rslt, hard);
|
2006-12-05 16:43:01 +00:00
|
|
|
else rslt = 0.0f;
|
|
|
|
|
|
|
|
return rslt;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* reduced cook torrance spec (for off-specular peak) */
|
2012-05-26 16:04:31 +00:00
|
|
|
static float CookTorr_Spec(const float n[3], const float l[3], const float v[3], int hard, int tangent)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
float i, nh, nv, h[3];
|
|
|
|
|
|
|
|
h[0]= v[0]+l[0];
|
|
|
|
h[1]= v[1]+l[1];
|
|
|
|
h[2]= v[2]+l[2];
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(h);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2];
|
2012-03-24 06:38:07 +00:00
|
|
|
if (tangent) nh= sasqrt(1.0f - nh*nh);
|
|
|
|
else if (nh<0.0f) return 0.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2];
|
2012-03-24 06:38:07 +00:00
|
|
|
if (tangent) nv= sasqrt(1.0f - nv*nv);
|
|
|
|
else if (nv<0.0f) nv= 0.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
i= spec(nh, hard);
|
|
|
|
|
2011-09-02 03:32:57 +00:00
|
|
|
i= i/(0.1f+nv);
|
2006-12-05 16:43:01 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Blinn spec */
|
2012-05-26 16:04:31 +00:00
|
|
|
static float Blinn_Spec(const float n[3], const float l[3], const float v[3], float refrac, float spec_power, int tangent)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
float i, nh, nv, nl, vh, h[3];
|
|
|
|
float a, b, c, g=0.0f, p, f, ang;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (refrac < 1.0f) return 0.0f;
|
|
|
|
if (spec_power == 0.0f) return 0.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* conversion from 'hardness' (1-255) to 'spec_power' (50 maps at 0.1) */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (spec_power<100.0f)
|
2014-09-17 14:11:37 +10:00
|
|
|
spec_power = sqrtf(1.0f / spec_power);
|
2006-12-05 16:43:01 +00:00
|
|
|
else spec_power= 10.0f/spec_power;
|
|
|
|
|
|
|
|
h[0]= v[0]+l[0];
|
|
|
|
h[1]= v[1]+l[1];
|
|
|
|
h[2]= v[2]+l[2];
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(h);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (tangent) nh= sasqrt(1.0f - nh*nh);
|
|
|
|
else if (nh<0.0f) return 0.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (tangent) nv= sasqrt(1.0f - nv*nv);
|
|
|
|
if (nv<=0.01f) nv= 0.01f; /* hrms... */
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
nl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (tangent) nl= sasqrt(1.0f - nl*nl);
|
|
|
|
if (nl<=0.01f) {
|
2006-12-05 16:43:01 +00:00
|
|
|
return 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; /* Dot product between view vector and half-way vector */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (vh<=0.0f) vh= 0.01f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
a = 1.0f;
|
|
|
|
b = (2.0f*nh*nv)/vh;
|
|
|
|
c = (2.0f*nh*nl)/vh;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if ( a < b && a < c ) g = a;
|
|
|
|
else if ( b < a && b < c ) g = b;
|
|
|
|
else if ( c < a && c < b ) g = c;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-04-29 17:11:40 +00:00
|
|
|
p = sqrt((double)((refrac * refrac)+(vh * vh) - 1.0f));
|
2006-12-05 16:43:01 +00:00
|
|
|
f = (((p-vh)*(p-vh))/((p+vh)*(p+vh)))*(1+((((vh*(p+vh))-1.0f)*((vh*(p+vh))-1.0f))/(((vh*(p-vh))+1.0f)*((vh*(p-vh))+1.0f))));
|
|
|
|
ang = saacos(nh);
|
|
|
|
|
|
|
|
i= f * g * exp((double)(-(ang*ang) / (2.0f*spec_power*spec_power)));
|
2012-03-24 06:38:07 +00:00
|
|
|
if (i<0.0f) i= 0.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* cartoon render spec */
|
2012-05-26 16:04:31 +00:00
|
|
|
static float Toon_Spec(const float n[3], const float l[3], const float v[3], float size, float smooth, int tangent)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
float h[3];
|
|
|
|
float ang;
|
|
|
|
float rslt;
|
|
|
|
|
|
|
|
h[0] = l[0] + v[0];
|
|
|
|
h[1] = l[1] + v[1];
|
|
|
|
h[2] = l[2] + v[2];
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(h);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2];
|
2012-03-24 06:38:07 +00:00
|
|
|
if (tangent) rslt = sasqrt(1.0f - rslt*rslt);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
ang = saacos( rslt );
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if ( ang < size ) rslt = 1.0f;
|
|
|
|
else if ( ang >= (size + smooth) || smooth == 0.0f ) rslt = 0.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
else rslt = 1.0f - ((ang - size) / smooth);
|
|
|
|
|
|
|
|
return rslt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Ward isotropic gaussian spec */
|
2012-05-26 16:04:31 +00:00
|
|
|
static float WardIso_Spec(const float n[3], const float l[3], const float v[3], float rms, int tangent)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
float i, nh, nv, nl, h[3], angle, alpha;
|
|
|
|
|
|
|
|
|
|
|
|
/* half-way vector */
|
|
|
|
h[0] = l[0] + v[0];
|
|
|
|
h[1] = l[1] + v[1];
|
|
|
|
h[2] = l[2] + v[2];
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(h);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
nh = n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (tangent) nh = sasqrt(1.0f - nh*nh);
|
|
|
|
if (nh<=0.0f) nh = 0.001f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
nv = n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (tangent) nv = sasqrt(1.0f - nv*nv);
|
|
|
|
if (nv<=0.0f) nv = 0.001f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
nl = n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (tangent) nl = sasqrt(1.0f - nl*nl);
|
|
|
|
if (nl<=0.0f) nl = 0.001f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2014-09-17 14:11:37 +10:00
|
|
|
angle = tanf(saacos(nh));
|
2006-12-05 16:43:01 +00:00
|
|
|
alpha = MAX2(rms, 0.001f);
|
|
|
|
|
2011-11-11 12:00:08 +00:00
|
|
|
i= nl * (1.0f/(4.0f*(float)M_PI*alpha*alpha)) * (expf( -(angle*angle)/(alpha*alpha))/(sqrtf(nv*nl)));
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* cartoon render diffuse */
|
2012-05-26 16:04:31 +00:00
|
|
|
static float Toon_Diff(const float n[3], const float l[3], const float UNUSED(v[3]), float size, float smooth)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
float rslt, ang;
|
|
|
|
|
|
|
|
rslt = n[0]*l[0] + n[1]*l[1] + n[2]*l[2];
|
|
|
|
|
2014-09-17 14:11:37 +10:00
|
|
|
ang = saacos(rslt);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if ( ang < size ) rslt = 1.0f;
|
|
|
|
else if ( ang >= (size + smooth) || smooth == 0.0f ) rslt = 0.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
else rslt = 1.0f - ((ang - size) / smooth);
|
|
|
|
|
|
|
|
return rslt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Oren Nayar diffuse */
|
|
|
|
|
|
|
|
/* 'nl' is either dot product, or return value of area light */
|
|
|
|
/* in latter case, only last multiplication uses 'nl' */
|
2012-05-26 16:04:31 +00:00
|
|
|
static float OrenNayar_Diff(float nl, const float n[3], const float l[3], const float v[3], float rough )
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
2011-09-22 03:14:50 +00:00
|
|
|
float i/*, nh*/, nv /*, vh */, realnl, h[3];
|
2006-12-05 16:43:01 +00:00
|
|
|
float a, b, t, A, B;
|
|
|
|
float Lit_A, View_A, Lit_B[3], View_B[3];
|
|
|
|
|
|
|
|
h[0]= v[0]+l[0];
|
|
|
|
h[1]= v[1]+l[1];
|
|
|
|
h[2]= v[2]+l[2];
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(h);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2011-04-24 10:51:45 +00:00
|
|
|
/* nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; */ /* Dot product between surface normal and half-way vector */
|
2012-03-24 07:52:14 +00:00
|
|
|
/* if (nh<0.0f) nh = 0.0f; */
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (nv<=0.0f) nv= 0.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
realnl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (realnl<=0.0f) return 0.0f;
|
|
|
|
if (nl<0.0f) return 0.0f; /* value from area light */
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2011-09-22 03:14:50 +00:00
|
|
|
/* vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; */ /* Dot product between view vector and halfway vector */
|
2012-03-24 07:52:14 +00:00
|
|
|
/* if (vh<=0.0f) vh= 0.0f; */
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
Lit_A = saacos(realnl);
|
|
|
|
View_A = saacos( nv );
|
|
|
|
|
|
|
|
Lit_B[0] = l[0] - (realnl * n[0]);
|
|
|
|
Lit_B[1] = l[1] - (realnl * n[1]);
|
|
|
|
Lit_B[2] = l[2] - (realnl * n[2]);
|
2012-04-29 17:11:40 +00:00
|
|
|
normalize_v3(Lit_B);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
View_B[0] = v[0] - (nv * n[0]);
|
|
|
|
View_B[1] = v[1] - (nv * n[1]);
|
|
|
|
View_B[2] = v[2] - (nv * n[2]);
|
2012-04-29 17:11:40 +00:00
|
|
|
normalize_v3(View_B);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
t = Lit_B[0]*View_B[0] + Lit_B[1]*View_B[1] + Lit_B[2]*View_B[2];
|
2012-03-24 06:38:07 +00:00
|
|
|
if ( t < 0 ) t = 0;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if ( Lit_A > View_A ) {
|
2006-12-05 16:43:01 +00:00
|
|
|
a = Lit_A;
|
|
|
|
b = View_A;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
a = View_A;
|
|
|
|
b = Lit_A;
|
|
|
|
}
|
|
|
|
|
|
|
|
A = 1.0f - (0.5f * ((rough * rough) / ((rough * rough) + 0.33f)));
|
|
|
|
B = 0.45f * ((rough * rough) / ((rough * rough) + 0.09f));
|
|
|
|
|
|
|
|
b*= 0.95f; /* prevent tangens from shooting to inf, 'nl' can be not a dot product here. */
|
|
|
|
/* overflow only happens with extreme size area light, and higher roughness */
|
2011-11-11 12:00:08 +00:00
|
|
|
i = nl * ( A + ( B * t * sinf(a) * tanf(b) ) );
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Minnaert diffuse */
|
2012-05-26 16:04:31 +00:00
|
|
|
static float Minnaert_Diff(float nl, const float n[3], const float v[3], float darkness)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
float i, nv;
|
|
|
|
|
|
|
|
/* nl = dot product between surface normal and light vector */
|
|
|
|
if (nl <= 0.0f)
|
|
|
|
return 0.0f;
|
|
|
|
|
|
|
|
/* nv = dot product between surface normal and view vector */
|
2012-07-06 22:48:28 +00:00
|
|
|
nv = dot_v3v3(n, v);
|
2006-12-05 16:43:01 +00:00
|
|
|
if (nv < 0.0f)
|
|
|
|
nv = 0.0f;
|
|
|
|
|
|
|
|
if (darkness <= 1.0f)
|
2012-10-23 13:28:22 +00:00
|
|
|
i = nl * pow(max_ff(nv * nl, 0.1f), (darkness - 1.0f) ); /*The Real model*/
|
2006-12-05 16:43:01 +00:00
|
|
|
else
|
|
|
|
i = nl * pow( (1.001f - nv), (darkness - 1.0f) ); /*Nvidia model*/
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2011-06-20 15:17:02 +00:00
|
|
|
static float Fresnel_Diff(float *vn, float *lv, float *UNUSED(view), float fac_i, float fac)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
return fresnel_fac(lv, vn, fac_i, fac);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------- */
|
|
|
|
/* also called from texture.c */
|
|
|
|
void calc_R_ref(ShadeInput *shi)
|
|
|
|
{
|
|
|
|
float i;
|
|
|
|
|
|
|
|
/* shi->vn dot shi->view */
|
|
|
|
i= -2*(shi->vn[0]*shi->view[0]+shi->vn[1]*shi->view[1]+shi->vn[2]*shi->view[2]);
|
|
|
|
|
|
|
|
shi->ref[0]= (shi->view[0]+i*shi->vn[0]);
|
|
|
|
shi->ref[1]= (shi->view[1]+i*shi->vn[1]);
|
|
|
|
shi->ref[2]= (shi->view[2]+i*shi->vn[2]);
|
2012-03-24 06:38:07 +00:00
|
|
|
if (shi->osatex) {
|
|
|
|
if (shi->vlr->flag & R_SMOOTH) {
|
2006-12-05 16:43:01 +00:00
|
|
|
i= -2*( (shi->vn[0]+shi->dxno[0])*(shi->view[0]+shi->dxview) +
|
|
|
|
(shi->vn[1]+shi->dxno[1])*shi->view[1]+ (shi->vn[2]+shi->dxno[2])*shi->view[2] );
|
|
|
|
|
|
|
|
shi->dxref[0]= shi->ref[0]- ( shi->view[0]+shi->dxview+i*(shi->vn[0]+shi->dxno[0]));
|
|
|
|
shi->dxref[1]= shi->ref[1]- (shi->view[1]+ i*(shi->vn[1]+shi->dxno[1]));
|
|
|
|
shi->dxref[2]= shi->ref[2]- (shi->view[2]+ i*(shi->vn[2]+shi->dxno[2]));
|
|
|
|
|
|
|
|
i= -2*( (shi->vn[0]+shi->dyno[0])*shi->view[0]+
|
|
|
|
(shi->vn[1]+shi->dyno[1])*(shi->view[1]+shi->dyview)+ (shi->vn[2]+shi->dyno[2])*shi->view[2] );
|
|
|
|
|
|
|
|
shi->dyref[0]= shi->ref[0]- (shi->view[0]+ i*(shi->vn[0]+shi->dyno[0]));
|
|
|
|
shi->dyref[1]= shi->ref[1]- (shi->view[1]+shi->dyview+i*(shi->vn[1]+shi->dyno[1]));
|
|
|
|
shi->dyref[2]= shi->ref[2]- (shi->view[2]+ i*(shi->vn[2]+shi->dyno[2]));
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
i= -2*( shi->vn[0]*(shi->view[0]+shi->dxview) +
|
|
|
|
shi->vn[1]*shi->view[1]+ shi->vn[2]*shi->view[2] );
|
|
|
|
|
|
|
|
shi->dxref[0]= shi->ref[0]- (shi->view[0]+shi->dxview+i*shi->vn[0]);
|
|
|
|
shi->dxref[1]= shi->ref[1]- (shi->view[1]+ i*shi->vn[1]);
|
|
|
|
shi->dxref[2]= shi->ref[2]- (shi->view[2]+ i*shi->vn[2]);
|
|
|
|
|
|
|
|
i= -2*( shi->vn[0]*shi->view[0]+
|
|
|
|
shi->vn[1]*(shi->view[1]+shi->dyview)+ shi->vn[2]*shi->view[2] );
|
|
|
|
|
|
|
|
shi->dyref[0]= shi->ref[0]- (shi->view[0]+ i*shi->vn[0]);
|
|
|
|
shi->dyref[1]= shi->ref[1]- (shi->view[1]+shi->dyview+i*shi->vn[1]);
|
|
|
|
shi->dyref[2]= shi->ref[2]- (shi->view[2]+ i*shi->vn[2]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-11-01 12:32:04 +11:00
|
|
|
/* called from rayshade.c */
|
2006-12-05 16:43:01 +00:00
|
|
|
void shade_color(ShadeInput *shi, ShadeResult *shr)
|
|
|
|
{
|
|
|
|
Material *ma= shi->mat;
|
|
|
|
|
2017-05-24 23:14:32 +10:00
|
|
|
if (ma->mode & (MA_VERTEXCOLP)) {
|
2011-10-22 16:16:14 +00:00
|
|
|
float neg_alpha = 1.0f - shi->vcol[3];
|
|
|
|
shi->r= shi->r*neg_alpha + shi->vcol[0]*shi->vcol[3];
|
|
|
|
shi->g= shi->g*neg_alpha + shi->vcol[1]*shi->vcol[3];
|
|
|
|
shi->b= shi->b*neg_alpha + shi->vcol[2]*shi->vcol[3];
|
2011-07-24 17:03:33 +00:00
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->texco)
|
2011-10-31 13:01:06 +00:00
|
|
|
do_material_tex(shi, &R);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->fresnel_tra!=0.0f)
|
2006-12-05 16:43:01 +00:00
|
|
|
shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra);
|
2011-03-11 07:59:43 +00:00
|
|
|
|
|
|
|
if (!(shi->mode & MA_TRANSP)) shi->alpha= 1.0f;
|
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
shr->diff[0]= shi->r;
|
|
|
|
shr->diff[1]= shi->g;
|
|
|
|
shr->diff[2]= shi->b;
|
|
|
|
shr->alpha= shi->alpha;
|
2013-06-28 15:00:05 +00:00
|
|
|
|
|
|
|
/* modulate by the object color */
|
|
|
|
if ((ma->shade_flag & MA_OBCOLOR) && shi->obr->ob) {
|
|
|
|
float obcol[4];
|
|
|
|
|
|
|
|
copy_v4_v4(obcol, shi->obr->ob->col);
|
|
|
|
CLAMP(obcol[3], 0.0f, 1.0f);
|
|
|
|
|
|
|
|
shr->diff[0] *= obcol[0];
|
|
|
|
shr->diff[1] *= obcol[1];
|
|
|
|
shr->diff[2] *= obcol[2];
|
|
|
|
if (shi->mode & MA_TRANSP) shr->alpha *= obcol[3];
|
|
|
|
}
|
2014-02-26 16:55:50 +01:00
|
|
|
|
|
|
|
copy_v3_v3(shr->diffshad, shr->diff);
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ramp for at end of shade */
|
|
|
|
static void ramp_diffuse_result(float *diff, ShadeInput *shi)
|
|
|
|
{
|
|
|
|
Material *ma= shi->mat;
|
2011-09-24 14:34:24 +00:00
|
|
|
float col[4];
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->ramp_col) {
|
|
|
|
if (ma->rampin_col==MA_RAMP_IN_RESULT) {
|
2015-03-17 15:20:33 +01:00
|
|
|
float fac = IMB_colormanagement_get_luminance(diff);
|
2006-12-05 16:43:01 +00:00
|
|
|
do_colorband(ma->ramp_col, fac, col);
|
|
|
|
|
|
|
|
/* blending method */
|
|
|
|
fac= col[3]*ma->rampfac_col;
|
|
|
|
|
2011-11-26 13:11:55 +00:00
|
|
|
ramp_blend(ma->rampblend_col, diff, fac, col);
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* r,g,b denote energy, ramp is used with different values to make new material color */
|
2015-03-19 12:59:36 +11:00
|
|
|
static void add_to_diffuse(float diff[3], const ShadeInput *shi, const float is, const float rgb[3])
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
Material *ma= shi->mat;
|
2011-09-24 14:34:24 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->ramp_col && (ma->mode & MA_RAMP_COL)) {
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* MA_RAMP_IN_RESULT is exceptional */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->rampin_col==MA_RAMP_IN_RESULT) {
|
2012-07-07 22:51:57 +00:00
|
|
|
/* normal add */
|
2015-03-19 12:59:36 +11:00
|
|
|
diff[0] += rgb[0] * shi->r;
|
|
|
|
diff[1] += rgb[1] * shi->g;
|
|
|
|
diff[2] += rgb[2] * shi->b;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-09-24 14:34:24 +00:00
|
|
|
float colt[3], col[4];
|
|
|
|
float fac;
|
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
/* input */
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (ma->rampin_col) {
|
2006-12-05 16:43:01 +00:00
|
|
|
case MA_RAMP_IN_ENERGY:
|
2015-03-19 12:59:36 +11:00
|
|
|
fac = IMB_colormanagement_get_luminance(rgb);
|
2006-12-05 16:43:01 +00:00
|
|
|
break;
|
|
|
|
case MA_RAMP_IN_SHADER:
|
2015-03-19 12:59:36 +11:00
|
|
|
fac = is;
|
2006-12-05 16:43:01 +00:00
|
|
|
break;
|
|
|
|
case MA_RAMP_IN_NOR:
|
2015-03-19 12:59:36 +11:00
|
|
|
fac = dot_v3v3(shi->view, shi->vn);
|
2006-12-05 16:43:01 +00:00
|
|
|
break;
|
2011-09-24 14:34:24 +00:00
|
|
|
default:
|
2015-03-19 12:59:36 +11:00
|
|
|
fac = 0.0f;
|
2011-09-24 14:34:24 +00:00
|
|
|
break;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
do_colorband(ma->ramp_col, fac, col);
|
|
|
|
|
|
|
|
/* blending method */
|
2015-03-19 12:59:36 +11:00
|
|
|
fac = col[3] * ma->rampfac_col;
|
|
|
|
copy_v3_v3(colt, &shi->r);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2011-11-26 13:11:55 +00:00
|
|
|
ramp_blend(ma->rampblend_col, colt, fac, col);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* output to */
|
2015-03-19 12:59:36 +11:00
|
|
|
diff[0] += rgb[0] * colt[0];
|
|
|
|
diff[1] += rgb[1] * colt[1];
|
|
|
|
diff[2] += rgb[2] * colt[2];
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2015-03-19 12:59:36 +11:00
|
|
|
diff[0] += rgb[0] * shi->r;
|
|
|
|
diff[1] += rgb[1] * shi->g;
|
|
|
|
diff[2] += rgb[2] * shi->b;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-26 13:11:55 +00:00
|
|
|
static void ramp_spec_result(float spec_col[3], ShadeInput *shi)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
Material *ma= shi->mat;
|
2011-09-24 14:34:24 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->ramp_spec && (ma->rampin_spec==MA_RAMP_IN_RESULT)) {
|
2011-09-24 14:34:24 +00:00
|
|
|
float col[4];
|
2015-03-17 15:20:33 +01:00
|
|
|
float fac = IMB_colormanagement_get_luminance(spec_col);
|
2011-09-24 14:34:24 +00:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
do_colorband(ma->ramp_spec, fac, col);
|
|
|
|
|
|
|
|
/* blending method */
|
|
|
|
fac= col[3]*ma->rampfac_spec;
|
|
|
|
|
2011-11-26 13:11:55 +00:00
|
|
|
ramp_blend(ma->rampblend_spec, spec_col, fac, col);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* is = dot product shade, t = spec energy */
|
2011-09-24 14:34:24 +00:00
|
|
|
static void do_specular_ramp(ShadeInput *shi, float is, float t, float spec[3])
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
|
|
|
Material *ma= shi->mat;
|
2011-09-24 14:34:24 +00:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
spec[0]= shi->specr;
|
|
|
|
spec[1]= shi->specg;
|
|
|
|
spec[2]= shi->specb;
|
|
|
|
|
|
|
|
/* MA_RAMP_IN_RESULT is exception */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) {
|
2011-09-24 14:34:24 +00:00
|
|
|
float fac;
|
|
|
|
float col[4];
|
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
/* input */
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (ma->rampin_spec) {
|
2006-12-05 16:43:01 +00:00
|
|
|
case MA_RAMP_IN_ENERGY:
|
|
|
|
fac= t;
|
|
|
|
break;
|
|
|
|
case MA_RAMP_IN_SHADER:
|
|
|
|
fac= is;
|
|
|
|
break;
|
|
|
|
case MA_RAMP_IN_NOR:
|
|
|
|
fac= shi->view[0]*shi->vn[0] + shi->view[1]*shi->vn[1] + shi->view[2]*shi->vn[2];
|
|
|
|
break;
|
2011-09-24 14:34:24 +00:00
|
|
|
default:
|
|
|
|
fac= 0.0f;
|
|
|
|
break;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
do_colorband(ma->ramp_spec, fac, col);
|
|
|
|
|
|
|
|
/* blending method */
|
|
|
|
fac= col[3]*ma->rampfac_spec;
|
|
|
|
|
2011-11-26 13:11:55 +00:00
|
|
|
ramp_blend(ma->rampblend_spec, spec, fac, col);
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* pure AO, check for raytrace and world should have been done */
|
2009-05-31 11:22:11 +00:00
|
|
|
/* preprocess, textures were not done, don't use shi->amb for that reason */
|
2006-12-05 16:43:01 +00:00
|
|
|
void ambient_occlusion(ShadeInput *shi)
|
|
|
|
{
|
2012-03-24 06:38:07 +00:00
|
|
|
if ((R.wrld.ao_gather_method == WO_AOGATHER_APPROX) && shi->mat->amb!=0.0f) {
|
2008-01-17 19:27:16 +00:00
|
|
|
sample_occ(&R, shi);
|
2012-02-07 21:04:10 +00:00
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
else if ((R.r.mode & R_RAYTRACE) && shi->mat->amb!=0.0f) {
|
2010-01-27 21:40:08 +00:00
|
|
|
ray_ao(shi, shi->ao, shi->env);
|
2012-02-07 21:04:10 +00:00
|
|
|
}
|
|
|
|
else {
|
2006-12-05 16:43:01 +00:00
|
|
|
shi->ao[0]= shi->ao[1]= shi->ao[2]= 1.0f;
|
2012-02-07 21:04:10 +00:00
|
|
|
zero_v3(shi->env);
|
|
|
|
zero_v3(shi->indirect);
|
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* wrld mode was checked for */
|
2010-01-27 21:40:08 +00:00
|
|
|
static void ambient_occlusion_apply(ShadeInput *shi, ShadeResult *shr)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
2010-01-27 21:40:08 +00:00
|
|
|
float f= R.wrld.aoenergy;
|
|
|
|
float tmp[3], tmpspec[3];
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (!((R.r.mode & R_RAYTRACE) || R.wrld.ao_gather_method == WO_AOGATHER_APPROX))
|
2010-01-27 21:40:08 +00:00
|
|
|
return;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (f == 0.0f)
|
2010-01-27 21:40:08 +00:00
|
|
|
return;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (R.wrld.aomix==WO_AOADD) {
|
2010-01-27 21:40:08 +00:00
|
|
|
shr->combined[0] += shi->ao[0]*shi->r*shi->refl*f;
|
|
|
|
shr->combined[1] += shi->ao[1]*shi->g*shi->refl*f;
|
|
|
|
shr->combined[2] += shi->ao[2]*shi->b*shi->refl*f;
|
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (R.wrld.aomix==WO_AOMUL) {
|
2010-01-27 21:40:08 +00:00
|
|
|
mul_v3_v3v3(tmp, shr->combined, shi->ao);
|
|
|
|
mul_v3_v3v3(tmpspec, shr->spec, shi->ao);
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (f == 1.0f) {
|
2010-01-27 21:40:08 +00:00
|
|
|
copy_v3_v3(shr->combined, tmp);
|
|
|
|
copy_v3_v3(shr->spec, tmpspec);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
interp_v3_v3v3(shr->combined, shr->combined, tmp, f);
|
|
|
|
interp_v3_v3v3(shr->spec, shr->spec, tmpspec, f);
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
2010-01-27 21:40:08 +00:00
|
|
|
}
|
|
|
|
|
2010-02-07 15:24:10 +00:00
|
|
|
void environment_lighting_apply(ShadeInput *shi, ShadeResult *shr)
|
2010-01-27 21:40:08 +00:00
|
|
|
{
|
|
|
|
float f= R.wrld.ao_env_energy*shi->amb;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (!((R.r.mode & R_RAYTRACE) || R.wrld.ao_gather_method == WO_AOGATHER_APPROX))
|
2010-01-27 21:40:08 +00:00
|
|
|
return;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (f == 0.0f)
|
2010-01-27 21:40:08 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
shr->combined[0] += shi->env[0]*shi->r*shi->refl*f;
|
|
|
|
shr->combined[1] += shi->env[1]*shi->g*shi->refl*f;
|
|
|
|
shr->combined[2] += shi->env[2]*shi->b*shi->refl*f;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void indirect_lighting_apply(ShadeInput *shi, ShadeResult *shr)
|
|
|
|
{
|
|
|
|
float f= R.wrld.ao_indirect_energy;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (!((R.r.mode & R_RAYTRACE) || R.wrld.ao_gather_method == WO_AOGATHER_APPROX))
|
2010-01-27 21:40:08 +00:00
|
|
|
return;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (f == 0.0f)
|
2010-01-27 21:40:08 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
shr->combined[0] += shi->indirect[0]*shi->r*shi->refl*f;
|
|
|
|
shr->combined[1] += shi->indirect[1]*shi->g*shi->refl*f;
|
|
|
|
shr->combined[2] += shi->indirect[2]*shi->b*shi->refl*f;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* result written in shadfac */
|
2011-09-24 14:34:24 +00:00
|
|
|
void lamp_get_shadow(LampRen *lar, ShadeInput *shi, float inp, float shadfac[4], int do_real)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
2006-12-08 09:40:44 +00:00
|
|
|
LampShadowSubSample *lss= &(lar->shadsamp[shi->thread].s[shi->sample]);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (do_real || lss->samplenr!=shi->samplenr) {
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 1.0f;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->shb) {
|
|
|
|
if (lar->buftype==LA_SHADBUF_IRREGULAR)
|
2006-12-05 16:43:01 +00:00
|
|
|
shadfac[3]= ISB_getshadow(shi, lar->shb);
|
|
|
|
else
|
2008-02-13 11:18:08 +00:00
|
|
|
shadfac[3] = testshadowbuf(&R, lar->shb, shi->co, shi->dxco, shi->dyco, inp, shi->mat->lbias);
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (lar->mode & LA_SHAD_RAY) {
|
2006-12-05 16:43:01 +00:00
|
|
|
ray_shadow(shi, lar, shadfac);
|
|
|
|
}
|
2006-12-08 09:40:44 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (shi->depth==0) {
|
2011-11-06 16:38:21 +00:00
|
|
|
copy_v4_v4(lss->shadfac, shadfac);
|
2006-12-08 14:40:33 +00:00
|
|
|
lss->samplenr= shi->samplenr;
|
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-11-06 16:38:21 +00:00
|
|
|
copy_v4_v4(shadfac, lss->shadfac);
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* lampdistance and spot angle, writes in lv and dist */
|
2011-09-24 14:34:24 +00:00
|
|
|
float lamp_get_visibility(LampRen *lar, const float co[3], float lv[3], float *dist)
|
2006-12-05 16:43:01 +00:00
|
|
|
{
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->type==LA_SUN || lar->type==LA_HEMI) {
|
2006-12-05 16:43:01 +00:00
|
|
|
*dist= 1.0f;
|
2011-09-12 04:14:12 +00:00
|
|
|
copy_v3_v3(lv, lar->vec);
|
2006-12-05 16:43:01 +00:00
|
|
|
return 1.0f;
|
|
|
|
}
|
|
|
|
else {
|
2016-03-13 02:00:12 +01:00
|
|
|
float visifac= 1.0f, visifac_r;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2011-09-11 02:50:01 +00:00
|
|
|
sub_v3_v3v3(lv, co, lar->co);
|
2015-11-23 12:28:01 +11:00
|
|
|
mul_v3_fl(lv, 1.0f / (*dist = len_v3(lv)));
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* area type has no quad or sphere option */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->type==LA_AREA) {
|
2006-12-05 16:43:01 +00:00
|
|
|
/* area is single sided */
|
2012-04-21 12:51:47 +00:00
|
|
|
//if (dot_v3v3(lv, lar->vec) > 0.0f)
|
2007-12-01 17:55:16 +00:00
|
|
|
// visifac= 1.0f;
|
|
|
|
//else
|
|
|
|
// visifac= 0.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (lar->falloff_type) {
|
* Extra lamp falloff options, including custom curve!
This adds some new lamp attenuation options to the Lamp panel, replacing the old 'Quad' button. Yes, the panel layout is still nasty here, but I've ignored it for now to address properly in the panels cleanup work.
* Constant
http://mke3.net/blender/devel/rendering/falloff-constant.jpg
Lamp doesn't decay with distance
* Inverse Linear
http://mke3.net/blender/devel/rendering/falloff-invlinear.jpg
Default, and same as in older Blender without 'Quad' on. Decays linearly, with 'Dist' value as the lamp's half-energy-distance
* Inverse Square
http://mke3.net/blender/devel/rendering/falloff-invsquare.jpg
A sharper, more realistic decay, good for most electric lights (i.e. not sunlight). This is similar to the old Quad option with slight changes.
* Lin/Quad weighted
Exactly the same as in older Blenders with the old 'Quad' button enabled. When this setting is chosen, two sliders are shown, 'Linear' and 'Quad' (previously Quad1 and Quad2), which controls the 'linearness' or 'quadraticness' of the falloff curve. Lamps in old files with the 'Quad' button on will be initialised to this setting.
But much better for precise control over the lamp falloff now is:
* Custom Curve
This shows an extra 'Falloff Curve' panel, where you can use the standard Blender curve UI control to precisely control how the light falls off. The Y axis is intensity, and the X axis is distance, stretched over the length of the 'Dist' value.
Some example curves and renders:
http://mke3.net/blender/devel/rendering/falloff-curve1-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve1.jpg
http://mke3.net/blender/devel/rendering/falloff-curve2-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve2.jpg
http://mke3.net/blender/devel/rendering/falloff-curve3-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve3.jpg (whee)
2007-09-16 13:50:34 +00:00
|
|
|
case LA_FALLOFF_CONSTANT:
|
|
|
|
visifac = 1.0f;
|
|
|
|
break;
|
|
|
|
case LA_FALLOFF_INVLINEAR:
|
|
|
|
visifac = lar->dist/(lar->dist + dist[0]);
|
|
|
|
break;
|
|
|
|
case LA_FALLOFF_INVSQUARE:
|
2010-10-11 09:52:25 +00:00
|
|
|
/* NOTE: This seems to be a hack since commit r12045 says this
|
|
|
|
* option is similar to old Quad, but with slight changes.
|
|
|
|
* Correct inv square would be (which would be old Quad):
|
|
|
|
* visifac = lar->distkw / (lar->distkw + dist[0]*dist[0]);
|
|
|
|
*/
|
* Extra lamp falloff options, including custom curve!
This adds some new lamp attenuation options to the Lamp panel, replacing the old 'Quad' button. Yes, the panel layout is still nasty here, but I've ignored it for now to address properly in the panels cleanup work.
* Constant
http://mke3.net/blender/devel/rendering/falloff-constant.jpg
Lamp doesn't decay with distance
* Inverse Linear
http://mke3.net/blender/devel/rendering/falloff-invlinear.jpg
Default, and same as in older Blender without 'Quad' on. Decays linearly, with 'Dist' value as the lamp's half-energy-distance
* Inverse Square
http://mke3.net/blender/devel/rendering/falloff-invsquare.jpg
A sharper, more realistic decay, good for most electric lights (i.e. not sunlight). This is similar to the old Quad option with slight changes.
* Lin/Quad weighted
Exactly the same as in older Blenders with the old 'Quad' button enabled. When this setting is chosen, two sliders are shown, 'Linear' and 'Quad' (previously Quad1 and Quad2), which controls the 'linearness' or 'quadraticness' of the falloff curve. Lamps in old files with the 'Quad' button on will be initialised to this setting.
But much better for precise control over the lamp falloff now is:
* Custom Curve
This shows an extra 'Falloff Curve' panel, where you can use the standard Blender curve UI control to precisely control how the light falls off. The Y axis is intensity, and the X axis is distance, stretched over the length of the 'Dist' value.
Some example curves and renders:
http://mke3.net/blender/devel/rendering/falloff-curve1-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve1.jpg
http://mke3.net/blender/devel/rendering/falloff-curve2-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve2.jpg
http://mke3.net/blender/devel/rendering/falloff-curve3-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve3.jpg (whee)
2007-09-16 13:50:34 +00:00
|
|
|
visifac = lar->dist / (lar->dist + dist[0]*dist[0]);
|
|
|
|
break;
|
|
|
|
case LA_FALLOFF_SLIDERS:
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->ld1>0.0f)
|
* Extra lamp falloff options, including custom curve!
This adds some new lamp attenuation options to the Lamp panel, replacing the old 'Quad' button. Yes, the panel layout is still nasty here, but I've ignored it for now to address properly in the panels cleanup work.
* Constant
http://mke3.net/blender/devel/rendering/falloff-constant.jpg
Lamp doesn't decay with distance
* Inverse Linear
http://mke3.net/blender/devel/rendering/falloff-invlinear.jpg
Default, and same as in older Blender without 'Quad' on. Decays linearly, with 'Dist' value as the lamp's half-energy-distance
* Inverse Square
http://mke3.net/blender/devel/rendering/falloff-invsquare.jpg
A sharper, more realistic decay, good for most electric lights (i.e. not sunlight). This is similar to the old Quad option with slight changes.
* Lin/Quad weighted
Exactly the same as in older Blenders with the old 'Quad' button enabled. When this setting is chosen, two sliders are shown, 'Linear' and 'Quad' (previously Quad1 and Quad2), which controls the 'linearness' or 'quadraticness' of the falloff curve. Lamps in old files with the 'Quad' button on will be initialised to this setting.
But much better for precise control over the lamp falloff now is:
* Custom Curve
This shows an extra 'Falloff Curve' panel, where you can use the standard Blender curve UI control to precisely control how the light falls off. The Y axis is intensity, and the X axis is distance, stretched over the length of the 'Dist' value.
Some example curves and renders:
http://mke3.net/blender/devel/rendering/falloff-curve1-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve1.jpg
http://mke3.net/blender/devel/rendering/falloff-curve2-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve2.jpg
http://mke3.net/blender/devel/rendering/falloff-curve3-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve3.jpg (whee)
2007-09-16 13:50:34 +00:00
|
|
|
visifac= lar->dist/(lar->dist+lar->ld1*dist[0]);
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->ld2>0.0f)
|
* Extra lamp falloff options, including custom curve!
This adds some new lamp attenuation options to the Lamp panel, replacing the old 'Quad' button. Yes, the panel layout is still nasty here, but I've ignored it for now to address properly in the panels cleanup work.
* Constant
http://mke3.net/blender/devel/rendering/falloff-constant.jpg
Lamp doesn't decay with distance
* Inverse Linear
http://mke3.net/blender/devel/rendering/falloff-invlinear.jpg
Default, and same as in older Blender without 'Quad' on. Decays linearly, with 'Dist' value as the lamp's half-energy-distance
* Inverse Square
http://mke3.net/blender/devel/rendering/falloff-invsquare.jpg
A sharper, more realistic decay, good for most electric lights (i.e. not sunlight). This is similar to the old Quad option with slight changes.
* Lin/Quad weighted
Exactly the same as in older Blenders with the old 'Quad' button enabled. When this setting is chosen, two sliders are shown, 'Linear' and 'Quad' (previously Quad1 and Quad2), which controls the 'linearness' or 'quadraticness' of the falloff curve. Lamps in old files with the 'Quad' button on will be initialised to this setting.
But much better for precise control over the lamp falloff now is:
* Custom Curve
This shows an extra 'Falloff Curve' panel, where you can use the standard Blender curve UI control to precisely control how the light falls off. The Y axis is intensity, and the X axis is distance, stretched over the length of the 'Dist' value.
Some example curves and renders:
http://mke3.net/blender/devel/rendering/falloff-curve1-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve1.jpg
http://mke3.net/blender/devel/rendering/falloff-curve2-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve2.jpg
http://mke3.net/blender/devel/rendering/falloff-curve3-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve3.jpg (whee)
2007-09-16 13:50:34 +00:00
|
|
|
visifac*= lar->distkw/(lar->distkw+lar->ld2*dist[0]*dist[0]);
|
|
|
|
break;
|
2016-03-13 02:00:12 +01:00
|
|
|
case LA_FALLOFF_INVCOEFFICIENTS:
|
|
|
|
visifac_r = lar->coeff_const +
|
|
|
|
lar->coeff_lin * dist[0] +
|
|
|
|
lar->coeff_quad * dist[0] * dist[0];
|
|
|
|
if (visifac_r > 0.0)
|
|
|
|
visifac = 1.0 / visifac_r;
|
|
|
|
else
|
|
|
|
visifac = 0.0;
|
|
|
|
break;
|
* Extra lamp falloff options, including custom curve!
This adds some new lamp attenuation options to the Lamp panel, replacing the old 'Quad' button. Yes, the panel layout is still nasty here, but I've ignored it for now to address properly in the panels cleanup work.
* Constant
http://mke3.net/blender/devel/rendering/falloff-constant.jpg
Lamp doesn't decay with distance
* Inverse Linear
http://mke3.net/blender/devel/rendering/falloff-invlinear.jpg
Default, and same as in older Blender without 'Quad' on. Decays linearly, with 'Dist' value as the lamp's half-energy-distance
* Inverse Square
http://mke3.net/blender/devel/rendering/falloff-invsquare.jpg
A sharper, more realistic decay, good for most electric lights (i.e. not sunlight). This is similar to the old Quad option with slight changes.
* Lin/Quad weighted
Exactly the same as in older Blenders with the old 'Quad' button enabled. When this setting is chosen, two sliders are shown, 'Linear' and 'Quad' (previously Quad1 and Quad2), which controls the 'linearness' or 'quadraticness' of the falloff curve. Lamps in old files with the 'Quad' button on will be initialised to this setting.
But much better for precise control over the lamp falloff now is:
* Custom Curve
This shows an extra 'Falloff Curve' panel, where you can use the standard Blender curve UI control to precisely control how the light falls off. The Y axis is intensity, and the X axis is distance, stretched over the length of the 'Dist' value.
Some example curves and renders:
http://mke3.net/blender/devel/rendering/falloff-curve1-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve1.jpg
http://mke3.net/blender/devel/rendering/falloff-curve2-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve2.jpg
http://mke3.net/blender/devel/rendering/falloff-curve3-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve3.jpg (whee)
2007-09-16 13:50:34 +00:00
|
|
|
case LA_FALLOFF_CURVE:
|
2012-08-21 14:43:51 +00:00
|
|
|
/* curvemapping_initialize is called from #add_render_lamp */
|
* Extra lamp falloff options, including custom curve!
This adds some new lamp attenuation options to the Lamp panel, replacing the old 'Quad' button. Yes, the panel layout is still nasty here, but I've ignored it for now to address properly in the panels cleanup work.
* Constant
http://mke3.net/blender/devel/rendering/falloff-constant.jpg
Lamp doesn't decay with distance
* Inverse Linear
http://mke3.net/blender/devel/rendering/falloff-invlinear.jpg
Default, and same as in older Blender without 'Quad' on. Decays linearly, with 'Dist' value as the lamp's half-energy-distance
* Inverse Square
http://mke3.net/blender/devel/rendering/falloff-invsquare.jpg
A sharper, more realistic decay, good for most electric lights (i.e. not sunlight). This is similar to the old Quad option with slight changes.
* Lin/Quad weighted
Exactly the same as in older Blenders with the old 'Quad' button enabled. When this setting is chosen, two sliders are shown, 'Linear' and 'Quad' (previously Quad1 and Quad2), which controls the 'linearness' or 'quadraticness' of the falloff curve. Lamps in old files with the 'Quad' button on will be initialised to this setting.
But much better for precise control over the lamp falloff now is:
* Custom Curve
This shows an extra 'Falloff Curve' panel, where you can use the standard Blender curve UI control to precisely control how the light falls off. The Y axis is intensity, and the X axis is distance, stretched over the length of the 'Dist' value.
Some example curves and renders:
http://mke3.net/blender/devel/rendering/falloff-curve1-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve1.jpg
http://mke3.net/blender/devel/rendering/falloff-curve2-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve2.jpg
http://mke3.net/blender/devel/rendering/falloff-curve3-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve3.jpg (whee)
2007-09-16 13:50:34 +00:00
|
|
|
visifac = curvemapping_evaluateF(lar->curfalloff, 0, dist[0]/lar->dist);
|
|
|
|
break;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->mode & LA_SPHERE) {
|
2006-12-05 16:43:01 +00:00
|
|
|
float t= lar->dist - dist[0];
|
2012-03-24 06:38:07 +00:00
|
|
|
if (t<=0.0f)
|
2006-12-05 16:43:01 +00:00
|
|
|
visifac= 0.0f;
|
|
|
|
else
|
|
|
|
visifac*= t/lar->dist;
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (visifac > 0.0f) {
|
|
|
|
if (lar->type==LA_SPOT) {
|
2015-11-23 12:28:01 +11:00
|
|
|
float inpr, t;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->mode & LA_SQUARE) {
|
|
|
|
if (dot_v3v3(lv, lar->vec) > 0.0f) {
|
2006-12-05 16:43:01 +00:00
|
|
|
float lvrot[3], x;
|
|
|
|
|
|
|
|
/* rotate view to lampspace */
|
2011-09-12 04:14:12 +00:00
|
|
|
copy_v3_v3(lvrot, lv);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_m3_v3(lar->imat, lvrot);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-10-23 13:28:22 +00:00
|
|
|
x = max_ff(fabsf(lvrot[0]/lvrot[2]), fabsf(lvrot[1]/lvrot[2]));
|
2006-12-05 16:43:01 +00:00
|
|
|
/* 1.0f/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
|
|
|
|
|
2014-09-17 14:11:37 +10:00
|
|
|
inpr = 1.0f / (sqrtf(1.0f + x * x));
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
else inpr= 0.0f;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
t= lar->spotsi;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (inpr<=t)
|
2006-12-05 16:43:01 +00:00
|
|
|
visifac= 0.0f;
|
|
|
|
else {
|
|
|
|
t= inpr-t;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (t<lar->spotbl && lar->spotbl!=0.0f) {
|
2006-12-05 16:43:01 +00:00
|
|
|
/* soft area */
|
|
|
|
float i= t/lar->spotbl;
|
|
|
|
t= i*i;
|
|
|
|
inpr*= (3.0f*t-2.0f*t*i);
|
|
|
|
}
|
|
|
|
visifac*= inpr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-09-02 03:32:57 +00:00
|
|
|
if (visifac <= 0.001f) visifac = 0.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
return visifac;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-07 14:17:38 +00:00
|
|
|
/* function returns raw diff, spec and full shadowed diff in the 'shad' pass */
|
2006-12-05 16:43:01 +00:00
|
|
|
static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int passflag)
|
|
|
|
{
|
|
|
|
Material *ma= shi->mat;
|
|
|
|
VlakRen *vlr= shi->vlr;
|
2008-09-19 16:01:22 +00:00
|
|
|
float lv[3], lampdist, lacol[3], shadfac[4], lashdw[3];
|
2006-12-05 16:43:01 +00:00
|
|
|
float i, is, i_noshad, inp, *vn, *view, vnor[3], phongcorr=1.0f;
|
|
|
|
float visifac;
|
|
|
|
|
|
|
|
vn= shi->vn;
|
|
|
|
view= shi->view;
|
|
|
|
|
* Extra lamp falloff options, including custom curve!
This adds some new lamp attenuation options to the Lamp panel, replacing the old 'Quad' button. Yes, the panel layout is still nasty here, but I've ignored it for now to address properly in the panels cleanup work.
* Constant
http://mke3.net/blender/devel/rendering/falloff-constant.jpg
Lamp doesn't decay with distance
* Inverse Linear
http://mke3.net/blender/devel/rendering/falloff-invlinear.jpg
Default, and same as in older Blender without 'Quad' on. Decays linearly, with 'Dist' value as the lamp's half-energy-distance
* Inverse Square
http://mke3.net/blender/devel/rendering/falloff-invsquare.jpg
A sharper, more realistic decay, good for most electric lights (i.e. not sunlight). This is similar to the old Quad option with slight changes.
* Lin/Quad weighted
Exactly the same as in older Blenders with the old 'Quad' button enabled. When this setting is chosen, two sliders are shown, 'Linear' and 'Quad' (previously Quad1 and Quad2), which controls the 'linearness' or 'quadraticness' of the falloff curve. Lamps in old files with the 'Quad' button on will be initialised to this setting.
But much better for precise control over the lamp falloff now is:
* Custom Curve
This shows an extra 'Falloff Curve' panel, where you can use the standard Blender curve UI control to precisely control how the light falls off. The Y axis is intensity, and the X axis is distance, stretched over the length of the 'Dist' value.
Some example curves and renders:
http://mke3.net/blender/devel/rendering/falloff-curve1-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve1.jpg
http://mke3.net/blender/devel/rendering/falloff-curve2-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve2.jpg
http://mke3.net/blender/devel/rendering/falloff-curve3-curve.png
http://mke3.net/blender/devel/rendering/falloff-curve3.jpg (whee)
2007-09-16 13:50:34 +00:00
|
|
|
|
2011-09-02 03:32:57 +00:00
|
|
|
if (lar->energy == 0.0f) return;
|
2008-02-07 06:00:08 +00:00
|
|
|
/* only shadow lamps shouldn't affect shadow-less materials at all */
|
|
|
|
if ((lar->mode & LA_ONLYSHADOW) && (!(ma->mode & MA_SHADOW) || !(R.r.mode & R_SHADOW)))
|
|
|
|
return;
|
2012-03-02 16:05:54 +00:00
|
|
|
/* optimization, don't render fully black lamps */
|
2007-11-15 00:11:00 +00:00
|
|
|
if (!(lar->mode & LA_TEXTURE) && (lar->r + lar->g + lar->b == 0.0f))
|
|
|
|
return;
|
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
/* lampdist, spot angle, area side, ... */
|
|
|
|
visifac= lamp_get_visibility(lar, shi->co, lv, &lampdist);
|
2012-03-24 06:38:07 +00:00
|
|
|
if (visifac==0.0f)
|
2006-12-05 16:43:01 +00:00
|
|
|
return;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->type==LA_SPOT) {
|
|
|
|
if (lar->mode & LA_OSATEX) {
|
2006-12-05 16:43:01 +00:00
|
|
|
shi->osatex= 1; /* signal for multitex() */
|
|
|
|
|
|
|
|
shi->dxlv[0]= lv[0] - (shi->co[0]-lar->co[0]+shi->dxco[0])/lampdist;
|
|
|
|
shi->dxlv[1]= lv[1] - (shi->co[1]-lar->co[1]+shi->dxco[1])/lampdist;
|
|
|
|
shi->dxlv[2]= lv[2] - (shi->co[2]-lar->co[2]+shi->dxco[2])/lampdist;
|
|
|
|
|
|
|
|
shi->dylv[0]= lv[0] - (shi->co[0]-lar->co[0]+shi->dyco[0])/lampdist;
|
|
|
|
shi->dylv[1]= lv[1] - (shi->co[1]-lar->co[1]+shi->dyco[1])/lampdist;
|
|
|
|
shi->dylv[2]= lv[2] - (shi->co[2]-lar->co[2]+shi->dyco[2])/lampdist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* lamp color texture */
|
|
|
|
lacol[0]= lar->r;
|
|
|
|
lacol[1]= lar->g;
|
|
|
|
lacol[2]= lar->b;
|
|
|
|
|
2008-09-19 16:01:22 +00:00
|
|
|
lashdw[0]= lar->shdwr;
|
|
|
|
lashdw[1]= lar->shdwg;
|
|
|
|
lashdw[2]= lar->shdwb;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv, shi, lacol, LA_TEXTURE);
|
|
|
|
if (lar->mode & LA_SHAD_TEX) do_lamp_tex(lar, lv, shi, lashdw, LA_SHAD_TEX);
|
2007-12-04 13:57:28 +00:00
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
/* tangent case; calculate fake face normal, aligned with lampvector */
|
2007-12-04 13:57:28 +00:00
|
|
|
/* note, vnor==vn is used as tangent trigger for buffer shadow */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (vlr->flag & R_TANGENT) {
|
2007-12-04 13:57:28 +00:00
|
|
|
float cross[3], nstrand[3], blend;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->mode & MA_STR_SURFDIFF) {
|
2009-11-10 20:43:45 +00:00
|
|
|
cross_v3_v3v3(cross, shi->surfnor, vn);
|
|
|
|
cross_v3_v3v3(nstrand, vn, cross);
|
2007-12-04 13:57:28 +00:00
|
|
|
|
2011-09-11 02:50:01 +00:00
|
|
|
blend= dot_v3v3(nstrand, shi->surfnor);
|
2008-01-21 14:18:24 +00:00
|
|
|
blend= 1.0f - blend;
|
2007-12-04 13:57:28 +00:00
|
|
|
CLAMP(blend, 0.0f, 1.0f);
|
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
interp_v3_v3v3(vnor, nstrand, shi->surfnor, blend);
|
|
|
|
normalize_v3(vnor);
|
2007-12-04 13:57:28 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-11-10 20:43:45 +00:00
|
|
|
cross_v3_v3v3(cross, lv, vn);
|
|
|
|
cross_v3_v3v3(vnor, cross, vn);
|
|
|
|
normalize_v3(vnor);
|
2007-12-04 13:57:28 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->strand_surfnor > 0.0f) {
|
|
|
|
if (ma->strand_surfnor > shi->surfdist) {
|
2007-12-04 13:57:28 +00:00
|
|
|
blend= (ma->strand_surfnor - shi->surfdist)/ma->strand_surfnor;
|
2009-11-10 20:43:45 +00:00
|
|
|
interp_v3_v3v3(vnor, vnor, shi->surfnor, blend);
|
|
|
|
normalize_v3(vnor);
|
2007-12-04 13:57:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2];
|
|
|
|
vn= vnor;
|
|
|
|
}
|
|
|
|
else if (ma->mode & MA_TANGENT_V) {
|
|
|
|
float cross[3];
|
2009-11-10 20:43:45 +00:00
|
|
|
cross_v3_v3v3(cross, lv, shi->tang);
|
|
|
|
cross_v3_v3v3(vnor, cross, shi->tang);
|
|
|
|
normalize_v3(vnor);
|
2006-12-05 16:43:01 +00:00
|
|
|
vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2];
|
|
|
|
vn= vnor;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* dot product and reflectivity */
|
|
|
|
/* inp = dotproduct, is = shader result, i = lamp energy (with shadow), i_noshad = i without shadow */
|
2011-09-11 07:06:21 +00:00
|
|
|
inp= dot_v3v3(vn, lv);
|
|
|
|
|
2012-10-20 20:36:51 +00:00
|
|
|
/* phong threshold to prevent backfacing faces having artifacts on ray shadow (terminator problem) */
|
2006-12-05 16:43:01 +00:00
|
|
|
/* this complex construction screams for a nicer implementation! (ton) */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (R.r.mode & R_SHADOW) {
|
|
|
|
if (ma->mode & MA_SHADOW) {
|
2012-10-07 09:48:59 +00:00
|
|
|
if (lar->type == LA_HEMI || lar->type == LA_AREA) {
|
|
|
|
/* pass */
|
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
else if ((ma->mode & MA_RAYBIAS) && (lar->mode & LA_SHAD_RAY) && (vlr->flag & R_SMOOTH)) {
|
Render Instancing
=================
Big commit, but little user visible changes.
- Dupliverts and duplifaces are now rendered as instances, instead
of storing all of the geometry for each dupli, now an instance is
created with a matrix transform refering to the source object.
This should allow us to render tree leaves more memory efficient.
- Radiosity and to some degree raytracing of such objects is not
really efficient still. For radiosity this is fundamentally hard
to solve, but raytracing an octree could be created for each object,
but the current octree code with it's fixed size doesn't allow this
efficiently.
- The regression tests survived, but with I expect that some bugs will
pop up .. hopefully not too many :).
Implementation Notes
====================
- Dupligroups and linked meshes are not rendered as instances yet,
since they can in fact be different due to various reasons,
instancing of these types of duplis that are the same can be added
for them at a later point.
- Each ObjectRen now stores it's own database, instead of there being
one big databases of faces, verts, .. . Which objects that are actually
rendered are defined by the list of ObjectRenInstances, which all refer
to an ObjectRen.
- Homogeneous coordinatess and clipping is now not stored in vertices
anymore, but instead computed on the fly. This couldn't work for
instances. That does mean some extra computation has to be done, but
memory lookups can be slow too, and this saves some memory. Overall
I didn't find a significant speed impact.
- OSA rendering for solid and ztransp now is different. Instead of e.g.
going 8 times over the databases times and rendering the z-buffer, it
now goes over the database once and renders each polygon 8 times. That
was necessary to keep instances efficient, and can also give some
performance improvement without instances.
- There was already instancing support in the yafray export code, now it
uses Blender's render instances for export.
- UV and color layer storage in the render was a bit messy before, now
should be easier to understand.
- convertblender.c was reorganized somewhat. Regular render, speedvector
and baking now use a single function to create the database, previously
there was code duplicated for it.
- Some of these changes were done with future multithreading of scene
and shadow buffer creation in mind, though especially for scene creation
much work remains to be done to make it threadsafe, since it also involves
a lot of code from blenkernel, and there is an ugly conflict with the way
dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
|
|
|
float thresh= shi->obr->ob->smoothresh;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (inp>thresh)
|
2006-12-05 16:43:01 +00:00
|
|
|
phongcorr= (inp-thresh)/(inp*(1.0f-thresh));
|
|
|
|
else
|
|
|
|
phongcorr= 0.0f;
|
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (ma->sbias!=0.0f && ((lar->mode & LA_SHAD_RAY) || lar->shb)) {
|
|
|
|
if (inp>ma->sbias)
|
2006-12-05 16:43:01 +00:00
|
|
|
phongcorr= (inp-ma->sbias)/(inp*(1.0f-ma->sbias));
|
|
|
|
else
|
|
|
|
phongcorr= 0.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* diffuse shaders */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->mode & LA_NO_DIFF) {
|
2012-07-07 22:51:57 +00:00
|
|
|
is = 0.0f; /* skip shaders */
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (lar->type==LA_HEMI) {
|
2012-07-07 22:51:57 +00:00
|
|
|
is = 0.5f * inp + 0.5f;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->type==LA_AREA)
|
2007-12-01 17:55:16 +00:00
|
|
|
inp= area_lamp_energy_multisample(lar, shi->co, vn);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* diffuse shaders (oren nayer gets inp from area light) */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(inp, vn, lv, view, ma->roughness);
|
|
|
|
else if (ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(vn, lv, view, ma->param[0], ma->param[1]);
|
|
|
|
else if (ma->diff_shader==MA_DIFF_MINNAERT) is= Minnaert_Diff(inp, vn, view, ma->darkness);
|
|
|
|
else if (ma->diff_shader==MA_DIFF_FRESNEL) is= Fresnel_Diff(vn, lv, view, ma->param[0], ma->param[1]);
|
2012-07-07 22:51:57 +00:00
|
|
|
else is= inp; /* Lambert */
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
2012-07-07 22:51:57 +00:00
|
|
|
|
2007-12-28 13:11:27 +00:00
|
|
|
/* 'is' is diffuse */
|
2012-07-07 22:51:57 +00:00
|
|
|
if ((ma->shade_flag & MA_CUBIC) && is > 0.0f && is < 1.0f) {
|
|
|
|
is= 3.0f * is * is - 2.0f * is * is * is; /* nicer termination of shades */
|
|
|
|
}
|
2007-12-28 13:11:27 +00:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
i= is*phongcorr;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (i>0.0f) {
|
2006-12-05 16:43:01 +00:00
|
|
|
i*= visifac*shi->refl;
|
|
|
|
}
|
|
|
|
i_noshad= i;
|
|
|
|
|
2012-07-07 22:51:57 +00:00
|
|
|
vn = shi->vn; /* bring back original vector, we use special specular shaders for tangent */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->mode & MA_TANGENT_V)
|
2006-12-05 16:43:01 +00:00
|
|
|
vn= shi->tang;
|
|
|
|
|
|
|
|
/* init transp shadow */
|
|
|
|
shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 1.0f;
|
|
|
|
|
|
|
|
/* shadow and spec, (visifac==0 outside spot) */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (visifac> 0.0f) {
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if ((R.r.mode & R_SHADOW)) {
|
|
|
|
if (ma->mode & MA_SHADOW) {
|
|
|
|
if (lar->shb || (lar->mode & LA_SHAD_RAY)) {
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (vn==vnor) /* tangent trigger */
|
2011-09-11 02:50:01 +00:00
|
|
|
lamp_get_shadow(lar, shi, dot_v3v3(shi->vn, lv), shadfac, shi->depth);
|
2006-12-08 11:51:31 +00:00
|
|
|
else
|
|
|
|
lamp_get_shadow(lar, shi, inp, shadfac, shi->depth);
|
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
/* warning, here it skips the loop */
|
2012-03-24 06:38:07 +00:00
|
|
|
if ((lar->mode & LA_ONLYSHADOW) && i>0.0f) {
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
shadfac[3]= i*lar->energy*(1.0f-shadfac[3]);
|
2008-09-19 16:01:22 +00:00
|
|
|
shr->shad[0] -= shadfac[3]*shi->r*(1.0f-lashdw[0]);
|
|
|
|
shr->shad[1] -= shadfac[3]*shi->g*(1.0f-lashdw[1]);
|
|
|
|
shr->shad[2] -= shadfac[3]*shi->b*(1.0f-lashdw[2]);
|
2007-07-27 21:54:01 +00:00
|
|
|
|
2014-05-30 22:11:06 +09:00
|
|
|
if (!(lar->mode & LA_NO_SPEC)) {
|
|
|
|
shr->spec[0] -= shadfac[3]*shi->specr*(1.0f-lashdw[0]);
|
|
|
|
shr->spec[1] -= shadfac[3]*shi->specg*(1.0f-lashdw[1]);
|
|
|
|
shr->spec[2] -= shadfac[3]*shi->specb*(1.0f-lashdw[2]);
|
|
|
|
}
|
2007-07-31 05:27:41 +00:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
i*= shadfac[3];
|
2010-10-19 16:10:30 +00:00
|
|
|
shr->shad[3] = shadfac[3]; /* store this for possible check in troublesome cases */
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
2015-06-28 10:46:42 +02:00
|
|
|
else {
|
|
|
|
shr->shad[3] = 1.0f; /* No shadow at all! */
|
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-23 02:28:47 +00:00
|
|
|
/* in case 'no diffuse' we still do most calculus, spec can be in shadow.*/
|
2012-03-24 06:38:07 +00:00
|
|
|
if (!(lar->mode & LA_NO_DIFF)) {
|
|
|
|
if (i>0.0f) {
|
2015-03-19 12:59:36 +11:00
|
|
|
if (ma->mode & MA_SHADOW_TRA) {
|
|
|
|
const float tcol[3] = {
|
|
|
|
i * shadfac[0] * lacol[0],
|
|
|
|
i * shadfac[1] * lacol[1],
|
|
|
|
i * shadfac[2] * lacol[2],
|
|
|
|
};
|
|
|
|
add_to_diffuse(shr->shad, shi, is, tcol);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const float tcol[3] = {
|
|
|
|
i * lacol[0],
|
|
|
|
i * lacol[1],
|
|
|
|
i * lacol[2],
|
|
|
|
};
|
|
|
|
add_to_diffuse(shr->shad, shi, is, tcol);
|
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
2008-09-19 16:01:22 +00:00
|
|
|
/* add light for colored shadow */
|
|
|
|
if (i_noshad>i && !(lashdw[0]==0 && lashdw[1]==0 && lashdw[2]==0)) {
|
2015-03-19 12:59:36 +11:00
|
|
|
const float tcol[3] = {
|
|
|
|
lashdw[0] * (i_noshad - i) * lacol[0],
|
|
|
|
lashdw[1] * (i_noshad - i) * lacol[1],
|
|
|
|
lashdw[2] * (i_noshad - i) * lacol[2],
|
|
|
|
};
|
|
|
|
add_to_diffuse(shr->shad, shi, is, tcol);
|
2008-09-19 16:01:22 +00:00
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
if (i_noshad>0.0f) {
|
2014-09-28 16:08:33 +02:00
|
|
|
if (passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW) ||
|
|
|
|
((passflag & SCE_PASS_COMBINED) && !(shi->combinedflag & SCE_PASS_SHADOW)))
|
|
|
|
{
|
2015-03-19 12:59:36 +11:00
|
|
|
const float tcol[3] = {
|
|
|
|
i_noshad * lacol[0],
|
|
|
|
i_noshad * lacol[1],
|
|
|
|
i_noshad * lacol[2]
|
|
|
|
};
|
|
|
|
add_to_diffuse(shr->diff, shi, is, tcol);
|
2006-12-07 14:17:38 +00:00
|
|
|
}
|
2014-09-28 16:08:33 +02:00
|
|
|
else {
|
2011-09-12 04:14:12 +00:00
|
|
|
copy_v3_v3(shr->diff, shr->shad);
|
2014-09-28 16:08:33 +02:00
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* specularity */
|
2008-07-20 10:09:19 +00:00
|
|
|
shadfac[3]*= phongcorr; /* note, shadfac not allowed to be stored nonlocal */
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (shadfac[3]>0.0f && shi->spec!=0.0f && !(lar->mode & LA_NO_SPEC) && !(lar->mode & LA_ONLYSHADOW)) {
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-10-07 09:48:59 +00:00
|
|
|
if (!(passflag & (SCE_PASS_COMBINED | SCE_PASS_SPEC))) {
|
|
|
|
/* pass */
|
|
|
|
}
|
|
|
|
else if (lar->type == LA_HEMI) {
|
2006-12-05 16:43:01 +00:00
|
|
|
float t;
|
|
|
|
/* hemi uses no spec shaders (yet) */
|
|
|
|
|
|
|
|
lv[0]+= view[0];
|
|
|
|
lv[1]+= view[1];
|
|
|
|
lv[2]+= view[2];
|
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(lv);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
t= vn[0]*lv[0]+vn[1]*lv[1]+vn[2]*lv[2];
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->type==LA_HEMI) {
|
2011-09-02 03:32:57 +00:00
|
|
|
t= 0.5f*t+0.5f;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
t= shadfac[3]*shi->spec*spec(t, shi->har);
|
|
|
|
|
|
|
|
shr->spec[0]+= t*(lacol[0] * shi->specr);
|
|
|
|
shr->spec[1]+= t*(lacol[1] * shi->specg);
|
|
|
|
shr->spec[2]+= t*(lacol[2] * shi->specb);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* specular shaders */
|
|
|
|
float specfac, t;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->spec_shader==MA_SPEC_PHONG)
|
2006-12-05 16:43:01 +00:00
|
|
|
specfac= Phong_Spec(vn, lv, view, shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (ma->spec_shader==MA_SPEC_COOKTORR)
|
2006-12-05 16:43:01 +00:00
|
|
|
specfac= CookTorr_Spec(vn, lv, view, shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (ma->spec_shader==MA_SPEC_BLINN)
|
2006-12-05 16:43:01 +00:00
|
|
|
specfac= Blinn_Spec(vn, lv, view, ma->refrac, (float)shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (ma->spec_shader==MA_SPEC_WARDISO)
|
2006-12-05 16:43:01 +00:00
|
|
|
specfac= WardIso_Spec( vn, lv, view, ma->rms, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
|
|
|
|
else
|
|
|
|
specfac= Toon_Spec(vn, lv, view, ma->param[2], ma->param[3], (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
|
|
|
|
|
|
|
|
/* area lamp correction */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->type==LA_AREA) specfac*= inp;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
t= shadfac[3]*shi->spec*visifac*specfac;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->mode & MA_RAMP_SPEC) {
|
2006-12-05 16:43:01 +00:00
|
|
|
float spec[3];
|
|
|
|
do_specular_ramp(shi, specfac, t, spec);
|
|
|
|
shr->spec[0]+= t*(lacol[0] * spec[0]);
|
|
|
|
shr->spec[1]+= t*(lacol[1] * spec[1]);
|
|
|
|
shr->spec[2]+= t*(lacol[2] * spec[2]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
shr->spec[0]+= t*(lacol[0] * shi->specr);
|
|
|
|
shr->spec[1]+= t*(lacol[1] * shi->specg);
|
|
|
|
shr->spec[2]+= t*(lacol[2] * shi->specb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr)
|
|
|
|
{
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (R.r.mode & R_SHADOW) {
|
2006-12-08 18:37:55 +00:00
|
|
|
ListBase *lights;
|
2006-12-05 16:43:01 +00:00
|
|
|
LampRen *lar;
|
|
|
|
GroupObject *go;
|
|
|
|
float inpr, lv[3];
|
2011-09-20 08:48:48 +00:00
|
|
|
float /* *view, */ shadfac[4];
|
2006-12-05 16:43:01 +00:00
|
|
|
float ir, accum, visifac, lampdist;
|
2011-03-08 16:08:43 +00:00
|
|
|
float shaded = 0.0f, lightness = 0.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2008-09-29 17:08:11 +00:00
|
|
|
|
2011-09-20 08:48:48 +00:00
|
|
|
/* view= shi->view; */ /* UNUSED */
|
2006-12-05 16:43:01 +00:00
|
|
|
accum= ir= 0.0f;
|
|
|
|
|
2006-12-08 18:37:55 +00:00
|
|
|
lights= get_lights(shi);
|
2012-03-24 06:38:07 +00:00
|
|
|
for (go=lights->first; go; go= go->next) {
|
2006-12-05 16:43:01 +00:00
|
|
|
lar= go->lampren;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar==NULL) continue;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 07:52:14 +00:00
|
|
|
if (lar->mode & LA_LAYER) if ((lar->lay & shi->obi->lay)==0) continue;
|
2012-03-24 06:38:07 +00:00
|
|
|
if ((lar->lay & shi->lay)==0) continue;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar->shb || (lar->mode & LA_SHAD_RAY)) {
|
2006-12-05 16:43:01 +00:00
|
|
|
visifac= lamp_get_visibility(lar, shi->co, lv, &lampdist);
|
2011-04-26 15:29:12 +00:00
|
|
|
ir+= 1.0f;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (visifac <= 0.0f) {
|
2011-04-26 15:29:12 +00:00
|
|
|
if (shi->mat->shadowonly_flag == MA_SO_OLD)
|
2011-03-08 16:08:43 +00:00
|
|
|
accum+= 1.0f;
|
2011-04-26 15:29:12 +00:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
continue;
|
2006-12-12 11:13:43 +00:00
|
|
|
}
|
2011-09-11 02:50:01 +00:00
|
|
|
inpr= dot_v3v3(shi->vn, lv);
|
2012-03-24 06:38:07 +00:00
|
|
|
if (inpr <= 0.0f) {
|
2011-04-26 15:29:12 +00:00
|
|
|
if (shi->mat->shadowonly_flag == MA_SO_OLD)
|
2011-03-08 16:08:43 +00:00
|
|
|
accum+= 1.0f;
|
2011-04-26 15:29:12 +00:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
continue;
|
2011-03-08 16:08:43 +00:00
|
|
|
}
|
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
lamp_get_shadow(lar, shi, inpr, shadfac, shi->depth);
|
2006-12-12 11:13:43 +00:00
|
|
|
|
2011-03-08 16:08:43 +00:00
|
|
|
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
|
|
|
|
/* Old "Shadows Only" */
|
2015-03-17 15:20:33 +01:00
|
|
|
accum+= (1.0f-visifac) + (visifac)*IMB_colormanagement_get_luminance(shadfac)*shadfac[3];
|
2011-03-08 16:08:43 +00:00
|
|
|
}
|
|
|
|
else {
|
2015-03-17 15:20:33 +01:00
|
|
|
shaded += IMB_colormanagement_get_luminance(shadfac)*shadfac[3] * visifac * lar->energy;
|
2011-03-08 16:08:43 +00:00
|
|
|
|
|
|
|
if (shi->mat->shadowonly_flag == MA_SO_SHADOW) {
|
|
|
|
lightness += visifac * lar->energy;
|
|
|
|
}
|
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
2011-03-08 16:08:43 +00:00
|
|
|
|
|
|
|
/* Apply shadows as alpha */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ir>0.0f) {
|
2011-03-08 16:08:43 +00:00
|
|
|
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
|
|
|
|
accum = 1.0f - accum/ir;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (shi->mat->shadowonly_flag == MA_SO_SHADOW) {
|
|
|
|
if (lightness > 0.0f) {
|
|
|
|
/* Get shadow value from between 0.0f and non-shadowed lightness */
|
|
|
|
accum = (lightness - shaded) / (lightness);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
accum = 0.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else { /* shadowonly_flag == MA_SO_SHADED */
|
|
|
|
/* Use shaded value */
|
|
|
|
accum = 1.0f - shaded;
|
2014-09-30 17:28:04 +06:00
|
|
|
}
|
|
|
|
}
|
2011-03-08 16:08:43 +00:00
|
|
|
|
2011-03-11 07:59:43 +00:00
|
|
|
shr->alpha= (shi->alpha)*(accum);
|
2011-04-26 15:29:12 +00:00
|
|
|
if (shr->alpha<0.0f) shr->alpha=0.0f;
|
2011-03-08 16:08:43 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* If "fully shaded", use full alpha even on areas that have no lights */
|
2011-04-26 15:29:12 +00:00
|
|
|
if (shi->mat->shadowonly_flag == MA_SO_SHADED) shr->alpha=shi->alpha;
|
2011-03-08 16:08:43 +00:00
|
|
|
else shr->alpha= 0.f;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
/* quite disputable this... also note it doesn't mirror-raytrace */
|
2012-03-24 06:38:07 +00:00
|
|
|
if ((R.wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT)) && shi->amb!=0.0f) {
|
2006-12-05 16:43:01 +00:00
|
|
|
float f;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (R.wrld.mode & WO_AMB_OCC) {
|
2010-02-07 11:17:19 +00:00
|
|
|
f= R.wrld.aoenergy*shi->amb;
|
2011-03-08 16:08:43 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (R.wrld.aomix==WO_AOADD) {
|
2011-03-08 16:08:43 +00:00
|
|
|
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
|
2015-03-17 15:20:33 +01:00
|
|
|
f= f*(1.0f - IMB_colormanagement_get_luminance(shi->ao));
|
2011-03-08 16:08:43 +00:00
|
|
|
shr->alpha= (shr->alpha + f)*f;
|
|
|
|
}
|
|
|
|
else {
|
2015-03-17 15:20:33 +01:00
|
|
|
shr->alpha -= f*IMB_colormanagement_get_luminance(shi->ao);
|
2011-03-08 16:08:43 +00:00
|
|
|
if (shr->alpha<0.0f) shr->alpha=0.0f;
|
|
|
|
}
|
2010-02-13 13:17:15 +00:00
|
|
|
}
|
2011-03-08 16:08:43 +00:00
|
|
|
else /* AO Multiply */
|
2015-03-17 15:20:33 +01:00
|
|
|
shr->alpha= (1.0f - f)*shr->alpha + f*(1.0f - (1.0f - shr->alpha)*IMB_colormanagement_get_luminance(shi->ao));
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
2010-02-07 11:17:19 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (R.wrld.mode & WO_ENV_LIGHT) {
|
2011-03-08 16:08:43 +00:00
|
|
|
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
|
2015-03-17 15:20:33 +01:00
|
|
|
f= R.wrld.ao_env_energy*shi->amb*(1.0f - IMB_colormanagement_get_luminance(shi->env));
|
2011-03-08 16:08:43 +00:00
|
|
|
shr->alpha= (shr->alpha + f)*f;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
f= R.wrld.ao_env_energy*shi->amb;
|
2015-03-17 15:20:33 +01:00
|
|
|
shr->alpha -= f*IMB_colormanagement_get_luminance(shi->env);
|
2011-03-08 16:08:43 +00:00
|
|
|
if (shr->alpha<0.0f) shr->alpha=0.0f;
|
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-14 18:00:58 +00:00
|
|
|
/* let's map negative light as if it mirrors positive light, otherwise negative values disappear */
|
2011-09-24 14:34:24 +00:00
|
|
|
static void wrld_exposure_correct(float diff[3])
|
2006-12-07 14:17:38 +00:00
|
|
|
{
|
2008-02-14 18:00:58 +00:00
|
|
|
|
2011-11-11 12:00:08 +00:00
|
|
|
diff[0]= R.wrld.linfac*(1.0f-expf( diff[0]*R.wrld.logfac) );
|
|
|
|
diff[1]= R.wrld.linfac*(1.0f-expf( diff[1]*R.wrld.logfac) );
|
|
|
|
diff[2]= R.wrld.linfac*(1.0f-expf( diff[2]*R.wrld.logfac) );
|
2006-12-07 14:17:38 +00:00
|
|
|
}
|
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
|
|
|
|
{
|
2014-08-13 22:43:11 +06:00
|
|
|
/* Passes which might need to know material color.
|
|
|
|
*
|
|
|
|
* It seems to be faster to just calculate material color
|
2014-08-16 10:51:07 +10:00
|
|
|
* even if the pass doesn't really need it than trying to
|
2014-08-13 22:43:11 +06:00
|
|
|
* figure out whether color is really needed or not.
|
|
|
|
*/
|
|
|
|
const int color_passes =
|
|
|
|
SCE_PASS_COMBINED | SCE_PASS_RGBA | SCE_PASS_DIFFUSE | SCE_PASS_SPEC |
|
2014-09-29 18:27:58 +06:00
|
|
|
SCE_PASS_REFLECT | SCE_PASS_NORMAL | SCE_PASS_REFRACT | SCE_PASS_EMIT | SCE_PASS_SHADOW;
|
2014-08-13 22:43:11 +06:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
Material *ma= shi->mat;
|
|
|
|
int passflag= shi->passflag;
|
2014-08-13 22:43:11 +06:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
memset(shr, 0, sizeof(ShadeResult));
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (!(shi->mode & MA_TRANSP)) shi->alpha = 1.0f;
|
2011-03-11 07:59:43 +00:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
/* separate loop */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->mode & MA_ONLYSHADOW) {
|
2006-12-05 16:43:01 +00:00
|
|
|
shade_lamp_loop_only_shadow(shi, shr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* envmap hack, always reset */
|
|
|
|
shi->refcol[0]= shi->refcol[1]= shi->refcol[2]= shi->refcol[3]= 0.0f;
|
|
|
|
|
|
|
|
/* material color itself */
|
2014-08-13 22:43:11 +06:00
|
|
|
if (passflag & color_passes) {
|
2017-05-24 23:14:32 +10:00
|
|
|
if (false) {
|
|
|
|
/* pass */
|
2011-07-24 17:03:33 +00:00
|
|
|
}
|
2012-12-20 07:57:26 +00:00
|
|
|
#ifdef WITH_FREESTYLE
|
2012-03-25 08:20:19 +00:00
|
|
|
else if (ma->vcol_alpha) {
|
2011-11-12 23:38:41 +00:00
|
|
|
shi->r= shi->vcol[0];
|
|
|
|
shi->g= shi->vcol[1];
|
|
|
|
shi->b= shi->vcol[2];
|
|
|
|
shi->alpha= shi->vcol[3];
|
|
|
|
}
|
2012-12-20 07:57:26 +00:00
|
|
|
#endif
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (ma->mode & (MA_VERTEXCOLP)) {
|
2011-10-22 16:16:14 +00:00
|
|
|
float neg_alpha = 1.0f - shi->vcol[3];
|
|
|
|
shi->r= shi->r*neg_alpha + shi->vcol[0]*shi->vcol[3];
|
|
|
|
shi->g= shi->g*neg_alpha + shi->vcol[1]*shi->vcol[3];
|
|
|
|
shi->b= shi->b*neg_alpha + shi->vcol[2]*shi->vcol[3];
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->texco) {
|
2011-10-31 13:01:06 +00:00
|
|
|
do_material_tex(shi, &R);
|
2011-03-11 07:59:43 +00:00
|
|
|
if (!(shi->mode & MA_TRANSP)) shi->alpha = 1.0f;
|
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
shr->col[0]= shi->r*shi->alpha;
|
|
|
|
shr->col[1]= shi->g*shi->alpha;
|
|
|
|
shr->col[2]= shi->b*shi->alpha;
|
|
|
|
shr->col[3]= shi->alpha;
|
2008-04-30 12:02:09 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if ((ma->sss_flag & MA_DIFF_SSS) && !sss_pass_done(&R, ma)) {
|
|
|
|
if (ma->sss_texfac == 0.0f) {
|
2008-04-30 12:02:09 +00:00
|
|
|
shi->r= shi->g= shi->b= shi->alpha= 1.0f;
|
|
|
|
shr->col[0]= shr->col[1]= shr->col[2]= shr->col[3]= 1.0f;
|
|
|
|
}
|
|
|
|
else {
|
2013-04-02 17:49:31 +00:00
|
|
|
shi->r= pow(max_ff(shi->r, 0.0f), ma->sss_texfac);
|
|
|
|
shi->g= pow(max_ff(shi->g, 0.0f), ma->sss_texfac);
|
|
|
|
shi->b= pow(max_ff(shi->b, 0.0f), ma->sss_texfac);
|
|
|
|
shi->alpha= pow(max_ff(shi->alpha, 0.0f), ma->sss_texfac);
|
2008-04-30 12:02:09 +00:00
|
|
|
|
2013-04-02 17:49:31 +00:00
|
|
|
shr->col[0]= pow(max_ff(shr->col[0], 0.0f), ma->sss_texfac);
|
|
|
|
shr->col[1]= pow(max_ff(shr->col[1], 0.0f), ma->sss_texfac);
|
|
|
|
shr->col[2]= pow(max_ff(shr->col[2], 0.0f), ma->sss_texfac);
|
|
|
|
shr->col[3]= pow(max_ff(shr->col[3], 0.0f), ma->sss_texfac);
|
2008-04-30 12:02:09 +00:00
|
|
|
}
|
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->mode & MA_SHLESS) {
|
2006-12-05 16:43:01 +00:00
|
|
|
shr->combined[0]= shi->r;
|
|
|
|
shr->combined[1]= shi->g;
|
|
|
|
shr->combined[2]= shi->b;
|
|
|
|
shr->alpha= shi->alpha;
|
2015-09-26 01:36:27 +10:00
|
|
|
goto finally_shadeless;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
2012-07-07 22:51:57 +00:00
|
|
|
if ( (ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL ) { /* vertexcolor light */
|
2011-12-31 10:46:21 +00:00
|
|
|
shr->emit[0]= shi->r*(shi->emit+shi->vcol[0]*shi->vcol[3]);
|
|
|
|
shr->emit[1]= shi->g*(shi->emit+shi->vcol[1]*shi->vcol[3]);
|
|
|
|
shr->emit[2]= shi->b*(shi->emit+shi->vcol[2]*shi->vcol[3]);
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-01-27 21:40:08 +00:00
|
|
|
shr->emit[0]= shi->r*shi->emit;
|
|
|
|
shr->emit[1]= shi->g*shi->emit;
|
|
|
|
shr->emit[2]= shi->b*shi->emit;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* AO pass */
|
2013-11-12 10:59:40 +00:00
|
|
|
if (((passflag & SCE_PASS_COMBINED) && (shi->combinedflag & (SCE_PASS_AO|SCE_PASS_ENVIRONMENT|SCE_PASS_INDIRECT))) ||
|
|
|
|
(passflag & (SCE_PASS_AO|SCE_PASS_ENVIRONMENT|SCE_PASS_INDIRECT))) {
|
|
|
|
if ((R.wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && (R.r.mode & R_SHADOW)) {
|
|
|
|
/* AO was calculated for scanline already */
|
|
|
|
if (shi->depth || shi->volume_depth)
|
|
|
|
ambient_occlusion(shi);
|
|
|
|
copy_v3_v3(shr->ao, shi->ao);
|
|
|
|
copy_v3_v3(shr->env, shi->env); /* XXX multiply */
|
|
|
|
copy_v3_v3(shr->indirect, shi->indirect); /* XXX multiply */
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
shr->ao[0]= shr->ao[1]= shr->ao[2]= 1.0f;
|
|
|
|
zero_v3(shr->env);
|
|
|
|
zero_v3(shr->indirect);
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* lighting pass */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (passflag & (SCE_PASS_COMBINED|SCE_PASS_DIFFUSE|SCE_PASS_SPEC|SCE_PASS_SHADOW)) {
|
2006-12-05 16:43:01 +00:00
|
|
|
GroupObject *go;
|
2006-12-08 18:37:55 +00:00
|
|
|
ListBase *lights;
|
2006-12-05 16:43:01 +00:00
|
|
|
LampRen *lar;
|
|
|
|
|
2006-12-08 18:37:55 +00:00
|
|
|
lights= get_lights(shi);
|
2012-03-24 06:38:07 +00:00
|
|
|
for (go=lights->first; go; go= go->next) {
|
2006-12-05 16:43:01 +00:00
|
|
|
lar= go->lampren;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (lar==NULL) continue;
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* test for lamp layer */
|
2012-03-24 07:52:14 +00:00
|
|
|
if (lar->mode & LA_LAYER) if ((lar->lay & shi->obi->lay)==0) continue;
|
2012-03-24 06:38:07 +00:00
|
|
|
if ((lar->lay & shi->lay)==0) continue;
|
2006-12-08 18:37:55 +00:00
|
|
|
|
2006-12-07 14:17:38 +00:00
|
|
|
/* accumulates in shr->diff and shr->spec and shr->shad (diffuse with shadow!) */
|
2006-12-05 16:43:01 +00:00
|
|
|
shade_one_light(lar, shi, shr, passflag);
|
|
|
|
}
|
2007-05-03 21:37:52 +00:00
|
|
|
|
2012-03-09 18:28:30 +00:00
|
|
|
/* this check is to prevent only shadow lamps from producing negative
|
|
|
|
* colors.*/
|
2007-07-31 05:27:41 +00:00
|
|
|
if (shr->spec[0] < 0) shr->spec[0] = 0;
|
|
|
|
if (shr->spec[1] < 0) shr->spec[1] = 0;
|
|
|
|
if (shr->spec[2] < 0) shr->spec[2] = 0;
|
|
|
|
|
|
|
|
if (shr->shad[0] < 0) shr->shad[0] = 0;
|
|
|
|
if (shr->shad[1] < 0) shr->shad[1] = 0;
|
|
|
|
if (shr->shad[2] < 0) shr->shad[2] = 0;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->sss_flag & MA_DIFF_SSS) {
|
2008-04-30 12:02:09 +00:00
|
|
|
float sss[3], col[3], invalpha, texfac= ma->sss_texfac;
|
2007-05-03 21:37:52 +00:00
|
|
|
|
|
|
|
/* this will return false in the preprocess stage */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (sample_sss(&R, ma, shi->co, sss)) {
|
2008-04-30 12:02:09 +00:00
|
|
|
invalpha= (shr->col[3] > FLT_EPSILON)? 1.0f/shr->col[3]: 1.0f;
|
2008-04-12 16:31:29 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (texfac==0.0f) {
|
2011-09-12 04:14:12 +00:00
|
|
|
copy_v3_v3(col, shr->col);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(col, invalpha);
|
2007-05-03 21:37:52 +00:00
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (texfac==1.0f) {
|
2007-05-03 21:37:52 +00:00
|
|
|
col[0]= col[1]= col[2]= 1.0f;
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(col, invalpha);
|
2007-05-03 21:37:52 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-09-12 04:14:12 +00:00
|
|
|
copy_v3_v3(col, shr->col);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(col, invalpha);
|
2013-04-02 17:49:31 +00:00
|
|
|
col[0]= pow(max_ff(col[0], 0.0f), 1.0f-texfac);
|
|
|
|
col[1]= pow(max_ff(col[1], 0.0f), 1.0f-texfac);
|
|
|
|
col[2]= pow(max_ff(col[2], 0.0f), 1.0f-texfac);
|
2007-05-03 21:37:52 +00:00
|
|
|
}
|
|
|
|
|
2008-04-30 12:02:09 +00:00
|
|
|
shr->diff[0]= sss[0]*col[0];
|
|
|
|
shr->diff[1]= sss[1]*col[1];
|
|
|
|
shr->diff[2]= sss[2]*col[2];
|
2007-05-03 21:37:52 +00:00
|
|
|
|
2012-05-19 13:55:54 +00:00
|
|
|
if (shi->combinedflag & SCE_PASS_SHADOW) {
|
2008-04-12 16:31:29 +00:00
|
|
|
shr->shad[0]= shr->diff[0];
|
|
|
|
shr->shad[1]= shr->diff[1];
|
|
|
|
shr->shad[2]= shr->diff[2];
|
2007-05-03 21:37:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
if (shi->combinedflag & SCE_PASS_SHADOW)
|
2014-09-28 16:08:33 +02:00
|
|
|
copy_v3_v3(shr->diffshad, shr->shad);
|
2006-12-07 14:17:38 +00:00
|
|
|
else
|
2014-02-26 16:55:50 +01:00
|
|
|
copy_v3_v3(shr->diffshad, shr->diff);
|
|
|
|
|
|
|
|
copy_v3_v3(shr->combined, shr->diffshad);
|
2006-12-07 14:17:38 +00:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
/* calculate shadow pass, we use a multiplication mask */
|
2016-01-22 19:32:47 +01:00
|
|
|
/* Even if diff = 0,0,0, it does matter what the shadow pass is, since we may want it 'for itself'! */
|
|
|
|
if (passflag & SCE_PASS_SHADOW) {
|
2012-03-24 06:38:07 +00:00
|
|
|
if (shr->diff[0]!=0.0f) shr->shad[0]= shr->shad[0]/shr->diff[0];
|
2010-10-19 16:10:30 +00:00
|
|
|
/* can't determine proper shadow from shad/diff (0/0), so use shadow intensity */
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (shr->shad[0]==0.0f) shr->shad[0]= shr->shad[3];
|
2010-10-19 16:10:30 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (shr->diff[1]!=0.0f) shr->shad[1]= shr->shad[1]/shr->diff[1];
|
|
|
|
else if (shr->shad[1]==0.0f) shr->shad[1]= shr->shad[3];
|
2010-10-19 16:10:30 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (shr->diff[2]!=0.0f) shr->shad[2]= shr->shad[2]/shr->diff[2];
|
|
|
|
else if (shr->shad[2]==0.0f) shr->shad[2]= shr->shad[3];
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* exposure correction */
|
2012-03-24 06:38:07 +00:00
|
|
|
if ((R.wrld.exp!=0.0f || R.wrld.range!=1.0f) && !R.sss_points) {
|
2006-12-08 09:40:44 +00:00
|
|
|
wrld_exposure_correct(shr->combined); /* has no spec! */
|
2006-12-07 14:17:38 +00:00
|
|
|
wrld_exposure_correct(shr->spec);
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* alpha in end, spec can influence it */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (passflag & (SCE_PASS_COMBINED)) {
|
|
|
|
if ((ma->fresnel_tra!=0.0f) && (shi->mode & MA_TRANSP))
|
2006-12-05 16:43:01 +00:00
|
|
|
shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra);
|
|
|
|
|
2006-12-05 19:47:45 +00:00
|
|
|
/* note: shi->mode! */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (shi->mode & MA_TRANSP && (shi->mode & (MA_ZTRANSP|MA_RAYTRANSP))) {
|
|
|
|
if (shi->spectra!=0.0f) {
|
2012-12-21 05:07:26 +00:00
|
|
|
float t = max_fff(shr->spec[0], shr->spec[1], shr->spec[2]);
|
2006-12-05 16:43:01 +00:00
|
|
|
t *= shi->spectra;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (t>1.0f) t= 1.0f;
|
2006-12-05 16:43:01 +00:00
|
|
|
shi->alpha= (1.0f-t)*shi->alpha+t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
shr->alpha= shi->alpha;
|
|
|
|
|
2012-04-14 21:48:34 +00:00
|
|
|
/* from now stuff everything in shr->combined: ambient, AO, ramps, exposure */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (!(ma->sss_flag & MA_DIFF_SSS) || !sss_pass_done(&R, ma)) {
|
|
|
|
if (R.r.mode & R_SHADOW) {
|
2010-11-26 03:50:14 +00:00
|
|
|
/* add AO in combined? */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (R.wrld.mode & WO_AMB_OCC)
|
|
|
|
if (shi->combinedflag & SCE_PASS_AO)
|
2010-11-26 03:50:14 +00:00
|
|
|
ambient_occlusion_apply(shi, shr);
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (R.wrld.mode & WO_ENV_LIGHT)
|
|
|
|
if (shi->combinedflag & SCE_PASS_ENVIRONMENT)
|
2010-11-26 03:50:14 +00:00
|
|
|
environment_lighting_apply(shi, shr);
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (R.wrld.mode & WO_INDIRECT_LIGHT)
|
|
|
|
if (shi->combinedflag & SCE_PASS_INDIRECT)
|
2010-11-26 03:50:14 +00:00
|
|
|
indirect_lighting_apply(shi, shr);
|
|
|
|
}
|
2010-01-27 21:40:08 +00:00
|
|
|
|
2008-02-19 19:26:49 +00:00
|
|
|
shr->combined[0]+= shi->ambr;
|
|
|
|
shr->combined[1]+= shi->ambg;
|
|
|
|
shr->combined[2]+= shi->ambb;
|
2007-05-03 21:37:52 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->mode & MA_RAMP_COL) ramp_diffuse_result(shr->combined, shi);
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
2007-05-03 21:37:52 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ma->mode & MA_RAMP_SPEC) ramp_spec_result(shr->spec, shi);
|
2006-12-05 16:43:01 +00:00
|
|
|
|
|
|
|
/* refcol is for envmap only */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (shi->refcol[0]!=0.0f) {
|
2006-12-07 14:17:38 +00:00
|
|
|
float result[3];
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2006-12-07 14:17:38 +00:00
|
|
|
result[0]= shi->mirr*shi->refcol[1] + (1.0f - shi->mirr*shi->refcol[0])*shr->combined[0];
|
|
|
|
result[1]= shi->mirg*shi->refcol[2] + (1.0f - shi->mirg*shi->refcol[0])*shr->combined[1];
|
|
|
|
result[2]= shi->mirb*shi->refcol[3] + (1.0f - shi->mirb*shi->refcol[0])*shr->combined[2];
|
2006-12-05 16:43:01 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (passflag & SCE_PASS_REFLECT)
|
2011-09-11 02:50:01 +00:00
|
|
|
sub_v3_v3v3(shr->refl, result, shr->combined);
|
2006-12-07 14:17:38 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (shi->combinedflag & SCE_PASS_REFLECT)
|
2011-09-12 04:14:12 +00:00
|
|
|
copy_v3_v3(shr->combined, result);
|
2006-12-07 14:17:38 +00:00
|
|
|
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
2006-12-07 14:17:38 +00:00
|
|
|
|
2010-01-27 21:40:08 +00:00
|
|
|
/* and add emit and spec */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (shi->combinedflag & SCE_PASS_EMIT)
|
2011-11-06 16:38:21 +00:00
|
|
|
add_v3_v3(shr->combined, shr->emit);
|
2012-03-24 06:38:07 +00:00
|
|
|
if (shi->combinedflag & SCE_PASS_SPEC)
|
2011-11-06 16:38:21 +00:00
|
|
|
add_v3_v3(shr->combined, shr->spec);
|
2015-09-26 01:36:27 +10:00
|
|
|
|
|
|
|
|
|
|
|
/* Last section of this function applies to shadeless colors too */
|
|
|
|
finally_shadeless:
|
|
|
|
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
/* modulate by the object color */
|
2012-03-24 06:38:07 +00:00
|
|
|
if ((ma->shade_flag & MA_OBCOLOR) && shi->obr->ob) {
|
|
|
|
if (!(ma->sss_flag & MA_DIFF_SSS) || !sss_pass_done(&R, ma)) {
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
float obcol[4];
|
|
|
|
|
2011-11-06 16:38:21 +00:00
|
|
|
copy_v4_v4(obcol, shi->obr->ob->col);
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
CLAMP(obcol[3], 0.0f, 1.0f);
|
|
|
|
|
|
|
|
shr->combined[0] *= obcol[0];
|
|
|
|
shr->combined[1] *= obcol[1];
|
|
|
|
shr->combined[2] *= obcol[2];
|
2011-03-11 07:59:43 +00:00
|
|
|
if (shi->mode & MA_TRANSP) shr->alpha *= obcol[3];
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-07 14:17:38 +00:00
|
|
|
shr->combined[3]= shr->alpha;
|
2006-12-05 16:43:01 +00:00
|
|
|
}
|
|
|
|
|
2013-11-25 20:58:23 +09:00
|
|
|
/* used for "Lamp Data" shader node */
|
|
|
|
static float lamp_get_data_internal(ShadeInput *shi, GroupObject *go, float col[4], float lv[3], float *dist, float shadow[4])
|
|
|
|
{
|
|
|
|
LampRen *lar = go->lampren;
|
|
|
|
float visifac, inp;
|
|
|
|
|
2015-10-23 04:54:07 +11:00
|
|
|
if (!lar
|
2013-11-25 20:58:23 +09:00
|
|
|
|| ((lar->mode & LA_LAYER) && (lar->lay & shi->obi->lay) == 0)
|
|
|
|
|| (lar->lay & shi->lay) == 0)
|
|
|
|
return 0.0f;
|
|
|
|
|
|
|
|
if (lar->mode & LA_TEXTURE)
|
|
|
|
do_lamp_tex(lar, lv, shi, col, LA_TEXTURE);
|
|
|
|
|
|
|
|
visifac = lamp_get_visibility(lar, shi->co, lv, dist);
|
|
|
|
|
|
|
|
if (visifac == 0.0f
|
|
|
|
|| lar->type == LA_HEMI
|
|
|
|
|| (lar->type != LA_SPOT && !(lar->mode & LA_SHAD_RAY))
|
|
|
|
|| (R.r.scemode & R_BUTS_PREVIEW))
|
|
|
|
return visifac;
|
|
|
|
|
|
|
|
inp = dot_v3v3(shi->vn, lv);
|
|
|
|
|
|
|
|
if (inp > 0.0f) {
|
|
|
|
float shadfac[4];
|
|
|
|
|
|
|
|
shadow[0] = lar->shdwr;
|
|
|
|
shadow[1] = lar->shdwg;
|
|
|
|
shadow[2] = lar->shdwb;
|
|
|
|
|
|
|
|
if (lar->mode & LA_SHAD_TEX)
|
|
|
|
do_lamp_tex(lar, lv, shi, shadow, LA_SHAD_TEX);
|
|
|
|
|
2016-11-08 10:40:21 +01:00
|
|
|
if (R.r.mode & R_SHADOW) {
|
|
|
|
lamp_get_shadow(lar, shi, inp, shadfac, shi->depth);
|
2013-11-25 20:58:23 +09:00
|
|
|
|
2016-11-08 10:40:21 +01:00
|
|
|
shadow[0] = 1.0f - ((1.0f - shadfac[0] * shadfac[3]) * (1.0f - shadow[0]));
|
|
|
|
shadow[1] = 1.0f - ((1.0f - shadfac[1] * shadfac[3]) * (1.0f - shadow[1]));
|
|
|
|
shadow[2] = 1.0f - ((1.0f - shadfac[2] * shadfac[3]) * (1.0f - shadow[2]));
|
|
|
|
}
|
2013-11-25 20:58:23 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
return visifac;
|
|
|
|
}
|
|
|
|
|
|
|
|
float RE_lamp_get_data(ShadeInput *shi, Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4])
|
|
|
|
{
|
|
|
|
col[0] = col[1] = col[2] = 0.0f;
|
|
|
|
col[3] = 1.0f;
|
|
|
|
copy_v3_v3(lv, shi->vn);
|
|
|
|
*dist = 1.0f;
|
|
|
|
shadow[0] = shadow[1] = shadow[2] = shadow[3] = 1.0f;
|
|
|
|
|
|
|
|
if (lamp_obj->type == OB_LAMP) {
|
|
|
|
GroupObject *go;
|
|
|
|
Lamp *lamp = (Lamp *)lamp_obj->data;
|
|
|
|
|
|
|
|
col[0] = lamp->r * lamp->energy;
|
|
|
|
col[1] = lamp->g * lamp->energy;
|
|
|
|
col[2] = lamp->b * lamp->energy;
|
|
|
|
|
|
|
|
if (R.r.scemode & R_BUTS_PREVIEW) {
|
|
|
|
for (go = R.lights.first; go; go = go->next) {
|
|
|
|
/* "Lamp.002" is main key light of material preview */
|
2015-01-26 16:03:11 +01:00
|
|
|
if (STREQ(go->ob->id.name + 2, "Lamp.002"))
|
2013-11-25 20:58:23 +09:00
|
|
|
return lamp_get_data_internal(shi, go, col, lv, dist, shadow);
|
|
|
|
}
|
|
|
|
return 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shi->mat && shi->mat->group) {
|
|
|
|
for (go = shi->mat->group->gobject.first; go; go = go->next) {
|
|
|
|
if (go->ob == lamp_obj)
|
|
|
|
return lamp_get_data_internal(shi, go, col, lv, dist, shadow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (go = R.lights.first; go; go = go->next) {
|
|
|
|
if (go->ob == lamp_obj)
|
|
|
|
return lamp_get_data_internal(shi, go, col, lv, dist, shadow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0.0f;
|
|
|
|
}
|
Vector Transform node support for GLSL mode and the internal renderer
The Vector Transform node is a useful node which is present in the Cycles renderer.
{F144283}
This patch implements the Vector Transform node for GLSL mode and the internal renderer.
Example: {F273060}
Alexander (Blend4Web Team)
Reviewers: brecht, campbellbarton, sergey
Reviewed By: campbellbarton, sergey
Subscribers: psy-fi, duarteframos, RobM, lightbwk, sergey, AlexKowel, valentin_b4w, Evgeny_Rodygin, yurikovelenov
Projects: #bf_blender:_next
Differential Revision: https://developer.blender.org/D909
2016-01-23 15:27:36 +03:00
|
|
|
|
|
|
|
const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4]
|
|
|
|
{
|
|
|
|
if (obi) {
|
|
|
|
switch (matrix_id) {
|
|
|
|
case RE_OBJECT_INSTANCE_MATRIX_OB:
|
|
|
|
return (const float(*)[4])obi->obmat;
|
|
|
|
case RE_OBJECT_INSTANCE_MATRIX_OBINV:
|
|
|
|
return (const float(*)[4])obi->obinvmat;
|
|
|
|
case RE_OBJECT_INSTANCE_MATRIX_LOCALTOVIEW:
|
|
|
|
return (const float(*)[4])obi->localtoviewmat;
|
|
|
|
case RE_OBJECT_INSTANCE_MATRIX_LOCALTOVIEWINV:
|
|
|
|
return (const float(*)[4])obi->localtoviewinvmat;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-04-14 18:13:44 +03:00
|
|
|
float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi)
|
|
|
|
{
|
|
|
|
return obi->ob->index;
|
|
|
|
}
|
|
|
|
|
|
|
|
float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi)
|
|
|
|
{
|
|
|
|
return obi->random_id;
|
|
|
|
}
|
|
|
|
|
Vector Transform node support for GLSL mode and the internal renderer
The Vector Transform node is a useful node which is present in the Cycles renderer.
{F144283}
This patch implements the Vector Transform node for GLSL mode and the internal renderer.
Example: {F273060}
Alexander (Blend4Web Team)
Reviewers: brecht, campbellbarton, sergey
Reviewed By: campbellbarton, sergey
Subscribers: psy-fi, duarteframos, RobM, lightbwk, sergey, AlexKowel, valentin_b4w, Evgeny_Rodygin, yurikovelenov
Projects: #bf_blender:_next
Differential Revision: https://developer.blender.org/D909
2016-01-23 15:27:36 +03:00
|
|
|
const float (*RE_render_current_get_matrix(int matrix_id))[4]
|
|
|
|
{
|
2017-03-13 04:25:21 +11:00
|
|
|
switch (matrix_id) {
|
Vector Transform node support for GLSL mode and the internal renderer
The Vector Transform node is a useful node which is present in the Cycles renderer.
{F144283}
This patch implements the Vector Transform node for GLSL mode and the internal renderer.
Example: {F273060}
Alexander (Blend4Web Team)
Reviewers: brecht, campbellbarton, sergey
Reviewed By: campbellbarton, sergey
Subscribers: psy-fi, duarteframos, RobM, lightbwk, sergey, AlexKowel, valentin_b4w, Evgeny_Rodygin, yurikovelenov
Projects: #bf_blender:_next
Differential Revision: https://developer.blender.org/D909
2016-01-23 15:27:36 +03:00
|
|
|
case RE_VIEW_MATRIX:
|
|
|
|
return (const float(*)[4])R.viewmat;
|
|
|
|
case RE_VIEWINV_MATRIX:
|
|
|
|
return (const float(*)[4])R.viewinv;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-12-15 15:03:28 +03:00
|
|
|
|
|
|
|
float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta)
|
|
|
|
{
|
|
|
|
/* compute fresnel reflectance without explicitly computing
|
|
|
|
* the refracted direction */
|
|
|
|
float c = fabs(dot_v3v3(incoming, normal));
|
|
|
|
float g = eta * eta - 1.0 + c * c;
|
|
|
|
float result;
|
|
|
|
|
|
|
|
if (g > 0.0) {
|
|
|
|
g = sqrtf(g);
|
|
|
|
float A = (g - c) / (g + c);
|
|
|
|
float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0);
|
|
|
|
result = 0.5 * A * A * (1.0 + B * B);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
result = 1.0; /* TIR (no refracted component) */
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2017-03-13 04:25:21 +11:00
|
|
|
}
|