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:
Diffstat (limited to 'source/blender/render/intern/source/rendercore.c')
-rw-r--r--source/blender/render/intern/source/rendercore.c293
1 files changed, 293 insertions, 0 deletions
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 10201087f2d..1c5f56362bc 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -64,6 +64,7 @@
#include "pixelshading.h"
#include "shadbuf.h"
#include "shading.h"
+#include "sss.h"
#include "zbuf.h"
#include "PIL_time.h"
@@ -1113,6 +1114,298 @@ void zbufshade_tile(RenderPart *pa)
MEM_freeN(pa->clipflag); pa->clipflag= NULL;
}
+/* SSS preprocess tile render, fully threadable */
+typedef struct ZBufSSSHandle {
+ RenderPart *pa;
+ ListBase psmlist;
+ int totps;
+} ZBufSSSHandle;
+
+static void addps_sss(void *cb_handle, int facenr, int x, int y, int z)
+{
+ ZBufSSSHandle *handle = cb_handle;
+ RenderPart *pa= handle->pa;
+
+ if (pa->rectall) {
+ long *rs= pa->rectall + pa->rectx*y + x;
+
+ addps(&handle->psmlist, rs, facenr, z, 0);
+ handle->totps++;
+ }
+ if (pa->rectz) {
+ int *rz= pa->rectz + pa->rectx*y + x;
+ int *rp= pa->rectp + pa->rectx*y + x;
+
+ if (z < *rz) {
+ if(*rp == 0)
+ handle->totps++;
+ *rz= z;
+ *rp= facenr;
+ }
+ }
+ if (pa->rectbackz) {
+ int *rz= pa->rectbackz + pa->rectx*y + x;
+ int *rp= pa->rectbackp + pa->rectx*y + x;
+
+ if (z >= *rz) {
+ if(*rp == 0)
+ handle->totps++;
+ *rz= z;
+ *rp= facenr;
+ }
+ }
+}
+
+static void shade_sample_sss(ShadeSample *ssamp, Material *mat, VlakRen *vlr, int quad, int x, int y, float z, float *co, float *color, float *area)
+{
+ ShadeInput *shi= ssamp->shi;
+ ShadeResult shr;
+ float texfac, orthoarea, nor[3];
+
+ /* normal flipping must be disabled to make back scattering work, so that
+ backside faces actually face any lighting from the back */
+ shi->puno= 0;
+
+ /* cache for shadow */
+ shi->samplenr++;
+
+ if(quad)
+ shade_input_set_triangle_i(shi, vlr, 0, 2, 3);
+ else
+ shade_input_set_triangle_i(shi, vlr, 0, 1, 2);
+
+ /* we don't want flipped normals, they screw up back scattering */
+ if(vlr->noflag & R_FLIPPED_NO) {
+ shi->facenor[0]= -shi->facenor[0];
+ shi->facenor[1]= -shi->facenor[1];
+ shi->facenor[2]= -shi->facenor[2];
+ }
+
+ /* we estimate the area here using shi->dxco and shi->dyco. we need to
+ enabled shi->osatex these are filled. we compute two areas, one with
+ the normal pointed at the camera and one with the original normal, and
+ then clamp to avoid a too large contribution from a single pixel */
+ shi->osatex= 1;
+
+ VECCOPY(nor, shi->facenor);
+ calc_view_vector(shi->facenor, x, y);
+ Normalize(shi->facenor);
+ shade_input_set_viewco(shi, x, y, z);
+ orthoarea= VecLength(shi->dxco)*VecLength(shi->dyco);
+
+ VECCOPY(shi->facenor, nor);
+ shade_input_set_viewco(shi, x, y, z);
+ *area= VecLength(shi->dxco)*VecLength(shi->dyco);
+ *area= MIN2(*area, 2.0f*orthoarea);
+
+ shi->osatex= 0;
+
+ shade_input_set_uv(shi);
+ shade_input_set_normals(shi);
+
+ /* if nodetree, use the material that we are currently preprocessing
+ instead of the node material */
+ if(shi->mat->nodetree && shi->mat->use_nodes)
+ shi->mat= mat;
+
+ /* init material vars */
+ // note, keep this synced with render_types.h
+ memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
+ shi->har= shi->mat->har;
+
+ /* render */
+ shade_input_set_shade_texco(shi);
+
+ shade_samples_do_AO(ssamp);
+ shade_material_loop(shi, &shr);
+
+ VECCOPY(co, shi->co);
+ VECCOPY(color, shr.combined);
+
+ /* texture blending */
+ texfac= shi->mat->sss_texfac;
+
+ if(texfac == 0.0f) {
+ if(shr.col[0]!=0.0f) color[0] /= shr.col[0];
+ if(shr.col[1]!=0.0f) color[1] /= shr.col[1];
+ if(shr.col[2]!=0.0f) color[2] /= shr.col[2];
+ }
+ else if(texfac != 1.0f) {
+ if(shr.col[0]!=0.0f) color[0] *= pow(shr.col[0], texfac)/shr.col[0];
+ if(shr.col[1]!=0.0f) color[1] *= pow(shr.col[1], texfac)/shr.col[1];
+ if(shr.col[2]!=0.0f) color[2] *= pow(shr.col[2], texfac)/shr.col[2];
+ }
+}
+
+void zbufshade_sss_tile(RenderPart *pa)
+{
+ ShadeSample ssamp;
+ ZBufSSSHandle handle;
+ RenderResult *rr= pa->result;
+ RenderLayer *rl= rr->layers.first;
+ VlakRen *vlr;
+ Material *mat= R.sss_mat;
+ float (*co)[3], (*color)[3], *area, *fcol= rl->rectf;
+ int x, y, seed, quad, totpoint;
+#if 0
+ PixStr *ps;
+ long *rs;
+ int z;
+#else
+ int *rz, *rp, *rbz, *rbp;
+#endif
+
+ set_part_zbuf_clipflag(pa);
+
+ /* setup pixelstr list and buffer for zbuffering */
+ handle.pa= pa;
+ handle.totps= 0;
+
+#if 0
+ handle.psmlist.first= handle.psmlist.last= NULL;
+ addpsmain(&handle.psmlist);
+
+ pa->rectall= MEM_callocN(sizeof(long)*pa->rectx*pa->recty+4, "rectall");
+#else
+ pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
+ pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
+ pa->rectbackp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackp");
+ pa->rectbackz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackz");
+#endif
+
+ /* create the pixelstrs to be used later */
+ zbuffer_sss(pa, rl->lay, &handle, addps_sss);
+
+ co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo");
+ color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor");
+ area= MEM_mallocN(sizeof(float)*handle.totps, "SSSArea");
+
+#if 0
+ /* create ISB (does not work currently!) */
+ if(R.r.mode & R_SHADOW)
+ ISB_create(pa, NULL);
+#endif
+
+ /* setup shade sample with correct passes */
+ shade_sample_initialize(&ssamp, pa, rl);
+ ssamp.shi[0].passflag= SCE_PASS_DIFFUSE|SCE_PASS_AO|SCE_PASS_RADIO;
+ ssamp.shi[0].passflag |= SCE_PASS_RGBA;
+ ssamp.shi[0].combinedflag= ~(SCE_PASS_SPEC);
+
+ /* initialize scanline updates for main thread */
+ rr->renrect.ymin= 0;
+ rr->renlay= rl;
+
+ seed= pa->rectx*pa->disprect.ymin;
+#if 0
+ rs= pa->rectall;
+#else
+ rz= pa->rectz;
+ rp= pa->rectp;
+ rbz= pa->rectbackz;
+ rbp= pa->rectbackp;
+#endif
+ totpoint= 0;
+
+ for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++, rr->renrect.ymax++) {
+ for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, fcol+=4) {
+ /* per pixel fixed seed */
+ BLI_thread_srandom(pa->thread, seed++);
+
+#if 0
+ if(rs) {
+ /* for each sample in this pixel, shade it */
+ for(ps=(PixStr*)*rs; ps; ps=ps->next) {
+ vlr= RE_findOrAddVlak(&R, (ps->facenr-1) & RE_QUAD_MASK);
+ quad= (ps->facenr & RE_QUAD_OFFS);
+ z= ps->z;
+
+ shade_sample_sss(&ssamp, mat, vlr, quad, x, y, z,
+ co[totpoint], color[totpoint], &area[totpoint]);
+
+ totpoint++;
+
+ VECADD(fcol, fcol, color);
+ fcol[3]= 1.0f;
+ }
+
+ rs++;
+ }
+#else
+ if(rp) {
+ if(*rp != 0) {
+ /* shade front */
+ vlr= RE_findOrAddVlak(&R, (*rp-1) & RE_QUAD_MASK);
+ quad= ((*rp) & RE_QUAD_OFFS);
+
+ shade_sample_sss(&ssamp, mat, vlr, quad, x, y, *rz,
+ co[totpoint], color[totpoint], &area[totpoint]);
+
+ VECADD(fcol, fcol, color[totpoint]);
+ fcol[3]= 1.0f;
+ totpoint++;
+ }
+
+ rp++; rz++;
+ }
+
+ if(rbp) {
+ if(*rbp != 0 && *rbp != *(rp-1)) {
+ /* shade back */
+ vlr= RE_findOrAddVlak(&R, (*rbp-1) & RE_QUAD_MASK);
+ quad= ((*rbp) & RE_QUAD_OFFS);
+
+ shade_sample_sss(&ssamp, mat, vlr, quad, x, y, *rbz,
+ co[totpoint], color[totpoint], &area[totpoint]);
+
+ /* to indicate this is a back sample */
+ area[totpoint]= -area[totpoint];
+
+ VECADD(fcol, fcol, color[totpoint]);
+ fcol[3]= 1.0f;
+ totpoint++;
+ }
+
+ rbz++; rbp++;
+ }
+#endif
+ }
+
+ if(y&1)
+ if(R.test_break()) break;
+ }
+
+ /* note: after adding we do not free these arrays, sss keeps them */
+ if(totpoint > 0) {
+ sss_add_points(&R, co, color, area, totpoint);
+ }
+ else {
+ MEM_freeN(co);
+ MEM_freeN(color);
+ MEM_freeN(area);
+ }
+
+#if 0
+ if(R.r.mode & R_SHADOW)
+ ISB_free(pa);
+#endif
+
+ /* display active layer */
+ rr->renrect.ymin=rr->renrect.ymax= 0;
+ rr->renlay= render_get_active_layer(&R, rr);
+
+ MEM_freeN(pa->clipflag); pa->clipflag= NULL;
+#if 0
+ MEM_freeN(pa->rectall); pa->rectall= NULL;
+ freeps(&handle.psmlist);
+#else
+ MEM_freeN(pa->rectz); pa->rectz= NULL;
+ MEM_freeN(pa->rectp); pa->rectp= NULL;
+ MEM_freeN(pa->rectbackz); pa->rectbackz= NULL;
+ MEM_freeN(pa->rectbackp); pa->rectbackp= NULL;
+#endif
+}
+
/* ------------------------------------------------------------------------ */
static void renderhalo_post(RenderResult *rr, float *rectf, HaloRen *har) /* postprocess version */