diff options
Diffstat (limited to 'source/blender/render')
-rw-r--r-- | source/blender/render/extern/include/RE_pipeline.h | 59 | ||||
-rw-r--r-- | source/blender/render/extern/include/RE_shader_ext.h | 8 | ||||
-rw-r--r-- | source/blender/render/intern/include/pixelblending.h | 1 | ||||
-rw-r--r-- | source/blender/render/intern/include/rendercore.h | 2 | ||||
-rw-r--r-- | source/blender/render/intern/source/pipeline.c | 89 | ||||
-rw-r--r-- | source/blender/render/intern/source/pixelblending.c | 46 | ||||
-rw-r--r-- | source/blender/render/intern/source/ray.c | 24 | ||||
-rw-r--r-- | source/blender/render/intern/source/rendercore.c | 926 | ||||
-rw-r--r-- | source/blender/render/intern/source/zbuf.c | 16 |
9 files changed, 747 insertions, 424 deletions
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index a9b75184e36..1afce546791 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -55,6 +55,12 @@ typedef struct Render Render; and how it's converted */ +typedef struct RenderPass { + struct RenderPass *next, *prev; + int passtype; + float *rect; +} RenderPass; + /* a renderlayer is a full image, but with all passes and samples */ /* size of the rects is defined in RenderResult */ typedef struct RenderLayer { @@ -66,8 +72,6 @@ typedef struct RenderLayer { int layflag, passflag; float *rectf; /* 4 float, standard rgba buffer */ - float *rectz; /* 1 float, standard camera coordinate zbuffer */ - float *rectvec; /* 2 float, screen aligned speed vectors */ ListBase passes; @@ -113,19 +117,20 @@ typedef struct RenderStats { /* the name is used as identifier, so elsewhere in blender the result can retrieved */ /* calling a new render with same name, frees automatic existing render */ -Render *RE_NewRender (const char *name); -Render *RE_GetRender(const char *name); +struct Render *RE_NewRender (const char *name); +struct Render *RE_GetRender(const char *name); /* use free render as signal to do everything over (previews) */ -void RE_FreeRender (Render *re); +void RE_FreeRender (struct Render *re); /* only called on exit */ void RE_FreeAllRender (void); /* get results and statistics */ -RenderResult *RE_GetResult(Render *re); -void RE_GetResultImage(Render *re, RenderResult *rr); -RenderStats *RE_GetStats(Render *re); -void RE_ResultGet32(Render *re, unsigned int *rect); +RenderResult *RE_GetResult(struct Render *re); +void RE_GetResultImage(struct Render *re, RenderResult *rr); +RenderStats *RE_GetStats(struct Render *re); +void RE_ResultGet32(struct Render *re, unsigned int *rect); +float *RE_RenderLayerGetPass(RenderLayer *rl, int passtype); /* obligatory initialize call, disprect is optional */ void RE_InitState (struct Render *re, struct RenderData *rd, int winx, int winy, rcti *disprect); @@ -134,37 +139,37 @@ void RE_InitState (struct Render *re, struct RenderData *rd, int winx, int winy, void RE_SetDispRect (struct Render *re, rcti *disprect); /* set up the viewplane/perspective matrix, three choices */ -void RE_SetCamera(Render *re, struct Object *camera); -void RE_SetWindow (Render *re, rctf *viewplane, float clipsta, float clipend); -void RE_SetOrtho (Render *re, rctf *viewplane, float clipsta, float clipend); +void RE_SetCamera(struct Render *re, struct Object *camera); +void RE_SetWindow (struct Render *re, rctf *viewplane, float clipsta, float clipend); +void RE_SetOrtho (struct Render *re, rctf *viewplane, float clipsta, float clipend); /* option to set viewmatrix before making dbase */ -void RE_SetView (Render *re, float mat[][4]); +void RE_SetView (struct Render *re, float mat[][4]); /* make or free the dbase */ -void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view); -void RE_Database_Free (Render *re); +void RE_Database_FromScene(struct Render *re, struct Scene *scene, int use_camera_view); +void RE_Database_Free (struct Render *re); /* project dbase again, when viewplane/perspective changed */ -void RE_DataBase_ApplyWindow(Render *re); +void RE_DataBase_ApplyWindow(struct Render *re); /* the main processor, assumes all was set OK! */ -void RE_TileProcessor(Render *re); +void RE_TileProcessor(struct Render *re); /* only RE_NewRender() needed, main Blender render calls */ -void RE_BlenderFrame(Render *re, struct Scene *scene, int frame); -void RE_BlenderAnim(Render *re, struct Scene *scene, int sfra, int efra); +void RE_BlenderFrame(struct Render *re, struct Scene *scene, int frame); +void RE_BlenderAnim(struct Render *re, struct Scene *scene, int sfra, int efra); /* display and event callbacks */ -void RE_display_init_cb (Render *re, void (*f)(RenderResult *rr)); -void RE_display_clear_cb(Render *re, void (*f)(RenderResult *rr)); -void RE_display_draw_cb (Render *re, void (*f)(RenderResult *rr, struct rcti *rect)); -void RE_stats_draw_cb (Render *re, void (*f)(RenderStats *rs)); -void RE_timecursor_cb (Render *re, void (*f)(int)); -void RE_test_break_cb (Render *re, int (*f)(void)); -void RE_test_return_cb (Render *re, int (*f)(void)); -void RE_error_cb (Render *re, void (*f)(const char *str)); +void RE_display_init_cb (struct Render *re, void (*f)(RenderResult *rr)); +void RE_display_clear_cb(struct Render *re, void (*f)(RenderResult *rr)); +void RE_display_draw_cb (struct Render *re, void (*f)(RenderResult *rr, struct rcti *rect)); +void RE_stats_draw_cb (struct Render *re, void (*f)(RenderStats *rs)); +void RE_timecursor_cb (struct Render *re, void (*f)(int)); +void RE_test_break_cb (struct Render *re, int (*f)(void)); +void RE_test_return_cb (struct Render *re, int (*f)(void)); +void RE_error_cb (struct Render *re, void (*f)(const char *str)); diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index b8bd46d784e..54307d933e9 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -46,11 +46,15 @@ typedef struct TexResult { typedef struct ShadeResult { float combined[4]; + float col[4]; + float alpha; float diff[3]; float spec[3]; - float alpha; + float shad[3]; + float ao[3]; + float ray[3]; float nor[3]; - float winspeed[2]; + float winspeed[3]; } ShadeResult; diff --git a/source/blender/render/intern/include/pixelblending.h b/source/blender/render/intern/include/pixelblending.h index bc44c916701..2713b2023a9 100644 --- a/source/blender/render/intern/include/pixelblending.h +++ b/source/blender/render/intern/include/pixelblending.h @@ -34,6 +34,7 @@ * (float vecs to float vec) */ void add_filt_fmask(unsigned int mask, float *col, float *rowbuf, int row_w); +void add_filt_fmask_pixsize(unsigned int mask, float *in, float *rowbuf, int row_w, int pixsize); /** * Alpha-over blending for floats. diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index 793480458c6..91aeaf788c9 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -85,7 +85,7 @@ void shade_material_loop(struct ShadeInput *shi, struct ShadeResult *shr); void zbufshade(void); void zbufshadeDA(void); /* Delta Accum Pixel Struct */ -void *shadepixel(RenderPart *pa, float x, float y, int z, int facenr, int mask, struct ShadeResult *shr, float *rco); +void *shadepixel(RenderPart *pa, float x, float y, int z, int facenr, int mask, struct ShadeResult *shr, float *rco, int passflag); int count_mask(unsigned short mask); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index c1baa04553b..558e1cc17ff 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -133,6 +133,11 @@ void RE_freeN(void *poin) /* ********************** */ +static int g_break= 0; +static int thread_break(void) +{ + return g_break; +} /* default callbacks, set in each new render */ static void result_nothing(RenderResult *rr) {} @@ -148,9 +153,14 @@ static void free_render_result(RenderResult *res) while(res->layers.first) { RenderLayer *rl= res->layers.first; + if(rl->rectf) RE_freeN(rl->rectf); - if(rl->rectz) RE_freeN(rl->rectz); - if(rl->rectvec) RE_freeN(rl->rectvec); + while(rl->passes.first) { + RenderPass *rpass= rl->passes.first; + RE_freeN(rpass->rect); + BLI_remlink(&rl->passes, rpass); + RE_freeN(rpass); + } BLI_remlink(&res->layers, rl); RE_freeN(rl); } @@ -165,6 +175,25 @@ static void free_render_result(RenderResult *res) RE_freeN(res); } +static void render_layer_add_pass(RenderLayer *rl, int rectsize, int passtype, char *mallocstr) +{ + RenderPass *rpass= MEM_mallocN(sizeof(RenderPass), mallocstr); + + BLI_addtail(&rl->passes, rpass); + rpass->passtype= passtype; + rpass->rect= MEM_callocN(sizeof(float)*rectsize, mallocstr); +} + +float *RE_RenderLayerGetPass(RenderLayer *rl, int passtype) +{ + RenderPass *rpass; + + for(rpass=rl->passes.first; rpass; rpass= rpass->next) + if(rpass->passtype== passtype) + return rpass->rect; + return NULL; +} + /* called by main render as well for parts */ /* will read info from Render *re to define layers */ /* called in threads */ @@ -205,10 +234,25 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop) rl->passflag= srl->passflag; rl->rectf= RE_callocN(rectx*recty*sizeof(float)*4, "layer float rgba"); + if(srl->passflag & SCE_PASS_Z) - rl->rectz= RE_callocN(rectx*recty*sizeof(float), "layer float Z"); + render_layer_add_pass(rl, rectx*recty, SCE_PASS_Z, "Layer float Z"); if(srl->passflag & SCE_PASS_VECTOR) - rl->rectvec= RE_callocN(rectx*recty*sizeof(float)*2, "layer float Vector"); + render_layer_add_pass(rl, rectx*recty*2, SCE_PASS_VECTOR, "layer float Vector"); + if(srl->passflag & SCE_PASS_NORMAL) + render_layer_add_pass(rl, rectx*recty*3, SCE_PASS_NORMAL, "layer float Normal"); + if(srl->passflag & SCE_PASS_RGBA) + render_layer_add_pass(rl, rectx*recty*4, SCE_PASS_RGBA, "layer float Color"); + if(srl->passflag & SCE_PASS_DIFFUSE) + render_layer_add_pass(rl, rectx*recty*3, SCE_PASS_DIFFUSE, "layer float Diffuse"); + if(srl->passflag & SCE_PASS_SPEC) + render_layer_add_pass(rl, rectx*recty*3, SCE_PASS_SPEC, "layer float Spec"); + if(srl->passflag & SCE_PASS_SHADOW) + render_layer_add_pass(rl, rectx*recty*3, SCE_PASS_SHADOW, "layer float Shadow"); + if(srl->passflag & SCE_PASS_AO) + render_layer_add_pass(rl, rectx*recty*3, SCE_PASS_AO, "layer float AO"); + if(srl->passflag & SCE_PASS_RAY) + render_layer_add_pass(rl, rectx*recty*3, SCE_PASS_RAY, "layer float Mirror"); } /* previewrender and envmap don't do layers, so we make a default one */ @@ -217,13 +261,11 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop) BLI_addtail(&rr->layers, rl); rl->rectf= RE_callocN(rectx*recty*sizeof(float)*4, "prev/env float rgba"); - rl->rectz= RE_callocN(rectx*recty*sizeof(float), "prev/env float Z"); /* note, this has to be in sync with scene.c */ rl->lay= (1<<20) -1; rl->layflag= 0x7FFF; /* solid ztra halo strand */ - rl->passflag= SCE_PASS_COMBINED|SCE_PASS_Z; - + rl->passflag= SCE_PASS_COMBINED; } return rr; @@ -277,18 +319,30 @@ static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, static void merge_render_result(RenderResult *rr, RenderResult *rrpart) { RenderLayer *rl, *rlp; + RenderPass *rpass, *rpassp; for(rl= rr->layers.first, rlp= rrpart->layers.first; rl && rlp; rl= rl->next, rlp= rlp->next) { /* combined */ if(rl->rectf && rlp->rectf) do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4); - /* z */ - if(rl->rectz && rlp->rectz) - do_merge_tile(rr, rrpart, rl->rectz, rlp->rectz, 1); - /* vector */ - if(rl->rectvec && rlp->rectvec) - do_merge_tile(rr, rrpart, rl->rectvec, rlp->rectvec, 2); + + /* passes are allocated in sync */ + for(rpass= rl->passes.first, rpassp= rlp->passes.first; rpass && rpassp; rpass= rpass->next, rpassp= rpassp->next) { + switch(rpass->passtype) { + case SCE_PASS_Z: + do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, 1); + break; + case SCE_PASS_VECTOR: + do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, 2); + break; + case SCE_PASS_RGBA: + do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, 4); + break; + default: + do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, 3); + } + } } } @@ -337,7 +391,7 @@ void RE_GetResultImage(Render *re, RenderResult *rr) if(rr->rectf==NULL) rr->rectf= rl->rectf; if(rr->rectz==NULL) - rr->rectz= rl->rectz; + rr->rectz= RE_RenderLayerGetPass(rl, SCE_PASS_Z); } } } @@ -683,11 +737,12 @@ static void threaded_tile_processor(Render *re) /* assuming no new data gets added to dbase... */ R= *re; + /* set threadsafety */ + R.test_break= thread_break; malloc_lock = SDL_CreateMutex(); while(rendering) { - /* I noted that test_break() in a thread doesn't make ghost send ESC */ if(BLI_available_threads(&threads) && !re->test_break()) { pa= find_nicest_part(re); if(pa) { @@ -728,12 +783,14 @@ static void threaded_tile_processor(Render *re) drawtimer= 0; /* on break, wait for all slots to get freed */ - if(re->test_break() && BLI_available_threads(&threads)==maxthreads) + if( (g_break=re->test_break()) && BLI_available_threads(&threads)==maxthreads) rendering= 0; } + /* restore threadsafety */ if(malloc_lock) SDL_DestroyMutex(malloc_lock); malloc_lock= NULL; + g_break= 0; BLI_end_threads(&threads); freeparts(re); diff --git a/source/blender/render/intern/source/pixelblending.c b/source/blender/render/intern/source/pixelblending.c index ece9970e885..3048a151925 100644 --- a/source/blender/render/intern/source/pixelblending.c +++ b/source/blender/render/intern/source/pixelblending.c @@ -212,24 +212,18 @@ void add_filt_fmask(unsigned int mask, float *col, float *rowbuf, int row_w) } } -/* filtered adding to scanlines */ -void add_filt_fmask_alphaunder(unsigned int mask, float *col, float *rowbuf, int row_w) +void add_filt_fmask_pixsize(unsigned int mask, float *in, float *rowbuf, int row_w, int pixsize) { /* calc the value of mask */ float **fmask1= R.samples->fmask1, **fmask2=R.samples->fmask2; float *rb1, *rb2, *rb3; - float val, r, g, b, al, acol[4]; + float val; unsigned int a, maskand, maskshift; - int j; - - r= col[0]; - g= col[1]; - b= col[2]; - al= col[3]; + int i, j; - rb2= rowbuf-4; - rb3= rb2-4*row_w; - rb1= rb2+4*row_w; + rb2= rowbuf-pixsize; + rb3= rb2-pixsize*row_w; + rb1= rb2+pixsize*row_w; maskand= (mask & 255); maskshift= (mask >>8); @@ -240,40 +234,30 @@ void add_filt_fmask_alphaunder(unsigned int mask, float *col, float *rowbuf, int val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift); if(val!=0.0) { - acol[0]= val*r; - acol[1]= val*g; - acol[2]= val*b; - acol[3]= val*al; - addAlphaUnderFloat(rb1, acol); + for(i= 0; i<pixsize; i++) + rb1[i]+= val*in[i]; } a+=3; val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift); if(val!=0.0) { - acol[0]= val*r; - acol[1]= val*g; - acol[2]= val*b; - acol[3]= val*al; - addAlphaUnderFloat(rb2, acol); + for(i= 0; i<pixsize; i++) + rb2[i]+= val*in[i]; } a+=3; val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift); if(val!=0.0) { - acol[0]= val*r; - acol[1]= val*g; - acol[2]= val*b; - acol[3]= val*al; - addAlphaUnderFloat(rb3, acol); + for(i= 0; i<pixsize; i++) + rb3[i]+= val*in[i]; } - rb1+= 4; - rb2+= 4; - rb3+= 4; + rb1+= pixsize; + rb2+= pixsize; + rb3+= pixsize; } } - /* ------------------------------------------------------------------------- */ void addalphaAddFloat(float *dest, float *source) { diff --git a/source/blender/render/intern/source/ray.c b/source/blender/render/intern/source/ray.c index d5d0a951604..02dcf4bb60d 100644 --- a/source/blender/render/intern/source/ray.c +++ b/source/blender/render/intern/source/ray.c @@ -1516,7 +1516,7 @@ static void color_combine(float *result, float fac1, float fac2, float *col1, fl #endif /* the main recursive tracer itself */ -static void traceray(short depth, float *start, float *vec, float *col, VlakRen *vlr, int mask, int osatex, int traflag) +static void traceray(ShadeInput *origshi, short depth, float *start, float *vec, float *col, VlakRen *vlr, int traflag) { ShadeInput shi; ShadeResult shr; @@ -1533,9 +1533,13 @@ static void traceray(short depth, float *start, float *vec, float *col, VlakRen if( d3dda(&isec) ) { - shi.mask= mask; - shi.osatex= osatex; + shi.mask= origshi->mask; + shi.osatex= origshi->osatex; shi.depth= 1; // only now to indicate tracing + shi.thread= origshi->thread; + shi.xs= origshi->xs; + shi.ys= origshi->ys; + shi.do_preview= 0; shade_ray(&isec, &shi, &shr); @@ -1559,10 +1563,10 @@ static void traceray(short depth, float *start, float *vec, float *col, VlakRen refraction(refract, shi.vn, shi.view, shi.ang); } traflag |= RAY_TRA; - traceray(depth-1, shi.co, refract, tracol, shi.vlr, shi.mask, osatex, traflag ^ RAY_TRAFLIP); + traceray(origshi, depth-1, shi.co, refract, tracol, shi.vlr, traflag ^ RAY_TRAFLIP); } else - traceray(depth-1, shi.co, shi.view, tracol, shi.vlr, shi.mask, osatex, 0); + traceray(origshi, depth-1, shi.co, shi.view, tracol, shi.vlr, 0); f= shr.alpha; f1= 1.0-f; fr= 1.0+ shi.mat->filter*(shi.r-1.0); @@ -1591,7 +1595,7 @@ static void traceray(short depth, float *start, float *vec, float *col, VlakRen float mircol[4]; reflection(ref, shi.vn, shi.view, NULL); - traceray(depth-1, shi.co, ref, mircol, shi.vlr, shi.mask, osatex, 0); + traceray(origshi, depth-1, shi.co, ref, mircol, shi.vlr, 0); f1= 1.0-f; @@ -1767,10 +1771,10 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr) if(shi->mat->mode & MA_RAYTRANSP) { refraction(refract, shi->vn, shi->view, shi->ang); - traceray(shi->mat->ray_depth_tra, shi->co, refract, tracol, shi->vlr, shi->mask, 0, RAY_TRA|RAY_TRAFLIP); + traceray(shi, shi->mat->ray_depth_tra, shi->co, refract, tracol, shi->vlr, RAY_TRA|RAY_TRAFLIP); } else - traceray(shi->mat->ray_depth_tra, shi->co, shi->view, tracol, shi->vlr, shi->mask, 0, 0); + traceray(shi, shi->mat->ray_depth_tra, shi->co, shi->view, tracol, shi->vlr, 0); f= shr->alpha; f1= 1.0-f; fr= 1.0+ shi->mat->filter*(shi->r-1.0); @@ -1796,7 +1800,7 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr) else reflection(vec, shi->vn, shi->view, NULL); - traceray(shi->mat->ray_depth, shi->co, vec, mircol, shi->vlr, shi->mask, shi->osatex, 0); + 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; shr->diff[0]= f*mircol[0] + f1*shr->diff[0]; @@ -2073,7 +2077,7 @@ void ray_ao(ShadeInput *shi, float *shadfac) bias= 0.0; nrm= shi->facenor; } - + vec= sphere_sampler(R.wrld.aomode, R.wrld.aosamp, shi->thread, shi->xs, shi->ys); // warning: since we use full sphere now, and dotproduct is below, we do twice as much diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index ba45953eefc..c5d362d8c2d 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -1073,7 +1073,9 @@ static void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, floa /* blending method */ fac= col[3]*ma->rampfac_col; - colt[0]= shi->r; colt[1]= shi->g; colt[2]= shi->b; + colt[0]= shi->r; + colt[1]= shi->g; + colt[2]= shi->b; ramp_blend(ma->rampblend_col, colt, colt+1, colt+2, fac, col); @@ -1158,7 +1160,9 @@ static void ambient_occlusion(ShadeInput *shi, ShadeResult *shr) else if (R.wrld.aomix==WO_AOSUB) shadfac[3] = shadfac[3]-1.0; f= R.wrld.aoenergy*shadfac[3]*shi->amb; - add_to_diffuse(shr->diff, shi, f, f, f, f); + shr->ao[0]+= f; + shr->ao[1]+= f; + shr->ao[2]+= f; } else { if (R.wrld.aomix==WO_AOADDSUB) { @@ -1172,11 +1176,453 @@ static void ambient_occlusion(ShadeInput *shi, ShadeResult *shr) shadfac[2] = shadfac[2]-1.0; } f= R.wrld.aoenergy*shi->amb; - add_to_diffuse(shr->diff, shi, f, f*shadfac[0], f*shadfac[1], f*shadfac[2]); + 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, lacol[3], shadfac[4]; + float i, is, inp, i_noshad, *vn, *view, vnor[3], phongcorr; + + 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) */ + 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) { + if(inp>ma->sbias) + phongcorr= (inp-ma->sbias)/(inp*(1.0-ma->sbias)); + else + phongcorr= 0.0; + } + else phongcorr= 1.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) { + 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); + } + } + } + } + +} + + +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; + + /* 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->mode & (MA_ZTRA|MA_RAYTRANSP)) { + if(ma->fresnel_tra!=0.0) + shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra); + + 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; + } + +} + void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) { LampRen *lar; @@ -1184,11 +1630,6 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) Material *ma= shi->mat; VlakRen *vlr= shi->vlr; ListBase *lights; - float i, inp, inpr, is, t, lv[3], vnor[3], lacol[3], lampdist, ld = 0; - float lvrot[3], *vn, *view, shadfac[4], soft, phongcorr; // shadfac = rgba - - vn= shi->vn; - view= shi->view; memset(shr, 0, sizeof(ShadeResult)); @@ -1202,7 +1643,12 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) /* separate loop */ if(ma->mode & MA_ONLYSHADOW) { - float ir; + 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) { @@ -1322,20 +1768,21 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) } if( (ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL ) { // vertexcolor light - // add_to_diffuse(shr->diff, shi, 1.0, ma->emit+shi->vcol[0], ma->emit+shi->vcol[1], ma->emit+shi->vcol[2]); 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 { - // add_to_diffuse(shr->diff, shi, 1.0, ma->emit, ma->emit, ma->emit); shr->diff[0]= shi->r*shi->emit; shr->diff[1]= shi->g*shi->emit; shr->diff[2]= shi->b*shi->emit; } - ambient_occlusion(shi, shr); - + if(R.wrld.mode & WO_AMB_OCC) { + ambient_occlusion(shi, shr); + VECADD(shr->diff, shr->diff, shr->ao); + } + for(go=lights->first; go; go= go->next) { lar= go->lampren; if(lar==NULL) continue; @@ -1346,297 +1793,8 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) /* test for lamp layer */ if(lar->mode & LA_LAYER) if((lar->lay & vlr->lay)==0) continue; - /* 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) { - 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) { - t= lar->dist - ld; - if(t<0.0) continue; - - t/= lar->dist; - lampdist*= (t); - } - } - } - - lacol[0]= lar->r; - lacol[1]= lar->g; - lacol[2]= lar->b; - - /* init transp shadow */ - shadfac[3]= 1.0; - if(ma->mode & MA_SHADOW_TRA) shadfac[0]= shadfac[1]= shadfac[2]= 1.0; - - if(lar->type==LA_SPOT) { - - if(lar->mode & LA_SQUARE) { - if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) { - float 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) continue; - else { - t= inpr-t; - i= 1.0; - soft= 1.0; - if(t<lar->spotbl && lar->spotbl!=0.0) { - /* soft area */ - i= t/lar->spotbl; - t= i*i; - soft= (3.0*t-2.0*t*i); - inpr*= soft; - } - 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) */ - 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) { - if(inp>ma->sbias) - phongcorr= (inp-ma->sbias)/(inp*(1.0-ma->sbias)); - else - phongcorr= 0.0; - } - else phongcorr= 1.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; - } - - vn= shi->vn; // bring back original vector, we use special specular shaders for tangent - if(ma->mode & MA_TANGENT_V) - vn= shi->tang; - - /* 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) { - 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; - - continue; - } - - if(shadfac[3]==0.0) continue; - - i*= shadfac[3]; - } - } - } -#if 0 - if(R.r.mode & R_RAYTRACE) { - extern void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float *co); - float co[3], distfac; - - ray_translucent(shi, lar, &distfac, co); - - if(distfac<0.01f*G.rt) { - // printf("distfac %f\n", distfac); - distfac= 1.0f - distfac/(0.01f*G.rt); - shr->diff[0]+= distfac; - shr->diff[1]+= distfac; - shr->diff[2]+= distfac; - } - } -#endif - - /* specularity */ - if(shadfac[3]>0.0 && shi->spec!=0.0 && !(lar->mode & LA_NO_SPEC)) { - - if(lar->type==LA_HEMI) { - /* 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; - - 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); - } - } - } - } - - /* 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]); - } - } + /* accumulates in shr->diff and shr->spec, 0= no passrender */ + shade_one_light(lar, shi, shr, 0); } if(ma->mode & (MA_ZTRA|MA_RAYTRANSP)) { @@ -1644,8 +1802,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra); if(shi->spectra!=0.0) { - - t = MAX3(shr->spec[0], shr->spec[1], shr->spec[2]); + 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; @@ -2125,7 +2282,7 @@ void shade_material_loop(ShadeInput *shi, ShadeResult *shr) /* note, facenr declared volatile due to over-eager -O2 optimizations * on cygwin (particularly -frerun-cse-after-loop) */ -void *shadepixel(RenderPart *pa, float x, float y, int z, volatile int facenr, int mask, ShadeResult *shr, float *rco) +void *shadepixel(RenderPart *pa, float x, float y, int z, volatile int facenr, int mask, ShadeResult *shr, float *rco, int passflag) { ShadeInput shi; VlakRen *vlr=NULL; @@ -2347,7 +2504,10 @@ void *shadepixel(RenderPart *pa, float x, float y, int z, volatile int facenr, i memcpy(&shi.r, &shi.mat->r, 23*sizeof(float)); shi.har= shi.mat->har; - shade_material_loop(&shi, shr); +// if(passflag) +// shade_lamp_loop_pass(&shi, shr, passflag); +// else + shade_material_loop(&shi, shr); } /* after shading and composit layers */ @@ -2359,7 +2519,9 @@ void *shadepixel(RenderPart *pa, float x, float y, int z, volatile int facenr, i if(shr->diff[1]<0.0f) shr->diff[1]= 0.0f; if(shr->diff[2]<0.0f) shr->diff[2]= 0.0f; - VECADD(shr->combined, shr->diff, shr->spec); +// if(passflag==0) { + VECADD(shr->combined, shr->diff, shr->spec); +// } /* additional passes */ shr->winspeed[0]= shi.winspeed[0]; shr->winspeed[1]= shi.winspeed[1]; @@ -2423,12 +2585,12 @@ void *shadepixel(RenderPart *pa, float x, float y, int z, volatile int facenr, i return vlr; } -static void shadepixel_sky(RenderPart *pa, float x, float y, int z, int facenr, int mask, ShadeResult *shr) +static void shadepixel_sky(RenderPart *pa, float x, float y, int z, int facenr, int mask, ShadeResult *shr, int passflag) { VlakRen *vlr; float collector[4], rco[3]; - vlr= shadepixel(pa, x, y, z, facenr, mask, shr, rco); + vlr= shadepixel(pa, x, y, z, facenr, mask, shr, rco, passflag); if(shr->combined[3] != 1.0) { /* bail out when raytrace transparency (sky included already) */ @@ -2515,6 +2677,96 @@ static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect) /* ********************* MAINLOOPS ******************** */ +/* osa version */ +static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, ShadeResult *shr) +{ + RenderPass *rpass; + + for(rpass= rl->passes.first; rpass; rpass= rpass->next) { + float *fp, *col= NULL; + int pixsize= 3; + + switch(rpass->passtype) { + case SCE_PASS_RGBA: + col= shr->col; + 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_RAY: + col= shr->ray; + break; + case SCE_PASS_NORMAL: + col= shr->nor; + break; + case SCE_PASS_VECTOR: + col= shr->winspeed; + pixsize= 2; + break; + } + if(col) { + fp= rpass->rect + pixsize*offset; + add_filt_fmask_pixsize(curmask, col, fp, rectx, pixsize); + } + } +} + +/* non-osa version */ +static void add_passes(RenderLayer *rl, int offset, ShadeResult *shr) +{ + RenderPass *rpass; + + for(rpass= rl->passes.first; rpass; rpass= rpass->next) { + float *fp, *col= NULL; + int a, pixsize= 3; + + switch(rpass->passtype) { + case SCE_PASS_RGBA: + col= shr->col; + 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_RAY: + col= shr->ray; + break; + case SCE_PASS_NORMAL: + col= shr->nor; + break; + case SCE_PASS_VECTOR: + col= shr->winspeed; + pixsize= 2; + break; + } + if(col) { + fp= rpass->rect + pixsize*offset; + for(a=0; a<pixsize; a++) + fp[a]= col[a]; + } + } +} + + static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) { RenderResult *rr= pa->result; @@ -2524,7 +2776,7 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) float *fcol= shr.combined, *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; + int b, x, y, full_osa, seed, crop=0, offs=0, od, renderpassflag, addpassflag; if(R.test_break()) return; @@ -2533,6 +2785,13 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) fullmask= (1<<R.osa)-1; + /* bit clumsy, but with passes we need different shade code */ + if(rl->passflag & ~(SCE_PASS_Z|SCE_PASS_NORMAL|SCE_PASS_VECTOR|SCE_PASS_COMBINED)) + renderpassflag= rl->passflag; + else + renderpassflag= 0; + addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED); + /* filtered render, for now we assume only 1 filter size */ if(pa->crop) { crop= 1; @@ -2582,7 +2841,7 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) if(curmask & (1<<samp)) { xs= (float)x + R.jit[samp][0]; ys= (float)y + R.jit[samp][1]; - shadepixel_sky(pa, xs, ys, zbuf, face, (1<<samp), &shr); + shadepixel_sky(pa, xs, ys, zbuf, face, (1<<samp), &shr, renderpassflag); if(R.do_gamma) { fcol[0]= gammaCorrect(fcol[0]); @@ -2590,6 +2849,9 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) fcol[2]= gammaCorrect(fcol[2]); } add_filt_fmask(1<<samp, fcol, rf, pa->rectx); + + if(addpassflag) + add_filt_passes(rl, curmask, pa->rectx, od, &shr); } } } @@ -2597,7 +2859,7 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) b= R.samples->centmask[curmask]; xs= (float)x+R.samples->centLut[b & 15]; ys= (float)y+R.samples->centLut[b>>4]; - shadepixel_sky(pa, xs, ys, zbuf, face, curmask, &shr); + shadepixel_sky(pa, xs, ys, zbuf, face, curmask, &shr, renderpassflag); if(R.do_gamma) { fcol[0]= gammaCorrect(fcol[0]); @@ -2605,6 +2867,9 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) fcol[2]= gammaCorrect(fcol[2]); } add_filt_fmask(curmask, fcol, rf, pa->rectx); + + if(addpassflag) + add_filt_passes(rl, curmask, pa->rectx, od, &shr); } mask |= curmask; @@ -2612,13 +2877,6 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) if(ps==NULL) break; else ps= ps->next; } - - /* passes */ - if(rl->passflag & SCE_PASS_VECTOR) { - float *fp= rl->rectvec+2*od; - fp[0]= shr.winspeed[0]; - fp[1]= shr.winspeed[1]; - } } rectf+= 4*pa->rectx; @@ -2812,10 +3070,10 @@ void zbufshadeDA_tile(RenderPart *pa) /* supposed to be fully threadable! */ void zbufshade_tile(RenderPart *pa) { - ShadeResult shr; + ShadeResult *shr= RE_mallocN(sizeof(ShadeResult), "shaderesult"); RenderResult *rr= pa->result; RenderLayer *rl; - + set_part_zbuf_clipflag(pa); /* zbuffer code clears/inits rects */ @@ -2831,22 +3089,26 @@ void zbufshade_tile(RenderPart *pa) if(!R.test_break()) { if(rl->layflag & SCE_LAY_SOLID) { float *fcol= rl->rectf; - int x, y, *rp= pa->rectp, *rz= pa->rectz, offs=0; + int x, y, *rp= pa->rectp, *rz= pa->rectz, offs=0, renderpassflag, addpassflag; + + /* bit clumsy, but with passes we shade differently */ + if(rl->passflag & ~(SCE_PASS_Z|SCE_PASS_NORMAL|SCE_PASS_VECTOR|SCE_PASS_COMBINED)) + renderpassflag= rl->passflag; + else + renderpassflag= 0; + addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED); /* init scanline updates */ rr->renrect.ymin=rr->renrect.ymax= 0; 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++) { - shadepixel_sky(pa, (float)x, (float)y, *rz, *rp, 0, &shr); - QUATCOPY(fcol, shr.combined); + shadepixel_sky(pa, (float)x, (float)y, *rz, *rp, 0, shr, renderpassflag); + QUATCOPY(fcol, shr->combined); /* passes */ - if(*rp && (rl->passflag & SCE_PASS_VECTOR)) { - float *fp= rl->rectvec+2*(offs); - fp[0]= shr.winspeed[0]; - fp[1]= shr.winspeed[1]; - } + if(*rp && addpassflag) + add_passes(rl, offs, shr); } if(y&1) if(R.test_break()) break; @@ -2891,7 +3153,7 @@ void zbufshade_tile(RenderPart *pa) convert_zbuf_to_distbuf(pa, rl); } - + RE_freeN(shr); RE_freeN(pa->rectp); pa->rectp= NULL; RE_freeN(pa->rectz); pa->rectz= NULL; } diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 4830db352d7..eb1385cab95 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -2049,7 +2049,7 @@ static void shadetrapixel(RenderPart *pa, float x, float y, int z, int facenr, i if(vlr->flag & R_FULL_OSA) { for(a=0; a<R.osa; a++) { if(mask & (1<<a)) { - shadepixel(pa, x+R.jit[a][0], y+R.jit[a][1], z, facenr, 1<<a, &shr, rco); + shadepixel(pa, x+R.jit[a][0], y+R.jit[a][1], z, facenr, 1<<a, &shr, rco, 0); accumcol[0]+= shr.combined[0]; accumcol[1]+= shr.combined[1]; accumcol[2]+= shr.combined[2]; @@ -2067,12 +2067,12 @@ static void shadetrapixel(RenderPart *pa, float x, float y, int z, int facenr, i int b= R.samples->centmask[mask]; x= x+R.samples->centLut[b & 15]; y= y+R.samples->centLut[b>>4]; - shadepixel(pa, x, y, z, facenr, mask, &shr, rco); + shadepixel(pa, x, y, z, facenr, mask, &shr, rco, 0); QUATCOPY(fcol, shr.combined); } } else { - shadepixel(pa, x, y, z, facenr, mask, &shr, rco); + shadepixel(pa, x, y, z, facenr, mask, &shr, rco, 0); QUATCOPY(fcol, shr.combined); } } @@ -2238,15 +2238,21 @@ void zbuffer_transp_shade(RenderPart *pa, float *pass, unsigned int lay, short l /* uses part zbuffer values to convert into distances from camera in renderlayer */ void convert_zbuf_to_distbuf(RenderPart *pa, RenderLayer *rl) { + RenderPass *rpass; float *rectzf, zco; int a, *rectz, ortho= R.r.mode & R_ORTHO; if(pa->rectz==NULL) return; - if(rl->rectz==NULL) { + for(rpass= rl->passes.first; rpass; rpass= rpass->next) + if(rpass->passtype==SCE_PASS_Z) + break; + + if(rpass==NULL) { printf("called convert zbuf wrong...\n"); return; } - rectzf= rl->rectz; + + rectzf= rpass->rect; rectz= pa->rectz; for(a=pa->rectx*pa->recty; a>0; a--, rectz++, rectzf++) { |