Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2006-12-05 19:43:01 +0300
committerTon Roosendaal <ton@blender.org>2006-12-05 19:43:01 +0300
commit3177c4f69fcb53c2aad744ee951ea60d98a77c86 (patch)
tree01faa369202dce47cde8bca2f1c0c3c06c8bab0c /source/blender/render
parent246ab11255a4f5a3a2f024ef708b6807a5f63317 (diff)
Next stage of RenderPipe refactor: now everything within the pixel was
tackled. Resulting features: - render passes - new pass: Object Index, for masking - sub-sample alpha masks Docs: http://mediawiki.blender.org/index.php/BlenderDev/RenderPipeline http://www.blender3d.org/cms/Render_Passes.829.0.html http://www.blender3d.org/cms/New_Render_features.774.0.html Note that these changes might mean things to not render fully identical... For the next days a lot of testing is needed!
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/intern/include/pixelblending.h8
-rw-r--r--source/blender/render/intern/include/pixelshading.h5
-rw-r--r--source/blender/render/intern/include/render_types.h17
-rw-r--r--source/blender/render/intern/include/rendercore.h26
-rw-r--r--source/blender/render/intern/include/shading.h75
-rw-r--r--source/blender/render/intern/include/zbuf.h2
-rw-r--r--source/blender/render/intern/source/convertblender.c29
-rw-r--r--source/blender/render/intern/source/initrender.c10
-rw-r--r--source/blender/render/intern/source/pipeline.c36
-rw-r--r--source/blender/render/intern/source/pixelblending.c129
-rw-r--r--source/blender/render/intern/source/pixelshading.c168
-rw-r--r--source/blender/render/intern/source/ray.c373
-rw-r--r--source/blender/render/intern/source/rendercore.c3020
-rw-r--r--source/blender/render/intern/source/shadeinput.c999
-rw-r--r--source/blender/render/intern/source/shadeoutput.c1558
-rw-r--r--source/blender/render/intern/source/texture.c3
-rw-r--r--source/blender/render/intern/source/zbuf.c447
17 files changed, 3590 insertions, 3315 deletions
diff --git a/source/blender/render/intern/include/pixelblending.h b/source/blender/render/intern/include/pixelblending.h
index 2713b2023a9..04c5a3977a3 100644
--- a/source/blender/render/intern/include/pixelblending.h
+++ b/source/blender/render/intern/include/pixelblending.h
@@ -62,14 +62,6 @@ void addalphaAddFloat(float *dest, float *source);
*/
void addalphaUnderGammaFloat(float *doel, float *bron);
-/**
-* Copy the colour buffer output to R.rectot, to line y.
- */
-void transferColourBufferToOutput(float *buf, int y);
-/**
-* using default transforms for brightness, gamma, hue, saturation etc.
- */
-void std_floatcol_to_charcol(float *buf, char *target);
#endif /* PIXELBLENDING_EXT_H */
diff --git a/source/blender/render/intern/include/pixelshading.h b/source/blender/render/intern/include/pixelshading.h
index 67b0e5bcf3c..88c93a147fc 100644
--- a/source/blender/render/intern/include/pixelshading.h
+++ b/source/blender/render/intern/include/pixelshading.h
@@ -53,9 +53,8 @@ void shadeHaloFloat(HaloRen *har,
/**
* Render the sky at pixel (x, y).
*/
-void renderSkyPixelFloat(float *collector, float x, float y, float *rco);
-void shadeSkyPixel(float *collector, float fx, float fy, float *rco);
-void shadeSkyPixelFloat(float *colf, float *rco, float *view, float *dxyview);
+void shadeSkyPixel(float *collector, float fx, float fy);
+void shadeSkyView(float *colf, float *rco, float *view, float *dxyview);
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 3ac56e73099..77beb446c86 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -253,9 +253,8 @@ typedef struct RadFace {
int flag;
} RadFace;
-typedef struct VlakRen
-{
- struct VertRen *v1, *v2, *v3, *v4;
+typedef struct VlakRen {
+ struct VertRen *v1, *v2, *v3, *v4; /* keep in order for ** addressing */
unsigned int lay;
float n[3];
struct Material *mat;
@@ -290,8 +289,12 @@ struct MTex;
* For each lamp in a scene, a LampRen is created. It determines the
* properties of a lightsource.
*/
-typedef struct LampRen
-{
+
+typedef struct LampShadowSample {
+ float shadfac[16][4]; /* 16 = RE_MAX_OSA, 4 = rgba */
+} LampShadowSample;
+
+typedef struct LampRen {
float xs, ys, dist;
float co[3];
short type, mode;
@@ -340,6 +343,10 @@ typedef struct LampRen
float mat[3][3]; /* 3x3 part from lampmat x viewmat */
float area[8][3], areasize;
+ /* passes & node shader support: all shadow info for a pixel */
+ /* struct is currently 2k long... check on alloc? */
+ LampShadowSample shadsamp[BLENDER_MAX_THREADS];
+
/* yafray: photonlight params */
int YF_numphotons, YF_numsearch;
short YF_phdepth, YF_useqmc, YF_bufsize;
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
index e70913fbbde..9f22480f0cb 100644
--- a/source/blender/render/intern/include/rendercore.h
+++ b/source/blender/render/intern/include/rendercore.h
@@ -47,17 +47,11 @@ struct HaloRen;
struct ShadeInput;
struct ShadeResult;
struct World;
+struct RenderPart;
+struct RenderLayer;
/* ------------------------------------------------------------------------- */
-/* to make passing on variables to shadepixel() easier */
-typedef struct ShadePixelInfo {
- int thread;
- int layflag, passflag;
- unsigned int lay;
- ShadeResult shr;
-} ShadePixelInfo;
-
typedef struct PixStr
{
struct PixStr *next;
@@ -79,25 +73,17 @@ typedef struct PixStrMain
void calc_view_vector(float *view, float x, float y);
float mistfactor(float zcor, float *co); /* dist and height, return alpha */
+void renderspothalo(struct ShadeInput *shi, float *col, float alpha);
void add_halo_flare(Render *re);
-void shade_input_set_coords(ShadeInput *shi, float u, float v, int i1, int i2, int i3);
-
-void shade_color(struct ShadeInput *shi, ShadeResult *shr);
-void shade_lamp_loop(struct ShadeInput *shi, ShadeResult *shr);
-
-float fresnel_fac(float *view, float *vn, float fresnel, float fac);
-void calc_R_ref(struct ShadeInput *shi);
+void calc_renderco_zbuf(float *co, float *view, int z);
+void calc_renderco_ortho(float *co, float x, float y, int z);
-/* for nodes */
-void shade_material_loop(struct ShadeInput *shi, struct ShadeResult *shr);
+int count_mask(unsigned short mask);
void zbufshade(void);
void zbufshadeDA(void); /* Delta Accum Pixel Struct */
-void *shadepixel(ShadePixelInfo *shpi, float x, float y, int z, volatile int facenr, int mask, float *rco);
-int count_mask(unsigned short mask);
-
void zbufshade_tile(struct RenderPart *pa);
void zbufshadeDA_tile(struct RenderPart *pa);
diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h
new file mode 100644
index 00000000000..38ed0f73e70
--- /dev/null
+++ b/source/blender/render/intern/include/shading.h
@@ -0,0 +1,75 @@
+/**
+* $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+struct ShadeInput;
+struct ShadeResult;
+struct RenderPart;
+struct RenderLayer;
+struct PixStr;
+
+/* shadeinput.c */
+
+
+/* needed to calculate shadow and AO for an entire pixel */
+typedef struct ShadeSample {
+ int tot; /* amount of shi in use, can be 1 for not FULL_OSA */
+ ShadeInput shi[16]; /* RE_MAX_OSA */
+ ShadeResult shr[16]; /* RE_MAX_OSA */
+} ShadeSample;
+
+
+ /* also the node shader callback */
+void shade_material_loop(struct ShadeInput *shi, struct ShadeResult *shr);
+
+void shade_input_set_triangle_i(struct ShadeInput *shi, struct VlakRen *vlr, short i1, short i2, short i3);
+void shade_input_set_triangle(struct ShadeInput *shi, volatile int facenr, int normal_flip);
+void shade_input_copy_triangle(struct ShadeInput *shi, struct ShadeInput *from);
+void shade_input_set_viewco(struct ShadeInput *shi, float x, float y, float z);
+void shade_input_set_uv(struct ShadeInput *shi);
+void shade_input_set_normals(struct ShadeInput *shi);
+void shade_input_set_shade_texco(struct ShadeInput *shi);
+void shade_input_do_shade(struct ShadeInput *shi, struct ShadeResult *shr);
+
+void shade_sample_initialize(struct ShadeSample *ssamp, struct RenderPart *pa, struct RenderLayer *rl);
+void shade_samples_do_shadow(struct ShadeSample *ssamp);
+int shade_samples(struct ShadeSample *ssamp, struct PixStr *ps, int x, int y);
+
+void vlr_set_uv_indices(struct VlakRen *vlr, int *i1, int *i2, int *i3);
+
+void calc_R_ref(struct ShadeInput *shi);
+
+
+/* shadeoutput. */
+void shade_lamp_loop(struct ShadeInput *shi, struct ShadeResult *shr);
+
+void shade_color(struct ShadeInput *shi, ShadeResult *shr);
+
+void ambient_occlusion_to_diffuse(struct ShadeInput *shi, float *diff);
+void ambient_occlusion(struct ShadeInput *shi);
+
+float lamp_get_visibility(struct LampRen *lar, float *co, float *lv, float *dist);
+void lamp_get_shadow(struct LampRen *lar, ShadeInput *shi, float inp, float *shadfac, int do_real);
+
+float fresnel_fac(float *view, float *vn, float fresnel, float fac);
diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h
index 993ca711a18..c308ae25bce 100644
--- a/source/blender/render/intern/include/zbuf.h
+++ b/source/blender/render/intern/include/zbuf.h
@@ -49,7 +49,7 @@ int testclip(float *v);
void set_part_zbuf_clipflag(struct RenderPart *pa);
void zbuffer_shadow(struct Render *re, struct LampRen *lar, int *rectz, int size, float jitx, float jity);
void zbuffer_solid(struct RenderPart *pa, unsigned int layer, short layflag);
-void zbuffer_transp_shade(struct RenderPart *pa, struct RenderLayer *rl, float *pass);
+unsigned short *zbuffer_transp_shade(struct RenderPart *pa, struct RenderLayer *rl, float *pass);
void convert_zbuf_to_distbuf(struct RenderPart *pa, struct RenderLayer *rl);
typedef struct APixstr {
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 4142c5198d1..7232e0e6e71 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -101,6 +101,7 @@
#include "renderpipeline.h"
#include "radio.h"
#include "shadbuf.h"
+#include "shading.h"
#include "texture.h"
#include "zbuf.h"
@@ -2323,6 +2324,9 @@ static LampRen *add_render_lamp(Render *re, Object *ob)
}
}
+ else if(la->type==LA_HEMI) {
+ lar->mode &= ~(LA_SHAD_RAY|LA_SHAD_BUF);
+ }
for(c=0; c<MAX_MTEX; c++) {
if(la->mtex[c] && la->mtex[c]->tex) {
@@ -2353,11 +2357,18 @@ static LampRen *add_render_lamp(Render *re, Object *ob)
/* yafray: shadow flag should not be cleared, only used with internal renderer */
if (re->r.renderer==R_INTERN) {
+ int a, b;
+
/* to make sure we can check ray shadow easily in the render code */
if(lar->mode & LA_SHAD_RAY) {
if( (re->r.mode & R_RAYTRACE)==0)
lar->mode &= ~LA_SHAD_RAY;
}
+ /* shadfacs actually mean light, let's put them to 1 to prevent unitialized accidents */
+ for(c=0; c<re->r.threads; c++)
+ for(a=0; a<re->r.osa; a++)
+ for(b=0; b<4; b++)
+ lar->shadsamp[c].shadfac[a][b]= 1.0f;
}
return lar;
}
@@ -2974,6 +2985,9 @@ static void set_fullsample_flag(Render *re)
VlakRen *vlr;
int a, trace;
+ if(re->osa==0)
+ return;
+
trace= re->r.mode & R_RAYTRACE;
for(a=re->totvlak-1; a>=0; a--) {
@@ -3147,7 +3161,12 @@ void init_render_world(Render *re)
for(a=0; a<MAX_MTEX; a++)
if(re->wrld.mtex[a] && re->wrld.mtex[a]->tex) re->wrld.skytype |= WO_SKYTEX;
- while(re->wrld.aosamp*re->wrld.aosamp < re->osa) re->wrld.aosamp++;
+ /* AO samples should be OSA minimum */
+ if(re->osa)
+ while(re->wrld.aosamp*re->wrld.aosamp < re->osa)
+ re->wrld.aosamp++;
+ if(!(re->r.mode & R_RAYTRACE))
+ re->wrld.mode &= ~WO_AMB_OCC;
}
else {
memset(&re->wrld, 0, sizeof(World));
@@ -3200,12 +3219,12 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
}
init_render_world(re); /* do first, because of ambient. also requires re->osa set correct */
- if( (re->wrld.mode & WO_AMB_OCC) && (re->r.mode & R_RAYTRACE) )
+ if(re->wrld.mode & WO_AMB_OCC)
init_ao_sphere(&re->wrld);
/* still bad... doing all */
init_render_textures(re);
- init_render_materials(re->osa, &re->wrld.ambr);
+ init_render_materials(re->r.mode, &re->wrld.ambr);
set_node_shader_lamp_loop(shade_material_loop);
for(SETLOOPER(re->scene, base)) {
@@ -3871,12 +3890,12 @@ void RE_Database_Baking(Render *re, Scene *scene, int type)
}
init_render_world(re); /* do first, because of ambient. also requires re->osa set correct */
- if( (re->wrld.mode & WO_AMB_OCC) && (re->r.mode & R_RAYTRACE) )
+ if(re->wrld.mode & WO_AMB_OCC)
init_ao_sphere(&re->wrld);
/* still bad... doing all */
init_render_textures(re);
- init_render_materials(re->osa, &re->wrld.ambr);
+ init_render_materials(re->r.mode, &re->wrld.ambr);
set_node_shader_lamp_loop(shade_material_loop);
for(SETLOOPER(re->scene, base)) {
diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c
index 327b04f6c81..51ed2156a5b 100644
--- a/source/blender/render/intern/source/initrender.c
+++ b/source/blender/render/intern/source/initrender.c
@@ -74,7 +74,6 @@
#include "rendercore.h"
#include "pixelshading.h"
-#include "gammaCorrectionTables.h"
#include "zbuf.h"
/* Own includes */
@@ -98,7 +97,7 @@ static void init_render_jit(Render *re)
}
-/* ****************** GAMMA, MASKS and LUTS **************** */
+/* ****************** MASKS and LUTS **************** */
static float filt_quadratic(float x)
{
@@ -264,7 +263,6 @@ void make_sample_tables(Render *re)
/* optimization tables, only once */
if(firsttime) {
- makeGammaTables(2.0); /* tables only used for adding colors */
firsttime= 0;
}
@@ -278,12 +276,6 @@ void make_sample_tables(Render *re)
return;
}
- re->do_gamma= 0;
- if(re->r.mode & R_GAMMA) {
- if(re->r.alphamode!=R_ALPHAKEY) /* alpha corrected gamma doesnt work for key alpha */
- re->do_gamma= 1;
- }
-
st= re->samples= MEM_callocN(sizeof(SampleTables), "sample tables");
for(a=0; a<9;a++) {
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index ef6434cf65a..a4fd1168d22 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -290,11 +290,18 @@ static char *get_pass_name(int passtype, int channel)
else if(channel==1) return "AO.G";
else return "AO.B";
}
- if(passtype == SCE_PASS_RAY) {
- if(channel==0) return "Ray.R";
- else if(channel==1) return "Ray.G";
- else return "Ray.B";
- }
+ if(passtype == SCE_PASS_REFLECT) {
+ if(channel==0) return "Reflect.R";
+ else if(channel==1) return "Reflect.G";
+ else return "Reflect.B";
+ }
+ if(passtype == SCE_PASS_REFRACT) {
+ if(channel==0) return "Refract.R";
+ else if(channel==1) return "Refract.G";
+ else return "Refract.B";
+ }
+ if(passtype == SCE_PASS_INDEXOB)
+ return "IndexOB";
return "Unknown";
}
@@ -434,12 +441,19 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int
render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE);
if(srl->passflag & SCE_PASS_SPEC)
render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC);
- if(srl->passflag & SCE_PASS_SHADOW)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW);
- if(srl->passflag & SCE_PASS_AO)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_AO);
- if(srl->passflag & SCE_PASS_RAY)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_RAY);
+ if(re->r.mode & R_SHADOW)
+ if(srl->passflag & SCE_PASS_SHADOW)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW);
+ if(re->r.mode & R_RAYTRACE) {
+ if(srl->passflag & SCE_PASS_AO)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_AO);
+ if(srl->passflag & SCE_PASS_REFLECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT);
+ if(srl->passflag & SCE_PASS_REFRACT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT);
+ }
+ if(srl->passflag & SCE_PASS_INDEXOB)
+ render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB);
}
/* previewrender and envmap don't do layers, so we make a default one */
diff --git a/source/blender/render/intern/source/pixelblending.c b/source/blender/render/intern/source/pixelblending.c
index 3048a151925..136709b3ed5 100644
--- a/source/blender/render/intern/source/pixelblending.c
+++ b/source/blender/render/intern/source/pixelblending.c
@@ -280,134 +280,7 @@ void addalphaAddFloat(float *dest, float *source)
}
-/* ------------------------------------------------------------------------- */
-
-/* ------------------------------------------------------------------------- */
-/* Colour buffer related: */
-/* This transforms the 4 inputvalues RE_COLBUFTYPE to a new value */
-/* It expects the values R.r.postigamma, R.r.postmul and R.r.postadd. */
-/* This is the standard transformation, more elaborate tools are for later. */
-/* ------------------------------------------------------------------------- */
-void std_floatcol_to_charcol( float *buf, char *target)
-{
- float col[3];
-
- float dither_value;
-
- dither_value = ((BLI_frand()-0.5)*R.r.dither_intensity)/256.0;
-
- /* alpha */
- if((buf[3]+dither_value)<=0.0) target[3]= 0;
- else if((buf[3]+dither_value)>1.0) target[3]= 255;
- else target[3]= 255.0*(buf[3]+dither_value);
-
- if(R.r.postgamma==1.0) {
- /* r */
- col[0]= R.r.postmul*buf[0] + R.r.postadd + dither_value;
- /* g */
- col[1]= R.r.postmul*buf[1] + R.r.postadd + dither_value;
- /* b */
- col[2]= R.r.postmul*buf[2] + R.r.postadd + dither_value;
- }
- else {
- /* putting the postmul within the pow() gives an
- * easier control for the user, values from 1.0-2.0
- * are relevant then
- */
-
- /* r */
- col[0]= pow(R.r.postmul*buf[0], R.r.postigamma) + R.r.postadd + dither_value;
- /* g */
- col[1]= pow( R.r.postmul*buf[1], R.r.postigamma) + R.r.postadd + dither_value;
- /* b */
- col[2]= pow(R.r.postmul*buf[2], R.r.postigamma) + R.r.postadd + dither_value;
- }
-
- if(R.r.posthue!=0.0 || R.r.postsat!=1.0) {
- float hsv[3];
-
- rgb_to_hsv(col[0], col[1], col[2], hsv, hsv+1, hsv+2);
- hsv[0]+= R.r.posthue;
- if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
- hsv[1]*= R.r.postsat;
- if(hsv[1]>1.0) hsv[1]= 1.0; else if(hsv[1]<0.0) hsv[1]= 0.0;
- hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2);
- }
-
- if(col[0]<=0.0) target[0]= 0;
- else if(col[0]>1.0) target[0]= 255;
- else target[0]= 255.0*col[0];
-
- if(col[1]<=0.0) target[1]= 0;
- else if(col[1]>1.0) target[1]= 255;
- else target[1]= 255.0*col[1];
-
- if(col[2]<=0.0) target[2]= 0;
- else if(col[2]>1.0) target[2]= 255;
- else target[2]= 255.0*col[2];
-}
-
-/* ----------------------------------------------------------------------------
-
-Colour buffer related:
-
-The colour buffer is a buffer of a single screen line. It contains
-four fields of type RE_COLBUFTYPE per pixel.
-
-We can do several post-process steps. I would prefer to move them outside
-the render module later on, but it's ok to leave it here for now. For the
-time being, we have:
-- post-process function
- Does some operations with the colours.
-- Multiply with some factor
-- Add constant offset
-- Apply extra gamma correction (seems weird...)
-- key-alpha correction
- Key alpha means 'un-applying' the alpha. For fully covered pixels, this
- operation has no effect.
-
-- XXX WARNING! Added the inverse render gamma here, so this cannot be used external
- without setting Osa or Gamma flags off (ton)
-
----------------------------------------------------------------------------- */
-/* used external! */
-void transferColourBufferToOutput( float *buf, int y)
-{
- /* Copy the contents of AColourBuffer3 to R.rectot + y * R.rectx */
- int x = 0;
-// char *target = (char*) (R.rectot + (y * R.rectx));
-
- /* Copy the first <R.rectx> pixels. We can do some more clipping on */
- /* the z buffer, I think. */
- while (x < R.rectx) {
-
-
- /* invert gamma corrected additions */
- if(R.do_gamma) {
- buf[0] = invGammaCorrect(buf[0]);
- buf[1] = invGammaCorrect(buf[1]);
- buf[2] = invGammaCorrect(buf[2]);
- }
-
-// std_floatcol_to_charcol(buf, target);
-
- /*
- Key-alpha mode:
- Need to un-apply alpha if alpha is non-full. For full alpha,
- the operation doesn't have effect. Do this after the post-
- processing, so we can still use the benefits of that.
-
- */
-
- if (R.r.alphamode == R_ALPHAKEY) {
-// applyKeyAlphaCharCol(target);
- }
-
-// target+=4;
- buf+=4;
- x++;
- }
-}
+/* ---------------------------------------------------------------------------- */
/* eof pixelblending.c */
diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c
index bf5e34d3442..4955c65f55c 100644
--- a/source/blender/render/intern/source/pixelshading.c
+++ b/source/blender/render/intern/source/pixelshading.c
@@ -54,7 +54,6 @@
#include "pixelblending.h"
#include "rendercore.h"
#include "shadbuf.h"
-#include "gammaCorrectionTables.h"
#include "pixelshading.h"
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
@@ -438,42 +437,6 @@ void shadeHaloFloat(HaloRen *har, float *col, int zz,
}
/* ------------------------------------------------------------------------- */
-/*
-
- There are three different modes for blending sky behind a picture:
- 1. sky = blend in sky directly
- 2. premul = don't do sky, but apply alpha (so pretend the picture ends
- exactly at it's boundaries)
- 3. key = don't do anything
- Now the stupid thing is that premul means do nothing for us, and key
- we have to adjust a bit...
-
-*/
-
-
-/* This one renders into collector, as always. */
-void renderSkyPixelFloat(float *collector, float x, float y, float *rco)
-{
-
- switch (R.r.alphamode) {
- case R_ALPHAPREMUL:
- case R_ALPHAKEY:
- /* Premul or key: don't fill, and don't change the values! */
- /* key alpha used to fill in color in 'empty' pixels, doesn't work anymore this way */
- collector[0] = 0.0;
- collector[1] = 0.0;
- collector[2] = 0.0;
- collector[3] = 0.0;
- break;
- case R_ADDSKY:
- /* Fill in the sky as if it were a normal face. */
- shadeSkyPixel(collector, x, y, rco);
- collector[3]= 0.0;
- break;
- default:
- ; /* Error: illegal alpha blending state */
- }
-}
static void fillBackgroundImage(float *collector, float fx, float fy)
{
@@ -490,70 +453,8 @@ static void fillBackgroundImage(float *collector, float fx, float fy)
}
}
-/*
- Stuff the sky colour into the collector.
- */
-void shadeSkyPixel(float *collector, float fx, float fy, float *rco)
-{
- float view[3], dxyview[2];
-
- /*
- The rules for sky:
- 1. Draw an image, if a background image was provided. Stop
- 2. get texture and colour blend, and combine these.
- */
-
- float fac;
-
- /* 1. Do a backbuffer image: */
- if(R.r.bufflag & 1) {
- fillBackgroundImage(collector, fx, fy);
- return;
- } else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
- /*
- 2. Test for these types of sky. The old renderer always had to check for
- coverage, but we don't need that anymore
- - SKYBLEND or SKYTEX disabled: fill in a flat colour
- - otherwise, do the appropriate mapping (tex or colour blend)
- There used to be cached chars here, but they are not useful anymore
- */
- collector[0] = R.wrld.horr;
- collector[1] = R.wrld.horg;
- collector[2] = R.wrld.horb;
- collector[3] = 1.0f;
- } else {
- /*
- 3. Which type(s) is(are) this (these)? This has to be done when no simple
- way of determining the colour exists.
- */
-
- /* This one true because of the context of this routine */
- if(R.wrld.skytype & WO_SKYPAPER) {
- view[0]= -1.0f + 2.0f*(fx/(float)R.winx);
- view[1]= -1.0f + 2.0f*(fy/(float)R.winy);
- view[2]= 0.0;
-
- dxyview[0]= 1.0f/(float)R.winx;
- dxyview[1]= 1.0f/(float)R.winy;
- }
- else {
- calc_view_vector(view, fx, fy);
- fac= Normalise(view);
-
- if(R.wrld.skytype & WO_SKYTEX) {
- dxyview[0]= -R.viewdx/fac;
- dxyview[1]= -R.viewdy/fac;
- }
- }
-
- /* get sky colour in the collector */
- shadeSkyPixelFloat(collector, rco, view, dxyview);
- collector[3] = 1.0f;
- }
-}
-
/* Only view vector is important here. Result goes to colf[3] */
-void shadeSkyPixelFloat(float *colf, float *rco, float *view, float *dxyview)
+void shadeSkyView(float *colf, float *rco, float *view, float *dxyview)
{
float lo[3], zen[3], hor[3], blend, blendm;
int skyflag;
@@ -563,9 +464,9 @@ void shadeSkyPixelFloat(float *colf, float *rco, float *view, float *dxyview)
/* Some view vector stuff. */
if(R.wrld.skytype & WO_SKYREAL) {
-
+
blend= view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2];
-
+
if(blend<0.0) skyflag= 0;
blend= fabs(blend);
@@ -577,7 +478,7 @@ void shadeSkyPixelFloat(float *colf, float *rco, float *view, float *dxyview)
/* the fraction of how far we are above the bottom of the screen */
blend= fabs(0.5+ view[1]);
}
-
+
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;
@@ -588,16 +489,16 @@ void shadeSkyPixelFloat(float *colf, float *rco, float *view, float *dxyview)
if(R.wrld.skytype & WO_SKYREAL) {
MTC_Mat3MulVecfl(R.imat, lo);
-
+
SWAP(float, lo[1], lo[2]);
}
do_sky_tex(rco, lo, dxyview, hor, zen, &blend, skyflag);
}
-
+
if(blend>1.0) blend= 1.0;
blendm= 1.0-blend;
-
+
/* No clipping, no conversion! */
if(R.wrld.skytype & WO_SKYBLEND) {
colf[0] = (blendm*hor[0] + blend*zen[0]);
@@ -611,5 +512,60 @@ void shadeSkyPixelFloat(float *colf, float *rco, float *view, float *dxyview)
}
}
+/*
+ Stuff the sky colour into the collector.
+ */
+void shadeSkyPixel(float *collector, float fx, float fy)
+{
+ float view[3], dxyview[2];
+
+ /*
+ The rules for sky:
+ 1. Draw an image, if a background image was provided. Stop
+ 2. get texture and colour blend, and combine these.
+ */
+
+ float fac;
+
+ /* 1. Do a backbuffer image: */
+ if(R.r.bufflag & 1) {
+ fillBackgroundImage(collector, fx, fy);
+ return;
+ }
+ else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
+ /* 2. solid color */
+ collector[0] = R.wrld.horr;
+ collector[1] = R.wrld.horg;
+ collector[2] = R.wrld.horb;
+ collector[3] = 0.0f;
+ }
+ else {
+ /* 3. */
+
+ /* This one true because of the context of this routine */
+ if(R.wrld.skytype & WO_SKYPAPER) {
+ view[0]= -1.0f + 2.0f*(fx/(float)R.winx);
+ view[1]= -1.0f + 2.0f*(fy/(float)R.winy);
+ view[2]= 0.0;
+
+ dxyview[0]= 1.0f/(float)R.winx;
+ dxyview[1]= 1.0f/(float)R.winy;
+ }
+ else {
+ calc_view_vector(view, fx, fy);
+ fac= Normalise(view);
+
+ if(R.wrld.skytype & WO_SKYTEX) {
+ dxyview[0]= -R.viewdx/fac;
+ dxyview[1]= -R.viewdy/fac;
+ }
+ }
+
+ /* get sky colour in the collector */
+ shadeSkyView(collector, NULL, view, dxyview);
+ collector[3] = 0.0f;
+ }
+}
+
/* eof */
diff --git a/source/blender/render/intern/source/ray.c b/source/blender/render/intern/source/ray.c
index 972e4a8afc8..71c116e0c9b 100644
--- a/source/blender/render/intern/source/ray.c
+++ b/source/blender/render/intern/source/ray.c
@@ -51,6 +51,7 @@
#include "rendercore.h"
#include "pixelblending.h"
#include "pixelshading.h"
+#include "shading.h"
#include "texture.h"
#define DDA_SHADOW 0
@@ -337,32 +338,32 @@ static void d2dda(Octree *oc, short b1, short b2, short c1, short c2, char *ocfa
oy2= rtf[b2][c2];
if(ox1!=ox2) {
- if(ox2-ox1>0.0) {
- labdax= (ox1-ocx1-1.0)/(ox1-ox2);
- ldx= -1.0/(ox1-ox2);
+ if(ox2-ox1>0.0f) {
+ labdax= (ox1-ocx1-1.0f)/(ox1-ox2);
+ ldx= -1.0f/(ox1-ox2);
dx= 1;
} else {
labdax= (ox1-ocx1)/(ox1-ox2);
- ldx= 1.0/(ox1-ox2);
+ ldx= 1.0f/(ox1-ox2);
dx= -1;
}
} else {
- labdax=1.0;
+ labdax=1.0f;
ldx=0;
}
if(oy1!=oy2) {
- if(oy2-oy1>0.0) {
- labday= (oy1-ocy1-1.0)/(oy1-oy2);
- ldy= -1.0/(oy1-oy2);
+ if(oy2-oy1>0.0f) {
+ labday= (oy1-ocy1-1.0f)/(oy1-oy2);
+ ldy= -1.0f/(oy1-oy2);
dy= 1;
} else {
labday= (oy1-ocy1)/(oy1-oy2);
- ldy= 1.0/(oy1-oy2);
+ ldy= 1.0f/(oy1-oy2);
dy= -1;
}
} else {
- labday=1.0;
+ labday=1.0f;
ldy=0;
}
@@ -391,7 +392,7 @@ static void d2dda(Octree *oc, short b1, short b2, short c1, short c2, char *ocfa
}
labda=MIN2(labdax,labday);
if(labda==labdao) break;
- if(labda>=1.0) break;
+ if(labda>=1.0f) break;
}
ocface[oc->ocres*ocx2+ocy2]=1;
}
@@ -513,8 +514,8 @@ void makeoctree(Render *re)
memset(ocface, 0, 3*ocres2);
for(c=0;c<3;c++) { /* octree enlarge, still needed? */
- oc->min[c]-= 0.01;
- oc->max[c]+= 0.01;
+ oc->min[c]-= 0.01f;
+ oc->max[c]+= 0.01f;
}
t00= oc->max[0]-oc->min[0];
@@ -535,7 +536,7 @@ void makeoctree(Render *re)
vlr= re->blovl[v>>8];
if(re->test_break())
break;
- if(time-lasttime>1.0) {
+ if(time-lasttime>1.0f) {
char str[32];
sprintf(str, "Filling Octree: %d", v);
re->i.infostr= str;
@@ -697,16 +698,16 @@ static int intersection2(VlakRen *vlr, float r0, float r1, float r2, float rx1,
m2= rz1-v3->co[2];
det1= m0*x0+m1*x1+m2*x2;
- if(divdet!=0.0) {
+ if(divdet!=0.0f) {
u1= det1/divdet;
- if(u1<=0.0) {
+ if(u1<=0.0f) {
det= t00*(m1*r2-m2*r1);
det+= t01*(m2*r0-m0*r2);
det+= t02*(m0*r1-m1*r0);
v= det/divdet;
- if(v<=0.0 && (u1 + v) >= -1.0) {
+ if(v<=0.0f && (u1 + v) >= -1.0f) {
return 1;
}
}
@@ -719,16 +720,16 @@ static int intersection2(VlakRen *vlr, float r0, float r1, float r2, float rx1,
t22= v3->co[2]-v4->co[2];
divdet= t20*x0+t21*x1+t22*x2;
- if(divdet!=0.0) {
+ if(divdet!=0.0f) {
u2= det1/divdet;
- if(u2<=0.0) {
+ if(u2<=0.0f) {
det= t20*(m1*r2-m2*r1);
det+= t21*(m2*r0-m0*r2);
det+= t22*(m0*r1-m1*r0);
v= det/divdet;
- if(v<=0.0 && (u2 + v) >= -1.0) {
+ if(v<=0.0f && (u2 + v) >= -1.0f) {
return 2;
}
}
@@ -845,12 +846,12 @@ static int intersection(Isect *is)
m2= is->start[2]-v3->co[2];
det1= m0*x0+m1*x1+m2*x2;
- if(divdet!=0.0) {
+ if(divdet!=0.0f) {
float u;
- divdet= 1.0/divdet;
+ divdet= 1.0f/divdet;
u= det1*divdet;
- if(u<0.0 && u>-1.0) {
+ if(u<0.0f && u>-1.0f) {
float v, cros0, cros1, cros2;
cros0= m1*t02-m2*t01;
@@ -858,11 +859,11 @@ static int intersection(Isect *is)
cros2= m0*t01-m1*t00;
v= divdet*(cros0*r0 + cros1*r1 + cros2*r2);
- if(v<0.0 && (u + v) > -1.0) {
+ if(v<0.0f && (u + v) > -1.0f) {
float labda;
labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12);
- if(labda>0.0 && labda<1.0) {
+ if(labda>0.0f && labda<1.0f) {
is->labda= labda;
is->u= u; is->v= v;
ok= 1;
@@ -878,23 +879,23 @@ static int intersection(Isect *is)
t22= v3->co[2]-v4->co[2];
divdet= t20*x0+t21*x1+t22*x2;
- if(divdet!=0.0) {
+ if(divdet!=0.0f) {
float u;
- divdet= 1.0/divdet;
+ divdet= 1.0f/divdet;
u = det1*divdet;
- if(u<0.0 && u>-1.0) {
+ if(u<0.0f && u>-1.0f) {
float v, cros0, cros1, cros2;
cros0= m1*t22-m2*t21;
cros1= m2*t20-m0*t22;
cros2= m0*t21-m1*t20;
v= divdet*(cros0*r0 + cros1*r1 + cros2*r2);
- if(v<0.0 && (u + v) > -1.0) {
+ if(v<0.0f && (u + v) > -1.0f) {
float labda;
labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12);
- if(labda>0.0 && labda<1.0) {
+ if(labda>0.0f && labda<1.0f) {
ok= 2;
is->labda= labda;
is->u= u; is->v= v;
@@ -995,7 +996,7 @@ static int testnode(Isect *is, Node *no, OcVal ocval)
Isect isect;
int found= 0;
- is->labda= 1.0; /* needed? */
+ is->labda= 1.0f; /* needed? */
isect= *is; /* copy for sorting */
vlr= no->v[0];
@@ -1097,24 +1098,24 @@ static int cliptest(float p, float q, float *u1, float *u2)
{
float r;
- if(p<0.0) {
+ if(p<0.0f) {
if(q<p) return 0;
- else if(q<0.0) {
+ else if(q<0.0f) {
r= q/p;
if(r>*u2) return 0;
else if(r>*u1) *u1=r;
}
}
else {
- if(p>0.0) {
- if(q<0.0) return 0;
+ if(p>0.0f) {
+ if(q<0.0f) return 0;
else if(q<p) {
r= q/p;
if(r<*u1) return 0;
else if(r<*u2) *u2=r;
}
}
- else if(q<0.0) return 0;
+ else if(q<0.0f) return 0;
}
return 1;
}
@@ -1183,8 +1184,8 @@ static int d3dda(Isect *is)
}
ldx= is->end[0] - is->start[0];
- u1= 0.0;
- u2= 1.0;
+ u1= 0.0f;
+ u2= 1.0f;
/* clip with octree cube */
if(cliptest(-ldx, is->start[0]-R.oc.min[0], &u1,&u2)) {
@@ -1196,12 +1197,12 @@ static int d3dda(Isect *is)
if(cliptest(-ldz, is->start[2]-R.oc.min[2], &u1,&u2)) {
if(cliptest(ldz, R.oc.max[2]-is->start[2], &u1,&u2)) {
c1=1;
- if(u2<1.0) {
+ if(u2<1.0f) {
is->end[0]= is->start[0]+u2*ldx;
is->end[1]= is->start[1]+u2*ldy;
is->end[2]= is->start[2]+u2*ldz;
}
- if(u1>0.0) {
+ if(u1>0.0f) {
is->start[0]+=u1*ldx;
is->start[1]+=u1*ldy;
is->start[2]+=u1*ldz;
@@ -1243,7 +1244,7 @@ static int d3dda(Isect *is)
vec1[0]= ox1; vec1[1]= oy1; vec1[2]= oz1;
vec2[0]= ox2; vec2[1]= oy2; vec2[2]= oz2;
calc_ocval_ray(&ocval, (float)ocx1, (float)ocy1, (float)ocz1, vec1, vec2);
- is->ddalabda= 1.0;
+ is->ddalabda= 1.0f;
if( testnode(is, no, ocval) ) return 1;
}
}
@@ -1258,43 +1259,43 @@ static int d3dda(Isect *is)
doz= oz1-oz2;
if(dox<-FLT_EPSILON) {
- ldx= -1.0/dox;
- labdax= (ocx1-ox1+1.0)*ldx;
+ ldx= -1.0f/dox;
+ labdax= (ocx1-ox1+1.0f)*ldx;
dx= 1;
} else if(dox>FLT_EPSILON) {
- ldx= 1.0/dox;
+ ldx= 1.0f/dox;
labdax= (ox1-ocx1)*ldx;
dx= -1;
} else {
- labdax=1.0;
+ labdax=1.0f;
ldx=0;
dx= 0;
}
if(doy<-FLT_EPSILON) {
- ldy= -1.0/doy;
- labday= (ocy1-oy1+1.0)*ldy;
+ ldy= -1.0f/doy;
+ labday= (ocy1-oy1+1.0f)*ldy;
dy= 1;
} else if(doy>FLT_EPSILON) {
- ldy= 1.0/doy;
+ ldy= 1.0f/doy;
labday= (oy1-ocy1)*ldy;
dy= -1;
} else {
- labday=1.0;
+ labday=1.0f;
ldy=0;
dy= 0;
}
if(doz<-FLT_EPSILON) {
- ldz= -1.0/doz;
- labdaz= (ocz1-oz1+1.0)*ldz;
+ ldz= -1.0f/doz;
+ labdaz= (ocz1-oz1+1.0f)*ldz;
dz= 1;
} else if(doz>FLT_EPSILON) {
- ldz= 1.0/doz;
+ ldz= 1.0f/doz;
labdaz= (oz1-ocz1)*ldz;
dz= -1;
} else {
- labdaz=1.0;
+ labdaz=1.0f;
ldz=0;
dz= 0;
}
@@ -1307,7 +1308,7 @@ static int d3dda(Isect *is)
vec2[2]= oz1;
/* this loop has been constructed to make sure the first and last node of ray
- are always included, even when ddalabda==1.0 or larger */
+ are always included, even when ddalabda==1.0f or larger */
while(TRUE) {
@@ -1388,7 +1389,7 @@ static int d3dda(Isect *is)
ddalabda=MIN3(labdax,labday,labdaz);
if(ddalabda==labdao) break;
/* to make sure the last node is always checked */
- if(labdao>=1.0) break;
+ if(labdao>=1.0f) break;
}
}
@@ -1421,7 +1422,7 @@ static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
/* face normal, check for flip */
l= vlr->n[0]*shi->view[0]+vlr->n[1]*shi->view[1]+vlr->n[2]*shi->view[2];
- if(l<0.0) {
+ if(l<0.0f) {
shi->facenor[0]= -vlr->n[0];
shi->facenor[1]= -vlr->n[1];
shi->facenor[2]= -vlr->n[2];
@@ -1436,34 +1437,42 @@ static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
// Osa structs we leave unchanged now
SWAP(int, osatex, shi->osatex);
- shi->dxco[0]= shi->dxco[1]= shi->dxco[2]= 0.0;
- shi->dyco[0]= shi->dyco[1]= shi->dyco[2]= 0.0;
+ shi->dxco[0]= shi->dxco[1]= shi->dxco[2]= 0.0f;
+ shi->dyco[0]= shi->dyco[1]= shi->dyco[2]= 0.0f;
// but, set Osa stuff to zero where it can confuse texture code
if(shi->mat->texco & (TEXCO_NORM|TEXCO_REFL) ) {
- shi->dxno[0]= shi->dxno[1]= shi->dxno[2]= 0.0;
- shi->dyno[0]= shi->dyno[1]= shi->dyno[2]= 0.0;
+ shi->dxno[0]= shi->dxno[1]= shi->dxno[2]= 0.0f;
+ shi->dyno[0]= shi->dyno[1]= shi->dyno[2]= 0.0f;
}
if(vlr->v4) {
if(is->isect==2)
- shade_input_set_coords(shi, is->u, is->v, 2, 1, 3);
+ shade_input_set_triangle_i(shi, vlr, 2, 1, 3);
else
- shade_input_set_coords(shi, is->u, is->v, 0, 1, 3);
+ shade_input_set_triangle_i(shi, vlr, 0, 1, 3);
}
else {
- shade_input_set_coords(shi, is->u, is->v, 0, 1, 2);
+ shade_input_set_triangle_i(shi, vlr, 0, 1, 2);
}
+ shi->u= is->u;
+ shi->v= is->v;
+ shade_input_set_normals(shi);
+ shade_input_set_shade_texco(shi);
if(is->mode==DDA_SHADOW_TRA)
shade_color(shi, shr);
- else if(shi->mat->nodetree && shi->mat->use_nodes) {
- ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
- shi->mat= vlr->mat; /* shi->mat is being set in nodetree */
- }
- else
- shade_material_loop(shi, shr);
-
+ else {
+ if(shi->mat->nodetree && shi->mat->use_nodes) {
+ ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
+ shi->mat= vlr->mat; /* shi->mat is being set in nodetree */
+ }
+ else
+ shade_material_loop(shi, shr);
+
+ /* raytrace likes to separate the spec color */
+ VECSUB(shr->diff, shr->combined, shr->spec);
+ }
SWAP(int, osatex, shi->osatex); // XXXXX!!!!
@@ -1477,15 +1486,15 @@ static int refraction(float *refract, float *n, float *view, float index)
dot= view[0]*n[0] + view[1]*n[1] + view[2]*n[2];
- if(dot>0.0) {
- index = 1.0/index;
- fac= 1.0 - (1.0 - dot*dot)*index*index;
- if(fac<= 0.0) return 0;
+ if(dot>0.0f) {
+ index = 1.0f/index;
+ fac= 1.0f - (1.0f - dot*dot)*index*index;
+ if(fac<= 0.0f) return 0;
fac= -dot*index + sqrt(fac);
}
else {
- fac= 1.0 - (1.0 - dot*dot)*index*index;
- if(fac<= 0.0) return 0;
+ fac= 1.0f - (1.0f - dot*dot)*index*index;
+ if(fac<= 0.0f) return 0;
fac= -dot*index - sqrt(fac);
}
@@ -1501,7 +1510,7 @@ static void reflection(float *ref, float *n, float *view, float *orn)
{
float f1;
- f1= -2.0*(n[0]*view[0]+ n[1]*view[1]+ n[2]*view[2]);
+ f1= -2.0f*(n[0]*view[0]+ n[1]*view[1]+ n[2]*view[2]);
ref[0]= (view[0]+f1*n[0]);
ref[1]= (view[1]+f1*n[1]);
@@ -1510,8 +1519,8 @@ static void reflection(float *ref, float *n, float *view, float *orn)
if(orn) {
/* test phong normals, then we should prevent vector going to the back */
f1= ref[0]*orn[0]+ ref[1]*orn[1]+ ref[2]*orn[2];
- if(f1>0.0) {
- f1+= .01;
+ if(f1>0.0f) {
+ f1+= .01f;
ref[0]-= f1*orn[0];
ref[1]-= f1*orn[1];
ref[2]-= f1*orn[2];
@@ -1547,8 +1556,8 @@ static float shade_by_transmission(Isect *is, ShadeInput *shi, ShadeResult *shr)
if (0 == (shi->mat->mode & (MA_RAYTRANSP|MA_ZTRA)))
return -1;
- if (shi->mat->tx_limit <= 0.0) {
- d= 1.0;
+ if (shi->mat->tx_limit <= 0.0f) {
+ d= 1.0f;
}
else {
/* shi.co[] calculated by shade_ray() */
@@ -1560,12 +1569,12 @@ static float shade_by_transmission(Isect *is, ShadeInput *shi, ShadeResult *shr)
d= shi->mat->tx_limit;
p = shi->mat->tx_falloff;
- if(p < 0.0) p= 0.0;
- else if (p > 10.0) p= 10.0;
+ if(p < 0.0f) p= 0.0f;
+ else if (p > 10.0f) p= 10.0f;
shr->alpha *= pow(d, p);
- if (shr->alpha > 1.0)
- shr->alpha= 1.0;
+ if (shr->alpha > 1.0f)
+ shr->alpha= 1.0f;
}
return d;
@@ -1588,7 +1597,7 @@ static void traceray(ShadeInput *origshi, short depth, float *start, float *vec,
isec.vlrorig= vlr;
if( d3dda(&isec) ) {
- float d= 1.0;
+ float d= 1.0f;
shi.mask= origshi->mask;
shi.osatex= origshi->osatex;
@@ -1597,6 +1606,7 @@ static void traceray(ShadeInput *origshi, short depth, float *start, float *vec,
shi.xs= origshi->xs;
shi.ys= origshi->ys;
shi.lay= origshi->lay;
+ shi.passflag= origshi->passflag;
shi.do_preview= 0;
memset(&shr, 0, sizeof(ShadeResult));
@@ -1607,7 +1617,7 @@ static void traceray(ShadeInput *origshi, short depth, float *start, float *vec,
if(depth>0) {
- if(shi.mat->mode_l & (MA_RAYTRANSP|MA_ZTRA) && shr.alpha < 1.0) {
+ if(shi.mat->mode_l & (MA_RAYTRANSP|MA_ZTRA) && shr.alpha < 1.0f) {
float nf, f, f1, refract[3], tracol[4];
tracol[0]= shi.r;
@@ -1635,11 +1645,11 @@ static void traceray(ShadeInput *origshi, short depth, float *start, float *vec,
else
traceray(origshi, depth-1, shi.co, shi.view, tracol, shi.vlr, 0);
- f= shr.alpha; f1= 1.0-f;
+ f= shr.alpha; f1= 1.0f-f;
nf= d * shi.mat->filter;
- fr= 1.0+ nf*(shi.r-1.0);
- fg= 1.0+ nf*(shi.g-1.0);
- fb= 1.0+ nf*(shi.b-1.0);
+ fr= 1.0f+ nf*(shi.r-1.0f);
+ fg= 1.0f+ nf*(shi.g-1.0f);
+ fb= 1.0f+ nf*(shi.b-1.0f);
shr.diff[0]= f*shr.diff[0] + f1*fr*tracol[0];
shr.diff[1]= f*shr.diff[1] + f1*fg*tracol[1];
shr.diff[2]= f*shr.diff[2] + f1*fb*tracol[2];
@@ -1651,24 +1661,24 @@ static void traceray(ShadeInput *origshi, short depth, float *start, float *vec,
col[3]= f1*tracol[3] + f;
}
else
- col[3]= 1.0;
+ col[3]= 1.0f;
if(shi.mat->mode_l & MA_RAYMIRROR) {
f= shi.ray_mirror;
- if(f!=0.0) f*= fresnel_fac(shi.view, shi.vn, shi.mat->fresnel_mir_i, shi.mat->fresnel_mir);
+ if(f!=0.0f) f*= fresnel_fac(shi.view, shi.vn, shi.mat->fresnel_mir_i, shi.mat->fresnel_mir);
}
- else f= 0.0;
+ else f= 0.0f;
- if(f!=0.0) {
+ if(f!=0.0f) {
float mircol[4];
reflection(ref, shi.vn, shi.view, NULL);
traceray(origshi, depth-1, shi.co, ref, mircol, shi.vlr, 0);
- f1= 1.0-f;
+ f1= 1.0f-f;
/* combine */
- //color_combine(col, f*fr*(1.0-shr.spec[0]), f1, col, shr.diff);
+ //color_combine(col, f*fr*(1.0f-shr.spec[0]), f1, col, shr.diff);
//col[0]+= shr.spec[0];
//col[1]+= shr.spec[1];
//col[2]+= shr.spec[2];
@@ -1677,9 +1687,9 @@ static void traceray(ShadeInput *origshi, short depth, float *start, float *vec,
fg= shi.mirg;
fb= shi.mirb;
- col[0]= f*fr*(1.0-shr.spec[0])*mircol[0] + f1*shr.diff[0] + shr.spec[0];
- col[1]= f*fg*(1.0-shr.spec[1])*mircol[1] + f1*shr.diff[1] + shr.spec[1];
- col[2]= f*fb*(1.0-shr.spec[2])*mircol[2] + f1*shr.diff[2] + shr.spec[2];
+ col[0]= f*fr*(1.0f-shr.spec[0])*mircol[0] + f1*shr.diff[0] + shr.spec[0];
+ col[1]= f*fg*(1.0f-shr.spec[1])*mircol[1] + f1*shr.diff[1] + shr.spec[1];
+ col[2]= f*fb*(1.0f-shr.spec[2])*mircol[2] + f1*shr.diff[2] + shr.spec[2];
}
else {
col[0]= shr.diff[0] + shr.spec[0];
@@ -1698,7 +1708,7 @@ static void traceray(ShadeInput *origshi, short depth, float *start, float *vec,
VECCOPY(shi.view, vec);
Normalise(shi.view);
- shadeSkyPixelFloat(col, isec.start, shi.view, NULL);
+ shadeSkyView(col, isec.start, shi.view, NULL);
}
}
@@ -1714,7 +1724,7 @@ static void DP_energy(float *table, float *vec, int tot, float xsize, float ysiz
min= MIN2(xsize, ysize);
min*= min;
- result[0]= result[1]= 0.0;
+ result[0]= result[1]= 0.0f;
for(y= -1; y<2; y++) {
dy= ysize*y;
@@ -1725,7 +1735,7 @@ static void DP_energy(float *table, float *vec, int tot, float xsize, float ysiz
force[0]= vec[0] - fp[0]-dx;
force[1]= vec[1] - fp[1]-dy;
dist= force[0]*force[0] + force[1]*force[1];
- if(dist < min && dist>0.0) {
+ if(dist < min && dist>0.0f) {
result[0]+= force[0]/dist;
result[1]+= force[1]/dist;
}
@@ -1784,9 +1794,9 @@ void init_jitter_plane(LampRen *lar)
}
/* create the dithered tables (could just check lamp type!) */
- jitter_plane_offset(lar->jitter, lar->jitter+2*tot, tot, lar->area_size, lar->area_sizey, 0.5, 0.0);
- jitter_plane_offset(lar->jitter, lar->jitter+4*tot, tot, lar->area_size, lar->area_sizey, 0.5, 0.5);
- jitter_plane_offset(lar->jitter, lar->jitter+6*tot, tot, lar->area_size, lar->area_sizey, 0.0, 0.5);
+ jitter_plane_offset(lar->jitter, lar->jitter+2*tot, tot, lar->area_size, lar->area_sizey, 0.5f, 0.0f);
+ jitter_plane_offset(lar->jitter, lar->jitter+4*tot, tot, lar->area_size, lar->area_sizey, 0.5f, 0.5f);
+ jitter_plane_offset(lar->jitter, lar->jitter+6*tot, tot, lar->area_size, lar->area_sizey, 0.0f, 0.5f);
}
/* table around origin, -0.5*size to 0.5*size */
@@ -1824,25 +1834,36 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr)
float i, f, f1, fr, fg, fb, vec[3], mircol[4], tracol[4];
int do_tra, do_mir;
- do_tra= ((shi->mat->mode & (MA_RAYTRANSP)) && shr->alpha!=1.0);
- do_mir= ((shi->mat->mode & MA_RAYMIRROR) && shi->ray_mirror!=0.0);
+ do_tra= ((shi->mat->mode & (MA_RAYTRANSP)) && shr->alpha!=1.0f);
+ do_mir= ((shi->mat->mode & MA_RAYMIRROR) && shi->ray_mirror!=0.0f);
vlr= shi->vlr;
+ /* raytrace likes to separate the spec color */
+ VECSUB(shr->diff, shr->combined, shr->spec);
+
if(do_tra) {
float refract[3];
+ float olddiff[3];
tracol[3]= shr->alpha;
refraction(refract, shi->vn, shi->view, shi->ang);
traceray(shi, shi->mat->ray_depth_tra, shi->co, refract, tracol, shi->vlr, RAY_TRA|RAY_TRAFLIP);
- f= shr->alpha; f1= 1.0-f;
- fr= 1.0+ shi->mat->filter*(shi->r-1.0);
- fg= 1.0+ shi->mat->filter*(shi->g-1.0);
- fb= 1.0+ shi->mat->filter*(shi->b-1.0);
- shr->diff[0]= f*shr->diff[0] + f1*fr*tracol[0];
- shr->diff[1]= f*shr->diff[1] + f1*fg*tracol[1];
- shr->diff[2]= f*shr->diff[2] + f1*fb*tracol[2];
+ f= shr->alpha; f1= 1.0f-f;
+ fr= 1.0f+ shi->mat->filter*(shi->r-1.0f);
+ fg= 1.0f+ shi->mat->filter*(shi->g-1.0f);
+ fb= 1.0f+ shi->mat->filter*(shi->b-1.0f);
+
+ /* for refract pass */
+ VECCOPY(olddiff, shr->diff);
+
+ shr->diff[0]= f*shr->diff[0] + fr*tracol[0];
+ shr->diff[1]= f*shr->diff[1] + fr*tracol[1];
+ shr->diff[2]= f*shr->diff[2] + fr*tracol[2];
+
+ if(shi->passflag & SCE_PASS_REFRACT)
+ VECSUB(shr->refr, shr->diff, olddiff);
shr->alpha= tracol[3];
}
@@ -1850,10 +1871,10 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr)
if(do_mir) {
i= shi->ray_mirror*fresnel_fac(shi->view, shi->vn, shi->mat->fresnel_mir_i, shi->mat->fresnel_mir);
- if(i!=0.0) {
- fr= shi->mirr;
- fg= shi->mirg;
- fb= shi->mirb;
+ if(i!=0.0f) {
+ fr= i*shi->mirr;
+ fg= i*shi->mirg;
+ fb= i*shi->mirb;
if(vlr->flag & R_SMOOTH)
reflection(vec, shi->vn, shi->view, shi->facenor);
@@ -1862,16 +1883,25 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr)
traceray(shi, shi->mat->ray_depth, shi->co, vec, mircol, shi->vlr, 0);
- f= i*fr*(1.0-shr->spec[0]); f1= 1.0-i;
+ if(shi->passflag & SCE_PASS_REFLECT) {
+ /* mirror pass is not blocked out with spec */
+ shr->refl[0]= fr*mircol[0] - fr*shr->diff[0];
+ shr->refl[1]= fg*mircol[1] - fg*shr->diff[1];
+ shr->refl[2]= fb*mircol[2] - fb*shr->diff[2];
+ }
+ f= fr*(1.0f-shr->spec[0]); f1= 1.0f-i;
shr->diff[0]= f*mircol[0] + f1*shr->diff[0];
- f= i*fg*(1.0-shr->spec[1]); f1= 1.0-i;
+ f= fg*(1.0f-shr->spec[1]); f1= 1.0f-i;
shr->diff[1]= f*mircol[1] + f1*shr->diff[1];
- f= i*fb*(1.0-shr->spec[2]); f1= 1.0-i;
+ f= fb*(1.0f-shr->spec[2]); f1= 1.0f-i;
shr->diff[2]= f*mircol[2] + f1*shr->diff[2];
}
}
+
+ /* put back together */
+ VECADD(shr->combined, shr->diff, shr->spec);
}
/* color 'shadfac' passes through 'col' with alpha and filter */
@@ -1880,26 +1910,26 @@ static void addAlphaLight(float *shadfac, float *col, float alpha, float filter)
{
float fr, fg, fb;
- fr= 1.0+ filter*(col[0]-1.0);
- fg= 1.0+ filter*(col[1]-1.0);
- fb= 1.0+ filter*(col[2]-1.0);
+ fr= 1.0f+ filter*(col[0]-1.0f);
+ fg= 1.0f+ filter*(col[1]-1.0f);
+ fb= 1.0f+ filter*(col[2]-1.0f);
- shadfac[0]= alpha*col[0] + fr*(1.0-alpha)*shadfac[0];
- shadfac[1]= alpha*col[1] + fg*(1.0-alpha)*shadfac[1];
- shadfac[2]= alpha*col[2] + fb*(1.0-alpha)*shadfac[2];
+ shadfac[0]= alpha*col[0] + fr*(1.0f-alpha)*shadfac[0];
+ shadfac[1]= alpha*col[1] + fg*(1.0f-alpha)*shadfac[1];
+ shadfac[2]= alpha*col[2] + fb*(1.0f-alpha)*shadfac[2];
- shadfac[3]= (1.0-alpha)*shadfac[3];
+ shadfac[3]= (1.0f-alpha)*shadfac[3];
}
static void ray_trace_shadow_tra(Isect *is, int depth, int traflag)
{
/* ray to lamp, find first face that intersects, check alpha properties,
- if it has col[3]>0.0 continue. so exit when alpha is full */
+ if it has col[3]>0.0f continue. so exit when alpha is full */
ShadeInput shi;
ShadeResult shr;
if( d3dda(is)) {
- float d= 1.0;
+ float d= 1.0f;
/* we got a face */
shi.mask= 1;
@@ -1913,7 +1943,7 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag)
/* mix colors based on shadfac (rgb + amount of light factor) */
addAlphaLight(is->col, shr.diff, shr.alpha, d*shi.mat->filter);
- if(depth>0 && is->col[3]>0.0) {
+ if(depth>0 && is->col[3]>0.0f) {
/* adapt isect struct */
VECCOPY(is->start, shi.co);
@@ -1933,7 +1963,7 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr)
Isect isec;
ShadeInput shi;
ShadeResult shr_t;
- float vec[3], accum[3], div= 0.0;
+ float vec[3], accum[3], div= 0.0f;
int a;
if(only_one) {
@@ -1941,7 +1971,7 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr)
}
only_one= 1;
- accum[0]= accum[1]= accum[2]= 0.0;
+ accum[0]= accum[1]= accum[2]= 0.0f;
isec.mode= DDA_MIRROR;
isec.vlrorig= ship->vlr;
@@ -1950,7 +1980,7 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr)
counter+=3;
counter %= 768;
VECCOPY(vec, hashvectf+counter);
- if(ship->vn[0]*vec[0]+ship->vn[1]*vec[1]+ship->vn[2]*vec[2]>0.0) {
+ if(ship->vn[0]*vec[0]+ship->vn[1]*vec[1]+ship->vn[2]*vec[2]>0.0f) {
vec[0]-= vec[0];
vec[1]-= vec[1];
vec[2]-= vec[2];
@@ -1964,21 +1994,21 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr)
float fac;
shade_ray(&isec, &shi, &shr_t);
fac= isec.labda*isec.labda;
- fac= 1.0;
+ fac= 1.0f;
accum[0]+= fac*(shr_t.diff[0]+shr_t.spec[0]);
accum[1]+= fac*(shr_t.diff[1]+shr_t.spec[1]);
accum[2]+= fac*(shr_t.diff[2]+shr_t.spec[2]);
div+= fac;
}
- else div+= 1.0;
+ else div+= 1.0f;
}
- if(div!=0.0) {
+ if(div!=0.0f) {
shr->diff[0]+= accum[0]/div;
shr->diff[1]+= accum[1]/div;
shr->diff[2]+= accum[2]/div;
}
- shr->alpha= 1.0;
+ shr->alpha= 1.0f;
only_one= 0;
return 1;
@@ -2004,13 +2034,13 @@ static void DS_energy(float *sphere, int tot, float *vec)
float *fp, fac, force[3], res[3];
int a;
- res[0]= res[1]= res[2]= 0.0;
+ res[0]= res[1]= res[2]= 0.0f;
for(a=0, fp=sphere; a<tot; a++, fp+=3) {
VecSubf(force, vec, fp);
fac= force[0]*force[0] + force[1]*force[1] + force[2]*force[2];
- if(fac!=0.0) {
- fac= 1.0/fac;
+ if(fac!=0.0f) {
+ fac= 1.0f/fac;
res[0]+= fac*force[0];
res[1]+= fac*force[1];
res[2]+= fac*force[2];
@@ -2127,7 +2157,7 @@ static float *sphere_sampler(int type, int resol, int thread, int xs, int ys)
void ray_ao(ShadeInput *shi, float *shadfac)
{
Isect isec;
- float *vec, *nrm, div, bias, sh=0;
+ float *vec, *nrm, div, bias, sh=0.0f;
float maxdist = R.wrld.aodist;
float dxyview[3];
int j= -1, tot, actual=0, skyadded=0;
@@ -2137,7 +2167,7 @@ void ray_ao(ShadeInput *shi, float *shadfac)
isec.mode= (R.wrld.aomode & WO_AODIST)?DDA_SHADOW_TRA:DDA_SHADOW;
isec.lay= -1;
- shadfac[0]= shadfac[1]= shadfac[2]= 0.0;
+ shadfac[0]= shadfac[1]= shadfac[2]= 0.0f;
// bias prevents smoothed faces to appear flat
if(shi->vlr->flag & R_SMOOTH) {
@@ -2145,7 +2175,7 @@ void ray_ao(ShadeInput *shi, float *shadfac)
nrm= shi->vn;
}
else {
- bias= 0.0;
+ bias= 0.0f;
nrm= shi->facenor;
}
@@ -2163,7 +2193,7 @@ void ray_ao(ShadeInput *shi, float *shadfac)
while(tot--) {
if ((vec[0]*nrm[0] + vec[1]*nrm[1] + vec[2]*nrm[2]) > bias) {
- // only ao samples for mask
+ /* only ao samples for mask */
if(R.r.mode & R_OSA) {
j++;
if(j==R.osa) j= 0;
@@ -2184,7 +2214,7 @@ void ray_ao(ShadeInput *shi, float *shadfac)
/* do the trace */
if (d3dda(&isec)) {
if (R.wrld.aomode & WO_AODIST) sh+= exp(-isec.labda*R.wrld.aodistfac);
- else sh+= 1.0;
+ else sh+= 1.0f;
}
else if(R.wrld.aocolor!=WO_AOPLAIN) {
float skycol[4];
@@ -2196,13 +2226,13 @@ void ray_ao(ShadeInput *shi, float *shadfac)
Normalise(view);
if(R.wrld.aocolor==WO_AOSKYCOL) {
- fac= 0.5*(1.0+view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2]);
- shadfac[0]+= (1.0-fac)*R.wrld.horr + fac*R.wrld.zenr;
- shadfac[1]+= (1.0-fac)*R.wrld.horg + fac*R.wrld.zeng;
- shadfac[2]+= (1.0-fac)*R.wrld.horb + fac*R.wrld.zenb;
+ fac= 0.5*(1.0f+view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2]);
+ shadfac[0]+= (1.0f-fac)*R.wrld.horr + fac*R.wrld.zenr;
+ shadfac[1]+= (1.0f-fac)*R.wrld.horg + fac*R.wrld.zeng;
+ shadfac[2]+= (1.0f-fac)*R.wrld.horb + fac*R.wrld.zenb;
}
else { /* WO_AOSKYTEX */
- shadeSkyPixelFloat(skycol, isec.start, view, dxyview);
+ shadeSkyView(skycol, isec.start, view, dxyview);
shadfac[0]+= skycol[0];
shadfac[1]+= skycol[1];
shadfac[2]+= skycol[2];
@@ -2214,16 +2244,19 @@ void ray_ao(ShadeInput *shi, float *shadfac)
vec+= 3;
}
- if(actual==0) shadfac[3]= 1.0;
- else shadfac[3] = 1.0 - sh/((float)actual);
+ if(actual==0) sh= 1.0f;
+ else sh = 1.0f - sh/((float)actual);
if(R.wrld.aocolor!=WO_AOPLAIN && skyadded) {
- div= shadfac[3]/((float)skyadded);
+ div= sh/((float)skyadded);
shadfac[0]*= div; // average color times distances/hits formula
shadfac[1]*= div; // average color times distances/hits formula
shadfac[2]*= div; // average color times distances/hits formula
}
+ else {
+ shadfac[0]= shadfac[1]= shadfac[2]= sh;
+ }
}
@@ -2259,7 +2292,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
if(lar->ray_totsamp<2) {
isec.vlrorig= shi->vlr;
- shadfac[3]= 1.0; // 1.0=full light
+ shadfac[3]= 1.0f; // 1.0=full light
/* set up isec vec */
VECCOPY(isec.start, shi->co);
@@ -2267,27 +2300,27 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
if(isec.mode==DDA_SHADOW_TRA) {
/* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */
- isec.col[0]= isec.col[1]= isec.col[2]= 1.0;
- isec.col[3]= 1.0;
+ isec.col[0]= isec.col[1]= isec.col[2]= 1.0f;
+ isec.col[3]= 1.0f;
ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA, 0);
QUATCOPY(shadfac, isec.col);
//printf("shadfac %f %f %f %f\n", shadfac[0], shadfac[1], shadfac[2], shadfac[3]);
}
- else if( d3dda(&isec)) shadfac[3]= 0.0;
+ else if( d3dda(&isec)) shadfac[3]= 0.0f;
}
else {
/* area soft shadow */
float *jitlamp;
- float fac=0.0, div=0.0, vec[3];
+ float fac=0.0f, div=0.0f, vec[3];
int a, j= -1, mask;
if(isec.mode==DDA_SHADOW_TRA) {
- shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0;
+ shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f;
}
- else shadfac[3]= 1.0; // 1.0=full light
+ else shadfac[3]= 1.0f; // 1.0=full light
- fac= 0.0;
+ fac= 0.0f;
jitlamp= give_jitter_plane(lar, shi->thread, shi->xs, shi->ys);
a= lar->ray_totsamp;
@@ -2312,7 +2345,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
vec[0]= jitlamp[0];
vec[1]= jitlamp[1];
- vec[2]= 0.0;
+ vec[2]= 0.0f;
Mat3MulVecfl(lar->mat, vec);
/* set start and end, d3dda clips it */
@@ -2323,8 +2356,8 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
if(isec.mode==DDA_SHADOW_TRA) {
/* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */
- isec.col[0]= isec.col[1]= isec.col[2]= 1.0;
- isec.col[3]= 1.0;
+ isec.col[0]= isec.col[1]= isec.col[2]= 1.0f;
+ isec.col[3]= 1.0f;
ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA, 0);
shadfac[0] += isec.col[0];
@@ -2332,9 +2365,9 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
shadfac[2] += isec.col[2];
shadfac[3] += isec.col[3];
}
- else if( d3dda(&isec) ) fac+= 1.0;
+ else if( d3dda(&isec) ) fac+= 1.0f;
- div+= 1.0;
+ div+= 1.0f;
jitlamp+= 2;
}
@@ -2347,9 +2380,9 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
else {
// sqrt makes nice umbra effect
if(lar->ray_samp_type & LA_SAMP_UMBRA)
- shadfac[3]= sqrt(1.0-fac/div);
+ shadfac[3]= sqrt(1.0f-fac/div);
else
- shadfac[3]= 1.0-fac/div;
+ shadfac[3]= 1.0f-fac/div;
}
}
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 23777cea0f2..7416d6c7545 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -30,13 +30,10 @@
#include <stdio.h>
#include <math.h>
#include <string.h>
-#include <stdlib.h>
/* External modules: */
#include "MEM_guardedalloc.h"
-#include "MTC_matrixops.h"
-
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "BLI_jitter.h"
@@ -45,17 +42,12 @@
#include "BKE_utildefines.h"
-#include "DNA_group_types.h"
#include "DNA_image_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
-#include "DNA_texture_types.h"
#include "BKE_global.h"
-#include "BKE_material.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_texture.h"
@@ -69,12 +61,10 @@
#include "renderdatabase.h"
#include "pixelblending.h"
#include "pixelshading.h"
-#include "gammaCorrectionTables.h"
#include "shadbuf.h"
+#include "shading.h"
#include "zbuf.h"
-#include "texture.h"
-
#include "PIL_time.h"
/* own include */
@@ -120,305 +110,36 @@ void calc_view_vector(float *view, float x, float y)
view[0]= R.panoco*u + R.panosi*v;
view[2]= -R.panosi*u + R.panoco*v;
}
-
}
}
-#if 0
-static void fogcolor(float *colf, float *rco, float *view)
+void calc_renderco_ortho(float *co, float x, float y, int z)
{
- 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;
-
- VECCOPY(vec, rco);
+ /* x and y 3d coordinate can be derived from pixel coord and winmat */
+ float fx= 2.0f/(R.winx*R.winmat[0][0]);
+ float fy= 2.0f/(R.winy*R.winmat[1][1]);
+ float zco;
- /* we loop from cur coord to mist start in steps */
- stepsize= 1.0f;
+ co[0]= (x - 0.5f*R.winx)*fx - R.winmat[3][0]/R.winmat[0][0];
+ co[1]= (y - 0.5f*R.winy)*fy - R.winmat[3][1]/R.winmat[1][1];
- div= ABS(view[2]);
- dview[0]= view[0]/(stepsize*div);
- dview[1]= view[1]/(stepsize*div);
- dview[2]= -stepsize;
-
- startdist= -rco[2] + BLI_frand();
- for(dist= startdist; dist>R.wrld.miststa; dist-= stepsize) {
-
- 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);
-
- VECSUB(vec, vec, dview);
- }
+ zco= ((float)z)/2147483647.0f;
+ co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] );
}
-#endif
-/* zcor is distance, co the 3d coordinate in eye space, return alpha */
-float mistfactor(float zcor, float *co)
+void calc_renderco_zbuf(float *co, float *view, int z)
{
- float fac, hi;
+ float fac, zco;
- fac= zcor - R.wrld.miststa; /* zcor is calculated per pixel */
+ /* inverse of zbuf calc: zbuf = MAXZ*hoco_z/hoco_w */
+ zco= ((float)z)/2147483647.0f;
+ co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] );
- /* fac= -co[2]-R.wrld.miststa; */
-
- if(fac>0.0) {
- if(fac< R.wrld.mistdist) {
-
- fac= (fac/(R.wrld.mistdist));
-
- if(R.wrld.mistype==0) fac*= fac;
- else if(R.wrld.mistype==1);
- else fac= sqrt(fac);
- }
- else fac= 1.0;
- }
- else fac= 0.0;
-
- /* height switched off mist */
- if(R.wrld.misthi!=0.0 && fac!=0.0) {
- /* at height misthi the mist is completely gone */
-
- hi= R.viewinv[0][2]*co[0]+R.viewinv[1][2]*co[1]+R.viewinv[2][2]*co[2]+R.viewinv[3][2];
-
- if(hi>R.wrld.misthi) fac= 0.0;
- else if(hi>0.0) {
- hi= (R.wrld.misthi-hi)/R.wrld.misthi;
- fac*= hi*hi;
- }
- }
-
- return (1.0-fac)* (1.0-R.wrld.misi);
+ fac= co[2]/view[2];
+ co[0]= fac*view[0];
+ co[1]= fac*view[1];
}
-static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens)
-{
- double a, b, c, disc, nray[3], npos[3];
- float t0, t1 = 0.0, t2= 0.0, t3, haint;
- float p1[3], p2[3], ladist, maxz = 0.0, maxy = 0.0;
- int snijp, doclip=1, use_yco=0;
- int ok1=0, ok2=0;
-
- *intens= 0.0;
- haint= lar->haint;
-
- if(R.r.mode & R_ORTHO) {
- /* 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];
- MTC_Mat3MulVecfl(lar->imat, p1);
- VECCOPY(npos, p1); // npos is double!
- }
- else {
- VECCOPY(npos, lar->sh_invcampos); /* in initlamp calculated */
- }
-
- /* rotate view */
- VECCOPY(nray, shi->view);
- MTC_Mat3MulVecd(lar->imat, nray);
-
- if(R.wrld.mode & WO_MIST) {
- /* patchy... */
- haint *= mistfactor(-lar->co[2], lar->co);
- if(haint==0.0) {
- return;
- }
- }
-
-
- /* rotate maxz */
- if(shi->co[2]==0.0) doclip= 0; /* for when halo at sky */
- 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];
-
- if( fabs(nray[2]) <0.000001 ) use_yco= 1;
- }
-
- /* scale z to make sure volume is normalized */
- nray[2]*= lar->sh_zfac;
- /* 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];
-
- snijp= 0;
- if (fabs(a) < 0.00000001) {
- /*
- * Only one intersection point...
- */
- return;
- }
- else {
- disc = b*b - a*c;
-
- if(disc==0.0) {
- t1=t2= (-b)/ a;
- snijp= 2;
- }
- else if (disc > 0.0) {
- disc = sqrt(disc);
- t1 = (-b + disc) / a;
- t2 = (-b - disc) / a;
- snijp= 2;
- }
- }
- if(snijp==2) {
- /* sort */
- if(t1>t2) {
- 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 */
- if(p1[2]<=0.0) ok1= 1;
- if(p2[2]<=0.0 && t1!=t2) ok2= 1;
-
- /* at least 1 point with negative z */
- if(ok1==0 && ok2==0) return;
-
- /* intersction point with -ladist, the bottom of the cone */
- if(use_yco==0) {
- t3= (-ladist-npos[2])/nray[2];
-
- /* de we have to replace one of the intersection points? */
- if(ok1) {
- if(p1[2]<-ladist) t1= t3;
- }
- else {
- ok1= 1;
- t1= t3;
- }
- if(ok2) {
- if(p2[2]<-ladist) t2= t3;
- }
- else {
- ok2= 1;
- t2= t3;
- }
- }
- else if(ok1==0 || ok2==0) return;
-
- /* at least 1 visible interesction point */
- if(t1<0.0 && t2<0.0) return;
-
- if(t1<0.0) t1= 0.0;
- if(t2<0.0) t2= 0.0;
-
- if(t1==t2) return;
-
- /* sort again to be sure */
- if(t1>t2) {
- a= t1; t1= t2; t2= a;
- }
-
- /* calculate t0: is the maximum visible z (when halo is intersected by face) */
- if(doclip) {
- if(use_yco==0) t0= (maxz-npos[2])/nray[2];
- else t0= (maxy-npos[1])/nray[1];
-
- if(t0<t1) return;
- if(t0<t2) t2= t0;
- }
-
- /* 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 */
-
- a= sqrt(p1[0]*p1[0]+p1[1]*p1[1]+p1[2]*p1[2]);
- b= sqrt(p2[0]*p2[0]+p2[1]*p2[1]+p2[2]*p2[2]);
- c= VecLenf(p1, p2);
-
- 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
- at the edges (especially with narrow halos) */
- if(*intens<=0.0) return;
-
- /* soft area */
- /* not needed because t0 has been used for p1/p2 as well */
- /* if(doclip && t0<t2) { */
- /* *intens *= (t0-t1)/(t2-t1); */
- /* } */
-
- *intens *= haint;
-
- if(lar->shb && lar->shb->shadhalostep) {
- *intens *= shadow_halo(lar, p1, p2);
- }
-
- }
-}
-
-static void renderspothalo(ShadeInput *shi, float *col, float alpha)
-{
- GroupObject *go;
- LampRen *lar;
- float i;
-
- if(alpha==0.0f) return;
-
- for(go=R.lights.first; go; go= go->next) {
- lar= go->lampren;
-
- if(lar->type==LA_SPOT && (lar->mode & LA_HALO) && lar->haint>0) {
- if((lar->lay & shi->lay)==0) continue;
-
- spothalo(lar, shi, &i);
- if(i>0.0) {
- col[3]+= i*alpha; // all premul
- col[0]+= i*lar->r*alpha;
- col[1]+= i*lar->g*alpha;
- col[2]+= i*lar->b*alpha;
- }
- }
- }
- /* clip alpha, is needed for unified 'alpha threshold' (vanillaRenderPipe.c) */
- if(col[3]>1.0) col[3]= 1.0;
-}
-
-
-
/* also used in zbuf.c and shadbuf.c */
int count_mask(unsigned short mask)
{
@@ -445,7 +166,7 @@ static void halo_pixelstruct(HaloRen *har, float *rb, float dist, float xn, floa
int amount, amountm, zz, flarec;
amount= 0;
- accol[0]=accol[1]=accol[2]=accol[3]= 0.0;
+ accol[0]=accol[1]=accol[2]=accol[3]= 0.0f;
flarec= har->flarec;
while(ps) {
@@ -569,7 +290,7 @@ static void halo_tile(RenderPart *pa, float *pass, unsigned int lay)
static void lamphalo_tile(RenderPart *pa, float *pass, unsigned int lay)
{
ShadeInput shi;
- float zco, fac;
+ float fac;
long *rd= pa->rectdaps;
int x, y, *rz= pa->rectz;
@@ -585,13 +306,10 @@ static void lamphalo_tile(RenderPart *pa, float *pass, unsigned int lay)
int samp, totsamp= 0;
while(ps) {
- /* inverse of zbuf calc: zbuf = MAXZ*hoco_z/hoco_w */
- zco= ((float)ps->z)/2147483647.0f;
- shi.co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] );
-
- fac= shi.co[2]/shi.view[2];
- shi.co[0]= fac*shi.view[0];
- shi.co[1]= fac*shi.view[1];
+ if(R.r.mode & R_ORTHO)
+ calc_renderco_ortho(shi.co, (float)x, (float)y, ps->z);
+ else
+ calc_renderco_zbuf(shi.co, shi.view, ps->z);
totsamp+= samp= count_mask(ps->mask);
fac= ((float)samp)/(float)R.osa;
@@ -606,14 +324,12 @@ static void lamphalo_tile(RenderPart *pa, float *pass, unsigned int lay)
}
else {
- /* inverse of zbuf calc: zbuf = MAXZ*hoco_z/hoco_w */
- zco= ((float)*rz)/2147483647.0f;
- zco= shi.co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] );
- fac= shi.co[2]/shi.view[2];
- shi.co[0]= fac*shi.view[0];
- shi.co[1]= fac*shi.view[1];
+ if(R.r.mode & R_ORTHO)
+ calc_renderco_ortho(shi.co, (float)x, (float)y, *rz);
+ else
+ calc_renderco_zbuf(shi.co, shi.view, *rz);
- renderspothalo(&shi, pass, 1.0);
+ renderspothalo(&shi, pass, 1.0f);
}
if(rd) rd++;
@@ -623,2223 +339,6 @@ static void lamphalo_tile(RenderPart *pa, float *pass, unsigned int lay)
}
}
-/* ---------------- shaders ----------------------- */
-
-static double Normalise_d(double *n)
-{
- double d;
-
- d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
-
- if(d>0.00000000000000001) {
- d= sqrt(d);
-
- n[0]/=d;
- n[1]/=d;
- n[2]/=d;
- } else {
- n[0]=n[1]=n[2]= 0.0;
- d= 0.0;
- }
- return d;
-}
-
-/* mix of 'real' fresnel and allowing control. grad defines blending gradient */
-float fresnel_fac(float *view, float *vn, float grad, float fac)
-{
- float t1, t2;
-
- if(fac==0.0) return 1.0;
-
- t1= (view[0]*vn[0] + view[1]*vn[1] + view[2]*vn[2]);
- if(t1>0.0) t2= 1.0+t1;
- else t2= 1.0-t1;
-
- t2= grad + (1.0-grad)*pow(t2, fac);
-
- if(t2<0.0) return 0.0;
- else if(t2>1.0) return 1.0;
- return t2;
-}
-
-static double saacos_d(double fac)
-{
- if(fac<= -1.0f) return M_PI;
- else if(fac>=1.0f) return 0.0;
- else return acos(fac);
-}
-
-/* Stoke's form factor. Need doubles here for extreme small area sizes */
-static float area_lamp_energy(float *co, float *vn, LampRen *lar)
-{
- 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 */
-
- VECSUB(vec[0], co, lar->area[0]);
- VECSUB(vec[1], co, lar->area[1]);
- VECSUB(vec[2], co, lar->area[2]);
- VECSUB(vec[3], co, lar->area[3]);
-
- Normalise_d(vec[0]);
- Normalise_d(vec[1]);
- Normalise_d(vec[2]);
- Normalise_d(vec[3]);
-
- /* cross product */
- 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]);
-
- Normalise_d(cross[0]);
- Normalise_d(cross[1]);
- Normalise_d(cross[2]);
- Normalise_d(cross[3]);
-
- /* 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]);
-
- if(fac<=0.0) return 0.0;
- return pow(fac*lar->areasize, lar->k); // corrected for buttons size and lar->dist^2
-}
-
-static float spec(float inp, int hard)
-{
- float b1;
-
- if(inp>=1.0) return 1.0;
- else if (inp<=0.0) return 0.0;
-
- b1= inp*inp;
- /* avoid FPE */
- if(b1<0.01) b1= 0.01;
-
- if((hard & 1)==0) inp= 1.0;
- if(hard & 2) inp*= b1;
- b1*= b1;
- if(hard & 4) inp*= b1;
- b1*= b1;
- if(hard & 8) inp*= b1;
- b1*= b1;
- if(hard & 16) inp*= b1;
- b1*= b1;
-
- /* avoid FPE */
- if(b1<0.001) b1= 0.0;
-
- if(hard & 32) inp*= b1;
- b1*= b1;
- if(hard & 64) inp*=b1;
- b1*= b1;
- if(hard & 128) inp*=b1;
-
- if(b1<0.001) b1= 0.0;
-
- if(hard & 256) {
- b1*= b1;
- inp*=b1;
- }
-
- return inp;
-}
-
-static float Phong_Spec( float *n, float *l, float *v, int hard, int tangent )
-{
- float h[3];
- float rslt;
-
- h[0] = l[0] + v[0];
- h[1] = l[1] + v[1];
- h[2] = l[2] + v[2];
- Normalise(h);
-
- rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2];
- if(tangent) rslt= sasqrt(1.0 - rslt*rslt);
-
- if( rslt > 0.0 ) rslt= spec(rslt, hard);
- else rslt = 0.0;
-
- return rslt;
-}
-
-
-/* reduced cook torrance spec (for off-specular peak) */
-static float CookTorr_Spec(float *n, float *l, float *v, int hard, int tangent)
-{
- float i, nh, nv, h[3];
-
- h[0]= v[0]+l[0];
- h[1]= v[1]+l[1];
- h[2]= v[2]+l[2];
- Normalise(h);
-
- nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2];
- if(tangent) nh= sasqrt(1.0 - nh*nh);
- else if(nh<0.0) return 0.0;
-
- nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2];
- if(tangent) nv= sasqrt(1.0 - nv*nv);
- else if(nv<0.0) nv= 0.0;
-
- i= spec(nh, hard);
-
- i= i/(0.1+nv);
- return i;
-}
-
-/* Blinn spec */
-static float Blinn_Spec(float *n, float *l, float *v, float refrac, float spec_power, int tangent)
-{
- float i, nh, nv, nl, vh, h[3];
- float a, b, c, g=0.0, p, f, ang;
-
- if(refrac < 1.0) return 0.0;
- if(spec_power == 0.0) return 0.0;
-
- /* conversion from 'hardness' (1-255) to 'spec_power' (50 maps at 0.1) */
- if(spec_power<100.0)
- spec_power= sqrt(1.0/spec_power);
- else spec_power= 10.0/spec_power;
-
- h[0]= v[0]+l[0];
- h[1]= v[1]+l[1];
- h[2]= v[2]+l[2];
- Normalise(h);
-
- nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
- if(tangent) nh= sasqrt(1.0f - nh*nh);
- else if(nh<0.0) return 0.0;
-
- nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
- if(tangent) nv= sasqrt(1.0f - nv*nv);
- if(nv<=0.01) nv= 0.01; /* hrms... */
-
- nl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
- if(tangent) nl= sasqrt(1.0f - nl*nl);
- if(nl<=0.01) {
- return 0.0;
- }
-
- vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; /* Dot product between view vector and half-way vector */
- if(vh<=0.0) vh= 0.01;
-
- a = 1.0;
- b = (2.0*nh*nv)/vh;
- c = (2.0*nh*nl)/vh;
-
- if( a < b && a < c ) g = a;
- else if( b < a && b < c ) g = b;
- else if( c < a && c < b ) g = c;
-
- p = sqrt( (double)((refrac * refrac)+(vh*vh)-1.0) );
- f = (((p-vh)*(p-vh))/((p+vh)*(p+vh)))*(1+((((vh*(p+vh))-1.0)*((vh*(p+vh))-1.0))/(((vh*(p-vh))+1.0)*((vh*(p-vh))+1.0))));
- ang = saacos(nh);
-
- i= f * g * exp((double)(-(ang*ang) / (2.0*spec_power*spec_power)));
- if(i<0.0) i= 0.0;
-
- return i;
-}
-
-/* cartoon render spec */
-static float Toon_Spec( float *n, float *l, float *v, float size, float smooth, int tangent)
-{
- 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];
- Normalise(h);
-
- rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2];
- if(tangent) rslt = sasqrt(1.0f - rslt*rslt);
-
- ang = saacos( rslt );
-
- if( ang < size ) rslt = 1.0;
- else if( ang >= (size + smooth) || smooth == 0.0 ) rslt = 0.0;
- else rslt = 1.0 - ((ang - size) / smooth);
-
- return rslt;
-}
-
-/* Ward isotropic gaussian spec */
-static float WardIso_Spec( float *n, float *l, float *v, float rms, int tangent)
-{
- 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];
- Normalise(h);
-
- nh = n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
- if(tangent) nh = sasqrt(1.0f - nh*nh);
- if(nh<=0.0) nh = 0.001f;
-
- nv = n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
- if(tangent) nv = sasqrt(1.0f - nv*nv);
- if(nv<=0.0) nv = 0.001f;
-
- nl = n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
- if(tangent) nl = sasqrt(1.0f - nl*nl);
- if(nl<=0.0) nl = 0.001;
-
- angle = tan(saacos(nh));
- alpha = MAX2(rms,0.001);
-
- i= nl * (1.0/(4*M_PI*alpha*alpha)) * (exp( -(angle*angle)/(alpha*alpha))/(sqrt(nv*nl)));
-
- return i;
-}
-
-/* cartoon render diffuse */
-static float Toon_Diff( float *n, float *l, float *v, float size, float smooth )
-{
- float rslt, ang;
-
- rslt = n[0]*l[0] + n[1]*l[1] + n[2]*l[2];
-
- ang = saacos( (double)(rslt) );
-
- if( ang < size ) rslt = 1.0;
- else if( ang >= (size + smooth) || smooth == 0.0 ) rslt = 0.0;
- else rslt = 1.0 - ((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' */
-static float OrenNayar_Diff(float nl, float *n, float *l, float *v, float rough )
-{
- float i, nh, nv, vh, realnl, h[3];
- 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];
- Normalise(h);
-
- nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
- if(nh<0.0) nh = 0.0;
-
- nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
- if(nv<=0.0) nv= 0.0;
-
- realnl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
- if(realnl<=0.0) return 0.0;
- if(nl<0.0) return 0.0; /* value from area light */
-
- vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; /* Dot product between view vector and halfway vector */
- if(vh<=0.0) vh= 0.0;
-
- 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]);
- Normalise( Lit_B );
-
- View_B[0] = v[0] - (nv * n[0]);
- View_B[1] = v[1] - (nv * n[1]);
- View_B[2] = v[2] - (nv * n[2]);
- Normalise( View_B );
-
- t = Lit_B[0]*View_B[0] + Lit_B[1]*View_B[1] + Lit_B[2]*View_B[2];
- if( t < 0 ) t = 0;
-
- if( Lit_A > View_A ) {
- a = Lit_A;
- b = View_A;
- }
- else {
- a = View_A;
- b = Lit_A;
- }
-
- A = 1 - (0.5 * ((rough * rough) / ((rough * rough) + 0.33)));
- B = 0.45 * ((rough * rough) / ((rough * rough) + 0.09));
-
- b*= 0.95; /* 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 */
- i = nl * ( A + ( B * t * sin(a) * tan(b) ) );
-
- return i;
-}
-
-/* Minnaert diffuse */
-static float Minnaert_Diff(float nl, float *n, float *v, float darkness)
-{
-
- float i, nv;
-
- /* nl = dot product between surface normal and light vector */
- if (nl <= 0.0)
- return 0;
-
- /* nv = dot product between surface normal and view vector */
- nv = n[0]*v[0]+n[1]*v[1]+n[2]*v[2];
- if (nv < 0.0)
- nv = 0;
-
- if (darkness <= 1)
- i = nl * pow(MAX2(nv*nl, 0.1), (darkness - 1) ); /*The Real model*/
- else
- i = nl * pow( (1.001 - nv), (darkness - 1) ); /*Nvidia model*/
-
- return i;
-}
-
-static float Fresnel_Diff(float *vn, float *lv, float *view, float fac_i, float fac)
-{
- 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]);
- if(shi->osatex) {
- if(shi->vlr->flag & R_SMOOTH) {
- 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]);
- }
- }
-
-}
-
-/* called from ray.c */
-void shade_color(ShadeInput *shi, ShadeResult *shr)
-{
- Material *ma= shi->mat;
-
- if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
- shi->r= shi->vcol[0];
- shi->g= shi->vcol[1];
- shi->b= shi->vcol[2];
- }
-
- if(ma->texco) {
- if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
- shi->r= shi->vcol[0];
- shi->g= shi->vcol[1];
- shi->b= shi->vcol[2];
- }
- do_material_tex(shi);
- }
-
- if(ma->fresnel_tra!=0.0)
- shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra);
-
- shr->diff[0]= shi->r;
- shr->diff[1]= shi->g;
- shr->diff[2]= shi->b;
- shr->alpha= shi->alpha;
-}
-
-/* ramp for at end of shade */
-static void ramp_diffuse_result(float *diff, ShadeInput *shi)
-{
- Material *ma= shi->mat;
- float col[4], fac=0;
-
- if(ma->ramp_col) {
- if(ma->rampin_col==MA_RAMP_IN_RESULT) {
-
- fac= 0.3*diff[0] + 0.58*diff[1] + 0.12*diff[2];
- do_colorband(ma->ramp_col, fac, col);
-
- /* blending method */
- fac= col[3]*ma->rampfac_col;
-
- ramp_blend(ma->rampblend_col, diff, diff+1, diff+2, fac, col);
- }
- }
-}
-
-/* r,g,b denote energy, ramp is used with different values to make new material color */
-static void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, float g, float b)
-{
- Material *ma= shi->mat;
- float col[4], colt[3], fac=0;
-
- if(ma->ramp_col && (ma->mode & MA_RAMP_COL)) {
-
- /* MA_RAMP_IN_RESULT is exceptional */
- if(ma->rampin_col==MA_RAMP_IN_RESULT) {
- // normal add
- diff[0] += r * shi->r;
- diff[1] += g * shi->g;
- diff[2] += b * shi->b;
- }
- else {
- /* input */
- switch(ma->rampin_col) {
- case MA_RAMP_IN_ENERGY:
- fac= 0.3*r + 0.58*g + 0.12*b;
- 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;
- }
-
- do_colorband(ma->ramp_col, fac, col);
-
- /* blending method */
- fac= col[3]*ma->rampfac_col;
- colt[0]= shi->r;
- colt[1]= shi->g;
- colt[2]= shi->b;
-
- ramp_blend(ma->rampblend_col, colt, colt+1, colt+2, fac, col);
-
- /* output to */
- diff[0] += r * colt[0];
- diff[1] += g * colt[1];
- diff[2] += b * colt[2];
- }
- }
- else {
- diff[0] += r * shi->r;
- diff[1] += g * shi->g;
- diff[2] += b * shi->b;
- }
-}
-
-static void ramp_spec_result(float *specr, float *specg, float *specb, ShadeInput *shi)
-{
- Material *ma= shi->mat;
- float col[4];
- float fac;
-
- if(ma->ramp_spec && (ma->rampin_spec==MA_RAMP_IN_RESULT)) {
- fac= 0.3*(*specr) + 0.58*(*specg) + 0.12*(*specb);
- do_colorband(ma->ramp_spec, fac, col);
-
- /* blending method */
- fac= col[3]*ma->rampfac_spec;
-
- ramp_blend(ma->rampblend_spec, specr, specg, specb, fac, col);
-
- }
-}
-
-/* is = dot product shade, t = spec energy */
-static void do_specular_ramp(ShadeInput *shi, float is, float t, float *spec)
-{
- Material *ma= shi->mat;
- float col[4];
- float fac=0.0;
-
- spec[0]= shi->specr;
- spec[1]= shi->specg;
- spec[2]= shi->specb;
-
- /* MA_RAMP_IN_RESULT is exception */
- if(ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) {
-
- /* input */
- switch(ma->rampin_spec) {
- 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;
- }
-
- do_colorband(ma->ramp_spec, fac, col);
-
- /* blending method */
- fac= col[3]*ma->rampfac_spec;
-
- ramp_blend(ma->rampblend_spec, spec, spec+1, spec+2, fac, col);
- }
-}
-
-
-
-static void ambient_occlusion(ShadeInput *shi, ShadeResult *shr)
-{
- float f, shadfac[4];
-
- if((R.wrld.mode & WO_AMB_OCC) && (R.r.mode & R_RAYTRACE) && shi->amb!=0.0) {
- ray_ao(shi, shadfac);
-
- if(R.wrld.aocolor==WO_AOPLAIN) {
- if (R.wrld.aomix==WO_AOADDSUB) shadfac[3] = 2.0*shadfac[3]-1.0;
- else if (R.wrld.aomix==WO_AOSUB) shadfac[3] = shadfac[3]-1.0;
-
- f= R.wrld.aoenergy*shadfac[3]*shi->amb;
- shr->ao[0]+= f;
- shr->ao[1]+= f;
- shr->ao[2]+= f;
- }
- else {
- if (R.wrld.aomix==WO_AOADDSUB) {
- shadfac[0] = 2.0*shadfac[0]-1.0;
- shadfac[1] = 2.0*shadfac[1]-1.0;
- shadfac[2] = 2.0*shadfac[2]-1.0;
- }
- else if (R.wrld.aomix==WO_AOSUB) {
- shadfac[0] = shadfac[0]-1.0;
- shadfac[1] = shadfac[1]-1.0;
- shadfac[2] = shadfac[2]-1.0;
- }
- f= R.wrld.aoenergy*shi->amb;
- shr->ao[0]+= f*shadfac[0];
- shr->ao[1]+= f*shadfac[1];
- shr->ao[2]+= f*shadfac[2];
- }
- }
-}
-
-/* function returns diff, spec and optional shadow */
-/* if passrender it returns shadow color, otherwise it applies it to diffuse and spec */
-static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int passrender)
-{
- Material *ma= shi->mat;
- VlakRen *vlr= shi->vlr;
- float lv[3], lampdist, ld= 1.0f, lacol[3], shadfac[4];
- float i, is, inp, i_noshad, *vn, *view, vnor[3], phongcorr=1.0f;
-
- vn= shi->vn;
- view= shi->view;
-
- /* lampdist calculation */
- if(lar->type==LA_SUN || lar->type==LA_HEMI) {
- VECCOPY(lv, lar->vec);
- lampdist= 1.0;
- }
- else {
- lv[0]= shi->co[0]-lar->co[0];
- lv[1]= shi->co[1]-lar->co[1];
- lv[2]= shi->co[2]-lar->co[2];
- ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
- lv[0]/= ld;
- lv[1]/= ld;
- lv[2]/= ld;
-
- /* ld is re-used further on (texco's) */
- if(lar->type==LA_AREA) {
- lampdist= 1.0;
- }
- else {
- if(lar->mode & LA_QUAD) {
- float t= 1.0;
- if(lar->ld1>0.0)
- t= lar->dist/(lar->dist+lar->ld1*ld);
- if(lar->ld2>0.0)
- t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld);
-
- lampdist= t;
- }
- else {
- lampdist= (lar->dist/(lar->dist+ld));
- }
-
- if(lar->mode & LA_SPHERE) {
- float t= lar->dist - ld;
- if(t<0.0) return;
-
- t/= lar->dist;
- lampdist*= (t);
- }
- }
- }
-
- lacol[0]= lar->r;
- lacol[1]= lar->g;
- lacol[2]= lar->b;
-
- if(lar->type==LA_SPOT) {
- float t, inpr;
-
- if(lar->mode & LA_SQUARE) {
- if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) {
- float lvrot[3], x;
-
- /* rotate view to lampspace */
- VECCOPY(lvrot, lv);
- MTC_Mat3MulVecfl(lar->imat, lvrot);
-
- x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
- /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
-
- inpr= 1.0f/(sqrt(1.0f+x*x));
- }
- else inpr= 0.0;
- }
- else {
- inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
- }
-
- t= lar->spotsi;
- if(inpr<t) return;
- else {
- t= inpr-t;
- i= 1.0;
- if(t<lar->spotbl && lar->spotbl!=0.0) {
- /* soft area */
- i= t/lar->spotbl;
- t= i*i;
- inpr*= (3.0*t-2.0*t*i);
- }
- lampdist*=inpr;
- }
-
- if(lar->mode & LA_OSATEX) {
- shi->osatex= 1; /* signal for multitex() */
-
- shi->dxlv[0]= lv[0] - (shi->co[0]-lar->co[0]+shi->dxco[0])/ld;
- shi->dxlv[1]= lv[1] - (shi->co[1]-lar->co[1]+shi->dxco[1])/ld;
- shi->dxlv[2]= lv[2] - (shi->co[2]-lar->co[2]+shi->dxco[2])/ld;
-
- shi->dylv[0]= lv[0] - (shi->co[0]-lar->co[0]+shi->dyco[0])/ld;
- shi->dylv[1]= lv[1] - (shi->co[1]-lar->co[1]+shi->dyco[1])/ld;
- shi->dylv[2]= lv[2] - (shi->co[2]-lar->co[2]+shi->dyco[2])/ld;
- }
-
- }
-
- if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv, shi, lacol);
-
- /* dot product and reflectivity */
- /* inp = dotproduct, is = shader result, i = lamp energy (with shadow) */
-
- /* tangent case; calculate fake face normal, aligned with lampvector */
- if(vlr->flag & R_TANGENT) {
- float cross[3];
- Crossf(cross, lv, vn);
- Crossf(vnor, cross, vn);
- vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2];
- vn= vnor;
- }
- else if (ma->mode & MA_TANGENT_V) {
- float cross[3];
- Crossf(cross, lv, shi->tang);
- Crossf(vnor, cross, shi->tang);
- vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2];
- vn= vnor;
- }
-
- inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
-
- /* phong threshold to prevent backfacing faces having artefacts on ray shadow (terminator problem) */
- /* this complex construction screams for a nicer implementation! (ton) */
- if(R.r.mode & R_SHADOW) {
- if(ma->mode & MA_SHADOW) {
- if(lar->type==LA_HEMI);
- else if((ma->mode & MA_RAYBIAS) && (lar->mode & LA_SHAD_RAY) && (vlr->flag & R_SMOOTH)) {
- float thresh= vlr->ob->smoothresh;
- if(inp>thresh)
- phongcorr= (inp-thresh)/(inp*(1.0-thresh));
- else
- phongcorr= 0.0;
- }
- else if(ma->sbias!=0.0f && ((lar->mode & LA_SHAD_RAY) || lar->shb)) {
- if(inp>ma->sbias)
- phongcorr= (inp-ma->sbias)/(inp*(1.0-ma->sbias));
- else
- phongcorr= 0.0;
- }
- }
- }
-
- /* diffuse shaders */
- if(lar->mode & LA_NO_DIFF) {
- is= 0.0; // skip shaders
- }
- else if(lar->type==LA_HEMI) {
- is= 0.5*inp + 0.5;
- }
- else {
-
- if(lar->type==LA_AREA) {
- /* single sided */
- if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) {
- inp= area_lamp_energy(shi->co, vn, lar);
- }
- else inp= 0.0;
- }
-
- /* diffuse shaders (oren nayer gets inp from area light) */
- 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]);
- else is= inp; // Lambert
- }
-
- i= is*phongcorr;
-
- if(i>0.0) {
- i*= lampdist*shi->refl;
- }
- i_noshad= i;
-
- vn= shi->vn; // bring back original vector, we use special specular shaders for tangent
- if(ma->mode & MA_TANGENT_V)
- vn= shi->tang;
-
- /* init transp shadow */
- shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 1.0;
-
- /* shadow and spec, (lampdist==0 outside spot) */
- if(lampdist> 0.0) {
-
- if(i>0.0 && (R.r.mode & R_SHADOW)) {
- if(ma->mode & MA_SHADOW) {
- if(lar->type==LA_HEMI); // no shadow
- else {
- if(lar->shb) {
- if(lar->buftype==LA_SHADBUF_IRREGULAR)
- shadfac[3]= ISB_getshadow(shi, lar->shb);
- else
- shadfac[3] = testshadowbuf(lar->shb, shi->co, shi->dxco, shi->dyco, inp);
- }
- else if(lar->mode & LA_SHAD_RAY) {
- ray_shadow(shi, lar, shadfac);
- }
-
- /* warning, here it skips the loop */
- if(lar->mode & LA_ONLYSHADOW) {
-
- shadfac[3]= i*lar->energy*(1.0-shadfac[3]);
- shr->diff[0] -= shadfac[3]*shi->r;
- shr->diff[1] -= shadfac[3]*shi->g;
- shr->diff[2] -= shadfac[3]*shi->b;
- return;
- }
-
- if(passrender==0)
- if(shadfac[3]==0.0) return;
-
- i*= shadfac[3];
- }
- }
- }
-
- /* in case 'no diffuse' we still do most calculus, spec can be in shadow */
- if(i>0.0 && !(lar->mode & LA_NO_DIFF)) {
- if(ma->mode & MA_SHADOW_TRA)
- add_to_diffuse(shr->diff, shi, is, i*shadfac[0]*lacol[0], i*shadfac[1]*lacol[1], i*shadfac[2]*lacol[2]);
- else
- add_to_diffuse(shr->diff, shi, is, i*lacol[0], i*lacol[1], i*lacol[2]);
- }
- if(passrender && i_noshad>0.0 && !(lar->mode & LA_NO_DIFF)) {
- /* while passrender we store shadowless diffuse in shr->shad, so we can subtract */
- if(ma->mode & MA_SHADOW_TRA)
- add_to_diffuse(shr->shad, shi, is, i_noshad*shadfac[0]*lacol[0], i_noshad*shadfac[1]*lacol[1], i_noshad*shadfac[2]*lacol[2]);
- else
- add_to_diffuse(shr->shad, shi, is, i_noshad*lacol[0], i_noshad*lacol[1], i_noshad*lacol[2]);
- }
-
- /* specularity */
- if(shadfac[3]>0.0 && shi->spec!=0.0 && !(lar->mode & LA_NO_SPEC)) {
-
- if(lar->type==LA_HEMI) {
- float t;
- /* hemi uses no spec shaders (yet) */
-
- lv[0]+= view[0];
- lv[1]+= view[1];
- lv[2]+= view[2];
-
- Normalise(lv);
-
- t= vn[0]*lv[0]+vn[1]*lv[1]+vn[2]*lv[2];
-
- if(lar->type==LA_HEMI) {
- t= 0.5*t+0.5;
- }
-
- 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;
-
- if(ma->spec_shader==MA_SPEC_PHONG)
- specfac= Phong_Spec(vn, lv, view, shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
- else if(ma->spec_shader==MA_SPEC_COOKTORR)
- specfac= CookTorr_Spec(vn, lv, view, shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
- else if(ma->spec_shader==MA_SPEC_BLINN)
- specfac= Blinn_Spec(vn, lv, view, ma->refrac, (float)shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
- else if(ma->spec_shader==MA_SPEC_WARDISO)
- 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 */
- if(lar->type==LA_AREA) specfac*= inp;
-
- t= shadfac[3]*shi->spec*lampdist*specfac;
-
- if(ma->mode & MA_RAMP_SPEC) {
- 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);
- }
- }
- }
- }
-
-}
-
-#if 0
-static void shade_lamp_loop_pass(ShadeInput *shi, ShadeResult *shr, int passflag)
-{
- Material *ma= shi->mat;
- VlakRen *vlr= shi->vlr;
-
- memset(shr, 0, sizeof(ShadeResult));
-
- /* envmap hack, always reset */
- shi->refcol[0]= shi->refcol[1]= shi->refcol[2]= shi->refcol[3]= 0.0f;
-
- /* material color itself */
- if(passflag & (SCE_PASS_COMBINED|SCE_PASS_RGBA)) {
- if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
- shi->r= shi->vcol[0];
- shi->g= shi->vcol[1];
- shi->b= shi->vcol[2];
- }
- if(ma->texco)
- do_material_tex(shi);
-
- shr->col[0]= shi->r;
- shr->col[1]= shi->g;
- shr->col[2]= shi->b;
- }
-
- if(ma->mode & MA_SHLESS) {
- shr->diff[0]= shi->r;
- shr->diff[1]= shi->g;
- shr->diff[2]= shi->b;
- shr->alpha= shi->alpha;
- return;
- }
-
- if( (ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL ) { // vertexcolor light
- shr->diff[0]= shi->r*(shi->emit+shi->vcol[0]);
- shr->diff[1]= shi->g*(shi->emit+shi->vcol[1]);
- shr->diff[2]= shi->b*(shi->emit+shi->vcol[2]);
- }
- else {
- shr->diff[0]= shi->r*shi->emit;
- shr->diff[1]= shi->g*shi->emit;
- shr->diff[2]= shi->b*shi->emit;
- }
-
- /* AO pass */
- if(passflag & (SCE_PASS_COMBINED|SCE_PASS_AO)) {
- ambient_occlusion(shi, shr);
- }
-
- /* lighting pass */
- if(passflag & (SCE_PASS_COMBINED|SCE_PASS_DIFFUSE|SCE_PASS_SPEC|SCE_PASS_SHADOW)) {
- GroupObject *go;
- ListBase *lights;
- LampRen *lar;
- float diff[3];
-
- /* lights */
- if(ma->group)
- lights= &ma->group->gobject;
- else
- lights= &R.lights;
-
- for(go=lights->first; go; go= go->next) {
- lar= go->lampren;
- if(lar==NULL) continue;
-
- /* yafray: ignore shading by photonlights, not used in Blender */
- if (lar->type==LA_YF_PHOTON) continue;
-
- /* test for lamp layer */
- if(lar->mode & LA_LAYER) if((lar->lay & vlr->lay)==0) continue;
- if((lar->lay & shi->lay)==0) continue;
-
- /* accumulates in shr->diff and shr->spec and shr->shad */
- shade_one_light(lar, shi, shr, passflag);
- }
-
- /* calculate shadow */
- VECCOPY(diff, shr->shad);
- VECSUB(shr->shad, shr->shad, shr->diff);
- VECCOPY(shr->diff, diff);
- }
-
- /* alpha in end, spec can influence it */
- if(passflag & (SCE_PASS_COMBINED|SCE_PASS_RGBA)) {
- if(ma->fresnel_tra!=0.0)
- shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra);
-
- if(shi->mode & (MA_ZTRA|MA_RAYTRANSP)) {
- if(shi->spectra!=0.0) {
- float t = MAX3(shr->spec[0], shr->spec[1], shr->spec[2]);
- t *= shi->spectra;
- if(t>1.0) t= 1.0;
- shi->alpha= (1.0-t)*shi->alpha+t;
- }
- }
- shr->col[3]= shi->alpha;
- }
- shr->alpha= shi->alpha;
-
- shr->diff[0]+= shi->ambr + shi->r*shi->amb*shi->rad[0];
- shr->diff[1]+= shi->ambg + shi->g*shi->amb*shi->rad[1];
- shr->diff[2]+= shi->ambb + shi->b*shi->amb*shi->rad[2];
-
- if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(shr->diff, shi);
- if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(shr->spec, shr->spec+1, shr->spec+2, shi);
-
- /* refcol is for envmap only */
- if(shi->refcol[0]!=0.0) {
- shr->diff[0]= shi->mirr*shi->refcol[1] + (1.0 - shi->mirr*shi->refcol[0])*shr->diff[0];
- shr->diff[1]= shi->mirg*shi->refcol[2] + (1.0 - shi->mirg*shi->refcol[0])*shr->diff[1];
- shr->diff[2]= shi->mirb*shi->refcol[3] + (1.0 - shi->mirb*shi->refcol[0])*shr->diff[2];
- }
-
- if(passflag & SCE_PASS_COMBINED) {
- shr->combined[0]= shr->diff[0] + shr->ao[0]*shr->col[0] + shr->spec[0];
- shr->combined[1]= shr->diff[1] + shr->ao[1]*shr->col[1] + shr->spec[1];
- shr->combined[2]= shr->diff[2] + shr->ao[2]*shr->col[2] + shr->spec[2];
- shr->combined[3]= shr->alpha;
- }
-
- if(R.r.mode & R_RAYTRACE) {
-
- if((ma->mode & MA_RAYMIRROR)==0) shi->ray_mirror= 0.0;
-
- if(shi->ray_mirror!=0.0 || ((shi->mat->mode & MA_RAYTRANSP) && shr->alpha!=1.0)) {
- float diff[3];
-
- VECCOPY(diff, shr->diff);
-
- ray_trace(shi, shr);
-
- VECSUB(shr->ray, shr->diff, diff);
- VECCOPY(shr->diff, diff);
- VECADD(shr->combined, shr->combined, shr->ray);
- }
- }
- else {
- /* doesnt look 'correct', but is better for preview, plus envmaps dont raytrace this */
- if(shi->mat->mode & MA_RAYTRANSP) shr->alpha= 1.0;
- }
-}
-#endif
-
-void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
-{
- LampRen *lar;
- GroupObject *go;
- Material *ma= shi->mat;
- VlakRen *vlr= shi->vlr;
- ListBase *lights;
-
- memset(shr, 0, sizeof(ShadeResult));
-
- if((ma->mode & MA_RAYMIRROR)==0) shi->ray_mirror= 0.0;
-
- /* lights */
- if(ma->group)
- lights= &ma->group->gobject;
- else
- lights= &R.lights;
-
- /* separate loop */
- if(ma->mode & MA_ONLYSHADOW) {
- float i, inp, inpr, lv[3];
- float *vn, *view, shadfac[4];
- float t, ir;
-
- vn= shi->vn;
- view= shi->view;
-
- if(R.r.mode & R_SHADOW) {
-
- shadfac[3]= ir= 0.0;
- for(go=lights->first; go; go= go->next) {
- lar= go->lampren;
- if(lar==NULL) continue;
-
- /* yafray: ignore shading by photonlights, not used in Blender */
- if (lar->type==LA_YF_PHOTON) continue;
-
- if(lar->mode & LA_LAYER) if((lar->lay & vlr->lay)==0) continue;
- if((lar->lay & shi->lay)==0) continue;
-
- lv[0]= shi->co[0]-lar->co[0];
- lv[1]= shi->co[1]-lar->co[1];
- lv[2]= shi->co[2]-lar->co[2];
-
- if(lar->type==LA_SPOT) {
- /* only test within spotbundel */
- if(lar->shb || (lar->mode & LA_SHAD_RAY)) {
-
- Normalise(lv);
- inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
- if(inpr>lar->spotsi) {
-
- inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
-
- /* lampbuffer also returns 0.0 on backfacing normals now */
- if(inp <= 0.0f)
- i= 1.0f;
- else {
- if(lar->shb) {
- if(lar->buftype==LA_SHADBUF_IRREGULAR)
- i= ISB_getshadow(shi, lar->shb);
- else
- i = testshadowbuf(lar->shb, shi->co, shi->dxco, shi->dyco, inp);
- }
- else {
- float shad[4];
- ray_shadow(shi, lar, shad);
- i= shad[3];
- }
- }
-
- t= inpr - lar->spotsi;
- if(t<lar->spotbl && lar->spotbl!=0.0) {
- t/= lar->spotbl;
- t*= t;
- i= t*i+(1.0-t);
- }
-
- shadfac[3]+= i;
- ir+= 1.0;
- }
- else {
- shadfac[3]+= 1.0;
- ir+= 1.0;
- }
- }
- }
- else if(lar->mode & LA_SHAD_RAY) {
- float shad[4];
-
- /* single sided? */
- if( shi->facenor[0]*lv[0] + shi->facenor[1]*lv[1] + shi->facenor[2]*lv[2] > -0.01) {
- ray_shadow(shi, lar, shad);
- shadfac[3]+= shad[3];
- ir+= 1.0;
- }
- }
-
- }
- if(ir>0.0) {
- shadfac[3]/= ir;
- shr->alpha= (shi->alpha)*(1.0-shadfac[3]);
- }
- }
-
- if((R.wrld.mode & WO_AMB_OCC) && (R.r.mode & R_RAYTRACE) && shi->amb!=0.0) {
- float f;
-
- ray_ao(shi, shadfac); // shadfac==0: full light
- shadfac[3]= 1.0-shadfac[3];
-
- f= R.wrld.aoenergy*shadfac[3]*shi->amb;
-
- if(R.wrld.aomix==WO_AOADD) {
- shr->alpha += f;
- shr->alpha *= f;
- }
- else if(R.wrld.aomix==WO_AOSUB) {
- shr->alpha += f;
- }
- else {
- shr->alpha *= f;
- shr->alpha += f;
- }
- }
-
- return;
- }
-
- if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
- shi->r= shi->vcol[0];
- shi->g= shi->vcol[1];
- shi->b= shi->vcol[2];
- }
-
- /* envmap hack, always reset */
- shi->refcol[0]= shi->refcol[1]= shi->refcol[2]= shi->refcol[3]= 0.0;
-
- if(ma->texco) {
- if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
- shi->r= shi->vcol[0];
- shi->g= shi->vcol[1];
- shi->b= shi->vcol[2];
- }
- do_material_tex(shi);
- }
-
- if(ma->mode & MA_SHLESS) {
- shr->diff[0]= shi->r;
- shr->diff[1]= shi->g;
- shr->diff[2]= shi->b;
- shr->alpha= shi->alpha;
- return;
- }
-
- if( (ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL ) { // vertexcolor light
- shr->diff[0]= shi->r*(shi->emit+shi->vcol[0]);
- shr->diff[1]= shi->g*(shi->emit+shi->vcol[1]);
- shr->diff[2]= shi->b*(shi->emit+shi->vcol[2]);
- }
- else {
- shr->diff[0]= shi->r*shi->emit;
- shr->diff[1]= shi->g*shi->emit;
- shr->diff[2]= shi->b*shi->emit;
- }
-
- if(R.wrld.mode & WO_AMB_OCC) {
- ambient_occlusion(shi, shr);
- shr->diff[0] += shi->r*shr->ao[0];
- shr->diff[1] += shi->g*shr->ao[1];
- shr->diff[2] += shi->b*shr->ao[2];
- }
-
- for(go=lights->first; go; go= go->next) {
- lar= go->lampren;
- if(lar==NULL) continue;
-
- /* yafray: ignore shading by photonlights, not used in Blender */
- if (lar->type==LA_YF_PHOTON) continue;
-
- /* test for lamp layer */
- if(lar->mode & LA_LAYER) if((lar->lay & vlr->lay)==0) continue;
- if((lar->lay & shi->lay)==0) continue;
-
- /* accumulates in shr->diff and shr->spec, 0= no passrender */
- shade_one_light(lar, shi, shr, 0);
- }
-
- if(ma->fresnel_tra!=0.0)
- shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra);
-
- if(shi->mode & (MA_ZTRA|MA_RAYTRANSP)) {
- if(shi->spectra!=0.0) {
- float t = MAX3(shr->spec[0], shr->spec[1], shr->spec[2]);
- t *= shi->spectra;
- if(t>1.0) t= 1.0;
- shi->alpha= (1.0-t)*shi->alpha+t;
- }
- }
-
- shr->alpha= shi->alpha;
-
- if(shr->spec[0]<0.0f) shr->spec[0]= 0.0f;
- if(shr->spec[1]<0.0f) shr->spec[1]= 0.0f;
- if(shr->spec[2]<0.0f) shr->spec[2]= 0.0f;
-
- shr->diff[0]+= shi->r*shi->amb*shi->rad[0];
- shr->diff[0]+= shi->ambr;
- if(shr->diff[0]<0.0f) shr->diff[0]= 0.0f;
-
- shr->diff[1]+= shi->g*shi->amb*shi->rad[1];
- shr->diff[1]+= shi->ambg;
- if(shr->diff[1]<0.0f) shr->diff[1]= 0.0f;
-
- shr->diff[2]+= shi->b*shi->amb*shi->rad[2];
- shr->diff[2]+= shi->ambb;
- if(shr->diff[2]<0.0f) shr->diff[2]= 0.0f;
-
- if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(shr->diff, shi);
- if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(shr->spec, shr->spec+1, shr->spec+2, shi);
-
- /* refcol is for envmap only */
- if(shi->refcol[0]!=0.0) {
- shr->diff[0]= shi->mirr*shi->refcol[1] + (1.0 - shi->mirr*shi->refcol[0])*shr->diff[0];
- shr->diff[1]= shi->mirg*shi->refcol[2] + (1.0 - shi->mirg*shi->refcol[0])*shr->diff[1];
- shr->diff[2]= shi->mirb*shi->refcol[3] + (1.0 - shi->mirb*shi->refcol[0])*shr->diff[2];
- }
-
-}
-
-static void vlr_set_uv_indices(VlakRen *vlr, int *i1, int *i2, int *i3)
-{
- /* to prevent storing new tfaces or vcols, we check a split runtime */
- /* 4---3 4---3 */
- /* |\ 1| or |1 /| */
- /* |0\ | |/ 0| */
- /* 1---2 1---2 0 = orig face, 1 = new face */
-
- /* Update vert nums to point to correct verts of original face */
- if(vlr->flag & R_DIVIDE_24) {
- if(vlr->flag & R_FACE_SPLIT) {
- (*i1)++; (*i2)++; (*i3)++;
- }
- else {
- (*i3)++;
- }
- }
- else if(vlr->flag & R_FACE_SPLIT) {
- (*i2)++; (*i3)++;
- }
-}
-
-/* this function sets all coords for render (shared with raytracer) */
-/* warning; exception for ortho render is here, can be done better! */
-void shade_input_set_coords(ShadeInput *shi, float u, float v, int i1, int i2, int i3)
-{
- VertRen *v1, *v2, *v3;
- VlakRen *vlr= shi->vlr;
- float l, dl;
- int mode= shi->mode= shi->mat->mode_l; /* or-ed result for all nodes */
- short texco= shi->mat->texco;
- char p1, p2, p3;
-
- /* for rendering of quads, the following values are used to denote vertices:
- 0 1 2 scanline tria & first half quad, and ray tria
- 0 2 3 scanline 2nd half quad
- 0 1 3 raytracer first half quad
- 2 1 3 raytracer 2nd half quad
- */
-
- if(i1==0) {
- v1= vlr->v1;
- p1= ME_FLIPV1;
- } else {
- v1= vlr->v3;
- p1= ME_FLIPV3;
- }
-
- if(i2==1) {
- v2= vlr->v2;
- p2= ME_FLIPV2;
- } else {
- v2= vlr->v3;
- p2= ME_FLIPV3;
- }
-
- if(i3==2) {
- v3= vlr->v3;
- p3= ME_FLIPV3;
- } else {
- v3= vlr->v4;
- p3= ME_FLIPV4;
- }
-
- /* calculate U and V, for scanline (normal u and v are -1 to 0) */
- if(u==1.0) {
- if( (vlr->flag & R_SMOOTH) || (texco & NEED_UV) ) {
- /* exception case for wire render of edge */
- if(vlr->v2==vlr->v3) {
- float lend, lenc;
-
- lend= VecLenf(v2->co, v1->co);
- lenc= VecLenf(shi->co, v1->co);
-
- if(lend==0.0f) {
- u=v= 0.0f;
- }
- else {
- u= - (1.0f - lenc/lend);
- v= 0.0f;
- }
-
- if(shi->osatex) {
- shi->dxuv[0]= 0.0f;
- shi->dxuv[1]= 0.0f;
- shi->dyuv[0]= 0.0f;
- shi->dyuv[1]= 0.0f;
- }
- }
- else {
- float detsh, t00, t10, t01, t11;
-
- if(vlr->snproj==0) {
- t00= v3->co[0]-v1->co[0]; t01= v3->co[1]-v1->co[1];
- t10= v3->co[0]-v2->co[0]; t11= v3->co[1]-v2->co[1];
- }
- else if(vlr->snproj==1) {
- t00= v3->co[0]-v1->co[0]; t01= v3->co[2]-v1->co[2];
- t10= v3->co[0]-v2->co[0]; t11= v3->co[2]-v2->co[2];
- }
- else {
- t00= v3->co[1]-v1->co[1]; t01= v3->co[2]-v1->co[2];
- t10= v3->co[1]-v2->co[1]; t11= v3->co[2]-v2->co[2];
- }
-
- detsh= 1.0/(t00*t11-t10*t01);
- t00*= detsh; t01*=detsh;
- t10*=detsh; t11*=detsh;
-
- if(vlr->snproj==0) {
- u= (shi->co[0]-v3->co[0])*t11-(shi->co[1]-v3->co[1])*t10;
- v= (shi->co[1]-v3->co[1])*t00-(shi->co[0]-v3->co[0])*t01;
- if(shi->osatex) {
- shi->dxuv[0]= shi->dxco[0]*t11- shi->dxco[1]*t10;
- shi->dxuv[1]= shi->dxco[1]*t00- shi->dxco[0]*t01;
- shi->dyuv[0]= shi->dyco[0]*t11- shi->dyco[1]*t10;
- shi->dyuv[1]= shi->dyco[1]*t00- shi->dyco[0]*t01;
- }
- }
- else if(vlr->snproj==1) {
- u= (shi->co[0]-v3->co[0])*t11-(shi->co[2]-v3->co[2])*t10;
- v= (shi->co[2]-v3->co[2])*t00-(shi->co[0]-v3->co[0])*t01;
- if(shi->osatex) {
- shi->dxuv[0]= shi->dxco[0]*t11- shi->dxco[2]*t10;
- shi->dxuv[1]= shi->dxco[2]*t00- shi->dxco[0]*t01;
- shi->dyuv[0]= shi->dyco[0]*t11- shi->dyco[2]*t10;
- shi->dyuv[1]= shi->dyco[2]*t00- shi->dyco[0]*t01;
- }
- }
- else {
- u= (shi->co[1]-v3->co[1])*t11-(shi->co[2]-v3->co[2])*t10;
- v= (shi->co[2]-v3->co[2])*t00-(shi->co[1]-v3->co[1])*t01;
- if(shi->osatex) {
- shi->dxuv[0]= shi->dxco[1]*t11- shi->dxco[2]*t10;
- shi->dxuv[1]= shi->dxco[2]*t00- shi->dxco[1]*t01;
- shi->dyuv[0]= shi->dyco[1]*t11- shi->dyco[2]*t10;
- shi->dyuv[1]= shi->dyco[2]*t00- shi->dyco[1]*t01;
- }
- }
- /* u and v are in range -1 to 0, we allow a little bit extra but not too much, screws up speedvectors */
- CLAMP(u, -2.0f, 1.0f);
- CLAMP(v, -2.0f, 1.0f);
- }
- }
- }
- l= 1.0+u+v;
-
- /* calculate punos (vertexnormals) */
- if(vlr->flag & R_SMOOTH) {
- float n1[3], n2[3], n3[3];
-
- if(shi->puno & p1) {
- n1[0]= -v1->n[0]; n1[1]= -v1->n[1]; n1[2]= -v1->n[2];
- } else {
- n1[0]= v1->n[0]; n1[1]= v1->n[1]; n1[2]= v1->n[2];
- }
- if(shi->puno & p2) {
- n2[0]= -v2->n[0]; n2[1]= -v2->n[1]; n2[2]= -v2->n[2];
- } else {
- n2[0]= v2->n[0]; n2[1]= v2->n[1]; n2[2]= v2->n[2];
- }
-
- if(shi->puno & p3) {
- n3[0]= -v3->n[0]; n3[1]= -v3->n[1]; n3[2]= -v3->n[2];
- } else {
- n3[0]= v3->n[0]; n3[1]= v3->n[1]; n3[2]= v3->n[2];
- }
-
- shi->vn[0]= l*n3[0]-u*n1[0]-v*n2[0];
- shi->vn[1]= l*n3[1]-u*n1[1]-v*n2[1];
- shi->vn[2]= l*n3[2]-u*n1[2]-v*n2[2];
-
- Normalise(shi->vn);
-
- if(shi->osatex && (texco & (TEXCO_NORM|TEXCO_REFL)) ) {
- dl= shi->dxuv[0]+shi->dxuv[1];
- shi->dxno[0]= dl*n3[0]-shi->dxuv[0]*n1[0]-shi->dxuv[1]*n2[0];
- shi->dxno[1]= dl*n3[1]-shi->dxuv[0]*n1[1]-shi->dxuv[1]*n2[1];
- shi->dxno[2]= dl*n3[2]-shi->dxuv[0]*n1[2]-shi->dxuv[1]*n2[2];
- dl= shi->dyuv[0]+shi->dyuv[1];
- shi->dyno[0]= dl*n3[0]-shi->dyuv[0]*n1[0]-shi->dyuv[1]*n2[0];
- shi->dyno[1]= dl*n3[1]-shi->dyuv[0]*n1[1]-shi->dyuv[1]*n2[1];
- shi->dyno[2]= dl*n3[2]-shi->dyuv[0]*n1[2]-shi->dyuv[1]*n2[2];
-
- }
-
- /* qdn: normalmap tangent space separated from shading */
- if (mode & (MA_TANGENT_V|MA_NORMAP_TANG)) {
- float *s1, *s2, *s3;
-
- s1= RE_vertren_get_tangent(&R, v1, 0);
- s2= RE_vertren_get_tangent(&R, v2, 0);
- s3= RE_vertren_get_tangent(&R, v3, 0);
- if(s1 && s2 && s3) {
- shi->tang[0]= (l*s3[0] - u*s1[0] - v*s2[0]);
- shi->tang[1]= (l*s3[1] - u*s1[1] - v*s2[1]);
- shi->tang[2]= (l*s3[2] - u*s1[2] - v*s2[2]);
- /* qdn: normalize just in case */
- Normalise(shi->tang);
- }
- else shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f;
- }
- }
- else {
- VECCOPY(shi->vn, shi->facenor);
- /* qdn: normalmap tangent space separated from shading */
- if (mode & (MA_TANGENT_V|MA_NORMAP_TANG)) {
- /* qdn: flat faces have tangents too,
- could pick either one, using average here */
- float *s1 = RE_vertren_get_tangent(&R, v1, 0);
- float *s2 = RE_vertren_get_tangent(&R, v2, 0);
- float *s3 = RE_vertren_get_tangent(&R, v3, 0);
- if (s1 && s2 && s3) {
- shi->tang[0] = (s1[0] + s2[0] + s3[0]);
- shi->tang[1] = (s1[1] + s2[1] + s3[1]);
- shi->tang[2] = (s1[2] + s2[2] + s3[2]);
- Normalise(shi->tang);
- }
- }
- }
-
- /* used in nodes */
- VECCOPY(shi->vno, shi->vn);
-
- if(R.r.mode & R_SPEED) {
- float *s1, *s2, *s3;
-
- s1= RE_vertren_get_winspeed(&R, v1, 0);
- s2= RE_vertren_get_winspeed(&R, v2, 0);
- s3= RE_vertren_get_winspeed(&R, v3, 0);
- if(s1 && s2 && s3) {
- shi->winspeed[0]= (l*s3[0] - u*s1[0] - v*s2[0]);
- shi->winspeed[1]= (l*s3[1] - u*s1[1] - v*s2[1]);
- shi->winspeed[2]= (l*s3[2] - u*s1[2] - v*s2[2]);
- shi->winspeed[3]= (l*s3[3] - u*s1[3] - v*s2[3]);
- }
- else {
- shi->winspeed[0]= shi->winspeed[1]= shi->winspeed[2]= shi->winspeed[3]= 0.0f;
- }
- }
-
- /* texture coordinates. shi->dxuv shi->dyuv have been set */
- if(texco & NEED_UV) {
- if(texco & TEXCO_ORCO) {
- if(v1->orco) {
- float *o1, *o2, *o3;
-
- o1= v1->orco;
- o2= v2->orco;
- o3= v3->orco;
-
- shi->lo[0]= l*o3[0]-u*o1[0]-v*o2[0];
- shi->lo[1]= l*o3[1]-u*o1[1]-v*o2[1];
- shi->lo[2]= l*o3[2]-u*o1[2]-v*o2[2];
-
- if(shi->osatex) {
- dl= shi->dxuv[0]+shi->dxuv[1];
- shi->dxlo[0]= dl*o3[0]-shi->dxuv[0]*o1[0]-shi->dxuv[1]*o2[0];
- shi->dxlo[1]= dl*o3[1]-shi->dxuv[0]*o1[1]-shi->dxuv[1]*o2[1];
- shi->dxlo[2]= dl*o3[2]-shi->dxuv[0]*o1[2]-shi->dxuv[1]*o2[2];
- dl= shi->dyuv[0]+shi->dyuv[1];
- shi->dylo[0]= dl*o3[0]-shi->dyuv[0]*o1[0]-shi->dyuv[1]*o2[0];
- shi->dylo[1]= dl*o3[1]-shi->dyuv[0]*o1[1]-shi->dyuv[1]*o2[1];
- shi->dylo[2]= dl*o3[2]-shi->dyuv[0]*o1[2]-shi->dyuv[1]*o2[2];
- }
- }
- }
-
- if(texco & TEXCO_GLOB) {
- VECCOPY(shi->gl, shi->co);
- MTC_Mat4MulVecfl(R.viewinv, shi->gl);
- if(shi->osatex) {
- VECCOPY(shi->dxgl, shi->dxco);
- MTC_Mat3MulVecfl(R.imat, shi->dxco);
- VECCOPY(shi->dygl, shi->dyco);
- MTC_Mat3MulVecfl(R.imat, shi->dyco);
- }
- }
- if(texco & TEXCO_STRAND) {
- shi->strand= (l*v3->accum - u*v1->accum - v*v2->accum);
- if(shi->osatex) {
- dl= shi->dxuv[0]+shi->dxuv[1];
- shi->dxstrand= dl*v3->accum-shi->dxuv[0]*v1->accum-shi->dxuv[1]*v2->accum;
- dl= shi->dyuv[0]+shi->dyuv[1];
- shi->dystrand= dl*v3->accum-shi->dyuv[0]*v1->accum-shi->dyuv[1]*v2->accum;
- }
- }
- if((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE))) {
- int j1=i1, j2=i2, j3=i3;
-
- /* uv and vcols are not copied on split, so set them according vlr divide flag */
- vlr_set_uv_indices(vlr, &j1, &j2, &j3);
-
- if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) {
-
- if(vlr->vcol) {
- char *cp1, *cp2, *cp3;
-
- cp1= (char *)(vlr->vcol+j1);
- cp2= (char *)(vlr->vcol+j2);
- cp3= (char *)(vlr->vcol+j3);
-
- shi->vcol[0]= (l*((float)cp3[3]) - u*((float)cp1[3]) - v*((float)cp2[3]))/255.0;
- shi->vcol[1]= (l*((float)cp3[2]) - u*((float)cp1[2]) - v*((float)cp2[2]))/255.0;
- shi->vcol[2]= (l*((float)cp3[1]) - u*((float)cp1[1]) - v*((float)cp2[1]))/255.0;
- }
- else {
- shi->vcol[0]= 0.0;
- shi->vcol[1]= 0.0;
- shi->vcol[2]= 0.0;
- }
- }
- if(vlr->tface) {
- float *uv1, *uv2, *uv3;
-
- uv1= vlr->tface->uv[j1];
- uv2= vlr->tface->uv[j2];
- uv3= vlr->tface->uv[j3];
-
- shi->uv[0]= -1.0 + 2.0*(l*uv3[0]-u*uv1[0]-v*uv2[0]);
- shi->uv[1]= -1.0 + 2.0*(l*uv3[1]-u*uv1[1]-v*uv2[1]);
- shi->uv[2]= 0.0; // texture.c assumes there are 3 coords
-
- if(shi->osatex) {
- float duv[2];
-
- dl= shi->dxuv[0]+shi->dxuv[1];
- duv[0]= shi->dxuv[0];
- duv[1]= shi->dxuv[1];
-
- shi->dxuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
- shi->dxuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
-
- dl= shi->dyuv[0]+shi->dyuv[1];
- duv[0]= shi->dyuv[0];
- duv[1]= shi->dyuv[1];
-
- shi->dyuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
- shi->dyuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
- }
- if(mode & MA_FACETEXTURE) {
- if((mode & (MA_VERTEXCOL|MA_VERTEXCOLP))==0) {
- shi->vcol[0]= 1.0;
- shi->vcol[1]= 1.0;
- shi->vcol[2]= 1.0;
- }
- if(vlr->tface) render_realtime_texture(shi);
- }
- }
- else {
- shi->uv[0]= 2.0*(u+.5);
- shi->uv[1]= 2.0*(v+.5);
- shi->uv[2]= 0.0; // texture.c assumes there are 3 coords
- if(mode & MA_FACETEXTURE) {
- /* no tface? set at 1.0 */
- shi->vcol[0]= 1.0;
- shi->vcol[1]= 1.0;
- shi->vcol[2]= 1.0;
- }
- }
- }
- if(texco & TEXCO_NORM) {
- shi->orn[0]= -shi->vn[0];
- shi->orn[1]= -shi->vn[1];
- shi->orn[2]= -shi->vn[2];
- }
- if(mode & MA_RADIO) {
- float *r1, *r2, *r3;
-
- r1= RE_vertren_get_rad(&R, v1, 0);
- r2= RE_vertren_get_rad(&R, v2, 0);
- r3= RE_vertren_get_rad(&R, v3, 0);
-
- if(r1 && r2 && r3) {
- shi->rad[0]= (l*r3[0] - u*r1[0] - v*r2[0]);
- shi->rad[1]= (l*r3[1] - u*r1[1] - v*r2[1]);
- shi->rad[2]= (l*r3[2] - u*r1[2] - v*r2[2]);
- }
- else {
- shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0;
- }
- }
- else {
- shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0;
- }
- if(texco & TEXCO_REFL) {
- /* mirror reflection colour textures (and envmap) */
- calc_R_ref(shi); /* wrong location for normal maps! XXXXXXXXXXXXXX */
- }
- if(texco & TEXCO_STRESS) {
- float *s1, *s2, *s3;
-
- s1= RE_vertren_get_stress(&R, v1, 0);
- s2= RE_vertren_get_stress(&R, v2, 0);
- s3= RE_vertren_get_stress(&R, v3, 0);
- if(s1 && s2 && s3) {
- shi->stress= l*s3[0] - u*s1[0] - v*s2[0];
- if(shi->stress<1.0f) shi->stress-= 1.0f;
- else shi->stress= (shi->stress-1.0f)/shi->stress;
- }
- else shi->stress= 0.0f;
- }
- if(texco & TEXCO_TANGENT) {
- if((mode & MA_TANGENT_V)==0) {
- /* just prevent surprises */
- shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f;
- }
- }
- }
- else {
- shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0;
- }
-}
-
-#if 0
-/* return labda for view vector being closest to line v3-v4 */
-/* was used for wire render */
-static float isec_view_line(float *view, float *v3, float *v4)
-{
- float vec[3];
- float dot0, dot1, dot2, veclen, viewlen;
- float fac, div;
-
- vec[0]= v4[0] - v3[0];
- vec[1]= v4[1] - v3[1];
- vec[2]= v4[2] - v3[2];
-
- dot0 = v3[0]*vec[0] + v3[1]*vec[1] + v3[2]*vec[2];
- dot1 = vec[0]*view[0] + vec[1]*view[1] + vec[2]*view[2];
- dot2 = v3[0]*view[0] + v3[1]*view[1] + v3[2]*view[2];
-
- veclen = vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2];
- viewlen = view[0]*view[0] + view[1]*view[1] + view[2]*view[2];
-
- div = viewlen*veclen - dot1*dot1;
- if (div==0.0) return 0.0;
-
- fac = dot2*veclen - dot0*dot1;
- return fac/div;
-}
-#endif
-
-
-/* also used as callback for nodes */
-void shade_material_loop(ShadeInput *shi, ShadeResult *shr)
-{
-
- shade_lamp_loop(shi, shr); /* clears shr */
-
- if(shi->translucency!=0.0) {
- ShadeResult shr_t;
-
- VECCOPY(shi->vn, shi->vno);
- VecMulf(shi->vn, -1.0);
- VecMulf(shi->facenor, -1.0);
- shade_lamp_loop(shi, &shr_t);
-
- shr->diff[0]+= shi->translucency*shr_t.diff[0];
- shr->diff[1]+= shi->translucency*shr_t.diff[1];
- shr->diff[2]+= shi->translucency*shr_t.diff[2];
- VecMulf(shi->vn, -1.0);
- VecMulf(shi->facenor, -1.0);
- }
-
- /* depth >= 1 when ray-shading */
- if(shi->depth==0) {
- if(R.r.mode & R_RAYTRACE) {
- if(shi->ray_mirror!=0.0 || ((shi->mat->mode & MA_RAYTRANSP) && shr->alpha!=1.0)) {
- ray_trace(shi, shr);
- }
- }
- else {
- /* doesnt look 'correct', but is better for preview, plus envmaps dont raytrace this */
- if(shi->mat->mode & MA_RAYTRANSP) shr->alpha= 1.0;
- }
- }
-}
-
-/* x,y: window coordinate from 0 to rectx,y */
-/* return pointer to rendered face */
-/* note, facenr declared volatile due to over-eager -O2 optimizations
- * on cygwin (particularly -frerun-cse-after-loop)
- */
-void *shadepixel(ShadePixelInfo *shpi, float x, float y, int z, volatile int facenr, int mask, float *rco)
-{
- ShadeResult *shr= &shpi->shr;
- ShadeInput shi;
- VlakRen *vlr=NULL;
-
- /* currently in use for dithering (soft shadow), node preview, irregular shad */
- shi.xs= (int)(x);
- shi.ys= (int)(y);
-
- shi.thread= shpi->thread;
- shi.do_preview= R.r.scemode & R_NODE_PREVIEW;
- shi.lay= shpi->lay;
-
- /* mask is used to indicate amount of samples (ray shad/mir and AO) */
- shi.mask= mask;
- shi.depth= 0; // means first hit, not raytracing
-
- if(facenr<=0) { /* sky or env */
- memset(shr, 0, sizeof(ShadeResult));
- rco[0]= rco[1]= rco[2]= 0.0f;
- }
- else if( (facenr & RE_QUAD_MASK) <= R.totvlak) {
- VertRen *v1;
- float alpha, fac, zcor;
-
- shi.facenr= (facenr-1) & RE_QUAD_MASK;
- vlr= RE_findOrAddVlak(&R, shi.facenr);
-
- shi.vlr= vlr;
- shi.mat= vlr->mat;
-
- shi.osatex= (shi.mat->texco & TEXCO_OSA);
-
- /* copy the face normal (needed because it gets flipped for tracing */
- VECCOPY(shi.facenor, vlr->n);
- shi.puno= vlr->puno;
-
- v1= vlr->v1;
-
- /* COXYZ AND VIEW VECTOR */
- calc_view_vector(shi.view, x, y); /* returns not normalized, so is in viewplane coords */
-
- /* wire cannot use normal for calculating shi.co */
- if(shi.mat->mode & MA_WIRE) {
- float zco;
- /* inverse of zbuf calc: zbuf = MAXZ*hoco_z/hoco_w */
-
- zco= ((float)z)/2147483647.0f;
- shi.co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] );
-
- fac= zcor= shi.co[2]/shi.view[2];
-
- shi.co[0]= fac*shi.view[0];
- shi.co[1]= fac*shi.view[1];
- }
- else {
- float dface;
-
- dface= v1->co[0]*shi.facenor[0]+v1->co[1]*shi.facenor[1]+v1->co[2]*shi.facenor[2];
-
- /* ortho viewplane cannot intersect using view vector originating in (0,0,0) */
- if(R.r.mode & R_ORTHO) {
- /* x and y 3d coordinate can be derived from pixel coord and winmat */
- float fx= 2.0/(R.winx*R.winmat[0][0]);
- float fy= 2.0/(R.winy*R.winmat[1][1]);
-
- shi.co[0]= (x - 0.5*R.winx)*fx - R.winmat[3][0]/R.winmat[0][0];
- shi.co[1]= (y - 0.5*R.winy)*fy - R.winmat[3][1]/R.winmat[1][1];
-
- /* using a*x + b*y + c*z = d equation, (a b c) is normal */
- if(shi.facenor[2]!=0.0f)
- shi.co[2]= (dface - shi.facenor[0]*shi.co[0] - shi.facenor[1]*shi.co[1])/shi.facenor[2];
- else
- shi.co[2]= 0.0f;
-
- zcor= 1.0; // only to prevent not-initialize
-
- if(shi.osatex || (R.r.mode & R_SHADOW) ) {
- shi.dxco[0]= fx;
- shi.dxco[1]= 0.0;
- if(shi.facenor[2]!=0.0f)
- shi.dxco[2]= (shi.facenor[0]*fx)/shi.facenor[2];
- else
- shi.dxco[2]= 0.0f;
-
- shi.dyco[0]= 0.0;
- shi.dyco[1]= fy;
- if(shi.facenor[2]!=0.0f)
- shi.dyco[2]= (shi.facenor[1]*fy)/shi.facenor[2];
- else
- shi.dyco[2]= 0.0f;
- }
- }
- else {
- float div;
-
- div= shi.facenor[0]*shi.view[0] + shi.facenor[1]*shi.view[1] + shi.facenor[2]*shi.view[2];
- if (div!=0.0) fac= zcor= dface/div;
- else fac= zcor= 0.0;
-
- shi.co[0]= fac*shi.view[0];
- shi.co[1]= fac*shi.view[1];
- shi.co[2]= fac*shi.view[2];
-
- /* pixel dx/dy for render coord */
- if(shi.osatex || (R.r.mode & R_SHADOW) ) {
- float u= dface/(div - R.viewdx*shi.facenor[0]);
- float v= dface/(div - R.viewdy*shi.facenor[1]);
-
- shi.dxco[0]= shi.co[0]- (shi.view[0]-R.viewdx)*u;
- shi.dxco[1]= shi.co[1]- (shi.view[1])*u;
- shi.dxco[2]= shi.co[2]- (shi.view[2])*u;
-
- shi.dyco[0]= shi.co[0]- (shi.view[0])*v;
- shi.dyco[1]= shi.co[1]- (shi.view[1]-R.viewdy)*v;
- shi.dyco[2]= shi.co[2]- (shi.view[2])*v;
-
- }
- }
- }
- /* rco might be used for sky texture */
- VECCOPY(rco, shi.co);
-
- /* cannot normalise earlier, code above needs it at viewplane level */
- fac= Normalise(shi.view);
- zcor*= fac; // for mist, distance of point from camera
-
- if(shi.osatex) {
- if( (shi.mat->texco & TEXCO_REFL) ) {
- shi.dxview= -R.viewdx/fac;
- shi.dyview= -R.viewdy/fac;
- }
- }
-
- /* calcuate normals, texture coords, vertex colors, etc */
- if(facenr & RE_QUAD_OFFS)
- shade_input_set_coords(&shi, 1.0, 1.0, 0, 2, 3);
- else
- shade_input_set_coords(&shi, 1.0, 1.0, 0, 1, 2);
-
- /* this only avalailable for scanline */
- if(shi.mat->texco & TEXCO_WINDOW) {
- shi.winco[0]= -1.0f + 2.0f*x/(float)R.winx;
- shi.winco[1]= -1.0f + 2.0f*y/(float)R.winy;
- shi.winco[2]= 0.0;
- if(shi.osatex) {
- shi.dxwin[0]= 2.0/(float)R.winx;
- shi.dywin[1]= 2.0/(float)R.winy;
- shi.dxwin[1]= shi.dxwin[2]= 0.0;
- shi.dywin[0]= shi.dywin[2]= 0.0;
- }
- }
- /* after this the u and v AND shi.dxuv and shi.dyuv are incorrect */
- if(shi.mat->texco & TEXCO_STICKY) {
- VertRen *v2, *v3;
- float *s1, *s2, *s3;
-
- if(facenr & RE_QUAD_OFFS) {
- v2= vlr->v3; v3= vlr->v4;
- } else {
- v2= vlr->v2; v3= vlr->v3;
- }
-
- s1= RE_vertren_get_sticky(&R, v1, 0);
- s2= RE_vertren_get_sticky(&R, v2, 0);
- s3= RE_vertren_get_sticky(&R, v3, 0);
-
- if(s1 && s2 && s3) {
- float Zmulx, Zmuly;
- float hox, hoy, l, dl, u, v;
- float s00, s01, s10, s11, detsh;
-
- /* old globals, localized now */
- Zmulx= ((float)R.winx)/2.0; Zmuly= ((float)R.winy)/2.0;
-
- s00= v3->ho[0]/v3->ho[3] - v1->ho[0]/v1->ho[3];
- s01= v3->ho[1]/v3->ho[3] - v1->ho[1]/v1->ho[3];
- s10= v3->ho[0]/v3->ho[3] - v2->ho[0]/v2->ho[3];
- s11= v3->ho[1]/v3->ho[3] - v2->ho[1]/v2->ho[3];
-
- detsh= s00*s11-s10*s01;
- s00/= detsh; s01/=detsh;
- s10/=detsh; s11/=detsh;
-
- /* recalc u and v again */
- hox= x/Zmulx -1.0;
- hoy= y/Zmuly -1.0;
- u= (hox - v3->ho[0]/v3->ho[3])*s11 - (hoy - v3->ho[1]/v3->ho[3])*s10;
- v= (hoy - v3->ho[1]/v3->ho[3])*s00 - (hox - v3->ho[0]/v3->ho[3])*s01;
- l= 1.0+u+v;
-
- shi.sticky[0]= l*s3[0]-u*s1[0]-v*s2[0];
- shi.sticky[1]= l*s3[1]-u*s1[1]-v*s2[1];
- shi.sticky[2]= 0.0;
-
- if(shi.osatex) {
- shi.dxuv[0]= s11/Zmulx;
- shi.dxuv[1]= - s01/Zmulx;
- shi.dyuv[0]= - s10/Zmuly;
- shi.dyuv[1]= s00/Zmuly;
-
- dl= shi.dxuv[0]+shi.dxuv[1];
- shi.dxsticky[0]= dl*s3[0]-shi.dxuv[0]*s1[0]-shi.dxuv[1]*s2[0];
- shi.dxsticky[1]= dl*s3[1]-shi.dxuv[0]*s1[1]-shi.dxuv[1]*s2[1];
- dl= shi.dyuv[0]+shi.dyuv[1];
- shi.dysticky[0]= dl*s3[0]-shi.dyuv[0]*s1[0]-shi.dyuv[1]*s2[0];
- shi.dysticky[1]= dl*s3[1]-shi.dyuv[0]*s1[1]-shi.dyuv[1]*s2[1];
- }
- }
- }
-
- /* ------ main shading loop -------- */
-
- if(shi.mat->nodetree && shi.mat->use_nodes) {
- ntreeShaderExecTree(shi.mat->nodetree, &shi, shr);
- }
- else {
- /* copy all relevant material vars, note, keep this synced with render_types.h */
- memcpy(&shi.r, &shi.mat->r, 23*sizeof(float));
- shi.har= shi.mat->har;
-
-// if(passflag)
-// shade_lamp_loop_pass(&shi, shr, passflag);
-// else
- shade_material_loop(&shi, shr);
- }
-
- /* after shading and composit layers */
- if(shr->spec[0]<0.0f) shr->spec[0]= 0.0f;
- if(shr->spec[1]<0.0f) shr->spec[1]= 0.0f;
- if(shr->spec[2]<0.0f) shr->spec[2]= 0.0f;
-
- if(shr->diff[0]<0.0f) shr->diff[0]= 0.0f;
- if(shr->diff[1]<0.0f) shr->diff[1]= 0.0f;
- if(shr->diff[2]<0.0f) shr->diff[2]= 0.0f;
-
-// if(passflag==0) {
- VECADD(shr->combined, shr->diff, shr->spec);
-// }
-
- /* additional passes */
- QUATCOPY(shr->winspeed, shi.winspeed);
- VECCOPY(shr->nor, shi.vn);
-
- /* NOTE: this is not correct here, sky from raytrace gets corrected... */
- /* exposure correction */
- if(R.wrld.exp!=0.0 || R.wrld.range!=1.0) {
- if((shi.mat->mode & MA_SHLESS)==0) {
- shr->combined[0]= R.wrld.linfac*(1.0-exp( shr->combined[0]*R.wrld.logfac) );
- shr->combined[1]= R.wrld.linfac*(1.0-exp( shr->combined[1]*R.wrld.logfac) );
- shr->combined[2]= R.wrld.linfac*(1.0-exp( shr->combined[2]*R.wrld.logfac) );
- }
- }
-
- /* MIST */
- if((R.wrld.mode & WO_MIST) && (shi.mat->mode & MA_NOMIST)==0 ) {
- if(R.r.mode & R_ORTHO)
- alpha= mistfactor(-shi.co[2], shi.co);
- else
- alpha= mistfactor(zcor, shi.co);
- }
- else alpha= 1.0;
-
- if(shr->alpha!=1.0 || alpha!=1.0) {
- if(shi.mat->mode & MA_RAYTRANSP) {
-
- shr->combined[3]= shr->alpha;
- if(alpha!=1.0) {
- /* sky is already included in tracing, no useful alpha here, so we blend in shaded color with sky */
- float col[4], malpha;
-
- shadeSkyPixelFloat(col, shi.co, shi.view, NULL);
- malpha= 1.0f-alpha;
- shr->combined[0]= alpha*shr->combined[0] + malpha*col[0];
- shr->combined[1]= alpha*shr->combined[1] + malpha*col[1];
- shr->combined[2]= alpha*shr->combined[2] + malpha*col[2];
- }
- }
- else {
- fac= alpha*(shr->alpha);
- shr->combined[3]= fac;
-
- shr->combined[0]*= fac;
- shr->combined[1]*= fac;
- shr->combined[2]*= fac;
- }
- }
- else shr->combined[3]= 1.0;
- }
-
- if(R.flag & R_LAMPHALO) {
- if(shpi->layflag & SCE_LAY_HALO) {
-
- if(facenr<=0) { /* sky or env, calc view vector and put shi.co at far */
- if(R.r.mode & R_ORTHO) {
- /* x and y 3d coordinate can be derived from pixel coord and winmat */
- float fx= 2.0/(R.rectx*R.winmat[0][0]);
- float fy= 2.0/(R.recty*R.winmat[1][1]);
-
- shi.co[0]= (x - 0.5*R.rectx)*fx - R.winmat[3][0]/R.winmat[0][0];
- shi.co[1]= (y - 0.5*R.recty)*fy - R.winmat[3][1]/R.winmat[1][1];
- }
-
- calc_view_vector(shi.view, x, y);
- shi.co[2]= 0.0;
-
- renderspothalo(&shi, shr->combined, 1.0);
- }
- else
- renderspothalo(&shi, shr->combined, shr->combined[3]);
- }
- }
-
- return vlr;
-}
-
-static void shadepixel_sky(ShadePixelInfo *shpi, float x, float y, int z, int facenr, int mask)
-{
- VlakRen *vlr;
- float collector[4], rco[3];
-
- /* correction back for zbuffer filling in */
- x+= 0.5f;
- y+= 0.5f;
-
- vlr= shadepixel(shpi, x, y, z, facenr, mask, rco);
- if(shpi->shr.combined[3] != 1.0) {
-
- /* bail out when raytrace transparency (sky included already) */
- if(vlr && (R.r.mode & R_RAYTRACE))
- if(vlr->mat->mode & MA_RAYTRANSP) return;
-
- if(shpi->layflag & SCE_LAY_SKY) {
- renderSkyPixelFloat(collector, x, y, vlr?rco:NULL);
- addAlphaOverFloat(collector, shpi->shr.combined);
- QUATCOPY(shpi->shr.combined, collector);
- }
- }
-}
-
-/* adds only alpha values */
-static void edge_enhance_calc(RenderPart *pa, float *rectf)
-{
- /* use zbuffer to define edges, add it to the image */
- int y, x, col, *rz, *rz1, *rz2, *rz3;
- int zval1, zval2, zval3;
- float *rf;
-
- /* shift values in zbuffer 4 to the right (anti overflows), for filter we need multiplying with 12 max */
- rz= pa->rectz;
- if(rz==NULL) return;
-
- for(y=0; y<pa->recty; y++)
- for(x=0; x<pa->rectx; x++, rz++) (*rz)>>= 4;
-
- rz1= pa->rectz;
- rz2= rz1+pa->rectx;
- rz3= rz2+pa->rectx;
-
- rf= rectf+pa->rectx+1;
-
- for(y=0; y<pa->recty-2; y++) {
- for(x=0; x<pa->rectx-2; x++, rz1++, rz2++, rz3++, rf++) {
-
- /* prevent overflow with sky z values */
- zval1= rz1[0] + 2*rz1[1] + rz1[2];
- zval2= 2*rz2[0] + 2*rz2[2];
- zval3= rz3[0] + 2*rz3[1] + rz3[2];
-
- col= abs ( 4*rz2[1] - (zval1 + zval2 + zval3)/3 );
-
- col >>= 5;
- if(col > (1<<16)) col= (1<<16);
- else col= (R.r.edgeint*col)>>8;
-
- if(col>0) {
- float fcol;
-
- if(col>255) fcol= 1.0f;
- else fcol= (float)col/255.0f;
-
- if(R.osa)
- *rf+= fcol/(float)R.osa;
- else
- *rf= fcol;
- }
- }
- rz1+= 2;
- rz2+= 2;
- rz3+= 2;
- rf+= 2;
- }
-
- /* shift back zbuf values, we might need it still */
- rz= pa->rectz;
- for(y=0; y<pa->recty; y++)
- for(x=0; x<pa->rectx; x++, rz++) (*rz)<<= 4;
-
-}
-
-static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect)
-{
- float addcol[4];
- int pix;
-
- for(pix= pa->rectx*pa->recty; pix>0; pix--, arect++, rectf+=4) {
- if(*arect != 0.0f) {
- addcol[0]= *arect * R.r.edgeR;
- addcol[1]= *arect * R.r.edgeG;
- addcol[2]= *arect * R.r.edgeB;
- addcol[3]= *arect;
- addAlphaOverFloat(rectf, addcol);
- }
- }
-}
-
/* ********************* MAINLOOPS ******************** */
@@ -2865,7 +364,7 @@ static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl)
}
/* osa version */
-static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, ShadeResult *shr)
+static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, ShadeInput *shi, ShadeResult *shr)
{
RenderPass *rpass;
@@ -2879,7 +378,7 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
pixsize= 4;
break;
case SCE_PASS_DIFFUSE:
- col= shr->diff;
+ col= shr->diff_raw;
break;
case SCE_PASS_SPEC:
col= shr->spec;
@@ -2890,15 +389,25 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
case SCE_PASS_AO:
col= shr->ao;
break;
- case SCE_PASS_RAY:
- col= shr->ray;
+ case SCE_PASS_REFLECT:
+ col= shr->refl;
+ break;
+ case SCE_PASS_REFRACT:
+ col= shr->refr;
break;
case SCE_PASS_NORMAL:
col= shr->nor;
break;
+ case SCE_PASS_INDEXOB:
+ /* no filter */
+ if(shi->vlr) {
+ fp= rpass->rect + offset;
+ *fp= (float)shi->vlr->ob->index;
+ }
+ break;
case SCE_PASS_VECTOR:
{
- /* add minimum speed in pixel */
+ /* add minimum speed in pixel, no filter */
fp= rpass->rect + 4*offset;
if( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) {
fp[0]= shr->winspeed[0];
@@ -2919,7 +428,7 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
}
/* non-osa version */
-static void add_passes(RenderLayer *rl, int offset, ShadeResult *shr)
+static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult *shr)
{
RenderPass *rpass;
@@ -2933,7 +442,7 @@ static void add_passes(RenderLayer *rl, int offset, ShadeResult *shr)
pixsize= 4;
break;
case SCE_PASS_DIFFUSE:
- col= shr->diff;
+ col= shr->diff_raw;
break;
case SCE_PASS_SPEC:
col= shr->spec;
@@ -2944,8 +453,11 @@ static void add_passes(RenderLayer *rl, int offset, ShadeResult *shr)
case SCE_PASS_AO:
col= shr->ao;
break;
- case SCE_PASS_RAY:
- col= shr->ray;
+ case SCE_PASS_REFLECT:
+ col= shr->refl;
+ break;
+ case SCE_PASS_REFRACT:
+ col= shr->refr;
break;
case SCE_PASS_NORMAL:
col= shr->nor;
@@ -2954,6 +466,12 @@ static void add_passes(RenderLayer *rl, int offset, ShadeResult *shr)
col= shr->winspeed;
pixsize= 4;
break;
+ case SCE_PASS_INDEXOB:
+ if(shi->vlr) {
+ fp= rpass->rect + offset;
+ *fp= (float)shi->vlr->ob->index;
+ }
+ break;
}
if(col) {
fp= rpass->rect + pixsize*offset;
@@ -2966,11 +484,24 @@ static void add_passes(RenderLayer *rl, int offset, ShadeResult *shr)
/* only do sky, is default in the solid layer (shade_tile) btw */
static void sky_tile(RenderPart *pa, float *pass)
{
+ float col[4];
int x, y;
+ if(R.r.alphamode!=R_ADDSKY)
+ return;
+
for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) {
- for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, pass+=4)
- renderSkyPixelFloat(pass, x, y, NULL);
+ for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, pass+=4) {
+ if(pass[3]<1.0f) {
+ if(pass[3]==0.0f)
+ shadeSkyPixel(pass, x, y);
+ else {
+ shadeSkyPixel(col, x, y);
+ addAlphaOverFloat(col, pass);
+ QUATCOPY(pass, col);
+ }
+ }
+ }
if(y&1)
if(R.test_break()) break;
@@ -2980,13 +511,11 @@ static void sky_tile(RenderPart *pa, float *pass)
static void shadeDA_tile(RenderPart *pa, RenderLayer *rl)
{
RenderResult *rr= pa->result;
- ShadePixelInfo shpi;
- PixStr *ps;
- float xs, ys;
- float *fcol= shpi.shr.combined, *rf, *rectf= rl->rectf;
+ ShadeSample ssamp;
+ float *fcol, *rf, *rectf= rl->rectf;
long *rd, *rectdaps= pa->rectdaps;
- int zbuf, samp, curmask, face, mask, fullmask;
- int b, x, y, full_osa, seed, crop=0, offs=0, od, addpassflag;
+ int samp;
+ int x, y, seed, crop=0, offs=0, od, addpassflag;
if(R.test_break()) return;
@@ -2996,17 +525,9 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl)
/* we set per pixel a fixed seed, for random AO and shadow samples */
seed= pa->rectx*pa->disprect.ymin;
-
- fullmask= (1<<R.osa)-1;
- /* fill shadepixel info struct */
- shpi.thread= pa->thread;
- shpi.lay= rl->lay;
- shpi.layflag= rl->layflag;
- shpi.passflag= 0;
-
- if(rl->passflag & ~(SCE_PASS_Z|SCE_PASS_NORMAL|SCE_PASS_VECTOR|SCE_PASS_COMBINED))
- shpi.passflag= rl->passflag;
+ /* general shader info, passes */
+ shade_sample_initialize(&ssamp, pa, rl);
addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
/* filtered render, for now we assume only 1 filter size */
@@ -3030,70 +551,17 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl)
for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, rd++, rf+=4, od++) {
BLI_thread_srandom(pa->thread, seed++);
- ps= (PixStr *)(*rd);
- mask= 0;
-
- /* complex loop, because empty spots are sky, without mask */
- while(TRUE) {
-
- if(ps==NULL) {
- face= 0;
- curmask= (~mask) & fullmask;
- zbuf= 0x7FFFFFFF;
- }
- else {
- face= ps->facenr;
- curmask= ps->mask;
- zbuf= ps->z;
- }
-
- /* check osa level */
- if(face<=0) full_osa= 0;
- else {
- VlakRen *vlr= RE_findOrAddVlak(&R, (face-1) & RE_QUAD_MASK);
- full_osa= (vlr->flag & R_FULL_OSA);
- }
-
- if(full_osa) {
- for(samp=0; samp<R.osa; samp++) {
- if(curmask & (1<<samp)) {
- xs= (float)x + R.jit[samp][0];
- ys= (float)y + R.jit[samp][1];
- shadepixel_sky(&shpi, xs, ys, zbuf, face, (1<<samp));
-
- if(R.do_gamma) {
- fcol[0]= gammaCorrect(fcol[0]);
- fcol[1]= gammaCorrect(fcol[1]);
- fcol[2]= gammaCorrect(fcol[2]);
- }
- add_filt_fmask(1<<samp, fcol, rf, pa->rectx);
-
- if(addpassflag)
- add_filt_passes(rl, 1<<samp, pa->rectx, od, &shpi.shr);
- }
- }
- }
- else if(curmask) {
- b= R.samples->centmask[curmask];
- xs= (float)x+R.samples->centLut[b & 15];
- ys= (float)y+R.samples->centLut[b>>4];
- shadepixel_sky(&shpi, xs, ys, zbuf, face, curmask);
-
- if(R.do_gamma) {
- fcol[0]= gammaCorrect(fcol[0]);
- fcol[1]= gammaCorrect(fcol[1]);
- fcol[2]= gammaCorrect(fcol[2]);
+ if(*rd) {
+ if(shade_samples(&ssamp, (PixStr *)(*rd), x, y)) {
+ for(samp=0; samp<ssamp.tot; samp++) {
+
+ fcol= ssamp.shr[samp].combined;
+ add_filt_fmask(ssamp.shi[samp].mask, fcol, rf, pa->rectx);
+
+ if(addpassflag)
+ add_filt_passes(rl, ssamp.shi[samp].mask, pa->rectx, od, ssamp.shi, &ssamp.shr[samp]);
}
- add_filt_fmask(curmask, fcol, rf, pa->rectx);
-
- if(addpassflag)
- add_filt_passes(rl, curmask, pa->rectx, od, &shpi.shr);
}
-
- mask |= curmask;
-
- if(ps==NULL) break;
- else ps= ps->next;
}
}
@@ -3107,15 +575,6 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl)
/* disable scanline updating */
rr->renlay= NULL;
- if(R.do_gamma) {
- rectf= rl->rectf;
- for(y= pa->rectx*pa->recty; y>0; y--, rectf+=4) {
- rectf[0] = invGammaCorrect(rectf[0]);
- rectf[1] = invGammaCorrect(rectf[1]);
- rectf[2] = invGammaCorrect(rectf[2]);
- }
- }
-
if(R.r.mode & R_SHADOW)
ISB_free(pa);
}
@@ -3202,6 +661,26 @@ static void make_pixelstructs(RenderPart *pa, ListBase *lb)
}
}
+static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect)
+{
+ float addcol[4];
+ int pix;
+
+ if(arect==NULL)
+ return;
+
+ for(pix= pa->rectx*pa->recty; pix>0; pix--, arect++, rectf+=4) {
+ if(*arect != 0.0f) {
+ addcol[0]= *arect * R.r.edgeR;
+ addcol[1]= *arect * R.r.edgeG;
+ addcol[2]= *arect * R.r.edgeB;
+ addcol[3]= *arect;
+ addAlphaOverFloat(rectf, addcol);
+ }
+ }
+}
+
+
static void convert_to_key_alpha(RenderPart *pa, float *rectf)
{
int y;
@@ -3216,6 +695,126 @@ static void convert_to_key_alpha(RenderPart *pa, float *rectf)
}
}
+/* adds only alpha values */
+static void edge_enhance_tile(RenderPart *pa, float *rectf)
+{
+ /* use zbuffer to define edges, add it to the image */
+ int y, x, col, *rz, *rz1, *rz2, *rz3;
+ int zval1, zval2, zval3;
+ float *rf;
+
+ /* shift values in zbuffer 4 to the right (anti overflows), for filter we need multiplying with 12 max */
+ rz= pa->rectz;
+ if(rz==NULL) return;
+
+ for(y=0; y<pa->recty; y++)
+ for(x=0; x<pa->rectx; x++, rz++) (*rz)>>= 4;
+
+ rz1= pa->rectz;
+ rz2= rz1+pa->rectx;
+ rz3= rz2+pa->rectx;
+
+ rf= rectf+pa->rectx+1;
+
+ for(y=0; y<pa->recty-2; y++) {
+ for(x=0; x<pa->rectx-2; x++, rz1++, rz2++, rz3++, rf++) {
+
+ /* prevent overflow with sky z values */
+ zval1= rz1[0] + 2*rz1[1] + rz1[2];
+ zval2= 2*rz2[0] + 2*rz2[2];
+ zval3= rz3[0] + 2*rz3[1] + rz3[2];
+
+ col= ( 4*rz2[1] - (zval1 + zval2 + zval3)/3 );
+ if(col<0) col= -col;
+
+ col >>= 5;
+ if(col > (1<<16)) col= (1<<16);
+ else col= (R.r.edgeint*col)>>8;
+
+ if(col>0) {
+ float fcol;
+
+ if(col>255) fcol= 1.0f;
+ else fcol= (float)col/255.0f;
+
+ if(R.osa)
+ *rf+= fcol/(float)R.osa;
+ else
+ *rf= fcol;
+ }
+ }
+ rz1+= 2;
+ rz2+= 2;
+ rz3+= 2;
+ rf+= 2;
+ }
+
+ /* shift back zbuf values, we might need it still */
+ rz= pa->rectz;
+ for(y=0; y<pa->recty; y++)
+ for(x=0; x<pa->rectx; x++, rz++) (*rz)<<= 4;
+
+}
+
+static unsigned short *make_solid_mask(RenderPart *pa)
+{
+ long *rd= pa->rectdaps;
+ short *solidmask, *sp;
+ int x;
+
+ if(rd==NULL) return NULL;
+
+ sp=solidmask= MEM_mallocN(sizeof(short)*pa->rectx*pa->recty, "solidmask");
+
+ for(x=pa->rectx*pa->recty; x>0; x--, rd++, sp++) {
+ if(*rd) {
+ PixStr *ps= (PixStr *)*rd;
+
+ *sp= ps->mask;
+ for(ps= ps->next; ps; ps= ps->next)
+ *sp |= ps->mask;
+ }
+ else
+ *sp= 0;
+ }
+
+ return solidmask;
+}
+
+static void addAlphaOverFloatMask(float *dest, float *source, unsigned short dmask, unsigned short smask)
+{
+ unsigned short shared= dmask & smask;
+ float mul= 1.0 - source[3];
+
+ if(shared) { /* overlapping masks */
+
+ /* masks differ, we make a mixture of 'add' and 'over' */
+ if(shared!=dmask) {
+ float shared_bits= (float)count_mask(shared); /* alpha over */
+ float tot_bits= (float)count_mask(smask|dmask); /* alpha add */
+
+ float add= (tot_bits - shared_bits)/tot_bits; /* add level */
+ mul= add + (1.0f-add)*mul;
+ }
+ }
+ else if(dmask && smask) {
+ /* works for premul only, of course */
+ dest[0]+= source[0];
+ dest[1]+= source[1];
+ dest[2]+= source[2];
+ dest[3]+= source[3];
+
+ return;
+ }
+
+ dest[0]= (mul*dest[0]) + source[0];
+ dest[1]= (mul*dest[1]) + source[1];
+ dest[2]= (mul*dest[2]) + source[2];
+ dest[3]= (mul*dest[3]) + source[3];
+}
+
+
+/* main call for shading Delta Accum, for OSA */
/* supposed to be fully threadable! */
void zbufshadeDA_tile(RenderPart *pa)
{
@@ -3236,7 +835,10 @@ void zbufshadeDA_tile(RenderPart *pa)
/* initialize pixelstructs and edge buffer */
addpsmain(&psmlist);
pa->rectdaps= MEM_callocN(sizeof(long)*pa->rectx*pa->recty+4, "zbufDArectd");
- if(R.r.mode & R_EDGE) edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge");
+
+ if(rl->layflag & SCE_LAY_EDGE)
+ if(R.r.mode & R_EDGE)
+ edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge");
/* always fill visibility */
for(pa->sample=0; pa->sample<R.osa; pa->sample++) {
@@ -3245,7 +847,7 @@ void zbufshadeDA_tile(RenderPart *pa)
if(rl->layflag & SCE_LAY_EDGE)
if(R.r.mode & R_EDGE)
- edge_enhance_calc(pa, edgerect);
+ edge_enhance_tile(pa, edgerect);
if(R.test_break()) break;
}
@@ -3253,14 +855,11 @@ void zbufshadeDA_tile(RenderPart *pa)
/* shades solid */
if(rl->layflag & SCE_LAY_SOLID)
shadeDA_tile(pa, rl);
- else if(rl->layflag & SCE_LAY_SKY)
- sky_tile(pa, rl->rectf);
/* lamphalo after solid, before ztra, looks nicest because ztra does own halo */
if(R.flag & R_LAMPHALO)
if(rl->layflag & SCE_LAY_HALO)
- if(!(rl->layflag & SCE_LAY_SOLID))
- lamphalo_tile(pa, rl->rectf, rl->lay);
+ lamphalo_tile(pa, rl->rectf, rl->lay);
/* halo before ztra, because ztra fills in zbuffer now */
if(R.flag & R_HALO)
@@ -3270,8 +869,7 @@ void zbufshadeDA_tile(RenderPart *pa)
/* transp layer */
if(R.flag & R_ZTRA) {
if(rl->layflag & SCE_LAY_ZTRA) {
- float *fcol, *acol;
- int x;
+ unsigned short *ztramask, *solidmask= NULL; /* 16 bits, MAX_OSA */
/* allocate, but not free here, for asynchronous display of this rect in main thread */
rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer");
@@ -3282,16 +880,35 @@ void zbufshadeDA_tile(RenderPart *pa)
/* swap for live updates */
SWAP(float *, rl->acolrect, rl->rectf);
- zbuffer_transp_shade(pa, rl, rl->rectf);
+ ztramask= zbuffer_transp_shade(pa, rl, rl->rectf);
SWAP(float *, rl->acolrect, rl->rectf);
- fcol= rl->rectf; acol= rl->acolrect;
- for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) {
- addAlphaOverFloat(fcol, acol);
+ /* zbuffer transp only returns ztramask if there's solid rendered */
+ if(ztramask)
+ solidmask= make_solid_mask(pa);
+
+ if(ztramask && solidmask) {
+ unsigned short *sps= solidmask, *spz= ztramask;
+ float *fcol= rl->rectf; float *acol= rl->acolrect;
+ int x;
+ for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4, sps++, spz++)
+ addAlphaOverFloatMask(fcol, acol, *sps, *spz);
+ }
+ else {
+ float *fcol= rl->rectf; float *acol= rl->acolrect;
+ int x;
+ for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) {
+ addAlphaOverFloat(fcol, acol);
+ }
}
+ if(solidmask) MEM_freeN(solidmask);
+ if(ztramask) MEM_freeN(ztramask);
}
}
-
+ /* sky before edge */
+ if(rl->layflag & SCE_LAY_SKY)
+ sky_tile(pa, rl->rectf);
+
/* extra layers */
if(rl->layflag & SCE_LAY_EDGE)
if(R.r.mode & R_EDGE)
@@ -3325,34 +942,31 @@ void zbufshadeDA_tile(RenderPart *pa)
/* ------------------------------------------------------------------------ */
+/* non OSA case, full tile render */
/* supposed to be fully threadable! */
void zbufshade_tile(RenderPart *pa)
{
- ShadePixelInfo shpi;
+ ShadeSample ssamp;
RenderResult *rr= pa->result;
RenderLayer *rl;
+ PixStr ps;
float *edgerect= NULL;
int addpassflag;
+ /* fake pixel struct, to comply to osa render */
+ ps.next= NULL;
+ ps.mask= 0xFFFF;
+
set_part_zbuf_clipflag(pa);
/* zbuffer code clears/inits rects */
pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
- shpi.thread= pa->thread;
-
for(rl= rr->layers.first; rl; rl= rl->next) {
- if(R.r.mode & R_EDGE) edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge");
-
- /* fill shadepixel info struct */
- shpi.lay= rl->lay;
- shpi.layflag= rl->layflag;
- shpi.passflag= 0;
-
- if(rl->passflag & ~(SCE_PASS_Z|SCE_PASS_NORMAL|SCE_PASS_VECTOR|SCE_PASS_COMBINED))
- shpi.passflag= rl->passflag;
+ /* general shader info, passes */
+ shade_sample_initialize(&ssamp, pa, rl);
addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
zbuffer_solid(pa, rl->lay, rl->layflag);
@@ -3360,9 +974,12 @@ void zbufshade_tile(RenderPart *pa)
if(!R.test_break()) { /* NOTE: this if() is not consistant */
/* edges only for solid part, ztransp doesn't support it yet anti-aliased */
- if(rl->layflag & SCE_LAY_EDGE)
- if(R.r.mode & R_EDGE)
- edge_enhance_calc(pa, edgerect);
+ if(rl->layflag & SCE_LAY_EDGE) {
+ if(R.r.mode & R_EDGE) {
+ edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge");
+ edge_enhance_tile(pa, edgerect);
+ }
+ }
/* initialize scanline updates for main thread */
rr->renrect.ymin= 0;
@@ -3381,14 +998,20 @@ void zbufshade_tile(RenderPart *pa)
for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++, rr->renrect.ymax++) {
for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, rz++, rp++, fcol+=4, offs++) {
+ /* per pixel fixed seed */
BLI_thread_srandom(pa->thread, seed++);
- shadepixel_sky(&shpi, (float)x, (float)y, *rz, *rp, 0);
- QUATCOPY(fcol, shpi.shr.combined);
-
- /* passes */
- if(addpassflag)
- add_passes(rl, offs, &shpi.shr);
+ if(*rp) {
+ ps.facenr= *rp;
+ ps.z= *rz;
+ if(shade_samples(&ssamp, &ps, x, y)) {
+ QUATCOPY(fcol, ssamp.shr[0].combined);
+
+ /* passes */
+ if(addpassflag)
+ add_passes(rl, offs, ssamp.shi, ssamp.shr);
+ }
+ }
}
if(y&1)
if(R.test_break()) break;
@@ -3397,9 +1020,6 @@ void zbufshade_tile(RenderPart *pa)
if(R.r.mode & R_SHADOW)
ISB_free(pa);
}
- else if(rl->layflag & SCE_LAY_SKY) {
- sky_tile(pa, rl->rectf);
- }
/* disable scanline updating */
rr->renlay= NULL;
@@ -3408,14 +1028,13 @@ void zbufshade_tile(RenderPart *pa)
/* lamphalo after solid, before ztra, looks nicest because ztra does own halo */
if(R.flag & R_LAMPHALO)
if(rl->layflag & SCE_LAY_HALO)
- if(!(rl->layflag & SCE_LAY_SOLID))
lamphalo_tile(pa, rl->rectf, rl->lay);
+
/* halo before ztra, because ztra fills in zbuffer now */
if(R.flag & R_HALO)
if(rl->layflag & SCE_LAY_HALO)
halo_tile(pa, rl->rectf, rl->lay);
-
if(R.flag & R_ZTRA) {
if(rl->layflag & SCE_LAY_ZTRA) {
float *fcol, *acol;
@@ -3440,6 +1059,10 @@ void zbufshade_tile(RenderPart *pa)
}
}
+ /* sky before edge */
+ if(rl->layflag & SCE_LAY_SKY)
+ sky_tile(pa, rl->rectf);
+
if(!R.test_break()) {
if(rl->layflag & SCE_LAY_EDGE)
if(R.r.mode & R_EDGE)
@@ -3541,7 +1164,7 @@ static void renderflare(RenderResult *rr, float *rectf, HaloRen *har)
alfa= har->alfa;
visifac= R.ycor*(har->pixels);
- /* all radials added / r^3 == 1.0! */
+ /* all radials added / r^3 == 1.0f! */
visifac /= (har->rad*har->rad*har->rad);
visifac*= visifac;
@@ -3566,15 +1189,15 @@ static void renderflare(RenderResult *rr, float *rectf, HaloRen *har)
fla.g= fabs(rc[1]);
fla.b= fabs(rc[2]);
fla.alfa= ma->flareboost*fabs(alfa*visifac*rc[3]);
- fla.hard= 20.0 + fabs(70*rc[7]);
+ fla.hard= 20.0f + fabs(70*rc[7]);
fla.tex= 0;
type= (int)(fabs(3.9*rc[6]));
- fla.rad= ma->subsize*sqrt(fabs(2.0*har->rad*rc[4]));
+ fla.rad= ma->subsize*sqrt(fabs(2.0f*har->rad*rc[4]));
if(type==3) {
- fla.rad*= 3.0;
+ fla.rad*= 3.0f;
fla.rad+= R.rectx/10;
}
@@ -3582,7 +1205,7 @@ static void renderflare(RenderResult *rr, float *rectf, HaloRen *har)
vec[0]= 1.4*rc[5]*(har->xs-R.winx/2);
vec[1]= 1.4*rc[5]*(har->ys-R.winy/2);
- vec[2]= 32.0*sqrt(vec[0]*vec[0] + vec[1]*vec[1] + 1.0);
+ vec[2]= 32.0f*sqrt(vec[0]*vec[0] + vec[1]*vec[1] + 1.0f);
fla.xs= R.winx/2 + vec[0] + (1.2+rc[8])*R.rectx*vec[0]/vec[2];
fla.ys= R.winy/2 + vec[1] + (1.2+rc[8])*R.rectx*vec[1]/vec[2];
@@ -3676,7 +1299,7 @@ void RE_shade_external(Render *re, ShadeInput *shi, ShadeResult *shr)
#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val))
typedef struct BakeShade {
- ShadeInput shi;
+ ShadeSample ssamp;
VlakRen *vlr;
ZSpan *zspan;
@@ -3691,7 +1314,8 @@ typedef struct BakeShade {
static void do_bake_shade(void *handle, int x, int y, float u, float v)
{
BakeShade *bs= handle;
- ShadeInput *shi= &bs->shi;
+ ShadeSample *ssamp= &bs->ssamp;
+ ShadeInput *shi= ssamp->shi;
ShadeResult shr;
VlakRen *vlr= bs->vlr;
float l, *v1, *v2, *v3;
@@ -3700,11 +1324,7 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
if(R.test_break())
return;
- shi->xs= x;
- shi->ys= y;
-
- /* setup render coordinates, it's a copy of shade_ray mostly, but different.
- like for shadepixel, useful to restructure once. */
+ /* setup render coordinates */
if(bs->quad) {
v1= vlr->v1->co;
v2= vlr->v3->co;
@@ -3717,7 +1337,7 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
}
/* renderco */
- l= 1.0-u-v;
+ l= 1.0f-u-v;
shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0];
shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1];
@@ -3727,26 +1347,36 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
VECCOPY(shi->view, shi->co);
Normalise(shi->view);
- shi->vlr= vlr;
- shi->mat= vlr->mat;
- memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); // note, keep this synced with render_types.h
- shi->har= shi->mat->har;
-
/* no face normal flip */
- VECCOPY(shi->facenor, vlr->n);
shi->puno= 0;
-
+
if(bs->quad)
- shade_input_set_coords(shi, -u, -v, 0, 2, 3);
+ shade_input_set_triangle_i(shi, vlr, 0, 2, 3);
else
- shade_input_set_coords(shi, -u, -v, 0, 1, 2);
+ shade_input_set_triangle_i(shi, vlr, 0, 1, 2);
+
+ shi->u= -u;
+ shi->v= -v;
+ shi->xs= x;
+ shi->ys= y;
+
+ shade_input_set_normals(shi);
+
+ /* init material vars */
+ memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); // note, keep this synced with render_types.h
+ shi->har= shi->mat->har;
if(bs->type==RE_BAKE_AO) {
- shr.ao[0]= shr.ao[1]= shr.ao[2]= 0.0f;
- ambient_occlusion(shi, &shr);
- VECCOPY(shr.diff, shr.ao);
+ ambient_occlusion(shi);
+ ambient_occlusion_to_diffuse(shi, shr.diff);
}
else {
+
+ shade_input_set_shade_texco(shi);
+
+ if(R.r.mode & R_SHADOW)
+ shade_samples_do_shadow(ssamp);
+
if(shi->mat->nodetree && shi->mat->use_nodes) {
ntreeShaderExecTree(shi->mat->nodetree, shi, &shr);
shi->mat= vlr->mat; /* shi->mat is being set in nodetree */
@@ -3924,7 +1554,11 @@ int RE_bake_shade_all_selected(Render *re, int type)
for(a=0; a<re->r.threads; a++) {
/* set defaults in handles */
memset(&handles[a], 0, sizeof(BakeShade));
- handles[a].shi.lay= re->scene->lay;
+
+ handles[a].ssamp.shi[0].lay= re->scene->lay;
+ handles[a].ssamp.shi[0].passflag= SCE_PASS_COMBINED;
+ handles[a].ssamp.shi[0].thread= a;
+
handles[a].type= type;
handles[a].zspan= MEM_callocN(sizeof(ZSpan), "zspan for bake");
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
new file mode 100644
index 00000000000..9ee88167c3e
--- /dev/null
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -0,0 +1,999 @@
+/**
+* $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation
+ * All rights reserved.
+ *
+ * Contributors: Hos, Robert Wenzlaff.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+
+#include "MTC_matrixops.h"
+#include "BLI_arithb.h"
+
+#include "DNA_group_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_material_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_node.h"
+
+/* local include */
+#include "renderpipeline.h"
+#include "render_types.h"
+#include "renderdatabase.h"
+#include "rendercore.h"
+#include "shadbuf.h"
+#include "shading.h"
+#include "texture.h"
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
+/* only to be used here in this file, it's for speed */
+extern struct Render R;
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+
+#define VECADDISFAC(v1,v3,fac) {*(v1)+= *(v3)*(fac); *(v1+1)+= *(v3+1)*(fac); *(v1+2)+= *(v3+2)*(fac);}
+
+
+
+/* Shade Sample order:
+
+- shade_samples_fill_with_ps()
+ - for each sample
+ - shade_input_set_triangle() <- if prev sample-face is same, use shade_input_copy_triangle()
+ - if vlr
+ - shade_input_set_viewco() <- not for ray or bake
+ - shade_input_set_uv() <- not for ray or bake
+ - shade_input_set_normals()
+- shade_samples()
+ - if shadow or AO
+ - shade_samples_do_shadow()
+ - if shading happens
+ - for each sample
+ - shade_input_set_shade_texco()
+ - shade_samples_do_shade()
+- OSA: distribute sample result with filter masking
+
+ */
+
+
+/* also used as callback for nodes */
+/* delivers a fully filled in ShadeResult, for all passes */
+void shade_material_loop(ShadeInput *shi, ShadeResult *shr)
+{
+
+ shade_lamp_loop(shi, shr); /* clears shr */
+
+ if(shi->translucency!=0.0f) {
+ ShadeResult shr_t;
+ float fac= shi->translucency;
+
+ /* gotta copy it again */
+ memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
+ shi->har= shi->mat->har;
+
+ VECCOPY(shi->vn, shi->vno);
+ VECMUL(shi->vn, -1.0f);
+ VECMUL(shi->facenor, -1.0f);
+ shi->depth++; /* hack to get real shadow now */
+ shade_lamp_loop(shi, &shr_t);
+ shi->depth--;
+
+ /* a couple of passes */
+ VECADDISFAC(shr->combined, shr_t.combined, fac);
+ if(shi->passflag & SCE_PASS_SPEC)
+ VECADDISFAC(shr->spec, shr_t.spec, fac);
+ if(shi->passflag & SCE_PASS_DIFFUSE)
+ VECADDISFAC(shr->diff_raw, shr_t.diff_raw, fac);
+ if(shi->passflag & SCE_PASS_SHADOW)
+ VECADDISFAC(shr->shad, shr_t.shad, fac);
+
+ VECMUL(shi->vn, -1.0f);
+ VECMUL(shi->facenor, -1.0f);
+ }
+
+ /* depth >= 1 when ray-shading */
+ if(shi->depth==0) {
+ if(R.r.mode & R_RAYTRACE) {
+ if(shi->ray_mirror!=0.0f || ((shi->mat->mode & MA_RAYTRANSP) && shr->alpha!=1.0f)) {
+
+ /* ray trace works on combined, but gives pass info */
+ ray_trace(shi, shr);
+ }
+ }
+ /* disable adding of sky for raytransp */
+ if(shi->mat->mode & MA_RAYTRANSP)
+ if(shi->layflag & SCE_LAY_SKY)
+ shr->alpha= 1.0f;
+ }
+}
+
+
+/* do a shade, finish up some passes, apply mist */
+void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr)
+{
+ float alpha;
+
+ /* ------ main shading loop -------- */
+
+ if(shi->mat->nodetree && shi->mat->use_nodes) {
+ ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
+ }
+ else {
+ /* copy all relevant material vars, note, keep this synced with render_types.h */
+ memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
+ shi->har= shi->mat->har;
+
+ shade_material_loop(shi, shr);
+ }
+
+ /* additional passes */
+ QUATCOPY(shr->winspeed, shi->winspeed);
+ VECCOPY(shr->nor, shi->vn);
+
+ /* MIST */
+ if((R.wrld.mode & WO_MIST) && (shi->mat->mode & MA_NOMIST)==0 ) {
+ if(R.r.mode & R_ORTHO)
+ alpha= mistfactor(-shi->co[2], shi->co);
+ else
+ alpha= mistfactor(VecLength(shi->co), shi->co);
+ }
+ else alpha= 1.0f;
+
+ /* add mist and premul color */
+ if(shr->alpha!=1.0f || alpha!=1.0f) {
+ float fac= alpha*(shr->alpha);
+
+ shr->combined[3]= fac;
+ shr->combined[0]*= fac;
+ shr->combined[1]*= fac;
+ shr->combined[2]*= fac;
+ }
+ else shr->combined[3]= 1.0f;
+
+}
+
+/* **************************************************************************** */
+/* ShadeInput */
+/* **************************************************************************** */
+
+
+void vlr_set_uv_indices(VlakRen *vlr, int *i1, int *i2, int *i3)
+{
+ /* to prevent storing new tfaces or vcols, we check a split runtime */
+ /* 4---3 4---3 */
+ /* |\ 1| or |1 /| */
+ /* |0\ | |/ 0| */
+ /* 1---2 1---2 0 = orig face, 1 = new face */
+
+ /* Update vert nums to point to correct verts of original face */
+ if(vlr->flag & R_DIVIDE_24) {
+ if(vlr->flag & R_FACE_SPLIT) {
+ (*i1)++; (*i2)++; (*i3)++;
+ }
+ else {
+ (*i3)++;
+ }
+ }
+ else if(vlr->flag & R_FACE_SPLIT) {
+ (*i2)++; (*i3)++;
+ }
+}
+
+
+/* copy data from face to ShadeInput, general case */
+/* indices 0 1 2 3 only. shi->puno should be set! */
+void shade_input_set_triangle_i(ShadeInput *shi, VlakRen *vlr, short i1, short i2, short i3)
+{
+ VertRen **vpp= &vlr->v1;
+
+ shi->vlr= vlr;
+
+ shi->v1= vpp[i1];
+ shi->v2= vpp[i2];
+ shi->v3= vpp[i3];
+
+ shi->i1= i1;
+ shi->i2= i2;
+ shi->i3= i3;
+
+ shi->mat= vlr->mat;
+ shi->osatex= (shi->mat->texco & TEXCO_OSA);
+
+ /* calculate vertexnormals */
+ if(vlr->flag & R_SMOOTH) {
+ float *n1= shi->v1->n, *n2= shi->v2->n, *n3= shi->v3->n;
+ char p1, p2, p3;
+
+ p1= 1<<i1;
+ p2= 1<<i2;
+ p3= 1<<i3;
+
+ if(shi->puno & p1) {
+ shi->n1[0]= -n1[0]; shi->n1[1]= -n1[1]; shi->n1[2]= -n1[2];
+ } else {
+ VECCOPY(shi->n1, n1);
+ }
+ if(shi->puno & p2) {
+ shi->n2[0]= -n2[0]; shi->n2[1]= -n2[1]; shi->n2[2]= -n2[2];
+ } else {
+ VECCOPY(shi->n2, n2);
+ }
+ if(shi->puno & p3) {
+ shi->n3[0]= -n3[0]; shi->n3[1]= -n3[1]; shi->n3[2]= -n3[2];
+ } else {
+ VECCOPY(shi->n3, n3);
+ }
+ }
+ /* facenormal copy, can get flipped */
+ VECCOPY(shi->facenor, vlr->n);
+
+}
+
+/* note, facenr declared volatile due to over-eager -O2 optimizations
+ * on cygwin (particularly -frerun-cse-after-loop)
+ */
+
+/* copy data from face to ShadeInput, scanline case */
+void shade_input_set_triangle(ShadeInput *shi, volatile int facenr, int normal_flip)
+{
+ if(facenr>0) {
+ shi->facenr= (facenr-1) & RE_QUAD_MASK;
+ if( shi->facenr < R.totvlak ) {
+ VlakRen *vlr= RE_findOrAddVlak(&R, shi->facenr);
+
+ shi->puno= normal_flip?vlr->puno:0;
+
+ if(facenr & RE_QUAD_OFFS)
+ shade_input_set_triangle_i(shi, vlr, 0, 2, 3);
+ else
+ shade_input_set_triangle_i(shi, vlr, 0, 1, 2);
+ }
+ else
+ shi->vlr= NULL; /* general signal we got sky */
+ }
+ else
+ shi->vlr= NULL; /* general signal we got sky */
+
+}
+
+/* full osa case: copy static info */
+void shade_input_copy_triangle(ShadeInput *shi, ShadeInput *from)
+{
+ /* not so nice, but works... warning is in RE_shader_ext.h */
+ memcpy(shi, from, sizeof(struct ShadeInputCopy));
+}
+
+
+/* scanline pixel coordinates */
+/* requires set_triangle */
+void shade_input_set_viewco(ShadeInput *shi, float x, float y, float z)
+{
+ float fac;
+
+ /* currently in use for dithering (soft shadow), node preview, irregular shad */
+ shi->xs= (int)(x);
+ shi->ys= (int)(y);
+
+ calc_view_vector(shi->view, x, y); /* returns not normalized, so is in viewplane coords */
+
+ /* wire cannot use normal for calculating shi->co */
+ if(shi->mat->mode & MA_WIRE) {
+
+ if(R.r.mode & R_ORTHO)
+ calc_renderco_ortho(shi->co, x, y, z);
+ else
+ calc_renderco_zbuf(shi->co, shi->view, z);
+ }
+ else {
+ float dface, *v1= shi->v1->co;
+
+ dface= v1[0]*shi->facenor[0]+v1[1]*shi->facenor[1]+v1[2]*shi->facenor[2];
+
+ /* ortho viewplane cannot intersect using view vector originating in (0,0,0) */
+ if(R.r.mode & R_ORTHO) {
+ /* x and y 3d coordinate can be derived from pixel coord and winmat */
+ float fx= 2.0f/(R.winx*R.winmat[0][0]);
+ float fy= 2.0f/(R.winy*R.winmat[1][1]);
+
+ shi->co[0]= (x - 0.5f*R.winx)*fx - R.winmat[3][0]/R.winmat[0][0];
+ shi->co[1]= (y - 0.5f*R.winy)*fy - R.winmat[3][1]/R.winmat[1][1];
+
+ /* using a*x + b*y + c*z = d equation, (a b c) is normal */
+ if(shi->facenor[2]!=0.0f)
+ shi->co[2]= (dface - shi->facenor[0]*shi->co[0] - shi->facenor[1]*shi->co[1])/shi->facenor[2];
+ else
+ shi->co[2]= 0.0f;
+
+ if(shi->osatex || (R.r.mode & R_SHADOW) ) {
+ shi->dxco[0]= fx;
+ shi->dxco[1]= 0.0f;
+ if(shi->facenor[2]!=0.0f)
+ shi->dxco[2]= (shi->facenor[0]*fx)/shi->facenor[2];
+ else
+ shi->dxco[2]= 0.0f;
+
+ shi->dyco[0]= 0.0f;
+ shi->dyco[1]= fy;
+ if(shi->facenor[2]!=0.0f)
+ shi->dyco[2]= (shi->facenor[1]*fy)/shi->facenor[2];
+ else
+ shi->dyco[2]= 0.0f;
+
+ if( (shi->mat->texco & TEXCO_REFL) ) {
+ if(shi->co[2]!=0.0f) fac= 1.0f/shi->co[2]; else fac= 0.0f;
+ shi->dxview= -R.viewdx*fac;
+ shi->dyview= -R.viewdy*fac;
+ }
+ }
+ }
+ else {
+ float div;
+
+ div= shi->facenor[0]*shi->view[0] + shi->facenor[1]*shi->view[1] + shi->facenor[2]*shi->view[2];
+ if (div!=0.0f) fac= dface/div;
+ else fac= 0.0f;
+
+ shi->co[0]= fac*shi->view[0];
+ shi->co[1]= fac*shi->view[1];
+ shi->co[2]= fac*shi->view[2];
+
+ /* pixel dx/dy for render coord */
+ if(shi->osatex || (R.r.mode & R_SHADOW) ) {
+ float u= dface/(div - R.viewdx*shi->facenor[0]);
+ float v= dface/(div - R.viewdy*shi->facenor[1]);
+
+ shi->dxco[0]= shi->co[0]- (shi->view[0]-R.viewdx)*u;
+ shi->dxco[1]= shi->co[1]- (shi->view[1])*u;
+ shi->dxco[2]= shi->co[2]- (shi->view[2])*u;
+
+ shi->dyco[0]= shi->co[0]- (shi->view[0])*v;
+ shi->dyco[1]= shi->co[1]- (shi->view[1]-R.viewdy)*v;
+ shi->dyco[2]= shi->co[2]- (shi->view[2])*v;
+
+ if( (shi->mat->texco & TEXCO_REFL) ) {
+ if(fac!=0.0f) fac= 1.0f/fac;
+ shi->dxview= -R.viewdx*fac;
+ shi->dyview= -R.viewdy*fac;
+ }
+ }
+ }
+ }
+
+ /* cannot normalise earlier, code above needs it at viewplane level */
+ Normalise(shi->view);
+}
+
+/* calculate U and V, for scanline (silly render face u and v are in range -1 to 0) */
+void shade_input_set_uv(ShadeInput *shi)
+{
+ VlakRen *vlr= shi->vlr;
+
+ if( (vlr->flag & R_SMOOTH) || (shi->mat->texco & NEED_UV) ) {
+ float *v1= shi->v1->co, *v2= shi->v2->co, *v3= shi->v3->co;
+
+ /* exception case for wire render of edge */
+ if(vlr->v2==vlr->v3) {
+ float lend, lenc;
+
+ lend= VecLenf(v2, v1);
+ lenc= VecLenf(shi->co, v1);
+
+ if(lend==0.0f) {
+ shi->u=shi->v= 0.0f;
+ }
+ else {
+ shi->u= - (1.0f - lenc/lend);
+ shi->v= 0.0f;
+ }
+
+ if(shi->osatex) {
+ shi->dx_u= 0.0f;
+ shi->dx_v= 0.0f;
+ shi->dy_u= 0.0f;
+ shi->dy_v= 0.0f;
+ }
+ }
+ else {
+ /* most of this could become re-used for faces */
+ float detsh, t00, t10, t01, t11;
+
+ if(vlr->snproj==0) {
+ t00= v3[0]-v1[0]; t01= v3[1]-v1[1];
+ t10= v3[0]-v2[0]; t11= v3[1]-v2[1];
+ }
+ else if(vlr->snproj==1) {
+ t00= v3[0]-v1[0]; t01= v3[2]-v1[2];
+ t10= v3[0]-v2[0]; t11= v3[2]-v2[2];
+ }
+ else {
+ t00= v3[1]-v1[1]; t01= v3[2]-v1[2];
+ t10= v3[1]-v2[1]; t11= v3[2]-v2[2];
+ }
+
+ detsh= 1.0f/(t00*t11-t10*t01);
+ t00*= detsh; t01*=detsh;
+ t10*=detsh; t11*=detsh;
+
+ if(vlr->snproj==0) {
+ shi->u= (shi->co[0]-v3[0])*t11-(shi->co[1]-v3[1])*t10;
+ shi->v= (shi->co[1]-v3[1])*t00-(shi->co[0]-v3[0])*t01;
+ if(shi->osatex) {
+ shi->dx_u= shi->dxco[0]*t11- shi->dxco[1]*t10;
+ shi->dx_v= shi->dxco[1]*t00- shi->dxco[0]*t01;
+ shi->dy_u= shi->dyco[0]*t11- shi->dyco[1]*t10;
+ shi->dy_v= shi->dyco[1]*t00- shi->dyco[0]*t01;
+ }
+ }
+ else if(vlr->snproj==1) {
+ shi->u= (shi->co[0]-v3[0])*t11-(shi->co[2]-v3[2])*t10;
+ shi->v= (shi->co[2]-v3[2])*t00-(shi->co[0]-v3[0])*t01;
+ if(shi->osatex) {
+ shi->dx_u= shi->dxco[0]*t11- shi->dxco[2]*t10;
+ shi->dx_v= shi->dxco[2]*t00- shi->dxco[0]*t01;
+ shi->dy_u= shi->dyco[0]*t11- shi->dyco[2]*t10;
+ shi->dy_v= shi->dyco[2]*t00- shi->dyco[0]*t01;
+ }
+ }
+ else {
+ shi->u= (shi->co[1]-v3[1])*t11-(shi->co[2]-v3[2])*t10;
+ shi->v= (shi->co[2]-v3[2])*t00-(shi->co[1]-v3[1])*t01;
+ if(shi->osatex) {
+ shi->dx_u= shi->dxco[1]*t11- shi->dxco[2]*t10;
+ shi->dx_v= shi->dxco[2]*t00- shi->dxco[1]*t01;
+ shi->dy_u= shi->dyco[1]*t11- shi->dyco[2]*t10;
+ shi->dy_v= shi->dyco[2]*t00- shi->dyco[1]*t01;
+ }
+ }
+ /* u and v are in range -1 to 0, we allow a little bit extra but not too much, screws up speedvectors */
+ CLAMP(shi->u, -2.0f, 1.0f);
+ CLAMP(shi->v, -2.0f, 1.0f);
+ }
+ }
+}
+
+void shade_input_set_normals(ShadeInput *shi)
+{
+ float u= shi->u, v= shi->v;
+ float l= 1.0f+u+v;
+
+ /* calculate vertexnormals */
+ if(shi->vlr->flag & R_SMOOTH) {
+ float *n1= shi->n1, *n2= shi->n2, *n3= shi->n3;
+
+ shi->vn[0]= l*n3[0]-u*n1[0]-v*n2[0];
+ shi->vn[1]= l*n3[1]-u*n1[1]-v*n2[1];
+ shi->vn[2]= l*n3[2]-u*n1[2]-v*n2[2];
+
+ Normalise(shi->vn);
+ }
+ else {
+ VECCOPY(shi->vn, shi->facenor);
+ }
+
+ /* used in nodes */
+ VECCOPY(shi->vno, shi->vn);
+
+}
+
+void shade_input_set_shade_texco(ShadeInput *shi)
+{
+ VertRen *v1= shi->v1, *v2= shi->v2, *v3= shi->v3;
+ float u= shi->u, v= shi->v;
+ float l= 1.0f+u+v, dl;
+ int mode= shi->mode= shi->mat->mode_l; /* or-ed result for all nodes */
+ short texco= shi->mat->texco;
+
+ /* calculate dxno and tangents */
+ if(shi->vlr->flag & R_SMOOTH) {
+
+ if(shi->osatex && (texco & (TEXCO_NORM|TEXCO_REFL)) ) {
+ float *n1= shi->n1, *n2= shi->n2, *n3= shi->n3;
+
+ dl= shi->dx_u+shi->dx_v;
+ shi->dxno[0]= dl*n3[0]-shi->dx_u*n1[0]-shi->dx_v*n2[0];
+ shi->dxno[1]= dl*n3[1]-shi->dx_u*n1[1]-shi->dx_v*n2[1];
+ shi->dxno[2]= dl*n3[2]-shi->dx_u*n1[2]-shi->dx_v*n2[2];
+ dl= shi->dy_u+shi->dy_v;
+ shi->dyno[0]= dl*n3[0]-shi->dy_u*n1[0]-shi->dy_v*n2[0];
+ shi->dyno[1]= dl*n3[1]-shi->dy_u*n1[1]-shi->dy_v*n2[1];
+ shi->dyno[2]= dl*n3[2]-shi->dy_u*n1[2]-shi->dy_v*n2[2];
+
+ }
+
+ /* qdn: normalmap tangent space */
+ if (mode & (MA_TANGENT_V|MA_NORMAP_TANG)) {
+ float *s1, *s2, *s3;
+
+ s1= RE_vertren_get_tangent(&R, v1, 0);
+ s2= RE_vertren_get_tangent(&R, v2, 0);
+ s3= RE_vertren_get_tangent(&R, v3, 0);
+ if(s1 && s2 && s3) {
+ shi->tang[0]= (l*s3[0] - u*s1[0] - v*s2[0]);
+ shi->tang[1]= (l*s3[1] - u*s1[1] - v*s2[1]);
+ shi->tang[2]= (l*s3[2] - u*s1[2] - v*s2[2]);
+ /* qdn: normalize just in case */
+ Normalise(shi->tang);
+ }
+ else shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f;
+ }
+ }
+ else {
+ /* qdn: normalmap tangent space */
+ if (mode & (MA_TANGENT_V|MA_NORMAP_TANG)) {
+ /* qdn: flat faces have tangents too,
+ could pick either one, using average here */
+ float *s1 = RE_vertren_get_tangent(&R, v1, 0);
+ float *s2 = RE_vertren_get_tangent(&R, v2, 0);
+ float *s3 = RE_vertren_get_tangent(&R, v3, 0);
+ if (s1 && s2 && s3) {
+ shi->tang[0] = (s1[0] + s2[0] + s3[0]);
+ shi->tang[1] = (s1[1] + s2[1] + s3[1]);
+ shi->tang[2] = (s1[2] + s2[2] + s3[2]);
+ Normalise(shi->tang);
+ }
+ }
+ }
+
+ if(R.r.mode & R_SPEED) {
+ float *s1, *s2, *s3;
+
+ s1= RE_vertren_get_winspeed(&R, v1, 0);
+ s2= RE_vertren_get_winspeed(&R, v2, 0);
+ s3= RE_vertren_get_winspeed(&R, v3, 0);
+ if(s1 && s2 && s3) {
+ shi->winspeed[0]= (l*s3[0] - u*s1[0] - v*s2[0]);
+ shi->winspeed[1]= (l*s3[1] - u*s1[1] - v*s2[1]);
+ shi->winspeed[2]= (l*s3[2] - u*s1[2] - v*s2[2]);
+ shi->winspeed[3]= (l*s3[3] - u*s1[3] - v*s2[3]);
+ }
+ else {
+ shi->winspeed[0]= shi->winspeed[1]= shi->winspeed[2]= shi->winspeed[3]= 0.0f;
+ }
+ }
+
+ /* texture coordinates. shi->dxuv shi->dyuv have been set */
+ if(texco & NEED_UV) {
+
+ if(texco & TEXCO_ORCO) {
+ if(v1->orco) {
+ float *o1, *o2, *o3;
+
+ o1= v1->orco;
+ o2= v2->orco;
+ o3= v3->orco;
+
+ shi->lo[0]= l*o3[0]-u*o1[0]-v*o2[0];
+ shi->lo[1]= l*o3[1]-u*o1[1]-v*o2[1];
+ shi->lo[2]= l*o3[2]-u*o1[2]-v*o2[2];
+
+ if(shi->osatex) {
+ dl= shi->dx_u+shi->dx_v;
+ shi->dxlo[0]= dl*o3[0]-shi->dx_u*o1[0]-shi->dx_v*o2[0];
+ shi->dxlo[1]= dl*o3[1]-shi->dx_u*o1[1]-shi->dx_v*o2[1];
+ shi->dxlo[2]= dl*o3[2]-shi->dx_u*o1[2]-shi->dx_v*o2[2];
+ dl= shi->dy_u+shi->dy_v;
+ shi->dylo[0]= dl*o3[0]-shi->dy_u*o1[0]-shi->dy_v*o2[0];
+ shi->dylo[1]= dl*o3[1]-shi->dy_u*o1[1]-shi->dy_v*o2[1];
+ shi->dylo[2]= dl*o3[2]-shi->dy_u*o1[2]-shi->dy_v*o2[2];
+ }
+ }
+ }
+
+ if(texco & TEXCO_GLOB) {
+ VECCOPY(shi->gl, shi->co);
+ MTC_Mat4MulVecfl(R.viewinv, shi->gl);
+ if(shi->osatex) {
+ VECCOPY(shi->dxgl, shi->dxco);
+ MTC_Mat3MulVecfl(R.imat, shi->dxco);
+ VECCOPY(shi->dygl, shi->dyco);
+ MTC_Mat3MulVecfl(R.imat, shi->dyco);
+ }
+ }
+
+ if(texco & TEXCO_STRAND) {
+ shi->strand= (l*v3->accum - u*v1->accum - v*v2->accum);
+ if(shi->osatex) {
+ dl= shi->dx_u+shi->dx_v;
+ shi->dxstrand= dl*v3->accum-shi->dx_u*v1->accum-shi->dx_v*v2->accum;
+ dl= shi->dy_u+shi->dy_v;
+ shi->dystrand= dl*v3->accum-shi->dy_u*v1->accum-shi->dy_v*v2->accum;
+ }
+ }
+
+ if((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE))) {
+ VlakRen *vlr= shi->vlr;
+ int j1=shi->i1, j2=shi->i2, j3=shi->i3;
+
+ /* uv and vcols are not copied on split, so set them according vlr divide flag */
+ vlr_set_uv_indices(vlr, &j1, &j2, &j3);
+
+ if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) {
+
+ if(vlr->vcol) {
+ char *cp1, *cp2, *cp3;
+
+ cp1= (char *)(vlr->vcol+j1);
+ cp2= (char *)(vlr->vcol+j2);
+ cp3= (char *)(vlr->vcol+j3);
+
+ shi->vcol[0]= (l*((float)cp3[3]) - u*((float)cp1[3]) - v*((float)cp2[3]))/255.0f;
+ shi->vcol[1]= (l*((float)cp3[2]) - u*((float)cp1[2]) - v*((float)cp2[2]))/255.0f;
+ shi->vcol[2]= (l*((float)cp3[1]) - u*((float)cp1[1]) - v*((float)cp2[1]))/255.0f;
+ }
+ else {
+ shi->vcol[0]= 0.0f;
+ shi->vcol[1]= 0.0f;
+ shi->vcol[2]= 0.0f;
+ }
+ }
+ if(vlr->tface) {
+ float *uv1, *uv2, *uv3;
+
+ uv1= vlr->tface->uv[j1];
+ uv2= vlr->tface->uv[j2];
+ uv3= vlr->tface->uv[j3];
+
+ shi->uv[0]= -1.0f + 2.0f*(l*uv3[0]-u*uv1[0]-v*uv2[0]);
+ shi->uv[1]= -1.0f + 2.0f*(l*uv3[1]-u*uv1[1]-v*uv2[1]);
+ shi->uv[2]= 0.0f; // texture.c assumes there are 3 coords
+
+ if(shi->osatex) {
+ float duv[2];
+
+ dl= shi->dx_u+shi->dx_v;
+ duv[0]= shi->dx_u;
+ duv[1]= shi->dx_v;
+
+ shi->dxuv[0]= 2.0f*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
+ shi->dxuv[1]= 2.0f*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
+
+ dl= shi->dy_u+shi->dy_v;
+ duv[0]= shi->dy_u;
+ duv[1]= shi->dy_v;
+
+ shi->dyuv[0]= 2.0f*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]);
+ shi->dyuv[1]= 2.0f*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
+ }
+ if(mode & MA_FACETEXTURE) {
+ if((mode & (MA_VERTEXCOL|MA_VERTEXCOLP))==0) {
+ shi->vcol[0]= 1.0f;
+ shi->vcol[1]= 1.0f;
+ shi->vcol[2]= 1.0f;
+ }
+ if(vlr->tface) render_realtime_texture(shi);
+ }
+ }
+ else {
+ shi->uv[0]= 2.0f*(u+.5f);
+ shi->uv[1]= 2.0f*(v+.5f);
+ shi->uv[2]= 0.0f; // texture.c assumes there are 3 coords
+ if(mode & MA_FACETEXTURE) {
+ /* no tface? set at 1.0f */
+ shi->vcol[0]= 1.0f;
+ shi->vcol[1]= 1.0f;
+ shi->vcol[2]= 1.0f;
+ }
+ }
+ }
+
+ if(texco & TEXCO_NORM) {
+ shi->orn[0]= -shi->vn[0];
+ shi->orn[1]= -shi->vn[1];
+ shi->orn[2]= -shi->vn[2];
+ }
+
+ if(mode & MA_RADIO) {
+ float *r1, *r2, *r3;
+
+ r1= RE_vertren_get_rad(&R, v1, 0);
+ r2= RE_vertren_get_rad(&R, v2, 0);
+ r3= RE_vertren_get_rad(&R, v3, 0);
+
+ if(r1 && r2 && r3) {
+ shi->rad[0]= (l*r3[0] - u*r1[0] - v*r2[0]);
+ shi->rad[1]= (l*r3[1] - u*r1[1] - v*r2[1]);
+ shi->rad[2]= (l*r3[2] - u*r1[2] - v*r2[2]);
+ }
+ else {
+ shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0f;
+ }
+ }
+ else {
+ shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0f;
+ }
+
+ if(texco & TEXCO_REFL) {
+ /* mirror reflection colour textures (and envmap) */
+ calc_R_ref(shi); /* wrong location for normal maps! XXXXXXXXXXXXXX */
+ }
+
+ if(texco & TEXCO_STRESS) {
+ float *s1, *s2, *s3;
+
+ s1= RE_vertren_get_stress(&R, v1, 0);
+ s2= RE_vertren_get_stress(&R, v2, 0);
+ s3= RE_vertren_get_stress(&R, v3, 0);
+ if(s1 && s2 && s3) {
+ shi->stress= l*s3[0] - u*s1[0] - v*s2[0];
+ if(shi->stress<1.0f) shi->stress-= 1.0f;
+ else shi->stress= (shi->stress-1.0f)/shi->stress;
+ }
+ else shi->stress= 0.0f;
+ }
+
+ if(texco & TEXCO_TANGENT) {
+ if((mode & MA_TANGENT_V)==0) {
+ /* just prevent surprises */
+ shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f;
+ }
+ }
+ }
+ else {
+ shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0f;
+ }
+
+ /* this only avalailable for scanline renders */
+ if(shi->depth==0) {
+ float x= shi->xs;
+ float y= shi->ys;
+
+ if(texco & TEXCO_WINDOW) {
+ shi->winco[0]= -1.0f + 2.0f*x/(float)R.winx;
+ shi->winco[1]= -1.0f + 2.0f*y/(float)R.winy;
+ shi->winco[2]= 0.0f;
+ if(shi->osatex) {
+ shi->dxwin[0]= 2.0f/(float)R.winx;
+ shi->dywin[1]= 2.0f/(float)R.winy;
+ shi->dxwin[1]= shi->dxwin[2]= 0.0f;
+ shi->dywin[0]= shi->dywin[2]= 0.0f;
+ }
+ }
+
+ if(texco & TEXCO_STICKY) {
+ float *s1, *s2, *s3;
+
+ s1= RE_vertren_get_sticky(&R, v1, 0);
+ s2= RE_vertren_get_sticky(&R, v2, 0);
+ s3= RE_vertren_get_sticky(&R, v3, 0);
+
+ if(s1 && s2 && s3) {
+ float Zmulx, Zmuly;
+ float hox, hoy, l, dl, u, v;
+ float s00, s01, s10, s11, detsh;
+
+ /* old globals, localized now */
+ Zmulx= ((float)R.winx)/2.0f; Zmuly= ((float)R.winy)/2.0f;
+
+ s00= v3->ho[0]/v3->ho[3] - v1->ho[0]/v1->ho[3];
+ s01= v3->ho[1]/v3->ho[3] - v1->ho[1]/v1->ho[3];
+ s10= v3->ho[0]/v3->ho[3] - v2->ho[0]/v2->ho[3];
+ s11= v3->ho[1]/v3->ho[3] - v2->ho[1]/v2->ho[3];
+
+ detsh= s00*s11-s10*s01;
+ s00/= detsh; s01/=detsh;
+ s10/=detsh; s11/=detsh;
+
+ /* recalc u and v again */
+ hox= x/Zmulx -1.0f;
+ hoy= y/Zmuly -1.0f;
+ u= (hox - v3->ho[0]/v3->ho[3])*s11 - (hoy - v3->ho[1]/v3->ho[3])*s10;
+ v= (hoy - v3->ho[1]/v3->ho[3])*s00 - (hox - v3->ho[0]/v3->ho[3])*s01;
+ l= 1.0f+u+v;
+
+ shi->sticky[0]= l*s3[0]-u*s1[0]-v*s2[0];
+ shi->sticky[1]= l*s3[1]-u*s1[1]-v*s2[1];
+ shi->sticky[2]= 0.0f;
+
+ if(shi->osatex) {
+ float dxuv[2], dyuv[2];
+ dxuv[0]= s11/Zmulx;
+ dxuv[1]= - s01/Zmulx;
+ dyuv[0]= - s10/Zmuly;
+ dyuv[1]= s00/Zmuly;
+
+ dl= dxuv[0] + dxuv[1];
+ shi->dxsticky[0]= dl*s3[0] - dxuv[0]*s1[0] - dxuv[1]*s2[0];
+ shi->dxsticky[1]= dl*s3[1] - dxuv[0]*s1[1] - dxuv[1]*s2[1];
+ dl= dyuv[0] + dyuv[1];
+ shi->dysticky[0]= dl*s3[0] - dyuv[0]*s1[0] - dyuv[1]*s2[0];
+ shi->dysticky[1]= dl*s3[1] - dyuv[0]*s1[1] - dyuv[1]*s2[1];
+ }
+ }
+ }
+ }
+}
+
+/* ****************** ShadeSample ************************************** */
+
+
+
+static void shade_input_initialize(ShadeInput *shi, RenderPart *pa, RenderLayer *rl, int sample)
+{
+
+ memset(shi, 0, sizeof(ShadeInput));
+
+ shi->sample= sample;
+ shi->thread= pa->thread;
+ shi->do_preview= R.r.scemode & R_NODE_PREVIEW;
+ shi->lay= rl->lay;
+ shi->layflag= rl->layflag;
+ shi->passflag= rl->passflag;
+
+ /* note shi.depth==0 means first hit, not raytracing */
+}
+
+void shade_sample_initialize(ShadeSample *ssamp, RenderPart *pa, RenderLayer *rl)
+{
+ int a, tot;
+
+ tot= R.osa==0?1:R.osa;
+
+ for(a=0; a<tot; a++) {
+ shade_input_initialize(&ssamp->shi[a], pa, rl, a);
+ memset(&ssamp->shr[a], 0, sizeof(RenderResult));
+ }
+}
+
+/* for all lamps, for all samples, do shadow */
+/* renderdata mode was checked for */
+void shade_samples_do_shadow(ShadeSample *ssamp)
+{
+ GroupObject *go;
+ LampRen *lar;
+ ShadeInput *shi;
+ int sample;
+
+ if(ssamp->shi[0].passflag & (SCE_PASS_COMBINED|SCE_PASS_DIFFUSE|SCE_PASS_SPEC|SCE_PASS_SHADOW)) {
+ for(go=R.lights.first; go; go= go->next) {
+ lar= go->lampren;
+
+ /* if there's shadow */
+ if(lar->shb || (lar->mode & LA_SHAD_RAY)) {
+
+ for(sample=0, shi= ssamp->shi; sample<ssamp->tot; shi++, sample++) {
+ float visifac, lv[3], lampdist, inpr;
+
+ /* three tests to quickly reject */
+ if(!(shi->mat->mode & MA_SHADOW) || (shi->mat->mode & MA_SHLESS))
+ continue;
+
+ visifac= lamp_get_visibility(lar, shi->co, lv, &lampdist);
+ if(visifac==0.0f)
+ continue;
+
+ inpr= INPR(shi->vn, lv);
+
+ /* tangential faces always look at lamp */
+ if( (shi->mat->mode & MA_TANGENT_V) || (shi->vlr->flag & R_TANGENT) )
+ inpr= 1.0f - inpr*inpr;
+ else if(inpr <= 0.0f)
+ continue;
+
+ /* now we're going (1 = do it real) */
+ lamp_get_shadow(lar, shi, inpr, lar->shadsamp[shi->thread].shadfac[sample], 1);
+ }
+ }
+ }
+ }
+
+ /* do the AO */
+ if(R.wrld.mode & WO_AMB_OCC)
+ if(ssamp->shi[0].passflag & (SCE_PASS_COMBINED|SCE_PASS_DIFFUSE|SCE_PASS_AO))
+ for(sample=0, shi= ssamp->shi; sample<ssamp->tot; shi++, sample++)
+ if(!(shi->mat->mode & MA_SHLESS))
+ if(shi->mat->mode & MA_SHADOW)
+ ambient_occlusion(shi); /* stores in shi->ao[] */
+
+}
+
+static void shade_samples_fill_with_ps(ShadeSample *ssamp, PixStr *ps, int x, int y)
+{
+ ShadeInput *shi;
+ float xs, ys;
+
+ ssamp->tot= 0;
+
+ for(shi= ssamp->shi; ps; ps= ps->next, shi++) {
+ shade_input_set_triangle(shi, ps->facenr, 1);
+
+ /* officially should always be true... we have no sky info */
+ if(shi->vlr) {
+ unsigned short curmask= ps->mask;
+
+ /* full osa is only set for OSA renders */
+ if(shi->vlr->flag & R_FULL_OSA) {
+ short shi_inc= 0, samp;
+
+ for(samp=0; samp<R.osa; samp++) {
+ if(curmask & (1<<samp)) {
+ xs= (float)x + R.jit[samp][0] + 0.5f; /* zbuffer has this inverse corrected, ensures xs,ys are inside pixel */
+ ys= (float)y + R.jit[samp][1] + 0.5f;
+
+ if(shi_inc) {
+ shade_input_copy_triangle(shi+1, shi);
+ shi++;
+ }
+ shi->mask= (1<<samp);
+ shade_input_set_viewco(shi, xs, ys, (float)ps->z);
+ shade_input_set_uv(shi);
+ shade_input_set_normals(shi);
+
+ shi_inc= 1;
+ }
+ }
+ }
+ else {
+ if(R.osa) {
+ short b= R.samples->centmask[curmask];
+ xs= (float)x + R.samples->centLut[b & 15] + 0.5f;
+ ys= (float)y + R.samples->centLut[b>>4] + 0.5f;
+ }
+ else {
+ xs= (float)x + 0.5f;
+ ys= (float)y + 0.5f;
+ }
+ shi->mask= curmask;
+ shade_input_set_viewco(shi, xs, ys, (float)ps->z);
+ shade_input_set_uv(shi);
+ shade_input_set_normals(shi);
+ }
+
+ /* total sample amount, shi->sample is static set in initialize */
+ ssamp->tot= shi->sample+1;
+ }
+ }
+}
+
+/* shades samples, returns true if anything happened */
+int shade_samples(ShadeSample *ssamp, PixStr *ps, int x, int y)
+{
+ shade_samples_fill_with_ps(ssamp, ps, x, y);
+
+ if(ssamp->tot) {
+ ShadeInput *shi= ssamp->shi;
+ ShadeResult *shr= ssamp->shr;
+ int samp;
+
+ /* if shadow or AO? */
+ if(R.r.mode & R_SHADOW)
+ shade_samples_do_shadow(ssamp);
+
+ /* if shade (all shadepinputs have same passflag) */
+ if(ssamp->shi[0].passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB)) {
+
+ for(samp=0; samp<ssamp->tot; samp++, shi++, shr++) {
+ shade_input_set_shade_texco(shi);
+ shade_input_do_shade(shi, shr);
+ }
+ }
+
+ return 1;
+ }
+ return 0;
+}
+
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
new file mode 100644
index 00000000000..e62291497ce
--- /dev/null
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -0,0 +1,1558 @@
+/**
+* $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation
+ * All rights reserved.
+ *
+ * Contributors: Hos, Robert Wenzlaff.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+
+#include "MTC_matrixops.h"
+#include "BLI_arithb.h"
+
+#include "BKE_material.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+
+#include "DNA_group_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+
+/* local include */
+#include "renderpipeline.h"
+#include "render_types.h"
+#include "pixelblending.h"
+#include "rendercore.h"
+#include "shadbuf.h"
+#include "texture.h"
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
+/* only to be used here in this file, it's for speed */
+extern struct Render R;
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+
+#if 0
+static void fogcolor(float *colf, float *rco, float *view)
+{
+ 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;
+
+ VECCOPY(vec, rco);
+
+ /* 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();
+ for(dist= startdist; dist>R.wrld.miststa; dist-= stepsize) {
+
+ 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);
+
+ VECSUB(vec, vec, dview);
+ }
+}
+#endif
+
+/* zcor is distance, co the 3d coordinate in eye space, return alpha */
+float mistfactor(float zcor, float *co)
+{
+ float fac, hi;
+
+ fac= zcor - R.wrld.miststa; /* zcor is calculated per pixel */
+
+ /* fac= -co[2]-R.wrld.miststa; */
+
+ if(fac>0.0f) {
+ if(fac< R.wrld.mistdist) {
+
+ fac= (fac/(R.wrld.mistdist));
+
+ if(R.wrld.mistype==0) fac*= fac;
+ else if(R.wrld.mistype==1);
+ else fac= sqrt(fac);
+ }
+ else fac= 1.0f;
+ }
+ else fac= 0.0f;
+
+ /* height switched off mist */
+ if(R.wrld.misthi!=0.0f && fac!=0.0f) {
+ /* at height misthi the mist is completely gone */
+
+ hi= R.viewinv[0][2]*co[0]+R.viewinv[1][2]*co[1]+R.viewinv[2][2]*co[2]+R.viewinv[3][2];
+
+ if(hi>R.wrld.misthi) fac= 0.0f;
+ else if(hi>0.0f) {
+ hi= (R.wrld.misthi-hi)/R.wrld.misthi;
+ fac*= hi*hi;
+ }
+ }
+
+ return (1.0f-fac)* (1.0f-R.wrld.misi);
+}
+
+static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens)
+{
+ double a, b, c, disc, nray[3], npos[3];
+ float t0, t1 = 0.0f, t2= 0.0f, t3, haint;
+ float p1[3], p2[3], ladist, maxz = 0.0f, maxy = 0.0f;
+ int snijp, doclip=1, use_yco=0;
+ int ok1=0, ok2=0;
+
+ *intens= 0.0f;
+ haint= lar->haint;
+
+ if(R.r.mode & R_ORTHO) {
+ /* 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];
+ MTC_Mat3MulVecfl(lar->imat, p1);
+ VECCOPY(npos, p1); // npos is double!
+ }
+ else {
+ VECCOPY(npos, lar->sh_invcampos); /* in initlamp calculated */
+ }
+
+ /* rotate view */
+ VECCOPY(nray, shi->view);
+ MTC_Mat3MulVecd(lar->imat, nray);
+
+ if(R.wrld.mode & WO_MIST) {
+ /* patchy... */
+ haint *= mistfactor(-lar->co[2], lar->co);
+ if(haint==0.0f) {
+ return;
+ }
+ }
+
+
+ /* rotate maxz */
+ if(shi->co[2]==0.0f) doclip= 0; /* for when halo at sky */
+ 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];
+
+ if( fabs(nray[2]) <0.000001f ) use_yco= 1;
+ }
+
+ /* scale z to make sure volume is normalized */
+ nray[2]*= lar->sh_zfac;
+ /* 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];
+
+ snijp= 0;
+ if (fabs(a) < 0.00000001) {
+ /*
+ * Only one intersection point...
+ */
+ return;
+ }
+ else {
+ disc = b*b - a*c;
+
+ if(disc==0.0) {
+ t1=t2= (-b)/ a;
+ snijp= 2;
+ }
+ else if (disc > 0.0) {
+ disc = sqrt(disc);
+ t1 = (-b + disc) / a;
+ t2 = (-b - disc) / a;
+ snijp= 2;
+ }
+ }
+ if(snijp==2) {
+ /* sort */
+ if(t1>t2) {
+ 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 */
+ if(p1[2]<=0.0f) ok1= 1;
+ if(p2[2]<=0.0f && t1!=t2) ok2= 1;
+
+ /* at least 1 point with negative z */
+ if(ok1==0 && ok2==0) return;
+
+ /* intersction point with -ladist, the bottom of the cone */
+ if(use_yco==0) {
+ t3= (-ladist-npos[2])/nray[2];
+
+ /* de we have to replace one of the intersection points? */
+ if(ok1) {
+ if(p1[2]<-ladist) t1= t3;
+ }
+ else {
+ ok1= 1;
+ t1= t3;
+ }
+ if(ok2) {
+ if(p2[2]<-ladist) t2= t3;
+ }
+ else {
+ ok2= 1;
+ t2= t3;
+ }
+ }
+ else if(ok1==0 || ok2==0) return;
+
+ /* at least 1 visible interesction point */
+ if(t1<0.0f && t2<0.0f) return;
+
+ if(t1<0.0f) t1= 0.0f;
+ if(t2<0.0f) t2= 0.0f;
+
+ if(t1==t2) return;
+
+ /* sort again to be sure */
+ if(t1>t2) {
+ a= t1; t1= t2; t2= a;
+ }
+
+ /* calculate t0: is the maximum visible z (when halo is intersected by face) */
+ if(doclip) {
+ if(use_yco==0) t0= (maxz-npos[2])/nray[2];
+ else t0= (maxy-npos[1])/nray[1];
+
+ if(t0<t1) return;
+ if(t0<t2) t2= t0;
+ }
+
+ /* 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 */
+
+ a= sqrt(p1[0]*p1[0]+p1[1]*p1[1]+p1[2]*p1[2]);
+ b= sqrt(p2[0]*p2[0]+p2[1]*p2[1]+p2[2]*p2[2]);
+ c= VecLenf(p1, p2);
+
+ 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
+ at the edges (especially with narrow halos) */
+ if(*intens<=0.0f) return;
+
+ /* soft area */
+ /* not needed because t0 has been used for p1/p2 as well */
+ /* if(doclip && t0<t2) { */
+ /* *intens *= (t0-t1)/(t2-t1); */
+ /* } */
+
+ *intens *= haint;
+
+ if(lar->shb && lar->shb->shadhalostep) {
+ *intens *= shadow_halo(lar, p1, p2);
+ }
+
+ }
+}
+
+void renderspothalo(ShadeInput *shi, float *col, float alpha)
+{
+ GroupObject *go;
+ LampRen *lar;
+ float i;
+
+ if(alpha==0.0f) return;
+
+ for(go=R.lights.first; go; go= go->next) {
+ lar= go->lampren;
+
+ if(lar->type==LA_SPOT && (lar->mode & LA_HALO) && lar->haint>0) {
+ if((lar->lay & shi->lay)==0) continue;
+
+ spothalo(lar, shi, &i);
+ if(i>0.0f) {
+ col[3]+= i*alpha; // all premul
+ col[0]+= i*lar->r*alpha;
+ col[1]+= i*lar->g*alpha;
+ col[2]+= i*lar->b*alpha;
+ }
+ }
+ }
+ /* clip alpha, is needed for unified 'alpha threshold' (vanillaRenderPipe.c) */
+ if(col[3]>1.0f) col[3]= 1.0f;
+}
+
+
+
+/* ---------------- shaders ----------------------- */
+
+static double Normalise_d(double *n)
+{
+ double d;
+
+ d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+
+ if(d>0.00000000000000001) {
+ d= sqrt(d);
+
+ n[0]/=d;
+ n[1]/=d;
+ n[2]/=d;
+ } else {
+ n[0]=n[1]=n[2]= 0.0;
+ d= 0.0;
+ }
+ return d;
+}
+
+/* mix of 'real' fresnel and allowing control. grad defines blending gradient */
+float fresnel_fac(float *view, float *vn, float grad, float fac)
+{
+ float t1, t2;
+
+ if(fac==0.0f) return 1.0f;
+
+ t1= (view[0]*vn[0] + view[1]*vn[1] + view[2]*vn[2]);
+ if(t1>0.0f) t2= 1.0f+t1;
+ else t2= 1.0f-t1;
+
+ t2= grad + (1.0f-grad)*pow(t2, fac);
+
+ if(t2<0.0f) return 0.0f;
+ else if(t2>1.0f) return 1.0f;
+ return t2;
+}
+
+static double saacos_d(double fac)
+{
+ if(fac<= -1.0f) return M_PI;
+ else if(fac>=1.0f) return 0.0;
+ else return acos(fac);
+}
+
+/* Stoke's form factor. Need doubles here for extreme small area sizes */
+static float area_lamp_energy(float *co, float *vn, LampRen *lar)
+{
+ 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 */
+
+ VECSUB(vec[0], co, lar->area[0]);
+ VECSUB(vec[1], co, lar->area[1]);
+ VECSUB(vec[2], co, lar->area[2]);
+ VECSUB(vec[3], co, lar->area[3]);
+
+ Normalise_d(vec[0]);
+ Normalise_d(vec[1]);
+ Normalise_d(vec[2]);
+ Normalise_d(vec[3]);
+
+ /* cross product */
+ 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]);
+
+ Normalise_d(cross[0]);
+ Normalise_d(cross[1]);
+ Normalise_d(cross[2]);
+ Normalise_d(cross[3]);
+
+ /* 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]);
+
+ if(fac<=0.0) return 0.0;
+ return pow(fac*lar->areasize, lar->k); // corrected for buttons size and lar->dist^2
+}
+
+static float spec(float inp, int hard)
+{
+ float b1;
+
+ if(inp>=1.0f) return 1.0f;
+ else if (inp<=0.0f) return 0.0f;
+
+ b1= inp*inp;
+ /* avoid FPE */
+ if(b1<0.01f) b1= 0.01f;
+
+ if((hard & 1)==0) inp= 1.0f;
+ if(hard & 2) inp*= b1;
+ b1*= b1;
+ if(hard & 4) inp*= b1;
+ b1*= b1;
+ if(hard & 8) inp*= b1;
+ b1*= b1;
+ if(hard & 16) inp*= b1;
+ b1*= b1;
+
+ /* avoid FPE */
+ if(b1<0.001f) b1= 0.0f;
+
+ if(hard & 32) inp*= b1;
+ b1*= b1;
+ if(hard & 64) inp*=b1;
+ b1*= b1;
+ if(hard & 128) inp*=b1;
+
+ if(b1<0.001f) b1= 0.0f;
+
+ if(hard & 256) {
+ b1*= b1;
+ inp*=b1;
+ }
+
+ return inp;
+}
+
+static float Phong_Spec( float *n, float *l, float *v, int hard, int tangent )
+{
+ float h[3];
+ float rslt;
+
+ h[0] = l[0] + v[0];
+ h[1] = l[1] + v[1];
+ h[2] = l[2] + v[2];
+ Normalise(h);
+
+ rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2];
+ if(tangent) rslt= sasqrt(1.0f - rslt*rslt);
+
+ if( rslt > 0.0f ) rslt= spec(rslt, hard);
+ else rslt = 0.0f;
+
+ return rslt;
+}
+
+
+/* reduced cook torrance spec (for off-specular peak) */
+static float CookTorr_Spec(float *n, float *l, float *v, int hard, int tangent)
+{
+ float i, nh, nv, h[3];
+
+ h[0]= v[0]+l[0];
+ h[1]= v[1]+l[1];
+ h[2]= v[2]+l[2];
+ Normalise(h);
+
+ nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2];
+ if(tangent) nh= sasqrt(1.0f - nh*nh);
+ else if(nh<0.0f) return 0.0f;
+
+ nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2];
+ if(tangent) nv= sasqrt(1.0f - nv*nv);
+ else if(nv<0.0f) nv= 0.0f;
+
+ i= spec(nh, hard);
+
+ i= i/(0.1+nv);
+ return i;
+}
+
+/* Blinn spec */
+static float Blinn_Spec(float *n, float *l, float *v, float refrac, float spec_power, int tangent)
+{
+ float i, nh, nv, nl, vh, h[3];
+ float a, b, c, g=0.0f, p, f, ang;
+
+ if(refrac < 1.0f) return 0.0f;
+ if(spec_power == 0.0f) return 0.0f;
+
+ /* conversion from 'hardness' (1-255) to 'spec_power' (50 maps at 0.1) */
+ if(spec_power<100.0f)
+ spec_power= sqrt(1.0f/spec_power);
+ 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];
+ Normalise(h);
+
+ nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
+ if(tangent) nh= sasqrt(1.0f - nh*nh);
+ else if(nh<0.0f) return 0.0f;
+
+ nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
+ if(tangent) nv= sasqrt(1.0f - nv*nv);
+ if(nv<=0.01f) nv= 0.01f; /* hrms... */
+
+ nl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
+ if(tangent) nl= sasqrt(1.0f - nl*nl);
+ if(nl<=0.01f) {
+ 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 */
+ if(vh<=0.0f) vh= 0.01f;
+
+ a = 1.0f;
+ b = (2.0f*nh*nv)/vh;
+ c = (2.0f*nh*nl)/vh;
+
+ if( a < b && a < c ) g = a;
+ else if( b < a && b < c ) g = b;
+ else if( c < a && c < b ) g = c;
+
+ p = sqrt( (double)((refrac * refrac)+(vh*vh)-1.0f) );
+ 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)));
+ if(i<0.0f) i= 0.0f;
+
+ return i;
+}
+
+/* cartoon render spec */
+static float Toon_Spec( float *n, float *l, float *v, float size, float smooth, int tangent)
+{
+ 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];
+ Normalise(h);
+
+ rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2];
+ if(tangent) rslt = sasqrt(1.0f - rslt*rslt);
+
+ ang = saacos( rslt );
+
+ if( ang < size ) rslt = 1.0f;
+ else if( ang >= (size + smooth) || smooth == 0.0f ) rslt = 0.0f;
+ else rslt = 1.0f - ((ang - size) / smooth);
+
+ return rslt;
+}
+
+/* Ward isotropic gaussian spec */
+static float WardIso_Spec( float *n, float *l, float *v, float rms, int tangent)
+{
+ 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];
+ Normalise(h);
+
+ nh = n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
+ if(tangent) nh = sasqrt(1.0f - nh*nh);
+ if(nh<=0.0f) nh = 0.001f;
+
+ nv = n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
+ if(tangent) nv = sasqrt(1.0f - nv*nv);
+ if(nv<=0.0f) nv = 0.001f;
+
+ nl = n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
+ if(tangent) nl = sasqrt(1.0f - nl*nl);
+ if(nl<=0.0f) nl = 0.001f;
+
+ angle = tan(saacos(nh));
+ alpha = MAX2(rms, 0.001f);
+
+ i= nl * (1.0f/(4.0f*M_PI*alpha*alpha)) * (exp( -(angle*angle)/(alpha*alpha))/(sqrt(nv*nl)));
+
+ return i;
+}
+
+/* cartoon render diffuse */
+static float Toon_Diff( float *n, float *l, float *v, float size, float smooth )
+{
+ float rslt, ang;
+
+ rslt = n[0]*l[0] + n[1]*l[1] + n[2]*l[2];
+
+ ang = saacos( (double)(rslt) );
+
+ if( ang < size ) rslt = 1.0f;
+ else if( ang >= (size + smooth) || smooth == 0.0f ) rslt = 0.0f;
+ 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' */
+static float OrenNayar_Diff(float nl, float *n, float *l, float *v, float rough )
+{
+ float i, nh, nv, vh, realnl, h[3];
+ 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];
+ Normalise(h);
+
+ nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
+ if(nh<0.0f) nh = 0.0f;
+
+ nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
+ if(nv<=0.0f) nv= 0.0f;
+
+ realnl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */
+ if(realnl<=0.0f) return 0.0f;
+ if(nl<0.0f) return 0.0f; /* value from area light */
+
+ vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; /* Dot product between view vector and halfway vector */
+ if(vh<=0.0f) vh= 0.0f;
+
+ 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]);
+ Normalise( Lit_B );
+
+ View_B[0] = v[0] - (nv * n[0]);
+ View_B[1] = v[1] - (nv * n[1]);
+ View_B[2] = v[2] - (nv * n[2]);
+ Normalise( View_B );
+
+ t = Lit_B[0]*View_B[0] + Lit_B[1]*View_B[1] + Lit_B[2]*View_B[2];
+ if( t < 0 ) t = 0;
+
+ if( Lit_A > View_A ) {
+ 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 */
+ i = nl * ( A + ( B * t * sin(a) * tan(b) ) );
+
+ return i;
+}
+
+/* Minnaert diffuse */
+static float Minnaert_Diff(float nl, float *n, float *v, float darkness)
+{
+
+ 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 */
+ nv = n[0]*v[0]+n[1]*v[1]+n[2]*v[2];
+ if (nv < 0.0f)
+ nv = 0.0f;
+
+ if (darkness <= 1.0f)
+ i = nl * pow(MAX2(nv*nl, 0.1f), (darkness - 1.0f) ); /*The Real model*/
+ else
+ i = nl * pow( (1.001f - nv), (darkness - 1.0f) ); /*Nvidia model*/
+
+ return i;
+}
+
+static float Fresnel_Diff(float *vn, float *lv, float *view, float fac_i, float fac)
+{
+ 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]);
+ if(shi->osatex) {
+ if(shi->vlr->flag & R_SMOOTH) {
+ 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]);
+ }
+ }
+
+}
+
+/* called from ray.c */
+void shade_color(ShadeInput *shi, ShadeResult *shr)
+{
+ Material *ma= shi->mat;
+
+ if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
+ shi->r= shi->vcol[0];
+ shi->g= shi->vcol[1];
+ shi->b= shi->vcol[2];
+ }
+
+ if(ma->texco) {
+ if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
+ shi->r= shi->vcol[0];
+ shi->g= shi->vcol[1];
+ shi->b= shi->vcol[2];
+ }
+ do_material_tex(shi);
+ }
+
+ if(ma->fresnel_tra!=0.0f)
+ shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra);
+
+ shr->diff[0]= shi->r;
+ shr->diff[1]= shi->g;
+ shr->diff[2]= shi->b;
+ shr->alpha= shi->alpha;
+}
+
+/* ramp for at end of shade */
+static void ramp_diffuse_result(float *diff, ShadeInput *shi)
+{
+ Material *ma= shi->mat;
+ float col[4], fac=0;
+
+ if(ma->ramp_col) {
+ if(ma->rampin_col==MA_RAMP_IN_RESULT) {
+
+ fac= 0.3*diff[0] + 0.58*diff[1] + 0.12*diff[2];
+ do_colorband(ma->ramp_col, fac, col);
+
+ /* blending method */
+ fac= col[3]*ma->rampfac_col;
+
+ ramp_blend(ma->rampblend_col, diff, diff+1, diff+2, fac, col);
+ }
+ }
+}
+
+/* r,g,b denote energy, ramp is used with different values to make new material color */
+static void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, float g, float b)
+{
+ Material *ma= shi->mat;
+ float col[4], colt[3], fac=0;
+
+ if(ma->ramp_col && (ma->mode & MA_RAMP_COL)) {
+
+ /* MA_RAMP_IN_RESULT is exceptional */
+ if(ma->rampin_col==MA_RAMP_IN_RESULT) {
+ // normal add
+ diff[0] += r * shi->r;
+ diff[1] += g * shi->g;
+ diff[2] += b * shi->b;
+ }
+ else {
+ /* input */
+ switch(ma->rampin_col) {
+ case MA_RAMP_IN_ENERGY:
+ fac= 0.3*r + 0.58*g + 0.12*b;
+ 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;
+ }
+
+ do_colorband(ma->ramp_col, fac, col);
+
+ /* blending method */
+ fac= col[3]*ma->rampfac_col;
+ colt[0]= shi->r;
+ colt[1]= shi->g;
+ colt[2]= shi->b;
+
+ ramp_blend(ma->rampblend_col, colt, colt+1, colt+2, fac, col);
+
+ /* output to */
+ diff[0] += r * colt[0];
+ diff[1] += g * colt[1];
+ diff[2] += b * colt[2];
+ }
+ }
+ else {
+ diff[0] += r * shi->r;
+ diff[1] += g * shi->g;
+ diff[2] += b * shi->b;
+ }
+}
+
+static void ramp_spec_result(float *specr, float *specg, float *specb, ShadeInput *shi)
+{
+ Material *ma= shi->mat;
+ float col[4];
+ float fac;
+
+ if(ma->ramp_spec && (ma->rampin_spec==MA_RAMP_IN_RESULT)) {
+ fac= 0.3*(*specr) + 0.58*(*specg) + 0.12*(*specb);
+ do_colorband(ma->ramp_spec, fac, col);
+
+ /* blending method */
+ fac= col[3]*ma->rampfac_spec;
+
+ ramp_blend(ma->rampblend_spec, specr, specg, specb, fac, col);
+
+ }
+}
+
+/* is = dot product shade, t = spec energy */
+static void do_specular_ramp(ShadeInput *shi, float is, float t, float *spec)
+{
+ Material *ma= shi->mat;
+ float col[4];
+ float fac=0.0f;
+
+ spec[0]= shi->specr;
+ spec[1]= shi->specg;
+ spec[2]= shi->specb;
+
+ /* MA_RAMP_IN_RESULT is exception */
+ if(ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) {
+
+ /* input */
+ switch(ma->rampin_spec) {
+ 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;
+ }
+
+ do_colorband(ma->ramp_spec, fac, col);
+
+ /* blending method */
+ fac= col[3]*ma->rampfac_spec;
+
+ ramp_blend(ma->rampblend_spec, spec, spec+1, spec+2, fac, col);
+ }
+}
+
+/* pure AO, check for raytrace and world should have been done */
+void ambient_occlusion(ShadeInput *shi)
+{
+
+ if((R.r.mode & R_RAYTRACE) && shi->mat->amb!=0.0f)
+ ray_ao(shi, shi->ao);
+ else
+ shi->ao[0]= shi->ao[1]= shi->ao[2]= 1.0f;
+}
+
+
+/* wrld mode was checked for */
+void ambient_occlusion_to_diffuse(ShadeInput *shi, float *diff)
+{
+
+ if((R.r.mode & R_RAYTRACE) && shi->mat->amb!=0.0f) {
+ float f= R.wrld.aoenergy*shi->mat->amb;
+
+ if (R.wrld.aomix==WO_AOADDSUB) {
+ diff[0] = 2.0f*shi->ao[0]-1.0f;
+ diff[1] = 2.0f*shi->ao[1]-1.0f;
+ diff[2] = 2.0f*shi->ao[2]-1.0f;
+ }
+ else if (R.wrld.aomix==WO_AOSUB) {
+ diff[0] = shi->ao[0]-1.0f;
+ diff[1] = shi->ao[1]-1.0f;
+ diff[2] = shi->ao[2]-1.0f;
+ }
+ else {
+ VECCOPY(diff, shi->ao);
+ }
+
+ VECMUL(diff, f);
+ }
+ else
+ diff[0]= diff[1]= diff[2]= 0.0f;
+}
+
+/* result written in shadfac */
+void lamp_get_shadow(LampRen *lar, ShadeInput *shi, float inp, float *shadfac, int do_real)
+{
+
+ if(do_real) {
+
+ shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 1.0f;
+
+ if(lar->shb) {
+ if(lar->buftype==LA_SHADBUF_IRREGULAR)
+ shadfac[3]= ISB_getshadow(shi, lar->shb);
+ else
+ shadfac[3] = testshadowbuf(lar->shb, shi->co, shi->dxco, shi->dyco, inp);
+ }
+ else if(lar->mode & LA_SHAD_RAY) {
+ ray_shadow(shi, lar, shadfac);
+ }
+ }
+ else {
+ float *fp= lar->shadsamp[shi->thread].shadfac[shi->sample];
+ QUATCOPY(shadfac, fp);
+ }
+}
+
+/* lampdistance and spot angle, writes in lv and dist */
+float lamp_get_visibility(LampRen *lar, float *co, float *lv, float *dist)
+{
+ if(lar->type==LA_SUN || lar->type==LA_HEMI) {
+ *dist= 1.0f;
+ VECCOPY(lv, lar->vec);
+ return 1.0f;
+ }
+ else {
+ float visifac, t;
+
+ VECSUB(lv, co, lar->co);
+ *dist= sqrt( INPR(lv, lv));
+ t= 1.0f/dist[0];
+ VECMUL(lv, t);
+
+ /* area type has no quad or sphere option */
+ if(lar->type==LA_AREA) {
+ /* area is single sided */
+ if(INPR(lv, lar->vec) > 0.0f)
+ visifac= 1.0f;
+ else
+ visifac= 0.0f;
+ }
+ else {
+ if(lar->mode & LA_QUAD) {
+ if(lar->ld1>0.0f)
+ visifac= lar->dist/(lar->dist+lar->ld1*dist[0]);
+ if(lar->ld2>0.0f)
+ visifac*= lar->distkw/(lar->distkw+lar->ld2*dist[0]*dist[0]);
+ }
+ else {
+ visifac= (lar->dist/(lar->dist+dist[0]));
+ }
+
+ if(lar->mode & LA_SPHERE) {
+ float t= lar->dist - dist[0];
+ if(t<=0.0f)
+ visifac= 0.0f;
+ else
+ visifac*= t/lar->dist;
+ }
+
+ if(visifac > 0.0f) {
+ if(lar->type==LA_SPOT) {
+ float inpr;
+
+ if(lar->mode & LA_SQUARE) {
+ if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0f) {
+ float lvrot[3], x;
+
+ /* rotate view to lampspace */
+ VECCOPY(lvrot, lv);
+ MTC_Mat3MulVecfl(lar->imat, lvrot);
+
+ x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
+ /* 1.0f/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
+
+ inpr= 1.0f/(sqrt(1.0f+x*x));
+ }
+ else inpr= 0.0f;
+ }
+ else {
+ inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
+ }
+
+ t= lar->spotsi;
+ if(inpr<=t)
+ visifac= 0.0f;
+ else {
+ t= inpr-t;
+ if(t<lar->spotbl && lar->spotbl!=0.0f) {
+ /* soft area */
+ float i= t/lar->spotbl;
+ t= i*i;
+ inpr*= (3.0f*t-2.0f*t*i);
+ }
+ visifac*= inpr;
+ }
+ }
+ }
+ }
+ return visifac;
+ }
+}
+
+/* function returns diff, spec and raw diff */
+static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int passflag)
+{
+ Material *ma= shi->mat;
+ VlakRen *vlr= shi->vlr;
+ float lv[3], lampdist, lacol[3], shadfac[4];
+ float i, is, i_noshad, inp, *vn, *view, vnor[3], phongcorr=1.0f;
+ float visifac;
+
+ vn= shi->vn;
+ view= shi->view;
+
+ /* lampdist, spot angle, area side, ... */
+ visifac= lamp_get_visibility(lar, shi->co, lv, &lampdist);
+ if(visifac==0.0f)
+ return;
+
+ if(lar->type==LA_SPOT) {
+ if(lar->mode & LA_OSATEX) {
+ 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;
+
+ if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv, shi, lacol);
+
+ /* tangent case; calculate fake face normal, aligned with lampvector */
+ if(vlr->flag & R_TANGENT) {
+ float cross[3];
+ Crossf(cross, lv, vn);
+ Crossf(vnor, cross, vn);
+ vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2];
+ vn= vnor;
+ }
+ else if (ma->mode & MA_TANGENT_V) {
+ float cross[3];
+ Crossf(cross, lv, shi->tang);
+ Crossf(vnor, cross, shi->tang);
+ 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 */
+ inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+
+ /* phong threshold to prevent backfacing faces having artefacts on ray shadow (terminator problem) */
+ /* this complex construction screams for a nicer implementation! (ton) */
+ if(R.r.mode & R_SHADOW) {
+ if(ma->mode & MA_SHADOW) {
+ if(lar->type==LA_HEMI);
+ else if((ma->mode & MA_RAYBIAS) && (lar->mode & LA_SHAD_RAY) && (vlr->flag & R_SMOOTH)) {
+ float thresh= vlr->ob->smoothresh;
+ if(inp>thresh)
+ phongcorr= (inp-thresh)/(inp*(1.0f-thresh));
+ else
+ phongcorr= 0.0f;
+ }
+ else if(ma->sbias!=0.0f && ((lar->mode & LA_SHAD_RAY) || lar->shb)) {
+ if(inp>ma->sbias)
+ phongcorr= (inp-ma->sbias)/(inp*(1.0f-ma->sbias));
+ else
+ phongcorr= 0.0f;
+ }
+ }
+ }
+
+ /* diffuse shaders */
+ if(lar->mode & LA_NO_DIFF) {
+ is= 0.0f; // skip shaders
+ }
+ else if(lar->type==LA_HEMI) {
+ is= 0.5f*inp + 0.5f;
+ }
+ else {
+
+ if(lar->type==LA_AREA)
+ inp= area_lamp_energy(shi->co, vn, lar);
+
+ /* diffuse shaders (oren nayer gets inp from area light) */
+ 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]);
+ else is= inp; // Lambert
+ }
+
+ /* i is diffuse */
+ i= is*phongcorr;
+
+ if(i>0.0f) {
+ i*= visifac*shi->refl;
+ }
+ i_noshad= i;
+
+ vn= shi->vn; // bring back original vector, we use special specular shaders for tangent
+ if(ma->mode & MA_TANGENT_V)
+ vn= shi->tang;
+
+ /* init transp shadow */
+ shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 1.0f;
+
+ /* shadow and spec, (visifac==0 outside spot) */
+ if(visifac> 0.0f) {
+
+ if(i>0.0f && (R.r.mode & R_SHADOW)) {
+ if(ma->mode & MA_SHADOW) {
+ if(lar->shb || (lar->mode & LA_SHAD_RAY)) {
+
+ lamp_get_shadow(lar, shi, inp, shadfac, shi->depth);
+
+ /* warning, here it skips the loop */
+ if(lar->mode & LA_ONLYSHADOW) {
+
+ shadfac[3]= i*lar->energy*(1.0f-shadfac[3]);
+ shr->diff[0] -= shadfac[3]*shi->r;
+ shr->diff[1] -= shadfac[3]*shi->g;
+ shr->diff[2] -= shadfac[3]*shi->b;
+ return;
+ }
+
+ if(!(passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW)))
+ if(shadfac[3]==0.0f) return;
+
+ i*= shadfac[3];
+ }
+ }
+ }
+
+ /* in case 'no diffuse' we still do most calculus, spec can be in shadow */
+ if(!(lar->mode & LA_NO_DIFF)) {
+ if(i>0.0f) {
+ if(ma->mode & MA_SHADOW_TRA)
+ add_to_diffuse(shr->diff, shi, is, i*shadfac[0]*lacol[0], i*shadfac[1]*lacol[1], i*shadfac[2]*lacol[2]);
+ else
+ add_to_diffuse(shr->diff, shi, is, i*lacol[0], i*lacol[1], i*lacol[2]);
+ }
+ if(i_noshad>0.0f && (passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW))) {
+ if(ma->mode & MA_SHADOW_TRA)
+ add_to_diffuse(shr->diff_raw, shi, is, i_noshad*shadfac[0]*lacol[0], i_noshad*shadfac[1]*lacol[1], i_noshad*shadfac[2]*lacol[2]);
+ else
+ add_to_diffuse(shr->diff_raw, shi, is, i_noshad*lacol[0], i_noshad*lacol[1], i_noshad*lacol[2]);
+ }
+ }
+
+ /* specularity */
+ if(shadfac[3]>0.0f && shi->spec!=0.0f && !(lar->mode & LA_NO_SPEC)) {
+
+ if(!(passflag & (SCE_PASS_COMBINED|SCE_PASS_SPEC)));
+ else if(lar->type==LA_HEMI) {
+ float t;
+ /* hemi uses no spec shaders (yet) */
+
+ lv[0]+= view[0];
+ lv[1]+= view[1];
+ lv[2]+= view[2];
+
+ Normalise(lv);
+
+ t= vn[0]*lv[0]+vn[1]*lv[1]+vn[2]*lv[2];
+
+ if(lar->type==LA_HEMI) {
+ t= 0.5*t+0.5;
+ }
+
+ 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;
+
+ if(ma->spec_shader==MA_SPEC_PHONG)
+ specfac= Phong_Spec(vn, lv, view, shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
+ else if(ma->spec_shader==MA_SPEC_COOKTORR)
+ specfac= CookTorr_Spec(vn, lv, view, shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
+ else if(ma->spec_shader==MA_SPEC_BLINN)
+ specfac= Blinn_Spec(vn, lv, view, ma->refrac, (float)shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
+ else if(ma->spec_shader==MA_SPEC_WARDISO)
+ 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 */
+ if(lar->type==LA_AREA) specfac*= inp;
+
+ t= shadfac[3]*shi->spec*visifac*specfac;
+
+ if(ma->mode & MA_RAMP_SPEC) {
+ 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)
+{
+
+ if(R.r.mode & R_SHADOW) {
+ ListBase *lights;
+ LampRen *lar;
+ GroupObject *go;
+ float inpr, lv[3];
+ float *vn, *view, shadfac[4];
+ float ir, accum, visifac, lampdist;
+
+ vn= shi->vn;
+ view= shi->view;
+
+ /* lights */
+ if(shi->mat->group)
+ lights= &shi->mat->group->gobject;
+ else
+ lights= &R.lights;
+
+ accum= ir= 0.0f;
+
+ for(go=lights->first; go; go= go->next) {
+ lar= go->lampren;
+ if(lar==NULL) continue;
+
+ /* yafray: ignore shading by photonlights, not used in Blender */
+ if (lar->type==LA_YF_PHOTON) continue;
+
+ if(lar->mode & LA_LAYER) if((lar->lay & shi->vlr->lay)==0) continue;
+ if((lar->lay & shi->lay)==0) continue;
+
+ if(lar->shb || (lar->mode & LA_SHAD_RAY)) {
+ visifac= lamp_get_visibility(lar, shi->co, lv, &lampdist);
+ if(visifac < 0.0f)
+ continue;
+
+ inpr= INPR(shi->vn, lv);
+ if(inpr <= 0.0f)
+ continue;
+
+ lamp_get_shadow(lar, shi, inpr, shadfac, shi->depth);
+ ir+= 1.0f;
+ accum+= shadfac[3];
+ }
+ }
+ if(ir>0.0f) {
+ accum/= ir;
+ shr->alpha= (shi->alpha)*(1.0f-accum);
+ }
+ }
+
+ if((R.wrld.mode & WO_AMB_OCC) && shi->amb!=0.0f) {
+ float f;
+
+ f= shi->ao[0];
+
+ /* quite disputable this... also note it doesn't mirror-raytrace */
+ if(R.wrld.aomix==WO_AOADD) {
+ shr->alpha += f;
+ shr->alpha *= f;
+ }
+ else if(R.wrld.aomix==WO_AOSUB) {
+ shr->alpha += f;
+ }
+ else {
+ shr->alpha *= f;
+ shr->alpha += f;
+ }
+ }
+}
+
+void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
+{
+ Material *ma= shi->mat;
+ VlakRen *vlr= shi->vlr;
+ int passflag= shi->passflag;
+
+ memset(shr, 0, sizeof(ShadeResult));
+
+ /* separate loop */
+ if(ma->mode & MA_ONLYSHADOW) {
+ 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 */
+ if(passflag & (SCE_PASS_COMBINED|SCE_PASS_RGBA)) {
+ if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
+ shi->r= shi->vcol[0];
+ shi->g= shi->vcol[1];
+ shi->b= shi->vcol[2];
+ }
+ if(ma->texco)
+ do_material_tex(shi);
+
+ 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;
+ }
+
+ if(ma->mode & MA_SHLESS) {
+ shr->combined[0]= shi->r;
+ shr->combined[1]= shi->g;
+ shr->combined[2]= shi->b;
+ shr->alpha= shi->alpha;
+ return;
+ }
+
+ if( (ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL ) { // vertexcolor light
+ shr->diff[0]= shi->r*(shi->emit+shi->vcol[0]);
+ shr->diff[1]= shi->g*(shi->emit+shi->vcol[1]);
+ shr->diff[2]= shi->b*(shi->emit+shi->vcol[2]);
+ }
+ else {
+ shr->diff[0]= shi->r*shi->emit;
+ shr->diff[1]= shi->g*shi->emit;
+ shr->diff[2]= shi->b*shi->emit;
+ }
+
+ /* AO pass */
+ if(R.wrld.mode & WO_AMB_OCC) {
+ if(passflag & (SCE_PASS_COMBINED|SCE_PASS_AO)) {
+ /* AO was calculated for scanline already */
+ if(shi->depth)
+ ambient_occlusion(shi);
+ VECCOPY(shr->ao, shi->ao);
+ }
+ }
+
+ /* lighting pass */
+ if(passflag & (SCE_PASS_COMBINED|SCE_PASS_DIFFUSE|SCE_PASS_SPEC|SCE_PASS_SHADOW)) {
+ GroupObject *go;
+ ListBase *lights;
+ LampRen *lar;
+
+ /* lights */
+ if(ma->group)
+ lights= &ma->group->gobject;
+ else
+ lights= &R.lights;
+
+ for(go=lights->first; go; go= go->next) {
+ lar= go->lampren;
+ if(lar==NULL) continue;
+
+ /* yafray: ignore shading by photonlights, not used in Blender */
+ if (lar->type==LA_YF_PHOTON) continue;
+
+ /* test for lamp layer */
+ if(lar->mode & LA_LAYER) if((lar->lay & vlr->lay)==0) continue;
+ if((lar->lay & shi->lay)==0) continue;
+
+ /* accumulates in shr->diff and shr->spec and shr->diff_raw (diffuse without shadow!) */
+ shade_one_light(lar, shi, shr, passflag);
+ }
+
+ /* calculate shadow pass, we use a multiplication mask */
+ if(passflag & SCE_PASS_SHADOW) {
+ if(shr->diff_raw[0]!=0.0f) shr->shad[0]= shr->diff[0]/shr->diff_raw[0];
+ if(shr->diff_raw[1]!=0.0f) shr->shad[1]= shr->diff[1]/shr->diff_raw[1];
+ if(shr->diff_raw[2]!=0.0f) shr->shad[2]= shr->diff[2]/shr->diff_raw[2];
+ }
+
+ /* exposure correction */
+ if(R.wrld.exp!=0.0f || R.wrld.range!=1.0f) {
+ shr->diff[0]= R.wrld.linfac*(1.0f-exp( shr->diff[0]*R.wrld.logfac) );
+ shr->diff[1]= R.wrld.linfac*(1.0f-exp( shr->diff[1]*R.wrld.logfac) );
+ shr->diff[2]= R.wrld.linfac*(1.0f-exp( shr->diff[2]*R.wrld.logfac) );
+
+ shr->spec[0]= R.wrld.linfac*(1.0f-exp( shr->spec[0]*R.wrld.logfac) );
+ shr->spec[1]= R.wrld.linfac*(1.0f-exp( shr->spec[1]*R.wrld.logfac) );
+ shr->spec[2]= R.wrld.linfac*(1.0f-exp( shr->spec[2]*R.wrld.logfac) );
+ }
+ }
+
+ /* alpha in end, spec can influence it */
+ if(passflag & (SCE_PASS_COMBINED|SCE_PASS_RGBA)) {
+ if(ma->fresnel_tra!=0.0f)
+ shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra);
+
+ if(shi->mode & (MA_ZTRA|MA_RAYTRANSP)) {
+ if(shi->spectra!=0.0f) {
+ float t = MAX3(shr->spec[0], shr->spec[1], shr->spec[2]);
+ t *= shi->spectra;
+ if(t>1.0f) t= 1.0f;
+ shi->alpha= (1.0f-t)*shi->alpha+t;
+ }
+ }
+ }
+ shr->alpha= shi->alpha;
+
+ /* now stuff everything in shr->diff: ambient, AO, radio, ramps, exposure */
+ shr->diff[0]+= shi->ambr + shi->r*shi->amb*shi->rad[0];
+ shr->diff[1]+= shi->ambg + shi->g*shi->amb*shi->rad[1];
+ shr->diff[2]+= shi->ambb + shi->b*shi->amb*shi->rad[2];
+
+ if(R.wrld.mode & WO_AMB_OCC) {
+ float aodiff[3];
+ ambient_occlusion_to_diffuse(shi, aodiff);
+
+ shr->diff[0] += shi->r*aodiff[0];
+ shr->diff[1] += shi->g*aodiff[1];
+ shr->diff[2] += shi->b*aodiff[2];
+ }
+
+ if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(shr->diff, shi);
+ if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(shr->spec, shr->spec+1, shr->spec+2, shi);
+
+ /* refcol is for envmap only */
+ if(shi->refcol[0]!=0.0f) {
+ float olddiff[3];
+
+ VECCOPY(olddiff, shr->diff);
+
+ shr->diff[0]= shi->mirr*shi->refcol[1] + (1.0f - shi->mirr*shi->refcol[0])*shr->diff[0];
+ shr->diff[1]= shi->mirg*shi->refcol[2] + (1.0f - shi->mirg*shi->refcol[0])*shr->diff[1];
+ shr->diff[2]= shi->mirb*shi->refcol[3] + (1.0f - shi->mirb*shi->refcol[0])*shr->diff[2];
+
+ if(passflag & SCE_PASS_REFLECT)
+ VECSUB(shr->refl, shr->diff, olddiff);
+ }
+
+ /* XXX SOLVE */
+ if(passflag & SCE_PASS_COMBINED) {
+ shr->combined[0]= shr->diff[0]+ shr->spec[0];
+ shr->combined[1]= shr->diff[1]+ shr->spec[1];
+ shr->combined[2]= shr->diff[2]+ shr->spec[2];
+ shr->combined[3]= shr->alpha;
+ }
+}
+
+
diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c
index acf2b797704..ed434ac5370 100644
--- a/source/blender/render/intern/source/texture.c
+++ b/source/blender/render/intern/source/texture.c
@@ -59,10 +59,11 @@
#include "BKE_key.h"
#include "BKE_ipo.h"
+#include "envmap.h"
#include "renderpipeline.h"
#include "render_types.h"
#include "rendercore.h"
-#include "envmap.h"
+#include "shading.h"
#include "texture.h"
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index 43119960cce..1b30cbf6037 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -66,6 +66,7 @@
#include "renderdatabase.h"
#include "rendercore.h"
#include "shadbuf.h"
+#include "shading.h"
/* own includes */
#include "zbuf.h"
@@ -2533,14 +2534,14 @@ static void copyto_abufz(RenderPart *pa, int *arectz, int sample)
* Do accumulation z buffering.
*/
-static void zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, unsigned int lay)
+static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, unsigned int lay)
{
ZSpan zspan;
Material *ma=NULL;
VlakRen *vlr=NULL;
VertRen *v1, *v2, *v3, *v4;
float vec[3], hoco[4], mul, zval, fval;
- int v, zvlnr, zsample, dofill= 0;
+ int v, zvlnr= 0, zsample, dofill= 0;
char *clipflag= pa->clipflag;
zbuf_alloc_span(&zspan, pa->rectx, pa->recty);
@@ -2579,6 +2580,9 @@ static void zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, u
zspan.zofsx -= 0.5f;
zspan.zofsy -= 0.5f;
+ /* we use this to test if nothing was filled in */
+ zvlnr= 0;
+
for(v=0; v<R.totvlak; v++) {
if((v & 255)==0)
vlr= R.blovl[v>>8];
@@ -2644,11 +2648,13 @@ static void zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, u
if(R.osa==0) break;
if(R.test_break()) break;
+ if(zvlnr==0) break;
}
MEM_freeN(zspan.arectz);
zbuf_free_span(&zspan);
-
+
+ return zvlnr;
}
/* different rules for speed in transparent pass... */
@@ -2685,51 +2691,119 @@ static void add_transp_speed(RenderLayer *rl, int offset, float *speed, float al
}
}
+ break;
}
}
}
-static void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float weight)
+/* ONLY OSA! merge all shaderesult samples to one */
+/* target should have been cleared */
+static void merge_transp_passes(RenderLayer *rl, ShadeResult *shr)
{
RenderPass *rpass;
+ float weight= 1.0f/((float)R.osa);
+ int delta= sizeof(ShadeResult)/4;
for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
- float *fp, *col= NULL;
- int a, pixsize= 3;
+ float *col= NULL;
+ int pixsize= 0;
switch(rpass->passtype) {
case SCE_PASS_RGBA:
- if(shr) col= shr->col;
+ col= shr->col;
pixsize= 4;
break;
+ case SCE_PASS_VECTOR:
+ col= shr->winspeed;
+ pixsize= 4;
+ break;
+ case SCE_PASS_DIFFUSE:
+ col= shr->diff;
+ break;
+ case SCE_PASS_SPEC:
+ col= shr->spec;
+ break;
+ case SCE_PASS_SHADOW:
+ col= shr->shad;
+ break;
+ case SCE_PASS_AO:
+ col= shr->ao;
+ break;
+ case SCE_PASS_REFLECT:
+ col= shr->refl;
+ break;
+ case SCE_PASS_REFRACT:
+ col= shr->refr;
+ break;
+ case SCE_PASS_NORMAL:
+ col= shr->nor;
+ break;
+ }
+ if(col) {
+ float *fp= col+delta;
+ int samp;
+
+ for(samp= 1; samp<R.osa; samp++, fp+=delta) {
+ col[0]+= fp[0];
+ col[1]+= fp[1];
+ col[2]+= fp[2];
+ if(pixsize) col[3]+= fp[3];
+ }
+ col[0]*= weight;
+ col[1]*= weight;
+ col[2]*= weight;
+ if(pixsize) col[3]*= weight;
+ }
+ }
+
+}
+
+static void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha)
+{
+ RenderPass *rpass;
+
+ for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
+ float *fp, *col= NULL;
+
+ switch(rpass->passtype) {
+ case SCE_PASS_RGBA:
+ fp= rpass->rect + 4*offset;
+ addAlphaOverFloat(fp, shr->col);
+ break;
case SCE_PASS_DIFFUSE:
- if(shr) col= shr->diff;
+ col= shr->diff;
break;
case SCE_PASS_SPEC:
- if(shr) col= shr->spec;
+ col= shr->spec;
break;
case SCE_PASS_SHADOW:
- if(shr) col= shr->shad;
+ col= shr->shad;
break;
case SCE_PASS_AO:
- if(shr) col= shr->ao;
+ col= shr->ao;
+ break;
+ case SCE_PASS_REFLECT:
+ col= shr->refl;
break;
- case SCE_PASS_RAY:
- if(shr) col= shr->ray;
+ case SCE_PASS_REFRACT:
+ col= shr->refr;
break;
case SCE_PASS_NORMAL:
- if(shr) col= shr->nor;
+ col= shr->nor;
break;
}
if(col) {
- fp= rpass->rect + pixsize*offset;
- for(a=0; a<pixsize; a++)
- fp[a]+= weight*col[a];
+
+ fp= rpass->rect + 3*offset;
+ fp[0]= alpha*col[0] + (1.0f-alpha)*fp[0];
+ fp[1]= alpha*col[1] + (1.0f-alpha)*fp[1];
+ fp[2]= alpha*col[2] + (1.0f-alpha)*fp[2];
}
}
}
+
static int vergzvlak(const void *a1, const void *a2)
{
const int *x1=a1, *x2=a2;
@@ -2742,112 +2816,183 @@ static int vergzvlak(const void *a1, const void *a2)
/**
* Shade this face at this location in SCS.
*/
-static void shadetrapixel(ShadePixelInfo *shpi, float x, float y, int z, int facenr, int mask)
+
+static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int facenr, int curmask)
{
- float rco[3];
+ ShadeInput *shi= ssamp->shi;
+ float xs, ys;
- if(facenr<0)
- return;
- else if( (facenr & RE_QUAD_MASK) > R.totvlak) {
- printf("error in shadetrapixel nr: %d\n", (facenr & RE_QUAD_MASK));
- return;
- }
- /* correction back for zbuffer filling in */
- x+= 0.5f;
- y+= 0.5f;
-
- if(R.osa) {
- VlakRen *vlr= RE_findOrAddVlak(&R, (facenr-1) & RE_QUAD_MASK);
- float accumcol[4]={0,0,0,0}, tot=0.0;
- int a;
-
- if(vlr->flag & R_FULL_OSA) {
- for(a=0; a<R.osa; a++) {
- if(mask & (1<<a)) {
- shadepixel(shpi, x+R.jit[a][0], y+R.jit[a][1], z, facenr, 1<<a, rco);
- accumcol[0]+= shpi->shr.combined[0];
- accumcol[1]+= shpi->shr.combined[1];
- accumcol[2]+= shpi->shr.combined[2];
- accumcol[3]+= shpi->shr.combined[3];
- tot+= 1.0;
+ ssamp->tot= 0;
+
+ shade_input_set_triangle(shi, facenr, 1);
+
+ /* officially should always be true... we have no sky info */
+ if(shi->vlr) {
+
+ /* full osa is only set for OSA renders */
+ if(shi->vlr->flag & R_FULL_OSA) {
+ short shi_inc= 0, samp;
+
+ for(samp=0; samp<R.osa; samp++) {
+ if(curmask & (1<<samp)) {
+ xs= (float)x + R.jit[samp][0] + 0.5f; /* zbuffer has this inverse corrected, ensures xs,ys are inside pixel */
+ ys= (float)y + R.jit[samp][1] + 0.5f;
+
+ if(shi_inc) {
+ shade_input_copy_triangle(shi+1, shi);
+ shi++;
+ }
+ shi->mask= (1<<samp);
+ shade_input_set_viewco(shi, xs, ys, (float)z);
+ shade_input_set_uv(shi);
+ shade_input_set_normals(shi);
+
+ shi_inc= 1;
}
}
- tot= 1.0/tot;
- shpi->shr.combined[0]= accumcol[0]*tot;
- shpi->shr.combined[1]= accumcol[1]*tot;
- shpi->shr.combined[2]= accumcol[2]*tot;
- shpi->shr.combined[3]= accumcol[3]*tot;
}
else {
- int b= R.samples->centmask[mask];
- x= x+R.samples->centLut[b & 15];
- y= y+R.samples->centLut[b>>4];
- shadepixel(shpi, x, y, z, facenr, mask, rco);
+ if(R.osa) {
+ short b= R.samples->centmask[curmask];
+ xs= (float)x + R.samples->centLut[b & 15] + 0.5f;
+ ys= (float)y + R.samples->centLut[b>>4] + 0.5f;
+ }
+ else {
+ xs= (float)x + 0.5f;
+ ys= (float)y + 0.5f;
+ }
+ shi->mask= curmask;
+ shade_input_set_viewco(shi, xs, ys, (float)z);
+ shade_input_set_uv(shi);
+ shade_input_set_normals(shi);
}
+
+ /* total sample amount, shi->sample is static set in initialize */
+ ssamp->tot= shi->sample+1;
}
- else {
- shadepixel(shpi, x, y, z, facenr, mask, rco);
+}
+
+static int shade_tra_samples(ShadeSample *ssamp, int x, int y, int z, int facenr, int mask)
+{
+ shade_tra_samples_fill(ssamp, x, y, z, facenr, mask);
+
+ if(ssamp->tot) {
+ ShadeInput *shi= ssamp->shi;
+ ShadeResult *shr= ssamp->shr;
+ int samp;
+
+ /* if shadow or AO? */
+ if(R.r.mode & R_SHADOW)
+ shade_samples_do_shadow(ssamp);
+
+ /* if shade (all shadepinputs have same passflag) */
+ if(shi->passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB)) {
+ for(samp=0; samp<ssamp->tot; samp++, shi++, shr++) {
+ shade_input_set_shade_texco(shi);
+ shade_input_do_shade(shi, shr);
+
+ /* include lamphalos for ztra, since halo layer was added already */
+ if(R.flag & R_LAMPHALO)
+ if(shi->layflag & SCE_LAY_HALO)
+ renderspothalo(shi, shr->combined, shr->combined[3]);
+ }
+ }
+ return 1;
}
+ return 0;
+}
+
+static void addvecmul(float *v1, float *v2, float fac)
+{
+ v1[0]= v1[0]+fac*v2[0];
+ v1[1]= v1[1]+fac*v2[1];
+ v1[2]= v1[2]+fac*v2[2];
}
-static int addtosamp_shr(ShadeResult *samp_shr, ShadeResult *shr, int mask, int addpassflag)
+static int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag)
{
- int a, retval = R.osa;
+ int a, sample, retval = R.osa;
- for(a=0; a < R.osa; a++) {
- if(mask & (1<<a)) {
- addAlphaUnderFloat(samp_shr->combined, shr->combined);
-
- if(addpassflag & SCE_PASS_VECTOR) {
- QUATCOPY(samp_shr->winspeed, shr->winspeed);
- }
- else if(addpassflag & SCE_PASS_NORMAL) {
- VECCOPY(samp_shr->nor, shr->nor);
+ for(a=0; a < R.osa; a++, samp_shr++) {
+ ShadeInput *shi= ssamp->shi;
+ ShadeResult *shr= ssamp->shr;
+
+ for(sample=0; sample<ssamp->tot; sample++, shi++, shr++) {
+
+ if(shi->mask & (1<<a)) {
+ float fac= (1.0f - samp_shr->combined[3])*shr->combined[3];
+
+ addAlphaUnderFloat(samp_shr->combined, shr->combined);
+
+ if(addpassflag & SCE_PASS_VECTOR) {
+ QUATCOPY(samp_shr->winspeed, shr->winspeed);
+ }
+ /* optim... */
+ if(addpassflag & ~(SCE_PASS_VECTOR)) {
+
+ if(addpassflag & SCE_PASS_RGBA)
+ addAlphaUnderFloat(samp_shr->col, shr->col);
+
+ if(addpassflag & SCE_PASS_NORMAL)
+ addvecmul(samp_shr->nor, shr->nor, fac);
+
+ if(addpassflag & SCE_PASS_DIFFUSE)
+ addvecmul(samp_shr->diff, shr->diff, fac);
+
+ if(addpassflag & SCE_PASS_SPEC)
+ addvecmul(samp_shr->spec, shr->spec, fac);
+
+ if(addpassflag & SCE_PASS_SHADOW)
+ addvecmul(samp_shr->shad, shr->shad, fac);
+
+ if(addpassflag & SCE_PASS_AO)
+ addvecmul(samp_shr->ao, shr->ao, fac);
+
+ if(addpassflag & SCE_PASS_REFLECT)
+ addvecmul(samp_shr->refl, shr->refl, fac);
+
+ if(addpassflag & SCE_PASS_REFRACT)
+ addvecmul(samp_shr->refr, shr->refr, fac);
+ }
}
}
- if(samp_shr->combined[3]>0.999) retval--;
- samp_shr++;
+ if(samp_shr->combined[3]>0.999f) retval--;
}
return retval;
}
#define MAX_ZROW 2000
/* main render call to fill in pass the full transparent layer */
-
-void zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass)
+/* returns a mask, only if a) transp rendered and b) solid was rendered */
+unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass)
{
RenderResult *rr= pa->result;
- ShadePixelInfo shpi;
+ ShadeSample ssamp;
APixstr *APixbuf; /* Zbuffer: linked list of face samples */
APixstr *ap, *aprect, *apn;
ListBase apsmbase={NULL, NULL};
- ShadeResult samp_shr[16];
- float fac, sampalpha, *passrect= pass;
+ ShadeResult samp_shr[16]; /* MAX_OSA */
+ float sampalpha, *passrect= pass;
long *rdrect;
int x, y, crop=0, a, zrow[MAX_ZROW][3], totface;
- int sval, addpassflag, offs= 0, od, addzbuf;
-
+ int addpassflag, offs= 0, od, addzbuf;
+ unsigned short *ztramask= NULL;
+
/* looks nicer for calling code */
if(R.test_break())
- return;
+ return NULL;
APixbuf= MEM_callocN(pa->rectx*pa->recty*sizeof(APixstr), "APixbuf");
- if(R.osa>16) {
- printf("abufsetrow: osa too large\n");
+ if(R.osa>16) { /* MAX_OSA */
+ printf("zbuffer_transp_shade: osa too large\n");
G.afbreek= 1;
- return;
+ return NULL;
}
- /* fill shadepixel info struct */
- shpi.thread= pa->thread;
- shpi.lay= rl->lay;
- shpi.layflag= rl->layflag;
- shpi.passflag= 0;
-
- if(rl->passflag & ~(SCE_PASS_Z|SCE_PASS_NORMAL|SCE_PASS_VECTOR|SCE_PASS_COMBINED))
- shpi.passflag= rl->passflag;
+ /* general shader info, passes */
+ shade_sample_initialize(&ssamp, pa, rl);
addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
addzbuf= rl->passflag & SCE_PASS_Z;
@@ -2857,14 +3002,23 @@ void zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass)
sampalpha= 1.0f;
/* fill the Apixbuf */
- zbuffer_abuf(pa, APixbuf, &apsmbase, rl->lay);
+ if(0 == zbuffer_abuf(pa, APixbuf, &apsmbase, rl->lay)) {
+ /* nothing filled in */
+ MEM_freeN(APixbuf);
+ freepsA(&apsmbase);
+ return NULL;
+ }
aprect= APixbuf;
rdrect= pa->rectdaps;
/* irregular shadowb buffer creation */
if(R.r.mode & R_SHADOW)
ISB_create(pa, APixbuf);
-
+
+ /* masks, to have correct alpha combine */
+ if(R.osa && (rl->layflag & SCE_LAY_SOLID))
+ ztramask= MEM_callocN(pa->rectx*pa->recty*sizeof(short), "ztramask");
+
/* filtered render, for now we assume only 1 filter size */
if(pa->crop) {
crop= 1;
@@ -2911,86 +3065,68 @@ void zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass)
apn= apn->next;
}
- if(totface==1) {
-
- shadetrapixel(&shpi, (float)x, (float)y, zrow[0][0], zrow[0][1], zrow[0][2]);
-
- if(R.osa) {
- add_filt_fmask(zrow[0][2], shpi.shr.combined, pass, rr->rectx);
- }
- else {
- QUATCOPY(pass, shpi.shr.combined);
+ if(totface==2) {
+ if(zrow[0][0] < zrow[1][0]) {
+ a= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= a;
+ a= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= a;
+ a= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= a;
}
- if(addpassflag)
- add_transp_passes(rl, od, &shpi.shr, 1.0f);
-
- if(addpassflag & SCE_PASS_VECTOR)
- add_transp_speed(rl, od, shpi.shr.winspeed, pass[3], rdrect);
-
- if(addzbuf)
- if(pa->rectz[od]>zrow[0][0])
- pa->rectz[od]= zrow[0][0];
}
- else {
-
- if(totface==2) {
- if(zrow[0][0] < zrow[1][0]) {
- a= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= a;
- a= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= a;
- a= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= a;
- }
+ else if(totface>2) {
+ qsort(zrow, totface, sizeof(int)*3, vergzvlak);
+ }
+
+ if(addzbuf)
+ if(pa->rectz[od]>zrow[totface-1][0])
+ pa->rectz[od]= zrow[totface-1][0];
+
+ if(R.osa==0) {
+ while(totface>0) {
+ totface--;
- }
- else { /* totface>2 */
- qsort(zrow, totface, sizeof(int)*3, vergzvlak);
- }
-
- if(addzbuf)
- if(pa->rectz[od]>zrow[totface-1][0])
- pa->rectz[od]= zrow[totface-1][0];
-
- if(R.osa==0) {
- while(totface>0) {
- totface--;
-
- shadetrapixel(&shpi, (float)x, (float)y, zrow[totface][0], zrow[totface][1], zrow[totface][2]);
- addAlphaUnderFloat(pass, shpi.shr.combined);
+ if(shade_tra_samples(&ssamp, x, y, zrow[totface][0], zrow[totface][1], zrow[totface][2])) {
if(addpassflag)
- add_transp_passes(rl, od, &shpi.shr, 1.0f);
+ add_transp_passes(rl, od, ssamp.shr, (1.0f-pass[3])*ssamp.shr[0].combined[3]);
+ addAlphaUnderFloat(pass, ssamp.shr[0].combined);
if(pass[3]>=0.999) break;
}
- if(addpassflag & SCE_PASS_VECTOR)
- add_transp_speed(rl, od, shpi.shr.winspeed, pass[3], rdrect);
}
- else {
- /* for each mask-sample we alpha-under colors. then in end it's added using filter */
- memset(samp_shr, 0, sizeof(ShadeResult)*R.osa);
+ if(addpassflag & SCE_PASS_VECTOR)
+ add_transp_speed(rl, od, ssamp.shr[0].winspeed, pass[3], rdrect);
+ }
+ else {
+ short filled, *sp= ztramask+od;
+
+ /* for each mask-sample we alpha-under colors. then in end it's added using filter */
+ memset(samp_shr, 0, sizeof(ShadeResult)*R.osa);
- while(totface>0) {
- totface--;
-
- shadetrapixel(&shpi, (float)x, (float)y, zrow[totface][0], zrow[totface][1], zrow[totface][2]);
- sval= addtosamp_shr(samp_shr, &shpi.shr, zrow[totface][2], addpassflag);
-
- if(sval==0) break;
- }
-
- for(a=0; a<R.osa; a++) {
- add_filt_fmask(1<<a, samp_shr[a].combined, pass, rr->rectx);
-
- if(addpassflag)
- add_transp_passes(rl, od, samp_shr+a, sampalpha);
- }
+ while(totface>0) {
+ totface--;
- if(addpassflag & SCE_PASS_VECTOR) {
- fac= 0.0f;
- for(a=0; a<R.osa; a++)
- fac+= samp_shr[a].combined[3];
- add_transp_speed(rl, od, samp_shr[0].winspeed, fac*sampalpha, rdrect);
+ if(shade_tra_samples(&ssamp, x, y, zrow[totface][0], zrow[totface][1], zrow[totface][2])) {
+ filled= addtosamp_shr(samp_shr, &ssamp, addpassflag);
+
+ if(ztramask)
+ *sp |= zrow[totface][2];
+ if(filled==0)
+ break;
}
}
+
+ for(a=0; a<R.osa; a++) {
+ add_filt_fmask(1<<a, samp_shr[a].combined, pass, rr->rectx);
+ }
+
+ if(addpassflag) {
+ /* merge all in one, and then add */
+ merge_transp_passes(rl, samp_shr);
+ add_transp_passes(rl, od, samp_shr, pass[3]);
+
+ if(addpassflag & SCE_PASS_VECTOR)
+ add_transp_speed(rl, od, samp_shr[0].winspeed, pass[3], rdrect);
+ }
}
}
}
@@ -3009,6 +3145,7 @@ void zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass)
if(R.r.mode & R_SHADOW)
ISB_free(pa);
+ return ztramask;
}
/* *************** */