diff options
author | Ton Roosendaal <ton@blender.org> | 2003-12-30 21:03:37 +0300 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2003-12-30 21:03:37 +0300 |
commit | d8b21b01c38bf2b7007458c221b2c1685d766cfd (patch) | |
tree | d4001fd3c914f10602ec095341307f64569a4941 /source/blender/render | |
parent | 6c80064ab7e0ea1e5ec9b5a164db08497a94ccf4 (diff) |
Added improved exposure calculation
- based at 1.0-exp(-color) trick in Yafray. But to guarantee backwards
compatibility, and some more control, Stefano Selleri hacked a useful
formula for it.
- We now have 2 values to set:
- "exp": the exponential correction value (0-1)
- "range": the light range that maps on color 1.0 (0-5)
- Using exp(x) (is e^x) we can much better prevent overflows from render,
which are currently hard-clipped in Blender. Setting a small 'exp' value
wil efficiently smooth out high energy and map that back to a color for
display.
- total formula:
newcol= linfac*(1.0-exp(col*logfac))
col, newcol are colors
linfac= 1.0 + 1.0/((2.0*wrld.exp +0.5)^10)
logfac= log( (linfac-1.0)/linfac )/wrld.range
wrld.exp and wrld.range are the button values
- default setting: exp=0.0 and range=1.0 give results extremely close to
previous rendering.
- graph: http://www.selleri.org/Blender/buffer/Image1.png for 'exp' setting
ranging from 0-1, and with 'range'=2
Thanks Stefano for the help!
Diffstat (limited to 'source/blender/render')
-rw-r--r-- | source/blender/render/intern/source/rendercore.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index ba86ca6319f..99648750781 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -1457,7 +1457,9 @@ float Toon_Diff( float *n, float *l, float *v, float size, float smooth ) } /* Oren Nayar diffuse */ -/* nl is either dot product, or return value of area light */ + +/* 'nl' is either dot product, or return value of area light */ +/* in latter case, only last multiplication uses 'nl' */ float OrenNayar_Diff_i(float nl, float *n, float *l, float *v, float rough ) { float i, nh, nv, vh, realnl, h[3]; @@ -1477,7 +1479,7 @@ float OrenNayar_Diff_i(float nl, float *n, float *l, float *v, float rough ) 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) nl= 0.0; /* value from area light */ + 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; @@ -1510,7 +1512,7 @@ float OrenNayar_Diff_i(float nl, float *n, float *l, float *v, float rough ) 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 here can be not a dot product here. */ + 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) ) ); @@ -2441,6 +2443,13 @@ temp_y= floor(y); VecAddf(col, shr.diff, shr.spec); + /* exposure correction */ + if(R.wrld.exposure!=0.0 || R.wrld.range!=1.0) { + col[0]= R.wrld.linfac*(1.0-exp( col[0]*R.wrld.logfac) ); + col[1]= R.wrld.linfac*(1.0-exp( col[1]*R.wrld.logfac) ); + col[2]= R.wrld.linfac*(1.0-exp( col[2]*R.wrld.logfac) ); + } + /* MIST */ if( (R.wrld.mode & WO_MIST) && (shi.matren->mode & MA_NOMIST)==0 ){ alpha= mistfactor(shi.co); |