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>2003-12-16 17:12:01 +0300
committerTon Roosendaal <ton@blender.org>2003-12-16 17:12:01 +0300
commit97d4dbc9c317e6d5cd171a9e76ce4aeca2bdf93c (patch)
tree3136f667159fdaa3d0c804f9a0f16c7d27f2d1a7 /source/blender/render
parent356cf7953482891afe3dd289b1584b355de23b17 (diff)
Another commit for raytracing, now with glass refraction & fresnel!
Changelog: - enable refraction with button "Ray Transp" in Material buttons. - set "Angular Index" value for amount of refraction. - use the "Alpha" value to define transparency. - remember to set a higher "Depth" too... glass can bounce quite some more than expected. - for correct refraction, 3D models MUST have normals pointing in the right direction (consistently pointing outside). - refraction 'sees' the thickness of glass based on what you model. So make for realistic glass both sides of a surface. - I needed to do some rewriting for correct mirroring/refraction, especially to prevent specularity being blended away. Solved this with localizing shading results in the rendercore.c. Now specularity correctly is added, and reduces the 'mirror' value. - Localizing more parts of the render code is being planned. The old render heavily relies on struct Render and struct Osa to store globals. For scanline render no problem, but recursive raytracing dislikes that. - done test with gamma-corrected summation of colors during tracing, is commented out still. But this will give more balanced reflections. Now dark reflections that are reflected in a bright surface seem incorrect. - Introduced 'Fresnel' effect for Mirror and Transparency. This influences the amount of mirror/transparency based at viewing angle. Next to a new Fresnel slider, also a 'falloff' button has been added to define the way it spreads. - Fresnel also works for Ztransp rendering - created new Panel for Raytrace options I have to evaluate still where it all should be logically located. - material preview shows fake reflection and fake refraction as well.
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/intern/include/rendercore.h11
-rw-r--r--source/blender/render/intern/source/ray.c419
-rw-r--r--source/blender/render/intern/source/renderHelp.c4
-rw-r--r--source/blender/render/intern/source/rendercore.c203
4 files changed, 425 insertions, 212 deletions
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
index 0be15d90776..3e915b34b7c 100644
--- a/source/blender/render/intern/include/rendercore.h
+++ b/source/blender/render/intern/include/rendercore.h
@@ -38,10 +38,21 @@
struct HaloRen;
+typedef struct ShadeResult
+{
+ float diff[3];
+ float spec[3];
+ float alpha;
+
+} ShadeResult;
+
+
float mistfactor(float *co); /* dist en hoogte, return alpha */
void renderspothalo(unsigned short *col);
void render_lighting_halo(struct HaloRen *har, float *colf);
unsigned int calchalo_z(struct HaloRen *har, unsigned int zz);
+void shade_lamp_loop(int mask, ShadeResult *shr);
+float fresnel_fac(float *view, float *vn, float fresnel, float falloff);
float spec(float inp, int hard);
diff --git a/source/blender/render/intern/source/ray.c b/source/blender/render/intern/source/ray.c
index 40e13899852..5120c81d9e5 100644
--- a/source/blender/render/intern/source/ray.c
+++ b/source/blender/render/intern/source/ray.c
@@ -46,6 +46,7 @@
#include "render.h"
#include "render_intern.h"
+#include "rendercore.h"
#include "jitter.h"
#define OCRES 64
@@ -1143,9 +1144,8 @@ static int d3dda(Isect *is)
/* for now; mostly a duplicate of shadepixel() itself... could be unified once */
/* R.view has been set */
-static void shade_ray(Isect *is, int mask)
+static void shade_ray(Isect *is, int mask, ShadeResult *shr)
{
- extern void shade_lamp_loop(int );
VertRen *v1, *v2, *v3;
float n1[3], n2[3], n3[3];
float *o1, *o2, *o3;
@@ -1166,15 +1166,17 @@ static void shade_ray(Isect *is, int mask)
/* face normal, check for flip */
R.vno= R.vlr->n;
- l= R.vlr->n[0]*R.view[0]+R.vlr->n[1]*R.view[1]+R.vlr->n[2]*R.view[2];
- if(l<0.0) {
- flip= 1;
- R.vlr->n[0]= -R.vlr->n[0];
- R.vlr->n[1]= -R.vlr->n[1];
- R.vlr->n[2]= -R.vlr->n[2];
- R.vlr->puno= ~(R.vlr->puno);
+ if((R.mat->mode & MA_RAYTRANSP)==0) {
+ l= R.vlr->n[0]*R.view[0]+R.vlr->n[1]*R.view[1]+R.vlr->n[2]*R.view[2];
+ if(l<0.0) {
+ flip= 1;
+ R.vlr->n[0]= -R.vlr->n[0];
+ R.vlr->n[1]= -R.vlr->n[1];
+ R.vlr->n[2]= -R.vlr->n[2];
+ R.vlr->puno= ~(R.vlr->puno);
+ }
}
-
+
if(R.vlr->v4) {
if(is->isect==2) {
v1= R.vlr->v3;
@@ -1338,7 +1340,7 @@ static void shade_ray(Isect *is, int mask)
VECCOPY(R.vn, R.vlr->n);
}
- shade_lamp_loop(mask);
+ shade_lamp_loop(mask, shr);
if(flip) {
R.vlr->n[0]= -R.vlr->n[0];
@@ -1348,20 +1350,121 @@ static void shade_ray(Isect *is, int mask)
}
}
+static void refraction(float *refract, float *n, float *view, float index)
+{
+ float dot, fac;
+
+ VECCOPY(refract, view);
+ if(index==0.0) return;
+
+ dot= view[0]*n[0] + view[1]*n[1] + view[2]*n[2];
+
+ if(dot>0.0) {
+ fac= 1.0 - (1.0 - dot*dot)*index*index;
+ if(fac<= 0.0) return;
+ fac= -dot*index + sqrt(fac);
+ }
+ else {
+ index = 1.0/index;
+ fac= 1.0 - (1.0 - dot*dot)*index*index;
+ if(fac<= 0.0) return;
+ fac= -dot*index - sqrt(fac);
+ }
+
+ refract[0]= index*view[0] + fac*n[0];
+ refract[1]= index*view[1] + fac*n[1];
+ refract[2]= index*view[2] + fac*n[2];
+}
+
+static void calc_dx_dy_refract(float *ref, float *n, float *view, float index)
+{
+ float dref[3], dview[3], dnor[3];
+
+ refraction(ref, n, view, index);
+
+ dview[0]= view[0]+ O.dxview;
+ dview[1]= view[1];
+ dview[2]= view[2];
+
+ if(R.vlr->flag & R_SMOOTH) {
+ VecAddf(dnor, n, O.dxno);
+ refraction(dref, dnor, dview, index);
+ }
+ else {
+ refraction(dref, n, dview, index);
+ }
+ VecSubf(O.dxrefract, ref, dref);
+
+ dview[0]= view[0];
+ dview[1]= view[1]+ O.dyview;
+
+ if(R.vlr->flag & R_SMOOTH) {
+ VecAddf(dnor, n, O.dyno);
+ refraction(dref, dnor, dview, index);
+ }
+ else {
+ refraction(dref, n, dview, index);
+ }
+ VecSubf(O.dyrefract, ref, dref);
+
+}
+
+
+/* orn = original face normal */
+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]);
+
+ if(orn==NULL) {
+ // heuristic, should test this! is to prevent normal going to the back
+ if(f1> -0.2) f1= -0.2;
+ }
+
+ ref[0]= (view[0]+f1*n[0]);
+ ref[1]= (view[1]+f1*n[1]);
+ ref[2]= (view[2]+f1*n[2]);
+
+ 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;
+ ref[0]-= f1*orn[0];
+ ref[1]-= f1*orn[1];
+ ref[2]-= f1*orn[2];
+ }
+ }
+}
+
+static void color_combine(float *result, float fac1, float fac2, float *col1, float *col2)
+{
+ float col1t[3], col2t[3];
+
+ col1t[0]= sqrt(col1[0]);
+ col1t[1]= sqrt(col1[1]);
+ col1t[2]= sqrt(col1[2]);
+ col2t[0]= sqrt(col2[0]);
+ col2t[1]= sqrt(col2[1]);
+ col2t[2]= sqrt(col2[2]);
+
+ result[0]= (fac1*col1t[0] + fac2*col2t[0]);
+ result[0]*= result[0];
+ result[1]= (fac1*col1t[1] + fac2*col2t[1]);
+ result[1]*= result[1];
+ result[2]= (fac1*col1t[2] + fac2*col2t[2]);
+ result[2]*= result[2];
+}
+
/* the main recursive tracer itself */
-static void traceray(float f, short depth, float *start, float *vec, float *col, int mask)
+static void traceray(short depth, float *start, float *vec, float *col, int mask)
{
- extern unsigned short shortcol[4]; // only for old render, which stores ushort
+ ShadeResult shr;
Isect isec;
- float f1, fr, fg, fb;
+ float f, f1, fr, fg, fb;
float ref[3];
- if(depth<0) return;
-
- fr= R.mat->mirr;
- fg= R.mat->mirg;
- fb= R.mat->mirb;
-
VECCOPY(isec.start, start);
isec.end[0]= start[0]+g_oc.ocsize*vec[0];
isec.end[1]= start[1]+g_oc.ocsize*vec[1];
@@ -1374,26 +1477,65 @@ static void traceray(float f, short depth, float *start, float *vec, float *col,
VECCOPY(R.view, vec);
Normalise(R.view);
- shade_ray(&isec, mask); // returns shortcol
+ shade_ray(&isec, mask, &shr);
- f1= 1.0-f;
+ if(depth>0) {
- col[0]= f*fr*(shortcol[0]/65535.0)+ f1*col[0];
- col[1]= f*fg*(shortcol[1]/65535.0)+ f1*col[1];
- col[2]= f*fb*(shortcol[2]/65535.0)+ f1*col[2];
+ if(R.mat->mode & MA_RAYMIRROR) {
+ f= R.mat->ray_mirror;
+ if(f!=0.0) f*= fresnel_fac(R.view, R.vn, R.mat->fresnel_mir, R.mat->falloff_mir);
+ }
+ else f= 0.0;
+
+ /* have to do it here, make local vars... */
+ fr= R.mat->mirr;
+ fg= R.mat->mirg;
+ fb= R.mat->mirb;
- /* is already new material: */
- if(R.mat->ray_mirror>0.0) {
- f1= -2*(R.vn[0]*R.view[0]+R.vn[1]*R.view[1]+R.vn[2]*R.view[2]);
- if(f1> -0.2) f1= -0.2;
+ if(R.mat->mode & MA_RAYTRANSP && shr.alpha!=1.0) {
+ float f, f1, refract[3], tracol[3];
+
+ refraction(refract, R.vn, R.view, R.mat->ang);
+ traceray(depth-1, R.co, refract, tracol, mask);
+
+ f= shr.alpha; f1= 1.0-f;
+ shr.diff[0]= f*shr.diff[0] + f1*tracol[0];
+ shr.diff[1]= f*shr.diff[1] + f1*tracol[1];
+ shr.diff[2]= f*shr.diff[2] + f1*tracol[2];
+ shr.alpha= 1.0;
+ }
+
+ if(f!=0.0) {
- ref[0]= (R.view[0]+f1*R.vn[0]);
- ref[1]= (R.view[1]+f1*R.vn[1]);
- ref[2]= (R.view[2]+f1*R.vn[2]);
+ reflection(ref, R.vn, R.view, NULL);
+ traceray(depth-1, R.co, ref, col, mask);
+
+ f1= 1.0-f;
- f*= R.mat->ray_mirror;
- traceray(f, depth-1, R.co, ref, col, mask);
+ /* combine */
+ //color_combine(col, f*fr*(1.0-shr.spec[0]), f1, col, shr.diff);
+ //col[0]+= shr.spec[0];
+ //col[1]+= shr.spec[1];
+ //col[2]+= shr.spec[2];
+
+ col[0]= f*fr*(1.0-shr.spec[0])*col[0] + f1*shr.diff[0] + shr.spec[0];
+
+ col[1]= f*fg*(1.0-shr.spec[1])*col[1] + f1*shr.diff[1] + shr.spec[1];
+
+ col[2]= f*fb*(1.0-shr.spec[2])*col[2] + f1*shr.diff[2] + shr.spec[2];
+ }
+ else {
+ col[0]= shr.diff[0] + shr.spec[0];
+ col[1]= shr.diff[1] + shr.spec[1];
+ col[2]= shr.diff[2] + shr.spec[2];
+ }
+ }
+ else {
+ col[0]= shr.diff[0] + shr.spec[0];
+ col[1]= shr.diff[1] + shr.spec[1];
+ col[2]= shr.diff[2] + shr.spec[2];
}
+
}
else { /* sky */
char skycol[4];
@@ -1402,13 +1544,10 @@ static void traceray(float f, short depth, float *start, float *vec, float *col,
Normalise(R.view);
RE_sky(skycol);
-
- f1= 1.0-f;
- f/= 255.0;
- col[0]= f*fr*skycol[0]+ f1*col[0];
- col[1]= f*fg*skycol[1]+ f1*col[1];
- col[2]= f*fb*skycol[2]+ f1*col[2];
+ col[0]= skycol[0]/255.0;
+ col[1]= skycol[1]/255.0;
+ col[2]= skycol[2]/255.0;
}
}
@@ -1497,94 +1636,174 @@ static void *jitter_cube(int resol)
}
-/* ***************** extern calls ************** */
+/* ***************** main calls ************** */
/* extern call from render loop */
-void ray_mirror(int mask)
+void ray_trace(int mask, ShadeResult *shr)
{
- float i, vec[3];
+ VlakRen *vlr;
+ float i, f, f1, fr, fg, fb, vec[3], mircol[3], tracol[3];
+ int do_tra, do_mir;
+
+ do_tra= ((R.mat->mode & MA_RAYTRANSP) && shr->alpha!=1.0);
+ do_mir= ((R.mat->mode & MA_RAYMIRROR) && R.mat->ray_mirror!=0.0);
+ vlr= R.vlr;
if(R.r.mode & R_OSA) {
- VlakRen *vlr;
- float accum[3], rco[3], rvno[3], col[3], ref[3], dxref[3], dyref[3];
- float div= 0.0;
+ float accum[3], rco[3], ref[3], dxref[3], dyref[3];
+ float accur[3], refract[3], divr=0.0, div= 0.0;
int j;
+ if(do_tra) calc_dx_dy_refract(refract, R.vn, R.view, R.mat->ang);
+
accum[0]= accum[1]= accum[2]= 0.0;
+ accur[0]= accur[1]= accur[2]= 0.0;
/* store variables which change during tracing */
VECCOPY(rco, R.co);
- VECCOPY(rvno, R.vno);
VECCOPY(ref, R.ref);
VECCOPY(dxref, O.dxref);
VECCOPY(dyref, O.dyref);
- vlr= R.vlr;
-
+
for(j=0; j<R.osa; j++) {
if(mask & 1<<j) {
- vec[0]= ref[0] + (jit[j][0]-0.5)*dxref[0] + (jit[j][1]-0.5)*dyref[0] ;
- vec[1]= ref[1] + (jit[j][0]-0.5)*dxref[1] + (jit[j][1]-0.5)*dyref[1] ;
- vec[2]= ref[2] + (jit[j][0]-0.5)*dxref[2] + (jit[j][1]-0.5)*dyref[2] ;
- /* prevent normal go to backside */
- i= vec[0]*rvno[0]+ vec[1]*rvno[1]+ vec[2]*rvno[2];
- if(i>0.0) {
- i+= .01;
- vec[0]-= i*rvno[0];
- vec[1]-= i*rvno[1];
- vec[2]-= i*rvno[2];
+ if(do_tra) {
+ vec[0]= refract[0] + (jit[j][0]-0.5)*O.dxrefract[0] + (jit[j][1]-0.5)*O.dyrefract[0] ;
+ vec[1]= refract[1] + (jit[j][0]-0.5)*O.dxrefract[1] + (jit[j][1]-0.5)*O.dyrefract[1] ;
+ vec[2]= refract[2] + (jit[j][0]-0.5)*O.dxrefract[2] + (jit[j][1]-0.5)*O.dyrefract[2] ;
+
+ R.co[0]+= (jit[j][0]-0.5)*O.dxco[0] + (jit[j][1]-0.5)*O.dyco[0] ;
+ R.co[1]+= (jit[j][0]-0.5)*O.dxco[1] + (jit[j][1]-0.5)*O.dyco[1] ;
+ R.co[2]+= (jit[j][0]-0.5)*O.dxco[2] + (jit[j][1]-0.5)*O.dyco[2] ;
+
+ traceray(R.mat->ray_depth_tra, R.co, vec, tracol, mask);
+
+ VecAddf(accur, accur, tracol);
+ divr+= 1.0;
+
+ /* restore */
+ VECCOPY(R.co, rco);
+ R.vlr= vlr;
+ R.mat= vlr->mat;
+ R.matren= R.mat->ren;
}
-
- R.co[0]+= (jit[j][0]-0.5)*O.dxco[0] + (jit[j][1]-0.5)*O.dyco[0] ;
- R.co[1]+= (jit[j][0]-0.5)*O.dxco[1] + (jit[j][1]-0.5)*O.dyco[1] ;
- R.co[2]+= (jit[j][0]-0.5)*O.dxco[2] + (jit[j][1]-0.5)*O.dyco[2] ;
-
- /* we use a new mask here, only shadow uses it */
- /* result in accum, this is copied to R.refcol for shade_lamp_loop */
- traceray(1.0, R.mat->ray_depth, R.co, vec, col, 1<<j);
-
- VecAddf(accum, accum, col);
- div+= 1.0;
- /* restore */
- VECCOPY(R.co, rco);
- R.vlr= vlr;
- R.mat= vlr->mat;
- R.matren= R.mat->ren;
+ if(do_mir) {
+ vec[0]= ref[0] + 2.0*(jit[j][0]-0.5)*dxref[0] + 2.0*(jit[j][1]-0.5)*dyref[0] ;
+ vec[1]= ref[1] + 2.0*(jit[j][0]-0.5)*dxref[1] + 2.0*(jit[j][1]-0.5)*dyref[1] ;
+ vec[2]= ref[2] + 2.0*(jit[j][0]-0.5)*dxref[2] + 2.0*(jit[j][1]-0.5)*dyref[2] ;
+
+ /* prevent normal go to backside */
+ i= vec[0]*R.vlr->n[0]+ vec[1]*R.vlr->n[1]+ vec[2]*R.vlr->n[2];
+ if(i>0.0) {
+ i+= .01;
+ vec[0]-= i*R.vlr->n[0];
+ vec[1]-= i*R.vlr->n[1];
+ vec[2]-= i*R.vlr->n[2];
+ }
+
+ R.co[0]+= (jit[j][0]-0.5)*O.dxco[0] + (jit[j][1]-0.5)*O.dyco[0] ;
+ R.co[1]+= (jit[j][0]-0.5)*O.dxco[1] + (jit[j][1]-0.5)*O.dyco[1] ;
+ R.co[2]+= (jit[j][0]-0.5)*O.dxco[2] + (jit[j][1]-0.5)*O.dyco[2] ;
+
+ /* we use a new mask here, only shadow uses it */
+ /* result in accum, this is copied to shade_lamp_loop */
+ traceray(R.mat->ray_depth, R.co, vec, mircol, 1<<j);
+
+ VecAddf(accum, accum, mircol);
+ div+= 1.0;
+
+ /* restore */
+ VECCOPY(R.co, rco);
+ R.vlr= vlr;
+ R.mat= vlr->mat;
+ R.matren= R.mat->ren;
+ }
}
}
- R.refcol[0]= R.mat->ray_mirror;
- R.refcol[1]= R.mat->ray_mirror*accum[0]/div;
- R.refcol[2]= R.mat->ray_mirror*accum[1]/div;
- R.refcol[3]= R.mat->ray_mirror*accum[2]/div;
+
+ if(divr!=0.0) {
+ f= shr->alpha; f1= 1.0-f; f1/= divr;
+ shr->diff[0]= f*shr->diff[0] + f1*accur[0];
+ shr->diff[1]= f*shr->diff[1] + f1*accur[1];
+ shr->diff[2]= f*shr->diff[2] + f1*accur[2];
+ shr->alpha= 1.0;
+ }
+
+ if(div!=0.0) {
+ i= R.mat->ray_mirror;
+ fr= R.mat->mirr;
+ fg= R.mat->mirg;
+ fb= R.mat->mirb;
+
+ /* result */
+ f= i*fr*(1.0-shr->spec[0]); f1= 1.0-i; f/= div;
+ shr->diff[0]= f*accum[0] + f1*shr->diff[0];
+
+ f= i*fg*(1.0-shr->spec[1]); f1= 1.0-i; f/= div;
+ shr->diff[1]= f*accum[1] + f1*shr->diff[1];
+
+ f= i*fb*(1.0-shr->spec[2]); f1= 1.0-i; f/= div;
+ shr->diff[2]= f*accum[2] + f1*shr->diff[2];
+ }
}
else {
- i= -2.0*(R.vn[0]*R.view[0]+R.vn[1]*R.view[1]+R.vn[2]*R.view[2]);
- vec[0]= (R.view[0]+i*R.vn[0]);
- vec[1]= (R.view[1]+i*R.vn[1]);
- vec[2]= (R.view[2]+i*R.vn[2]);
-
- /* test phong normals, then we should prevent vector going to the back */
- if(R.vlr->flag & R_SMOOTH) {
- i= vec[0]*R.vno[0]+ vec[1]*R.vno[1]+ vec[2]*R.vno[2];
- if(i>0.0) {
- i+= .01;
- vec[0]-= i*R.vno[0];
- vec[1]-= i*R.vno[1];
- vec[2]-= i*R.vno[2];
- }
+ if(do_tra) {
+ float rvn[3], view[3], rco[3], ref[3], refract[3];
+
+ /* store variables which change during tracing */
+ VECCOPY(view, R.view);
+ VECCOPY(rco, R.co);
+ VECCOPY(rvn, R.vn);
+ VECCOPY(ref, R.ref);
+
+ refraction(refract, R.vn, R.view, R.mat->ang);
+ traceray(R.mat->ray_depth_tra, R.co, refract, tracol, mask);
+
+ f= shr->alpha; f1= 1.0-f;
+ shr->diff[0]= f*shr->diff[0] + f1*tracol[0];
+ shr->diff[1]= f*shr->diff[1] + f1*tracol[1];
+ shr->diff[2]= f*shr->diff[2] + f1*tracol[2];
+ shr->alpha= 1.0;
+
+ /* store variables which change during tracing */
+ VECCOPY(R.view, view);
+ VECCOPY(R.co, rco);
+ VECCOPY(R.ref, ref);
+ VECCOPY(R.vn, rvn);
+ R.vlr= vlr;
+ R.mat= vlr->mat;
+ R.matren= R.mat->ren;
}
- /* result in r.refcol, this is added in shade_lamp_loop */
- i= R.mat->ray_mirror;
- traceray(1.0, R.mat->ray_depth, R.co, vec, R.refcol+1, mask);
- R.refcol[0]= i;
- R.refcol[1]*= i;
- R.refcol[2]*= i;
- R.refcol[3]*= i;
+ if(do_mir) {
+ i= R.mat->ray_mirror*fresnel_fac(R.view, R.vn, R.mat->fresnel_mir, R.mat->falloff_mir);
+ if(i!=0.0) {
+ fr= R.mat->mirr;
+ fg= R.mat->mirg;
+ fb= R.mat->mirb;
+
+ if(R.vlr->flag & R_SMOOTH)
+ reflection(vec, R.vn, R.view, R.vlr->n);
+ else
+ reflection(vec, R.vn, R.view, NULL);
+
+ traceray(R.mat->ray_depth, R.co, vec, mircol, mask);
+
+ f= i*fr*(1.0-shr->spec[0]); f1= 1.0-i;
+ shr->diff[0]= f*mircol[0] + f1*shr->diff[0];
+
+ f= i*fg*(1.0-shr->spec[1]); f1= 1.0-i;
+ shr->diff[1]= f*mircol[1] + f1*shr->diff[1];
+
+ f= i*fb*(1.0-shr->spec[2]); f1= 1.0-i;
+ shr->diff[2]= f*mircol[2] + f1*shr->diff[2];
+ }
+ }
}
}
diff --git a/source/blender/render/intern/source/renderHelp.c b/source/blender/render/intern/source/renderHelp.c
index 6566e982f1d..d1ee202748d 100644
--- a/source/blender/render/intern/source/renderHelp.c
+++ b/source/blender/render/intern/source/renderHelp.c
@@ -265,8 +265,8 @@ void set_normalflags(void)
for(a1=0; a1<R.totvlak; a1++) {
if((a1 & 255)==0) vlr= R.blovl[a1>>8];
else vlr++;
-
- if(vlr->flag & R_NOPUNOFLIP) {
+
+ if((vlr->flag & R_NOPUNOFLIP)) {
/* we flip render normal here, is not that neat, but otherwise render() needs rewrite... */
vlr->n[0]= -vlr->n[0];
vlr->n[1]= -vlr->n[1];
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index c86a8299538..d1bc18fb544 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -1552,12 +1552,22 @@ void RE_calc_R_ref()
}
+float fresnel_fac(float *view, float *vn, float fresnel, float falloff)
+{
+ float fac= fabs(view[0]*vn[0] + view[1]*vn[1] + view[2]*vn[2]);
+
+ if(falloff>0.0) fac= pow(fac, falloff); else fac= 1.0;
+ if(fac>1.0) fac= 1.0;
+
+ return (1.0 - fresnel*fac);
+}
+
/* mask is used to define the amount of rays/samples */
-void shade_lamp_loop(int mask)
+void shade_lamp_loop(int mask, ShadeResult *shr)
{
LampRen *lar;
Material *ma;
- float i, inp, inpr, t, lv[3], lampdist, ld = 0, ir, ig, ib, isr=0,isg=0,isb=0;
+ float i, inp, inpr, t, lv[3], lampdist, ld = 0;
float lvrot[3], *vn, *view, shadfac, soft;
int a;
@@ -1565,8 +1575,12 @@ void shade_lamp_loop(int mask)
view= R.view;
ma= R.matren;
+ memset(shr, 0, sizeof(ShadeResult));
+
/* separate loop */
if(ma->mode & MA_ONLYSHADOW) {
+ float ir;
+
shadfac= ir= 0.0;
for(a=0; a<R.totlamp; a++) {
lar= R.la[a];
@@ -1603,9 +1617,7 @@ void shade_lamp_loop(int mask)
}
}
if(ir>0.0) shadfac/= ir;
- ma->alpha= (R.mat->alpha)*(1.0-shadfac);
-
- shortcol[0]=shortcol[1]=shortcol[2]= 0;
+ shr->alpha= (R.mat->alpha)*(1.0-shadfac);
return;
}
@@ -1615,6 +1627,8 @@ void shade_lamp_loop(int mask)
ma->g= R.vcol[1];
ma->b= R.vcol[2];
}
+
+ ma->alpha= R.mat->alpha; // copy to render material, for fresnel and spectra
if(ma->texco) {
if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
@@ -1626,38 +1640,18 @@ void shade_lamp_loop(int mask)
}
if(ma->mode & MA_SHLESS) {
- ir= ma->r;
- ig= ma->g;
- ib= ma->b;
-
- if(usegamtab) {
- a= 65535*ir;
- if(a<0) a=0; else if(a>65535) a= 65535;
- shortcol[0]= igamtab2[a];
- a= 65535*ig;
- if(a<0) a=0; else if(a>65535) a= 65535;
- shortcol[1]= igamtab2[a];
- a= 65535*ib;
- if(a<0) a=0; else if(a>65535) a= 65535;
- shortcol[2]= igamtab2[a];
- }
- else {
- a= 65535*ir;
- if(a<0) shortcol[0]= 0; else if(a>65535) shortcol[0]= 65535; else shortcol[0]= a;
- a= 65535*ig;
- if(a<0) shortcol[1]= 0; else if(a>65535) shortcol[1]= 65535; else shortcol[1]= a;
- a= 65535*ib;
- if(a<0) shortcol[2]= 0; else if(a>65535) shortcol[2]= 65535; else shortcol[2]= a;
- }
+ shr->diff[0]= ma->r;
+ shr->diff[1]= ma->g;
+ shr->diff[2]= ma->b;
return;
}
if( (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) {
- ir= ma->emit+R.vcol[0];
- ig= ma->emit+R.vcol[1];
- ib= ma->emit+R.vcol[2];
+ shr->diff[0]= ma->emit+R.vcol[0];
+ shr->diff[1]= ma->emit+R.vcol[1];
+ shr->diff[2]= ma->emit+R.vcol[2];
}
- else ir= ig= ib= ma->emit;
+ else shr->diff[0]= shr->diff[1]= shr->diff[2]= ma->emit;
for(a=0; a<R.totlamp; a++) {
lar= R.la[a];
@@ -1749,9 +1743,9 @@ void shade_lamp_loop(int mask)
shadfac = 1.0 - testshadowbuf(lar->shb, inp);
if(shadfac>0.0) {
shadfac*= inp*soft*lar->energy;
- ir -= shadfac;
- ig -= shadfac;
- ib -= shadfac;
+ shr->diff[0] -= shadfac;
+ shr->diff[1] -= shadfac;
+ shr->diff[2] -= shadfac;
continue;
}
@@ -1839,9 +1833,9 @@ void shade_lamp_loop(int mask)
}
t= ma->spec*spec(t, ma->har);
- isr+= t*(lar->r * ma->specr);
- isg+= t*(lar->g * ma->specg);
- isb+= t*(lar->b * ma->specb);
+ shr->spec[0]+= t*(lar->r * ma->specr);
+ shr->spec[1]+= t*(lar->g * ma->specg);
+ shr->spec[2]+= t*(lar->b * ma->specb);
}
else {
/* specular shaders */
@@ -1858,93 +1852,55 @@ void shade_lamp_loop(int mask)
t= shadfac*ma->spec*lampdist*specfac;
- isr+= t*(lar->r * ma->specr);
- isg+= t*(lar->g * ma->specg);
- isb+= t*(lar->b * ma->specb);
+ shr->spec[0]+= t*(lar->r * ma->specr);
+ shr->spec[1]+= t*(lar->g * ma->specg);
+ shr->spec[2]+= t*(lar->b * ma->specb);
}
}
}
/* in case 'no diffuse' we still do most calculus, spec can be in shadow */
if(i>0.0 && !(lar->mode & LA_NO_DIFF)) {
- ir+= i*lar->r;
- ig+= i*lar->g;
- ib+= i*lar->b;
+ shr->diff[0]+= i*lar->r;
+ shr->diff[1]+= i*lar->g;
+ shr->diff[2]+= i*lar->b;
}
}
-
- /* sum shading here, to make all variables local (because of raytrace) */
- if(ir<0.0) ir= 0.0; else ir*= ma->r;
- ir+= ma->ambr +ma->amb*R.rad[0];
-
- if(ig<0.0) ig= 0.0; else ig*= ma->g;
- ig+= ma->ambg +ma->amb*R.rad[1];
-
- if(ib<0.0) ib= 0.0; else ib*= ma->b;
- ib+= ma->ambb +ma->amb*R.rad[2];
-
- if(isr<0.0) isr= 0.0;
- if(isg<0.0) isg= 0.0;
- if(isb<0.0) isb= 0.0;
- if(ma->mode & MA_ZTRA) { /* ztra shade */
+ if(ma->mode & (MA_ZTRA|MA_RAYTRANSP)) {
+ if(ma->fresnel_tra!=0.0)
+ ma->alpha*= fresnel_fac(R.view, R.vn, ma->fresnel_tra, ma->falloff_tra);
+
if(ma->spectra!=0.0) {
- t = MAX3(isr, isb, isg);
+ t = MAX3(shr->spec[0], shr->spec[1], shr->spec[2]);
t *= ma->spectra;
if(t>1.0) t= 1.0;
- if(ma->mapto & MAP_ALPHA) ma->alpha= (1.0-t)*ma->alpha+t;
- else ma->alpha= (1.0-t)*R.mat->alpha+t;
+ ma->alpha= (1.0-t)*ma->alpha+t;
}
}
- /* Result of ray_mirror() is written in R.refcol.
- Ugly is that shade_lamp_loop is called from within ray_mirror as well */
- if(R.r.mode & R_RAYTRACE) {
- if(ma->ray_mirror!=0.0) {
- static int only_once= 1;
- if(only_once) {
- float mirr= ma->mirr, mirg= ma->mirg, mirb= ma->mirb;
- extern void ray_mirror(int);
-
- only_once= 0;
- ray_mirror(mask);
- only_once= 1;
-
- /* this is because the material mir color can be textured */
- ma->mirr= mirr; ma->mirb= mirb; ma->mirg= mirg;
- }
- }
- }
+ shr->alpha= ma->alpha;
+
+ if(shr->spec[0]<0.0) shr->spec[0]= 0.0;
+ if(shr->spec[1]<0.0) shr->spec[1]= 0.0;
+ if(shr->spec[2]<0.0) shr->spec[2]= 0.0;
+
+ if(shr->diff[0]<0.0) shr->diff[0]= 0.0; else shr->diff[0]*= ma->r;
+ shr->diff[0]+= ma->ambr +ma->amb*R.rad[0];
- if(R.refcol[0]==0.0) {
- a= 65535.0*( ir + isr);
- if(a>65535) a=65535; else if(a<0) a= 0;
- shortcol[0]= a;
- a= 65535.0*(ig + isg);
- if(a>65535) a=65535; else if(a<0) a= 0;
- shortcol[1]= a;
- a= 65535*(ib + isb);
- if(a>65535) a=65535; else if(a<0) a= 0;
- shortcol[2]= a;
- }
- else {
- a= 65535.0*( ma->mirr*R.refcol[1] + (1.0 - ma->mirr*R.refcol[0])*ir +isr);
- if(a>65535) a=65535; else if(a<0) a= 0;
- shortcol[0]= a;
- a= 65535.0*( ma->mirg*R.refcol[2] + (1.0 - ma->mirg*R.refcol[0])*ig +isg);
- if(a>65535) a=65535; else if(a<0) a= 0;
- shortcol[1]= a;
- a= 65535.0*( ma->mirb*R.refcol[3] + (1.0 - ma->mirb*R.refcol[0])*ib +isb);
- if(a>65535) a=65535; else if(a<0) a= 0;
- shortcol[2]= a;
- }
-
- if(usegamtab) {
- shortcol[0]= igamtab2[ shortcol[0] ];
- shortcol[1]= igamtab2[ shortcol[1] ];
- shortcol[2]= igamtab2[ shortcol[2] ];
+ if(shr->diff[1]<0.0) shr->diff[1]= 0.0; else shr->diff[1]*= ma->g;
+ shr->diff[1]+= ma->ambg +ma->amb*R.rad[1];
+
+ if(shr->diff[2]<0.0) shr->diff[2]= 0.0; else shr->diff[2]*= ma->b;
+ shr->diff[2]+= ma->ambb +ma->amb*R.rad[2];
+
+ if(R.refcol[0]!=0.0) {
+ shr->diff[0]= ma->mirr*R.refcol[1] + (1.0 - ma->mirr*R.refcol[0])*shr->diff[0];
+ shr->diff[1]= ma->mirg*R.refcol[2] + (1.0 - ma->mirg*R.refcol[0])*shr->diff[1];
+ shr->diff[2]= ma->mirb*R.refcol[3] + (1.0 - ma->mirb*R.refcol[0])*shr->diff[2];
}
+
}
@@ -1955,6 +1911,7 @@ void shadepixel(float x, float y, int vlaknr, int mask)
static VertRen *v1, *v2, *v3;
static float t00, t01, t10, t11, dvlak, n1[3], n2[3], n3[3];
static float s00, s01, s10, s11;
+ ShadeResult shr;
float *o1, *o2, *o3;
float u, v, l, dl, hox, hoy, detsh, fac, deler, alpha;
char *cp1, *cp2, *cp3;
@@ -2350,7 +2307,33 @@ void shadepixel(float x, float y, int vlaknr, int mask)
R.winco[1]= (y+(R.ystart))/(float)R.afmy;
}
- shade_lamp_loop(mask);
+ shade_lamp_loop(mask, &shr);
+
+ if(R.r.mode & R_RAYTRACE) {
+ if(R.matren->ray_mirror!=0.0 || (R.mat->mode & MA_RAYTRANSP && shr.alpha!=1.0)) {
+ extern void ray_trace(int, ShadeResult *);
+
+ ray_trace(mask, &shr);
+ }
+ }
+
+ fac= shr.diff[0] + shr.spec[0];
+ if(fac<=0.0) shortcol[0]= 0; else if(fac>=1.0) shortcol[0]= 65535;
+ else shortcol[0]= 65535.0*fac;
+
+ fac= shr.diff[1] + shr.spec[1];
+ if(fac<=0.0) shortcol[1]= 0; else if(fac>=1.0) shortcol[1]= 65535;
+ else shortcol[1]= 65535.0*fac;
+
+ fac= shr.diff[2] + shr.spec[2];
+ if(fac<=0.0) shortcol[2]= 0; else if(fac>=1.0) shortcol[2]= 65535;
+ else shortcol[2]= 65535.0*fac;
+
+ if(usegamtab) {
+ shortcol[0]= igamtab2[ shortcol[0] ];
+ shortcol[1]= igamtab2[ shortcol[1] ];
+ shortcol[2]= igamtab2[ shortcol[2] ];
+ }
/* MIST */
if( (R.wrld.mode & WO_MIST) && (R.matren->mode & MA_NOMIST)==0 ){
@@ -2358,8 +2341,8 @@ void shadepixel(float x, float y, int vlaknr, int mask)
}
else alpha= 1.0;
- if(R.matren->alpha!=1.0 || alpha!=1.0) {
- fac= alpha*(R.matren->alpha);
+ if(shr.alpha!=1.0 || alpha!=1.0) {
+ fac= alpha*(shr.alpha);
/* gamma */
if(R.osa && usegamtab) fac*= fac;