Index: source/blender/render/intern/source/spectrum.c =================================================================== --- source/blender/render/intern/source/spectrum.c (revision 0) +++ source/blender/render/intern/source/spectrum.c (revision 0) @@ -0,0 +1,173 @@ +/** + * + * ***** 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK *****/ + +#include "spectrum.h" +#include "spectrum_constants.h" + +float GetOzoneSample(float lambda) +{ + return GetSampleFromIrregularSpectralCurve(k_oAmplitudes, k_oWavelengths, 64, lambda); +} + +float GetWaterSample(float lambda) +{ + return GetSampleFromIrregularSpectralCurve(k_waAmplitudes, k_waWavelengths, 13, lambda); +} + +float GetGasSample(float lambda) +{ + return GetSampleFromIrregularSpectralCurve(k_gAmplitudes, k_gWavelengths, 4, lambda); +} + +float GetSolarSample(float lambda) +{ + return GetSampleFromRegularSpectralCurve(solAmplitudes, 380, 750, 38, lambda); +} + +float mix(float a, float b, float s) +{ + return((1.0 - s) * a + s * b); +} + +float GetSampleFromIrregularSpectralCurve(float *amplitudes, float *wavelengths, int divisions, float lambda) +{ + float x, result; + int i; + + if (divisions == 0) + return(0.0); + else if (divisions == 1) + return(amplitudes[0]); + + if (lambda < wavelengths[0]) + return(amplitudes[0]); + + i = 1; + while (i < divisions) + if (lambda < wavelengths[i]) + { + x = (lambda - wavelengths[i - 1]) / (wavelengths[i] - wavelengths[i - 1]); + + result = mix(amplitudes[i - 1], amplitudes[i], x); + + return(result); + } + else + i++; + + return(amplitudes[divisions - 1]); +} + +float GetSampleFromRegularSpectralCurve(float *amplitudes, int waveStart, int waveEnd, int divisions, float lambda) +{ + float waveDelta; + float result, x, dx; + int bin1, bin2; + + waveDelta = (waveEnd - waveStart) / (divisions - 1); + + if (lambda < waveStart || lambda > waveEnd) + return(0.0); + + x = (lambda - waveStart) / waveDelta; + + bin1 = (int) x; + dx = x - bin1; + if (dx > 1e-8) + bin2 = bin1 + 1; + else + bin2 = bin1; + if(bin1<0) + bin1 = 0; + if(bin2<0) + bin2 = 0; + if(bin1>=divisions) + bin1 = divisions - 1; + if(bin2>=divisions) + bin2 = divisions - 1; + + result = mix(amplitudes[bin1], amplitudes[bin2], dx); + + return(result); +} + +void GetSpectrumDataFromRegularSpectralCurve(float *amplitudes, int waveStart, int waveEnd, int divisions, + float spectrumData[SPECTRUM_MAX_COMPONENTS]) +{ + float lambda, x; + int i; + + for (i = 0; i < SPECTRUM_MAX_COMPONENTS; i++) + { + x = (i + 0.5) / SPECTRUM_MAX_COMPONENTS; + lambda = SPECTRUM_START + x * (SPECTRUM_END - SPECTRUM_START); + + spectrumData[i] = GetSampleFromRegularSpectralCurve(amplitudes, waveStart, waveEnd, divisions, lambda); + } +} + +float GetSampleFromChromaticitySpectrum(float x, float y, float lambda) +{ + float M1, M2; + M1 = (-1.3515 - 1.7703 * x + 5.9114 * y) / (0.0241 + 0.2562 * x - 0.7341 * y); + M2 = ( 0.03 -31.4424 * x + 30.0717 * y) / (0.0241 + 0.2562 * x - 0.7341 * y); + + return( GetSampleFromRegularSpectralCurve(tS0Amplitudes, 300, 830, 54, lambda) + + M1 * GetSampleFromRegularSpectralCurve(tS1Amplitudes, 300, 830, 54, lambda) + + M2 * GetSampleFromRegularSpectralCurve(tS2Amplitudes, 300, 830, 54, lambda)); +} + +void GetSpectrumDataFromChromaticitySpectrum(float x, float y, float spectrumData[SPECTRUM_MAX_COMPONENTS]) +{ + float lambda, cx; + int i; + + for (i = 0; i < SPECTRUM_MAX_COMPONENTS; i++) + { + cx = (i + 0.5) / SPECTRUM_MAX_COMPONENTS; + lambda = SPECTRUM_START + cx * (SPECTRUM_END - SPECTRUM_START); + + spectrumData[i] = GetSampleFromChromaticitySpectrum(x, y, lambda); + } +} + +void ConvertSpectrumDataToCIEXYZ(float spectrumData[SPECTRUM_MAX_COMPONENTS], float color[3]) +{ + int i; + color[0] = 0; + color[1] = 0; + color[2] = 0; + for (i = 0; i < SPECTRUM_MAX_COMPONENTS; i++) + { + float x = (i + 0.5) / SPECTRUM_MAX_COMPONENTS; + float lambda = mix(SPECTRUM_START, SPECTRUM_END, x); + + color[0] += GetSampleFromRegularSpectralCurve(tCIE_xbar, 360, 830, 95, lambda) * spectrumData[i]; + color[1] += GetSampleFromRegularSpectralCurve(tCIE_ybar, 360, 830, 95, lambda) * spectrumData[i]; + color[2] += GetSampleFromRegularSpectralCurve(tCIE_zbar, 360, 830, 95, lambda) * spectrumData[i]; + } +} + + Index: source/blender/render/intern/source/pipeline.c =================================================================== --- source/blender/render/intern/source/pipeline.c (revision 13152) +++ source/blender/render/intern/source/pipeline.c (working copy) @@ -994,6 +994,8 @@ /* init some variables */ re->ycor= 1.0f; + /* init sunsky*/ + re->sunSky = MEM_callocN(sizeof(SunSky), "SunSky"); return re; } @@ -1007,6 +1009,9 @@ RE_FreeRenderResult(re->result); RE_FreeRenderResult(re->pushedresult); + /* remove sunsky*/ + MEM_freeN(re->sunSky); + BLI_remlink(&RenderList, re); MEM_freeN(re); } @@ -1526,7 +1531,6 @@ if(!re->test_break()) add_halo_flare(re); - /* free all render verts etc */ RE_Database_Free(re); } Index: source/blender/render/intern/source/convertblender.c =================================================================== --- source/blender/render/intern/source/convertblender.c (revision 13152) +++ source/blender/render/intern/source/convertblender.c (working copy) @@ -110,6 +110,7 @@ #include "texture.h" #include "sss.h" #include "zbuf.h" +#include "sunsky.h" #ifndef DISABLE_YAFRAY /* disable yafray */ @@ -1496,7 +1497,7 @@ float loc[3],loc1[3],loc0[3],vel[3],mat[4][4],nmat[3][3],co[3],nor[3],time; float *orco=0,*surfnor=0,*uvco=0, strandlen=0.0f, curlen=0.0f; float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0); - float adapt_angle=0.0, adapt_pix=0.0, random; + float loc_tex[3], size_tex[3], adapt_angle=0.0, adapt_pix=0.0, random; float simplify[2]; int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 0; int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild; @@ -1608,6 +1609,8 @@ totpart=psys->totpart; + mesh_get_texspace(ob->data, loc_tex, NULL, size_tex); + if(psys->pathcache){ path_possible=1; keys_possible=1; @@ -1693,10 +1696,10 @@ /* get orco */ if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){ tpa=tpsys->particles+pa->num; - psys_particle_on_emitter(ob, psmd,tpart->from,tpa->num,pa->num_dmcache,tpa->fuv,tpa->foffset,co,nor,0,0,orco,0); + psys_particle_on_emitter(ob, psmd,tpart->from,tpa->num, -1,tpa->fuv,tpa->foffset,co,nor,0,0,orco,0); } else - psys_particle_on_emitter(ob, psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,0); + psys_particle_on_emitter(ob, psmd,part->from,pa->num,-1,pa->fuv,pa->foffset,co,nor,0,0,orco,0); if(uvco && ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){ layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE); @@ -1787,6 +1790,12 @@ } } + if(orco) { + orco[0] = (orco[0]-loc_tex[0])/size_tex[0]; + orco[1] = (orco[1]-loc_tex[1])/size_tex[1]; + orco[2] = (orco[2]-loc_tex[2])/size_tex[2]; + } + /* surface normal shading setup */ if(ma->mode_l & MA_STR_SURFDIFF) { Mat3MulVecfl(nmat, nor); @@ -3494,22 +3503,16 @@ /* this is the way used all over to check for shadow */ if(lar->shb || (lar->mode & LA_SHAD_RAY)) { - LampShadowSample *ls; LampShadowSubSample *lss; - int a, b; + int a, b, tot= re->r.threads*re->r.osa; lar->shadsamp= MEM_mallocN(re->r.threads*sizeof(LampShadowSample), "lamp shadow sample"); - ls= lar->shadsamp; - + lss= lar->shadsamp[0].s; /* shadfacs actually mean light, let's put them to 1 to prevent unitialized accidents */ - for(a=0; ar.threads; a++, ls++) { - lss= ls->s; - for(b=0; br.osa; b++, lss++) { + for(a=0; asamplenr= -1; /* used to detect whether we store or read */ - lss->shadfac[0]= 1.0f; - lss->shadfac[1]= 1.0f; - lss->shadfac[2]= 1.0f; - lss->shadfac[3]= 1.0f; + lss->shadfac[b]= 1.0f; } } } @@ -3606,6 +3609,48 @@ for(a=0; awrld.mtex[a] && re->wrld.mtex[a]->tex) re->wrld.skytype |= WO_SKYTEX; + if((re->wrld.skytype & WO_SKYSKY) ||(re->wrld.skytype & WO_SKYATM)) + { + if(re->wrld.sun_type == WO_SUNLOCATION) + { + ComputeSunSkyDirection(re->wrld.latitude,re->wrld.longitude, re->wrld.standard_meridation, + re->wrld.julian_day, re->wrld.time_of_day, &(re->sunSky->theta), &(re->sunSky->theta)); + }else if (re->wrld.sun_type == WO_SUNANGLE) + { + re->sunSky->theta = DegsToRads(re->wrld.sun_theta); + re->sunSky->phi = DegsToRads(re->wrld.sun_phi); + }else if (re->wrld.sun_type == WO_SUNOBJECT) + { + /* compute theta based on object's z-direction*/ + if(re->wrld.sun_ob != NULL) + { + float vec[3] = {0.0, 0.0, 1.0}; + Mat4MulVecfl(re->wrld.sun_ob->obmat, vec); + norm(vec, vec); + re->sunSky->theta = acos(vec[2]); + if (fabs(re->sunSky->theta) < 1e-5) + re->sunSky->phi = 0; + else + re->sunSky->phi = atan2(vec[1], vec[0]); + } + else + { + re->sunSky->theta = 0; + re->sunSky->phi = 0; + } + }else + { + re->sunSky->theta = 0; + re->sunSky->phi = 0; + } + InitSunSky(re->sunSky, re->wrld.turbidity); + if(re->wrld.skytype & WO_SKYATM) + { + InitAtmosphere(re->sunSky, re->wrld.atm_mief, re->wrld.atm_rayf, re->wrld.atm_inscatterf, + re->wrld.atm_extinctionf, re->wrld.atm_distancef); + } + } + /* AO samples should be OSA minimum */ if(re->osa) while(re->wrld.aosamp*re->wrld.aosamp < re->osa) @@ -4065,10 +4110,10 @@ return 1; } -static int allow_render_dupli_instance(Render *re, DupliObject *dob, Object *obd) +static int allow_render_dupli_instance(Render *re, Object *ob, Object *obd) { return (render_object_type(obd->type) && - (!(dob->type == OB_DUPLIGROUP)) && + (!(ob->transflag & OB_DUPLIGROUP)) && !(re->r.mode & R_RADIO)); } @@ -4077,7 +4122,7 @@ Base *base; Object *ob; Scene *sce; - float mat[4][4], obmat[4][4]; + float mat[4][4]; for(SETLOOPER(re->scene, base)) { ob= base->object; @@ -4110,7 +4155,6 @@ for(dob= lb->first; dob; dob= dob->next) { Object *obd= dob->ob; - Mat4CpyMat4(obmat, obd->obmat); Mat4CpyMat4(obd->obmat, dob->mat); /* group duplis need to set ob matrices correct, for deform. so no_draw is part handled */ @@ -4126,14 +4170,14 @@ if(!allow_render_object(obd, nolamps, onlyselected, actob)) continue; - if(allow_render_dupli_instance(re, dob, obd)) { + if(allow_render_dupli_instance(re, ob, obd)) { ParticleSystem *psys; int psysindex; float imat[4][4], mat[4][4]; /* compute difference between object matrix and * object matrix with dupli transform, in viewspace */ - Mat4Invert(imat, obmat); + Mat4Invert(imat, dob->omat); MTC_Mat4MulSerie(mat, re->viewmat, dob->mat, imat, re->viewinv, 0, 0, 0, 0); RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat); @@ -4144,8 +4188,6 @@ obd->flag |= OB_DONE; obd->transflag |= OB_RENDER_DUPLI; - - Mat4CpyMat4(obd->obmat, obmat); } else init_render_object(re, obd, ob, dob->index, only_verts); Index: source/blender/render/intern/source/pixelshading.c =================================================================== --- source/blender/render/intern/source/pixelshading.c (revision 13152) +++ source/blender/render/intern/source/pixelshading.c (working copy) @@ -56,6 +56,7 @@ #include "shadbuf.h" #include "pixelshading.h" + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ /* only to be used here in this file, it's for speed */ @@ -457,14 +458,73 @@ void shadeSkyView(float *colf, float *rco, float *view, float *dxyview) { float lo[3], zen[3], hor[3], blend, blendm; + float winColor[3]; int skyflag; + float scale; /* flag indicating if we render the top hemisphere */ skyflag = WO_ZENUP; /* Some view vector stuff. */ - if(R.wrld.skytype & WO_SKYREAL) { + if(R.wrld.skytype & WO_SKYSKY) { + float sunTheta, sunPhi; + float sunAngle; + float colorxyz[3]; + float sunColor[3]; + float dir[3], sunDir[3],d; + + sunAngle = sqrt(R.sunSky->sunSolidAngle / M_PI); + + sunDir[0] = R.sunSky->toSun[0]; + sunDir[1] = R.sunSky->toSun[1]; + sunDir[2] = R.sunSky->toSun[2]; + + ConvertSpectrumDataToCIEXYZ(R.sunSky->sunSpectralRaddata, colorxyz); + + scale = MAX3(colorxyz[0], colorxyz[1], colorxyz[2]); + colorxyz[0] /= scale; + colorxyz[1] /= scale; + colorxyz[2] /= scale; + xyz_to_rgb(colorxyz[0], colorxyz[1], colorxyz[2], &sunColor[0], &sunColor[1], &sunColor[2]); + + sunTheta = 90.0 - RadsToDegs(R.sunSky->theta); + sunPhi = 180.0 - RadsToDegs(R.sunSky->phi); + + d = 1.0f/sqrt(view[0]*view[0]+view[1]*view[1]+view[2]*view[2]); + dir[0] = d*view[0]; + dir[1] = d*view[1]; + dir[2] = d*view[2]; + MTC_Mat3MulVecfl(R.imat, dir); + if (dir[2] >= 0.0) + { + norm(dir,dir); + if (acos(dot(dir, sunDir)) < sunAngle) + { + winColor[0] = sunColor[0]; + winColor[1] = sunColor[1]; + winColor[2] = sunColor[2]; + } + else + { + GetSkyXYZRadiancef(R.sunSky, dir, colorxyz); + scale = MAX3(colorxyz[0], colorxyz[1], colorxyz[2]); + colorxyz[0] /= scale; + colorxyz[1] /= scale; + colorxyz[2] /= scale; + + xyz_to_rgb(colorxyz[0], colorxyz[1], colorxyz[2], &winColor[0], &winColor[1], &winColor[2]); + } + } + else{ + winColor[0] = 0.0; + winColor[1] = 0.0; + winColor[2] = 0.0; + } + ClipColour(winColor); + + } + else 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; @@ -504,6 +564,18 @@ colf[0] = (blendm*hor[0] + blend*zen[0]); colf[1] = (blendm*hor[1] + blend*zen[1]); colf[2] = (blendm*hor[2] + blend*zen[2]); + } else if(R.wrld.skytype & WO_SKYSKY){ + if(R.wrld.skytype & WO_SKYTEX){ + colf[0] = winColor[0] * (blendm*hor[0] + blend*zen[0]); + colf[1] = winColor[1] * (blendm*hor[1] + blend*zen[1]); + colf[2] = winColor[2] * (blendm*hor[2] + blend*zen[2]); + } + else{ + gamma_correct_rgb(&winColor[0], &winColor[1], &winColor[2]); + colf[0] = winColor[0]; + colf[1] = winColor[1]; + colf[2] = winColor[2]; + } } else { /* Done when a texture was grabbed. */ colf[0]= hor[0]; @@ -518,7 +590,7 @@ void shadeSkyPixel(float *collector, float fx, float fy) { float view[3], dxyview[2]; - + /*float pos[3]={fx,fy,0};*/ /* The rules for sky: 1. Draw an image, if a background image was provided. Stop @@ -532,13 +604,13 @@ fillBackgroundImage(collector, fx, fy); return; } - else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) { + else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX+WO_SKYSKY))==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. */ @@ -567,5 +639,21 @@ } } +/* aerial perspective */ +void shadeAtmPixel(float *collector, float fx, float fy, float distance) +{ + float view[3], dir[3]; + float d; + /* Do not apply aerial perspective on sky*/ + if(distance >= 9.9e10) /*return;*/ distance = 20000.0; + + calc_view_vector(view, fx, fy); + d = 1.0f/sqrt(view[0]*view[0]+view[1]*view[1]+view[2]*view[2]); + dir[0] = d*view[0]; + dir[1] = d*view[1]; + dir[2] = d*view[2]; + MTC_Mat3MulVecfl(R.imat, dir); + atmosphere_pixle_shader(R.sunSky, dir, distance, 1.0f, collector); +} /* eof */ Index: source/blender/render/intern/source/rendercore.c =================================================================== --- source/blender/render/intern/source/rendercore.c (revision 13152) +++ source/blender/render/intern/source/rendercore.c (working copy) @@ -513,6 +513,31 @@ } } +static void atm_tile(RenderPart *pa, RenderLayer *rl) +{ + RenderPass *zpass; + + int x, y; + float *zrect; + float *rgbrect; + + if(pa->rectz==NULL) return; + for(zpass= rl->passes.first; zpass; zpass= zpass->next) + if(zpass->passtype==SCE_PASS_Z) + break; + + if(zpass==NULL) return; + + zrect = zpass->rect; + rgbrect = rl->rectf; + + for(y=pa->disprect.ymin; ydisprect.ymax; y++) { + for(x=pa->disprect.xmin; xdisprect.xmax; x++, zrect++, rgbrect+=4) { + shadeAtmPixel(rgbrect, x, y, *zrect); + } + } +} + static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) { RenderResult *rr= pa->result; @@ -991,6 +1016,10 @@ if(rl->passflag & SCE_PASS_Z) convert_zbuf_to_distbuf(pa, rl); + if(rl->layflag & SCE_LAY_SKY) + if(R.wrld.skytype & WO_SKYATM) + atm_tile(pa, rl); + if(rl->passflag & SCE_PASS_VECTOR) reset_sky_speed(pa, rl); @@ -1167,6 +1196,10 @@ if(rl->passflag & SCE_PASS_Z) convert_zbuf_to_distbuf(pa, rl); + if(rl->layflag & SCE_LAY_SKY) + if(R.wrld.skytype & WO_SKYATM) + atm_tile(pa, rl); + if(rl->passflag & SCE_PASS_VECTOR) reset_sky_speed(pa, rl); Index: source/blender/render/intern/source/sunsky.c =================================================================== --- source/blender/render/intern/source/sunsky.c (revision 0) +++ source/blender/render/intern/source/sunsky.c (revision 0) @@ -0,0 +1,541 @@ +/** + * + * ***** 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK *****/ + + +#include "sunsky.h" +#include "math.h" + +/* Local Functions and Macros */ + +#define vec3opv(v1, v2, op, v3) \ + v1[0] = (v2[0] op v3[0]); \ + v1[1] = (v2[1] op v3[1]);\ + v1[2] = (v2[2] op v3[2]); + +#define vec3opf(v1, v2, op, f1)\ + v1[0] = (v2[0] op (f1));\ + v1[1] = (v2[1] op (f1));\ + v1[2] = (v2[2] op (f1)); + +#define fopvec3(v1, f1, op, v2)\ + v1[0] = ((f1) op v2[0]);\ + v1[1] = ((f1) op v2[1]);\ + v1[2] = ((f1) op v2[2]); + +float DegsToRads(float degrees) +{ + return degrees* M_PI / 180.0; +} + +float RadsToDegs(float rads) +{ + return(rads * (180.0 / M_PI)); +} + +float dot(float v1[3], float v2[3]) +{ + float sum = 0.0; + int i; + + for (i = 0; i < 3; i++) + sum += v1[i] * v2[i]; + + return(sum); +} + +void norm(float in_v[3], float out_v[3]) +{ + float len; + len = sqrt((in_v[0]*in_v[0])+(in_v[1]*in_v[1])+(in_v[2]*in_v[2])); + if(len==0){ + out_v[0] = 0.0; + out_v[1] = 0.0; + out_v[2] = 0.0; + } + else{ + out_v[0] = in_v[0]/len; + out_v[1] = in_v[1]/len; + out_v[2] = in_v[2]/len; + } +} + +void ClipColour(float c[3]) +{ + if (c[0] > 1.0) c[0] = 1.0; + if (c[0] < 0.0) c[0] = 0.0; + if (c[1] > 1.0) c[1] = 1.0; + if (c[1] < 0.0) c[1] = 0.0; + if (c[2] > 1.0) c[2] = 1.0; + if (c[2] < 0.0) c[2] = 0.0; +} + +/* All angles in radians, theta angles measured from normal */ +float AngleBetween(float thetav, float phiv, float theta, float phi) +{ + float cospsi = sin(thetav) * sin(theta) * cos(phi - phiv) + cos(thetav) * cos(theta); + + if (cospsi > 1.0) + return 0; + if (cospsi < -1.0) + return M_PI; + + return acos(cospsi); +} + +/* Global Functions */ +void ComputeSunSkyDirection(float lat, float longi, int sm, int jd, float tOfDay, float *theta, float * phi) +{ + float solarTime, + solarDeclination, + solarAltitude, + opp, adj, + solarAzimuth; + + solarTime = tOfDay + (0.170 * sin(4 * M_PI * (jd - 80) / 373) - 0.129 * sin(2 * M_PI * (jd - 8) / 355)) + + (sm - longi) / 15.0; + + solarDeclination = (0.4093 * sin(2 * M_PI * (jd - 81) / 368)); + + solarAltitude = asin(sin(DegsToRads(lat)) * sin(solarDeclination) - + cos(DegsToRads(lat)) * cos(solarDeclination) * cos(M_PI * solarTime / 12)); + + + opp = -cos(solarDeclination) * sin(M_PI * solarTime / 12); + adj = -(cos(DegsToRads(lat)) * sin(solarDeclination) + + sin(DegsToRads(lat)) * cos(solarDeclination) * cos(M_PI * solarTime / 12)); + solarAzimuth = atan2(opp, adj); + + *phi = -solarAzimuth; + *theta = M_PI / 2.0 - solarAltitude; +} + +void InitSunSky(struct SunSky *sunsky, float turb) +{ + + float theta2; + float theta3; + float T; + float T2; + float chi; + + sunsky->turbidity = turb; + + /* Junge's exponent */ + sunsky->V = 4.0; + + sunsky->toSun[0] = cos(sunsky->phi) * sin(sunsky->theta); + sunsky->toSun[1] = sin(sunsky->phi) * sin(sunsky->theta); + sunsky->toSun[2] = cos(sunsky->theta); + + ComputeAttenuatedSunlight(sunsky->theta, sunsky->turbidity, sunsky->sunSpectralRaddata); + sunsky->sunSolidAngle = 0.25 * M_PI * 1.39 * 1.39 / (150 * 150); // = 6.7443e-05 + + theta2 = sunsky->theta*sunsky->theta; + theta3 = theta2 * sunsky->theta; + T = turb; + T2 = turb*turb; + + chi = (4.0 / 9.0 - T / 120.0) * (M_PI - 2 * sunsky->theta); + sunsky->zenith_Y = (4.0453 * T - 4.9710) * tan(chi) - .2155 * T + 2.4192; + sunsky->zenith_Y *= 1000; // conversion from kcd/m^2 to cd/m^2 + + sunsky->zenith_x = + ( + 0.00165 * theta3 - 0.00374 * theta2 + 0.00208 * sunsky->theta + 0) * T2 + + ( -0.02902 * theta3 + 0.06377 * theta2 - 0.03202 * sunsky->theta + 0.00394) * T + + ( + 0.11693 * theta3 - 0.21196 * theta2 + 0.06052 * sunsky->theta + 0.25885); + + sunsky->zenith_y = + ( + 0.00275 * theta3 - 0.00610 * theta2 + 0.00316 * sunsky->theta + 0) * T2 + + ( -0.04214 * theta3 + 0.08970 * theta2 - 0.04153 * sunsky->theta + 0.00515) * T + + ( + 0.15346 * theta3 - 0.26756 * theta2 + 0.06669 * sunsky->theta + 0.26688); + + sunsky->perez_Y[1] = 0.17872 * T - 1.46303; + sunsky->perez_Y[2] = -0.35540 * T + 0.42749; + sunsky->perez_Y[3] = -0.02266 * T + 5.32505; + sunsky->perez_Y[4] = 0.12064 * T - 2.57705; + sunsky->perez_Y[5] = -0.06696 * T + 0.37027; + + sunsky->perez_x[1] = -0.01925 * T - 0.25922; + sunsky->perez_x[2] = -0.06651 * T + 0.00081; + sunsky->perez_x[3] = -0.00041 * T + 0.21247; + sunsky->perez_x[4] = -0.06409 * T - 0.89887; + sunsky->perez_x[5] = -0.00325 * T + 0.04517; + + sunsky->perez_y[1] = -0.01669 * T - 0.26078; + sunsky->perez_y[2] = -0.09495 * T + 0.00921; + sunsky->perez_y[3] = -0.00792 * T + 0.21023; + sunsky->perez_y[4] = -0.04405 * T - 1.65369; + sunsky->perez_y[5] = -0.01092 * T + 0.05291; + +} +void ComputeAttenuatedSunlight(float theta, int turbidity, float spectrumdata[SPECTRUM_MAX_COMPONENTS]) +{ + float data[91]; // (800 - 350) / 5 + 1 + float spectralsample; + + float beta; + float tauR, tauA, tauO, tauG, tauWA; + + float m; + + int i; + float lambda; + + const float alpha = 1.3; + const float lOzone = .35; + const float w = 2.0; + + beta = 0.04608365822050 * turbidity - 0.04586025928522; + m = 1.0 / (cos(theta) + 0.000940 * pow(1.6386 - theta, -1.253)); + + for (i = 0, lambda = 350; i < 91; i++, lambda += 5) + { + // Rayleigh Scattering + // Results agree with the graph (pg 115, MI) */ + tauR = exp( -m * 0.008735 * pow(lambda/1000, (float)(-4.08))); + + // Aerosal (water + dust) attenuation + // beta - amount of aerosols present + // alpha - ratio of small to large particle sizes. (0:4,usually 1.3) + // Results agree with the graph (pg 121, MI) + + tauA = exp(-m * beta * pow(lambda/1000, -alpha)); // lambda should be in um + + // Attenuation due to ozone absorption + // lOzone - amount of ozone in cm(NTP) + // Results agree with the graph (pg 128, MI) + + tauO = exp(-m * GetOzoneSample(lambda) * lOzone); + + // Attenuation due to mixed gases absorption + // Results agree with the graph (pg 131, MI) + spectralsample = GetGasSample(lambda); + tauG = exp(-1.41 * spectralsample * m / pow(1.0 + 118.93 * spectralsample * m, 0.45)); + + // Attenuation due to water vapor absorbtion + // w - precipitable water vapor in centimeters (standard = 2) + // Results agree with the graph (pg 132, MI) + + + spectralsample = GetWaterSample(lambda); + tauWA = exp(-0.2385 * spectralsample * w * m / pow(1.0 + 20.07 * spectralsample * w * m, 0.45)); + + data[i] = 106 * GetSolarSample(lambda) * tauR * tauA * tauO * tauG * tauWA; + } + + // Converts to Spectrum + GetSpectrumDataFromRegularSpectralCurve(data, 350, 800, 91, spectrumdata); +} + +void GetSkySpectralRadiancef(struct SunSky *sunsky, const float varg[3], float spectralData[SPECTRUM_MAX_COMPONENTS]) +{ + float theta, phi; + float v[3]; + int i; + + norm((float*)varg, v); + if (v[2] < 0) + { + for(i=0; itheta) + lam[5] * cos(sunsky->theta) * cos(sunsky->theta))); + + num = ((1 + lam[1] * exp(lam[2] / cos(theta))) * + (1 + lam[3] * exp(lam[4] * gamma) + lam[5] * cos(gamma) * cos(gamma))); + + return(lvz * num / den); +} + +void GetSkySpectralRadiance(struct SunSky *sunsky, float theta, float phi, float spectralData[SPECTRUM_MAX_COMPONENTS]) +{ + float gamma; + float x,y,Y; + float epsilon; + float color[3]; + + int i; + + gamma = AngleBetween(theta, phi, sunsky->theta, sunsky->phi); + epsilon = 1e-6; + // Compute xyY values + x = PerezFunction(sunsky, sunsky->perez_x, theta, gamma, sunsky->zenith_x); + y = PerezFunction(sunsky, sunsky->perez_y, theta, gamma, sunsky->zenith_y); + Y = PerezFunction(sunsky, sunsky->perez_Y, theta, gamma, sunsky->zenith_Y); + + GetSpectrumDataFromChromaticitySpectrum(x, y, spectralData); + + ConvertSpectrumDataToCIEXYZ(spectralData, color); + + for(i=0; itheta, sunsky->phi); + // Compute xyY values + x = PerezFunction(sunsky, sunsky->perez_x, theta, gamma, sunsky->zenith_x); + y = PerezFunction(sunsky, sunsky->perez_y, theta, gamma, sunsky->zenith_y); + Y = PerezFunction(sunsky, sunsky->perez_Y, theta, gamma, sunsky->zenith_Y); + + X = (x / y) * Y; + Z = ((1 - x - y) / y) * Y; + + color_out[0] = X; + color_out[1] = Y; + color_out[2] = Z; +} + + +void FastComputeAttenuatedSunlight(float theta, int turbidity, float fTau[3]) +{ + float fBeta ; + float fTauR, fTauA; + float m ; + float fAlpha; + + int i; + float fLambda[3]; + fLambda[0] = 0.65f; // red (in um.) + fLambda[1] = 0.57f; // green (in um.) + fLambda[2] = 0.475f; // blue (in um.) + + fAlpha = 1.3f; + fBeta = 0.04608365822050f * turbidity - 0.04586025928522f; + + m = 1.0/(cos(theta) + 0.15f*pow(93.885f-theta/M_PI*180.0f,-1.253f)); // Relative Optical Mass + + for(i = 0; i < 3; i++) + { + // Rayleigh Scattering + // Results agree with the graph (pg 115, MI) */ + // lambda in um. + fTauR = exp( -m * 0.008735f * pow(fLambda[i], (float)(-4.08f))); + + // Aerosal (water + dust) attenuation + // beta - amount of aerosols present + // alpha - ratio of small to large particle sizes. (0:4,usually 1.3) + // Results agree with the graph (pg 121, MI) + + fTauA = exp(-m * fBeta * pow(fLambda[i], -fAlpha)); // lambda should be in um + + + fTau[i] = fTauR * fTauA; + + } +} + +void InitAtmosphere(struct SunSky *sunSky, float mief, float rayf, float inscattf, float extincf, float disf) +{ + const float pi = 3.14159265358f; + const float n = 1.003f; // refractive index + const float N = 2.545e25; + const float pn = 0.035f; + const float T = 2.0f; + float fTemp, fTemp2, fTemp3, fBeta, fBetaDash; + float c = (6.544*T - 6.51)*1e-17; // from page 57 of my thesis. + float K[3] = {0.685f, 0.679f, 0.670f}; // from pg 64 of my thesis. + float vBetaMieTemp[3]; + + float fLambda[3],fLambda2[3], fLambda4[3]; + float vLambda2[3]; + float vLambda4[3]; + + int i; + + sunSky->atm_BetaMieMultiplier = mief; + sunSky->atm_BetaRayMultiplier = rayf; + sunSky->atm_InscatteringMultiplier = inscattf; + sunSky->atm_ExtinctionMultiplier = extincf; + sunSky->atm_DistanceMultiplier = disf; + + sunSky->atm_HGg=0.8; + + fLambda[0] = 1/650e-9f; // red // note 650e-9 m = 650nm. + fLambda[1] = 1/570e-9f; // green + fLambda[2] = 1/475e-9f; // blue + for (i=0; i < 3; i++) + { + fLambda2[i] = fLambda[i]*fLambda[i]; + fLambda4[i] = fLambda2[i]*fLambda2[i]; + } + + vLambda2[0] = fLambda2[0]; + vLambda2[1] = fLambda2[1]; + vLambda2[2] = fLambda2[2]; + + vLambda4[0] = fLambda4[0]; + vLambda4[1] = fLambda4[1]; + vLambda4[2] = fLambda4[2]; + + // Rayleigh scattering constants. + fTemp = pi*pi*(n*n-1)*(n*n-1)*(6+3*pn)/(6-7*pn)/N; + fBeta = 8*fTemp*pi/3; + + vec3opf(sunSky->atm_BetaRay, vLambda4, *, fBeta); + fBetaDash = fTemp/2; + vec3opf(sunSky->atm_BetaDashRay, vLambda4,*, fBetaDash); + + + // Mie scattering constants. + + + fTemp2 = 0.434*c*(2*pi)*(2*pi)*0.5f; + vec3opf(sunSky->atm_BetaDashMie, vLambda2, *, fTemp2); + + + fTemp3 = 0.434f*c*pi*(2*pi)*(2*pi); + + vec3opv(vBetaMieTemp, K, *, fLambda); + vec3opf(sunSky->atm_BetaMie, vBetaMieTemp,*, fTemp3); + +} + +void atmosphere_pixle_shader( struct SunSky* sunSky, float view[3], float s, float sunColorIntensity, float rgb[3]) +{ + float costheta; + float Phase_1; + float Phase_2; + + float E[3]; + float E1[3]; + float fReflectance = 1.0f; + float vDiffuse[3]={0.138f,0.113f, 0.08f}; // Taken from soil's relectance spectrum data. + + float I[3]; + float fTemp; + float vTemp1[3], vTemp2[3]; + + float sunDirection[3]; + + s *= sunSky->atm_DistanceMultiplier; + + sunDirection[0] = sunSky->toSun[0]; + sunDirection[1] = sunSky->toSun[1]; + sunDirection[2] = sunSky->toSun[2]; + + costheta = dot(view, sunDirection); // cos(theta) + Phase_1 = 1 + (costheta * costheta); // Phase_1 + + vec3opf(sunSky->atm_BetaRay, sunSky->atm_BetaRay, *, sunSky->atm_BetaRayMultiplier); + vec3opf(sunSky->atm_BetaMie, sunSky->atm_BetaMie, *, sunSky->atm_BetaMieMultiplier); + vec3opv(sunSky->atm_BetaRM, sunSky->atm_BetaRay, +, sunSky->atm_BetaMie); + + //e^(-(beta_1 + beta_2) * s) = E1 + vec3opf(E1, sunSky->atm_BetaRM, *, -s/log(2)); + E1[0] = exp(E1[0]); + E1[1] = exp(E1[1]); + E1[2] = exp(E1[2]); + vec3opf(vDiffuse, vDiffuse, *, fReflectance); + vec3opv(E, E1, *, vDiffuse); + vec3opf(E, E1, +, 0.0); + + //Phase2(theta) = (1-g^2)/(1+g-2g*cos(theta))^(3/2) + fTemp = 1 + sunSky->atm_HGg - 2 * sunSky->atm_HGg * costheta; + fTemp = fTemp * sqrt(fTemp); + Phase_2 = (1 - sunSky->atm_HGg * sunSky->atm_HGg)/fTemp; + + vec3opf(vTemp1, sunSky->atm_BetaDashRay, *, Phase_1); + vec3opf(vTemp2, sunSky->atm_BetaDashMie, *, Phase_2); + + vec3opv(vTemp1, vTemp1, +, vTemp2); + fopvec3(vTemp2, 1.0, -, E1); + vec3opv(vTemp1, vTemp1, *, vTemp2); + + fopvec3(vTemp2, 1.0, / , sunSky->atm_BetaRM); + + vec3opv(I, vTemp1, *, vTemp2); + + vec3opf(I, I, *, sunSky->atm_InscatteringMultiplier); + vec3opf(E, E, *, sunSky->atm_ExtinctionMultiplier); + + //scale to color sun + /*FastComputeAttenuatedSunlight(sunSky, sunSky->thetaS, sunSky->turbidity, sunColor); + vec3opv(E, E, *, sunColor); + vec3opf(E, E, *, sunColorIntensity); + + vec3opv(I, I, *, sunColor); + vec3opf(I, I, *, sunColorIntensity);*/ + + vec3opv(rgb, rgb, *, E); + vec3opv(rgb, rgb, +, I); +} +#undef vec3opv +#undef vec3opf +#undef fopvec3 Index: source/blender/render/intern/include/sunsky.h =================================================================== --- source/blender/render/intern/include/sunsky.h (revision 0) +++ source/blender/render/intern/include/sunsky.h (revision 0) @@ -0,0 +1,89 @@ +/** + * + * ***** 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "spectrum.h" + +#ifndef SUNSKY_H_ +#define SUNSKY_H_ + + +typedef struct SunSky +{ + float turbidity; + float theta, phi; + + float toSun[3]; + + float sunSpectralRaddata[SPECTRUM_MAX_COMPONENTS]; + float sunSolidAngle; + + float zenith_Y, zenith_x, zenith_y; + + float perez_Y[6], perez_x[6], perez_y[6]; + + float beta_mdata[SPECTRUM_MAX_COMPONENTS]; + float beta_pdata[SPECTRUM_MAX_COMPONENTS]; + float beta_m_ang_prefixdata[SPECTRUM_MAX_COMPONENTS]; + float beta_p_ang_prefixdata[SPECTRUM_MAX_COMPONENTS]; + float V; + + float atm_HGg; + + float atm_InscatteringMultiplier; + float atm_ExtinctionMultiplier; + float atm_BetaRayMultiplier; + float atm_BetaMieMultiplier; + float atm_DistanceMultiplier; + + float atm_BetaRay[3]; + float atm_BetaDashRay[3]; + float atm_BetaMie[3]; + float atm_BetaDashMie[3]; + float atm_BetaRM[3]; +}SunSky; + +/* Sun and Sky functions, Use Spectral Power Distribution - correct approch */ +void InitSunSky(struct SunSky *sunsky, float turb); +void ComputeSunSkyDirection(float lat, float longi, int sm, int jd, float tOfDay, float *theta, float * phi); +void ComputeAttenuatedSunlight(float theta, int turbidity, float spectrumdata[SPECTRUM_MAX_COMPONENTS]); +float PerezFunction(struct SunSky *sunsky, const float *lam, float theta, float gamma, float lvz); +void GetSkySpectralRadiancef(struct SunSky *sunsky, const float varg[3], float spectralData[SPECTRUM_MAX_COMPONENTS]); +void GetSkySpectralRadiance(struct SunSky *sunsky, float theta, float phi, float spectralData[SPECTRUM_MAX_COMPONENTS]); +void GetSkyXYZRadiance(struct SunSky* sunsky, float theta, float phi, float color_out[3]); +void GetSkyXYZRadiancef(struct SunSky* sunsky, const float varg[3], float color_out[3]); + +/* Atmosphere functions, Use RGB - fast approch*/ +void InitAtmosphere(struct SunSky *sunSky, float mief, float rayf, float inscattf, float extincf, float disf); +void atmosphere_pixle_shader( struct SunSky* sunSky, float view[3], float s, float sunColorIntensity, float rgb[3]); +void FastComputeAttenuatedSunlight(float theta, int turbidity, float fTau[3]); + +/* */ +float dot(float v1[3], float v2[3]); +float DegsToRads(float degrees); +float RadsToDegs(float rads); +void norm(float in_v[3], float out_v[3]); +void ClipColour(float c[3]); +#endif /*SUNSKY_H_*/ Index: source/blender/render/intern/include/spectrum_constants.h =================================================================== --- source/blender/render/intern/include/spectrum_constants.h (revision 0) +++ source/blender/render/intern/include/spectrum_constants.h (revision 0) @@ -0,0 +1,237 @@ +/** + * + * ***** 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK *****/ + +#ifndef SPECTRUM_CONSTANTS_H_ +#define SPECTRUM_CONSTANTS_H_ + +// k_o Spectrum table from pg 127, MI. +static float k_oWavelengths[64] = +{ + 300, 305, 310, 315, 320, + 325, 330, 335, 340, 345, + 350, 355, + + 445, 450, 455, 460, 465, + 470, 475, 480, 485, 490, + 495, + + 500, 505, 510, 515, 520, + 525, 530, 535, 540, 545, + 550, 555, 560, 565, 570, + 575, 580, 585, 590, 595, + + 600, 605, 610, 620, 630, + 640, 650, 660, 670, 680, + 690, + + 700, 710, 720, 730, 740, + 750, 760, 770, 780, 790, +}; + +static float k_oAmplitudes[65] = { + 10.0, 4.8, 2.7, 1.35, .8, .380, .160, .075, .04, .019, .007, .0, + + .003, .003, .004, .006, .008, .009, .012, .014, .017, .021, .025, + + .03, .035, .04, .045, .048, .057, .063, .07, .075, .08, .085, .095, + .103, .110, .12, .122, .12, .118, .115, .12, .125, .130, .12, .105, + .09, .079, .067, .057, .048, .036, .028, + + .023, .018, .014, .011, .010, .009, .007, .004, .0, .0 +}; + + +// k_g Spectrum table from pg 130, MI. +static float k_gWavelengths[4] = { + 759, + 760, + 770, + 771 +}; + +static float k_gAmplitudes[4] = { + 0, + 3.0, + 0.210, + 0 +}; + +// k_wa Spectrum table from pg 130, MI. +static float k_waWavelengths[13] = { + 689, 690, 700, 710, + 720, 730, 740, 750, + 760, 770, 780, 790, 800}; + +static float k_waAmplitudes[13] = { + 0, + 0.160e-1, + 0.240e-1, + 0.125e-1, + 0.100e+1, + 0.870, + 0.610e-1, + 0.100e-2, + 0.100e-4, + 0.100e-4, + 0.600e-3, + 0.175e-1, + 0.360e-1 +}; + +// 380-750 by 10nm +static float solAmplitudes[38] = +{ + 165.5, 162.3, 211.2, 258.8, 258.2, + 242.3, 267.6, 296.6, 305.4, 300.6, + 306.6, 288.3, 287.1, 278.2, 271.0, + 272.3, 263.6, 255.0, 250.6, 253.1, + 253.5, 251.3, 246.3, 241.7, 236.8, + 232.1, 228.2, 223.4, 219.7, 215.3, + 211.0, 207.3, 202.4, 198.7, 194.3, + 190.7, 186.3, 182.6 +}; + +// 300-830 10nm +static float tS0Amplitudes[54] = +{ + 0.04,6.0,29.6,55.3,57.3, + 61.8,61.5,68.8,63.4,65.8, + 94.8,104.8,105.9,96.8,113.9, + 125.6,125.5,121.3,121.3,113.5, + 113.1,110.8,106.5,108.8,105.3, + 104.4,100.0,96.0,95.1,89.1, + 90.5,90.3,88.4,84.0,85.1, + 81.9,82.6,84.9,81.3,71.9, + 74.3,76.4,63.3,71.7,77.0, + 65.2,47.7,68.6,65.0,66.0, + 61.0,53.3,58.9,61.9 +}; + +static float tS1Amplitudes[54] = +{ + 0.02,4.5,22.4,42.0,40.6, + 41.6,38.0,42.4,38.5,35.0, + 43.4,46.3,43.9,37.1,36.7, + 35.9,32.6,27.9,24.3,20.1, + 16.2,13.2,8.6,6.1,4.2, + 1.9,0.0,-1.6,-3.5,-3.5, + -5.8,-7.2,-8.6,-9.5,-10.9, + -10.7,-12.0,-14.0,-13.6,-12.0, + -13.3,-12.9,-10.6,-11.6,-12.2, + -10.2,-7.8,-11.2,-10.4,-10.6, + -9.7,-8.3,-9.3,-9.8 +}; + +static float tS2Amplitudes[54] = +{ + 0.0,2.0,4.0,8.5,7.8, + 6.7,5.3,6.1,3.0,1.2, + -1.1,-0.5,-0.7,-1.2,-2.6, + -2.9,-2.8,-2.6,-2.6,-1.8, + -1.5,-1.3,-1.2,-1.0,-0.5, + -0.3,0.0,0.2,0.5,2.1, + 3.2,4.1,4.7,5.1,6.7, + 7.3,8.6,9.8,10.2,8.3, + 9.6,8.5,7.0,7.6,8.0, + 6.7,5.2,7.4,6.8,7.0, + 6.4,5.5,6.1,6.5 +}; + +static float tCIE_xbar[95] = +{ +/* 360-830nm in steps of 5nm */ +0.000129900000, 0.000232100000, 0.000414900000, 0.000741600000, 0.001368000000, +0.002236000000, 0.004243000000, 0.007650000000, 0.014310000000, 0.023190000000, +0.043510000000, 0.077630000000, 0.134380000000, 0.214770000000, 0.283900000000, +0.328500000000, 0.348280000000, 0.348060000000, 0.336200000000, 0.318700000000, +0.290800000000, 0.251100000000, 0.195360000000, 0.142100000000, 0.095640000000, +0.057950010000, 0.032010000000, 0.014700000000, 0.004900000000, 0.002400000000, +0.009300000000, 0.029100000000, 0.063270000000, 0.109600000000, 0.165500000000, +0.225749900000, 0.290400000000, 0.359700000000, 0.433449900000, 0.512050100000, +0.594500000000, 0.678400000000, 0.762100000000, 0.842500000000, 0.916300000000, +0.978600000000, 1.026300000000, 1.056700000000, 1.062200000000, 1.045600000000, +1.002600000000, 0.938400000000, 0.854449900000, 0.751400000000, 0.642400000000, +0.541900000000, 0.447900000000, 0.360800000000, 0.283500000000, 0.218700000000, +0.164900000000, 0.121200000000, 0.087400000000, 0.063600000000, 0.046770000000, +0.032900000000, 0.022700000000, 0.015840000000, 0.011359160000, 0.008110916000, +0.005790346000, 0.004106457000, 0.002899327000, 0.002049190000, 0.001439971000, +0.000999949300, 0.000690078600, 0.000476021300, 0.000332301100, 0.000234826100, +0.000166150500, 0.000117413000, 0.000083075270, 0.000058706520, 0.000041509940, +0.000029353260, 0.000020673830, 0.000014559770, 0.000010253980, 0.000007221456, +0.000005085868, 0.000003581652, 0.000002522525, 0.000001776509, 0.000001251141 +}; + +static float tCIE_ybar[95] = +{ +/* 360-830nm in steps of 5nm */ + +0.000003917000, 0.000006965000, 0.000012390000, 0.000022020000, 0.000039000000, +0.000064000000, 0.000120000000, 0.000217000000, 0.000396000000, 0.000640000000, +0.001210000000, 0.002180000000, 0.004000000000, 0.007300000000, 0.011600000000, +0.016840000000, 0.023000000000, 0.029800000000, 0.038000000000, 0.048000000000, +0.060000000000, 0.073900000000, 0.090980000000, 0.112600000000, 0.139020000000, +0.169300000000, 0.208020000000, 0.258600000000, 0.323000000000, 0.407300000000, +0.503000000000, 0.608200000000, 0.710000000000, 0.793200000000, 0.862000000000, +0.914850100000, 0.954000000000, 0.980300000000, 0.994950100000, 1.000000000000, +0.995000000000, 0.978600000000, 0.952000000000, 0.915400000000, 0.870000000000, +0.816300000000, 0.757000000000, 0.694900000000, 0.631000000000, 0.566800000000, +0.503000000000, 0.441200000000, 0.381000000000, 0.321000000000, 0.265000000000, +0.217000000000, 0.175000000000, 0.138200000000, 0.107000000000, 0.081600000000, +0.061000000000, 0.044580000000, 0.032000000000, 0.023200000000, 0.017000000000, +0.011920000000, 0.008210000000, 0.005723000000, 0.004102000000, 0.002929000000, +0.002091000000, 0.001484000000, 0.001047000000, 0.000740000000, 0.000520000000, +0.000361100000, 0.000249200000, 0.000171900000, 0.000120000000, 0.000084800000, +0.000060000000, 0.000042400000, 0.000030000000, 0.000021200000, 0.000014990000, +0.000010600000, 0.000007465700, 0.000005257800, 0.000003702900, 0.000002607800, +0.000001836600, 0.000001293400, 0.000000910930, 0.000000641530, 0.000000451810 +}; + +static float tCIE_zbar[95] = +{ +/* 360-830nm in steps of 5nm */ + +0.000606100000, 0.001086000000, 0.001946000000, 0.003486000000, 0.006450001000, +0.010549990000, 0.020050010000, 0.036210000000, 0.067850010000, 0.110200000000, +0.207400000000, 0.371300000000, 0.645600000000, 1.039050100000, 1.385600000000, +1.622960000000, 1.747060000000, 1.782600000000, 1.772110000000, 1.744100000000, +1.669200000000, 1.528100000000, 1.287640000000, 1.041900000000, 0.812950100000, +0.616200000000, 0.465180000000, 0.353300000000, 0.272000000000, 0.212300000000, +0.158200000000, 0.111700000000, 0.078249990000, 0.057250010000, 0.042160000000, +0.029840000000, 0.020300000000, 0.013400000000, 0.008749999000, 0.005749999000, +0.003900000000, 0.002749999000, 0.002100000000, 0.001800000000, 0.001650001000, +0.001400000000, 0.001100000000, 0.001000000000, 0.000800000000, 0.000600000000, +0.000340000000, 0.000240000000, 0.000190000000, 0.000100000000, 0.000049999990, +0.000030000000, 0.000020000000, 0.000010000000, 0.000000000000, 0.000000000000, +0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, +0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, +0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, +0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, +0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, +0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, +0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000 +}; + + +#endif /*SPECTRUM_CONSTANTS_H_*/ Index: source/blender/render/intern/include/spectrum.h =================================================================== --- source/blender/render/intern/include/spectrum.h (revision 0) +++ source/blender/render/intern/include/spectrum.h (revision 0) @@ -0,0 +1,47 @@ +/** + * + * ***** 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK *****/ + +#ifndef SPECTRUM_H_ +#define SPECTRUM_H_ + +#define SPECTRUM_MAX_COMPONENTS 100 +#define SPECTRUM_START 350.0 +#define SPECTRUM_END 800.0 + +float GetOzoneSample(float lambda); +float GetWaterSample(float lambda); +float GetGasSample(float lambda); +float GetSolarSample(float lambda); + +float GetSampleFromIrregularSpectralCurve(float *amplitudes, float *wavelengths, int divisions, float lambda); +float GetSampleFromRegularSpectralCurve(float *amplitudes, int waveStart, int waveEnd, int divisions, float lambda); +float GetSampleFromChromaticitySpectrum(float x, float y, float lambda); +void GetSpectrumDataFromRegularSpectralCurve(float *amplitudes, int waveStart, int waveEnd, int divisions, + float spectrumData[SPECTRUM_MAX_COMPONENTS]); +void GetSpectrumDataFromChromaticitySpectrum(float x, float y, float spectrumData[SPECTRUM_MAX_COMPONENTS]); +void ConvertSpectrumDataToCIEXYZ(float spectrumData[SPECTRUM_MAX_COMPONENTS], float color[3]); + +float mix(float a, float b, float s); +#endif /*SPECTRUM_H_*/ Index: source/blender/render/intern/include/render_types.h =================================================================== --- source/blender/render/intern/include/render_types.h (revision 13152) +++ source/blender/render/intern/include/render_types.h (working copy) @@ -43,6 +43,8 @@ #include "RE_pipeline.h" #include "RE_shader_ext.h" /* TexResult, ShadeResult, ShadeInput */ +#include "sunsky.h" + struct Object; struct MemArena; struct VertTableNode; @@ -144,6 +146,9 @@ float clipsta; float clipend; + /* world sky */ + struct SunSky *sunSky; + /* samples */ SampleTables *samples; float jit[32][2]; Index: source/blender/render/intern/include/pixelshading.h =================================================================== --- source/blender/render/intern/include/pixelshading.h (revision 13152) +++ source/blender/render/intern/include/pixelshading.h (working copy) @@ -56,6 +56,9 @@ void shadeSkyPixel(float *collector, float fx, float fy); void shadeSkyView(float *colf, float *rco, float *view, float *dxyview); +/* Render Aerial Perspective at pixel (fx, fy).*/ +void shadeAtmPixel(float *collector, float fx, float fy, float distance); + /* ------------------------------------------------------------------------- */ #endif Index: source/blender/blenkernel/BKE_blender.h =================================================================== --- source/blender/blenkernel/BKE_blender.h (revision 13152) +++ source/blender/blenkernel/BKE_blender.h (working copy) @@ -44,7 +44,7 @@ struct MemFile; #define BLENDER_VERSION 245 -#define BLENDER_SUBVERSION 12 +#define BLENDER_SUBVERSION 13 #define BLENDER_MINVERSION 240 #define BLENDER_MINSUBVERSION 0 Index: source/blender/blenkernel/intern/ipo.c =================================================================== --- source/blender/blenkernel/intern/ipo.c (revision 13152) +++ source/blender/blenkernel/intern/ipo.c (working copy) @@ -146,6 +146,7 @@ WO_HOR_R, WO_HOR_G, WO_HOR_B, WO_ZEN_R, WO_ZEN_G, WO_ZEN_B, WO_EXPOS, WO_MISI, WO_MISTDI, WO_MISTSTA, WO_MISTHI, WO_STAR_R, WO_STAR_G, WO_STAR_B, WO_STARDIST, WO_STARSIZE, + WO_SUNTHETA, WO_SUNPHI, WO_SKYTURB, MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z, MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z, @@ -1463,6 +1464,13 @@ poin= &(wo->starg); break; case WO_STAR_B: poin= &(wo->starb); break; + + case WO_SUNTHETA: + poin= &(wo->sun_theta); break; + case WO_SUNPHI: + poin= &(wo->sun_phi); break; + case WO_SKYTURB: + poin= &(wo->turbidity); break; case WO_STARDIST: poin= &(wo->stardist); break; @@ -1785,6 +1793,13 @@ case WO_STARSIZE: break; + case WO_SUNTHETA: + icu->ymax = 180.0; break; + case WO_SUNPHI: + icu->ymax = 359.0; break; + case WO_SKYTURB: + icu->ymax = 50.0; break; + default: icu->ymax= 1.0; break; Index: source/blender/blenkernel/intern/world.c =================================================================== --- source/blender/blenkernel/intern/world.c (revision 13152) +++ source/blender/blenkernel/intern/world.c (working copy) @@ -94,6 +94,22 @@ wrld->stardist= 15.0f; wrld->starsize= 2.0f; wrld->gravity= 9.8f; + + wrld->sun_type = WO_SUNLOCATION; + wrld->latitude = 0.0f; + wrld->longitude = 0.0f; + wrld->standard_meridation = 0; + wrld->julian_day=1; + wrld->time_of_day=7.5; + wrld->turbidity=2.0f; + wrld->sun_theta=0.0f; + wrld->sun_phi=0.0f; + wrld->atm_distancef=1.0f; + wrld->atm_mief=1.0f; + wrld->atm_rayf=1.0f; + wrld->atm_inscatterf=1.0f; + wrld->atm_extinctionf=1.0f; + wrld->sun_ob=NULL; wrld->exp= 0.0f; wrld->exposure=wrld->range= 1.0f; Index: source/blender/makesdna/DNA_ipo_types.h =================================================================== --- source/blender/makesdna/DNA_ipo_types.h (revision 13152) +++ source/blender/makesdna/DNA_ipo_types.h (working copy) @@ -235,8 +235,8 @@ /* ******************** */ -#define WO_TOTIPO 29 -#define WO_TOTNAM 16 +#define WO_TOTIPO 32 +#define WO_TOTNAM 19 #define WO_HOR_R 1 #define WO_HOR_G 2 @@ -258,6 +258,10 @@ #define WO_STARDIST 15 #define WO_STARSIZE 16 +#define WO_SUNTHETA 17 +#define WO_SUNPHI 18 +#define WO_SKYTURB 19 + /* ******************** */ #define LA_TOTIPO 21 Index: source/blender/makesdna/DNA_world_types.h =================================================================== --- source/blender/makesdna/DNA_world_types.h (revision 13152) +++ source/blender/makesdna/DNA_world_types.h (working copy) @@ -110,7 +110,26 @@ float *aosphere, *aotables; + /* Sky and Atmosphere */ + short pad3; + short sun_type; + int standard_meridation; + int julian_day; + float latitude; + float longitude; + float time_of_day; + float turbidity; + float sun_theta; + float sun_phi; + + float atm_distancef; + float atm_mief; + float atm_rayf; + float atm_inscatterf; + float atm_extinctionf; + struct Object *sun_ob; + struct Ipo *ipo; struct MTex *mtex[10]; @@ -127,6 +146,8 @@ #define WO_SKYBLEND 1 #define WO_SKYREAL 2 #define WO_SKYPAPER 4 +#define WO_SKYSKY 32 +#define WO_SKYATM 64 /* while render: */ #define WO_SKYTEX 8 #define WO_ZENUP 16 @@ -138,6 +159,11 @@ #define WO_ACTIVITY_CULLING 8 #define WO_AMB_OCC 16 +/* sun type */ +#define WO_SUNLOCATION 0 +#define WO_SUNANGLE 1 +#define WO_SUNOBJECT 2 + /* aomix */ #define WO_AOADD 0 #define WO_AOSUB 1 Index: source/blender/src/editipo_lib.c =================================================================== --- source/blender/src/editipo_lib.c (revision 13152) +++ source/blender/src/editipo_lib.c (working copy) @@ -91,7 +91,7 @@ "Key 61", "Key 62", "Key 63"}; char *wo_ic_names[WO_TOTNAM] = { "HorR", "HorG", "HorB", "ZenR", "ZenG", "ZenB", "Expos", "Misi", "MisDi", "MisSta", "MisHi", "StarR", "StarB", - "StarG", "StarDi", "StarSi" }; + "StarG", "StarDi", "StarSi", "SunTheta", "SunPhi", "SkyTurbidity" }; char *la_ic_names[LA_TOTNAM] = { "Energ", "R", "G", "B", "Dist", "SpoSi", "SpoBl", "Quad1", "Quad2", "HaInt" }; /* yafray: two curve names added, 'Apert' for aperture, and 'FDist' for focal distance */ @@ -234,7 +234,7 @@ { if(nr>=MA_MAP1) return getname_mtex_ei((nr & (MA_MAP1-1))); else { - if(nr>=WO_HOR_R && nr<=WO_STARSIZE) return wo_ic_names[nr-1]; + if(nr>=WO_HOR_R && nr<=WO_SKYTURB) return wo_ic_names[nr-1]; } return ic_name_empty[0]; } Index: source/blender/src/editipo.c =================================================================== --- source/blender/src/editipo.c (revision 13152) +++ source/blender/src/editipo.c (working copy) @@ -2883,7 +2883,7 @@ id= G.buts->lockpoin; wo= G.buts->lockpoin; if(id) { - event= pupmenu("Insert Key %t|Zenith RGB%x0|Horizon RGB%x1|Mist%x2|Stars %x3|Offset%x12|Size%x13"); + event= pupmenu("Insert Key %t|Zenith RGB%x0|Horizon RGB%x1|Mist%x2|Stars %x3|Offset%x12|Size%x13|Sun Position%x14|SKY Turbidity%x15"); if(event== -1) return; map= texchannel_to_adrcode(wo->texact); @@ -2921,6 +2921,13 @@ insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Y, 0); insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Z, 0); } + if(event==14){ + insertkey(id, ID_WO, NULL, NULL, WO_SUNTHETA, 0); + insertkey(id, ID_WO, NULL, NULL, WO_SUNPHI, 0); + } + if(event==15){ + insertkey(id, ID_WO, NULL, NULL, WO_SKYTURB, 0); + } } } else if(tab==TAB_SHADING_LAMP) { Index: source/blender/src/buttons_shading.c =================================================================== --- source/blender/src/buttons_shading.c (revision 13152) +++ source/blender/src/buttons_shading.c (working copy) @@ -1945,6 +1945,52 @@ } } +static void world_panel_atmosphere(World *wrld) +{ + // Add the panel as a tab to the preview panel + uiBlock *block; + int y; + block= uiNewBlock(&curarea->uiblocks, "world_panel_atm", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("World", "World"); + if(uiNewPanel(curarea, block, "Sky / Atmosphere", "World", PANELX, PANELY, PANELW, PANELH)==0) return; + uiSetButLock(wrld->id.lib!=0, ERROR_LIBDATA_MESSAGE); + + uiDefButS(block, ROW, B_WORLDPRV, "Location", 10,230,BUTW3,19, &(wrld->sun_type), 1.0, 0.0, 0, 0, "Use Location information to compute sun direction."); + uiDefButS(block, ROW, B_WORLDPRV, "Angle", 14+BUTW3,230,BUTW3,19, &(wrld->sun_type), 1.0, 1.0, 0, 0, "Use Angle information to compute sun direction."); + uiDefButS(block, ROW, B_WORLDPRV, "Object", 18+2*BUTW3,230,BUTW3,19, &(wrld->sun_type), 1.0, 2.0, 0, 0, "Use Object z-direction as sun direction."); + y = 205; + if(wrld->sun_type == WO_SUNLOCATION) + { + uiDefButF(block, NUM, B_WORLDPRV, "Latitude:",10,205,BUTW2,19, &(wrld->latitude), 0.000f, 360.0f, 10, 0, "Viewer location latitude."); + uiDefButF(block, NUM, B_WORLDPRV, "Longitude:",14+BUTW2,205,BUTW2,19, &(wrld->longitude), -90.0f, 90.0f, 10, 0, "Viewer location longitude."); + uiDefButF(block, NUM, B_WORLDPRV, "Time:",10,180,BUTW2,19, &(wrld->time_of_day), 0.000f, 23.99f, 5, 0, "Viewer time."); + uiDefButI(block, NUM, B_WORLDPRV, "Day:",14+BUTW2,180,BUTW2,19, &(wrld->julian_day), 1.000f, 365.0f, 1, 0, "Viewer julian day."); + uiDefButI(block, NUM, B_WORLDPRV, "St. Meridation:",10,155,BUTW2,19, &wrld->standard_meridation, 0.000f, 24.0f, 1, 0, "Viewer standard meridation(Time Zone)."); + uiDefButF(block, NUM, B_WORLDPRV, "Turbidity:",14+BUTW2,155,BUTW2,19, &(wrld->turbidity), 0.000f, 30.0f, 1, 0, "Sky Turbidity"); + y = 130; + }else if(wrld->sun_type == WO_SUNANGLE) + { + uiDefButF(block, NUM, B_WORLDPRV, "Theta:",10,205,BUTW2,19, &(wrld->sun_theta), 0.0f, 180.0f, 10, 0, "Sun's Theta."); + uiDefButF(block, NUM, B_WORLDPRV, "Phi:",14+BUTW2,205,BUTW2,19, &(wrld->sun_phi), 0.0f, 359.0f, 10, 0, "Sun's Phi."); + uiDefButF(block, NUM, B_WORLDPRV, "Turbidity:",10,180,BUTW2,19, &(wrld->turbidity), 0.000f, 50.0f, 1, 0, "Sky Turbidity"); + y = 155; + }else if(wrld->sun_type == WO_SUNOBJECT) + { + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_WORLDPRV, "OB:", 10, 205, BUTW2, 19, &(wrld->sun_ob), "Object to use as Sun."); + uiDefButF(block, NUM, B_WORLDPRV, "Turbidity:",14+BUTW2,205,BUTW2,19, &(wrld->turbidity), 0.000f, 30.0f, 1, 0, "Sky Turbidity"); + y = 180; + } + uiDefButBitS(block, TOG, WO_SKYATM, B_WORLDPRV, "Aerial Perspective",10,y,BUTW1,19, &(wrld->skytype), 0.000f, 0.00f, 0, 0, "Enable Aerial Perspective."); + if(wrld->skytype & WO_SKYATM) + { + uiDefButF(block, NUM, B_WORLDPRV, "Mie F.:",10,y-25,BUTW2,19, &(wrld->atm_mief), 0.00f, 1.00f, 10, 0, "Mie(particles in the air) Scattering Contribution Factor."); + uiDefButF(block, NUM, B_WORLDPRV, "Rayleigh F.:",14+BUTW2,y-25,BUTW2,19, &(wrld->atm_rayf), 0.00f, 1.00f, 10, 0, "Rayleigh(molecules of the air) Scattering Contribution Factor."); + uiDefButF(block, NUM, B_WORLDPRV, "Inscattering F.:",10,y-50,BUTW2,19, &(wrld->atm_inscatterf), 0.00f, 1.00f, 10, 0, "In Scattering Contribution Factor."); + uiDefButF(block, NUM, B_WORLDPRV, "Extinction F.:",14+BUTW2,y-50,BUTW2,19, &(wrld->atm_extinctionf), 0.00f, 1.00f, 10, 0, "Extinction Scattering Contribution Factor."); + uiDefButF(block, NUM, B_WORLDPRV, "Distance F.:",10,y-75,BUTW2,19, &(wrld->atm_distancef), 0.000f, 500.0f, 10, 0, "Scale blender distance to real distance."); + } +} + static void world_panel_mapto(World *wrld) { uiBlock *block; @@ -2282,6 +2328,7 @@ uiDefButBitS(block, TOG, WO_SKYREAL, B_WORLDPRV,"Real", 200,175,80,25, &wrld->skytype, 0, 0, 0, 0, "Renders background with a real horizon"); uiDefButBitS(block, TOG, WO_SKYBLEND, B_WORLDPRV,"Blend",200,150,80,25, &wrld->skytype, 0, 0, 0, 0, "Renders background with natural progression from horizon to zenith"); uiDefButBitS(block, TOG,WO_SKYPAPER, B_WORLDPRV,"Paper",200,125,80,25, &wrld->skytype, 0, 0, 0, 0, "Flattens blend or texture coordinates"); + uiDefButBitS(block, TOG, WO_SKYSKY, B_WORLDPRV, "Sky", 200,100,80,25, &wrld->skytype, 0, 0, 0, 0, "Use physically based sky model to calculate color (overwrites blend and texture color)"); uiBlockEndAlign(block); } @@ -4234,6 +4281,7 @@ world_panel_preview(wrld); world_panel_world(wrld); + world_panel_atmosphere(wrld); if(wrld) { world_panel_mistaph(wrld); Index: source/blender/blenlib/BLI_arithb.h =================================================================== --- source/blender/blenlib/BLI_arithb.h (revision 13152) +++ source/blender/blenlib/BLI_arithb.h (working copy) @@ -319,6 +319,9 @@ void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb); void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr); void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv); +void xyz_to_rgb(float x, float y, float z, float *r, float *g, float *b); +int constrain_rgb(float *r, float *g, float *b); +void gamma_correct_rgb(float *r, float *g, float *b); unsigned int hsv_to_cpack(float h, float s, float v); unsigned int rgb_to_cpack(float r, float g, float b); void cpack_to_rgb(unsigned int col, float *r, float *g, float *b); Index: source/blender/blenlib/intern/arithb.c =================================================================== --- source/blender/blenlib/intern/arithb.c (revision 13152) +++ source/blender/blenlib/intern/arithb.c (working copy) @@ -3354,7 +3354,100 @@ *lv = v; } +/*http://www.fourmilab.ch/documents/specrend/*/ +void xyz_to_rgb(float xc, float yc, float zc, float *r, float *g, float *b) +{ + float SMPTE_colorsystem[9] = {0.630/*xRed*/, 0.340/*yRed*/, 0.310/*xGreen*/, 0.595/*yGreen*/, + 0.155/*xBlue*/, 0.070/*yBlue*/,0.3127/*xWhite D65*/, 0.3291/*yWhite D65*/, + 0.0 /* Gama Rec. 709 */ }; + float xr, yr, zr, xg, yg, zg, xb, yb, zb; + float xw, yw, zw; + float rx, ry, rz, gx, gy, gz, bx, by, bz; + float rw, gw, bw; + xr = SMPTE_colorsystem[0]; yr = SMPTE_colorsystem[1]; zr = 1 - (xr + yr); + xg = SMPTE_colorsystem[2]; yg = SMPTE_colorsystem[3]; zg = 1 - (xg + yg); + xb = SMPTE_colorsystem[4]; yb = SMPTE_colorsystem[5]; zb = 1 - (xb + yb); + + xw = SMPTE_colorsystem[6]; yw = SMPTE_colorsystem[7]; zw = 1 - (xw + yw); + + /* xyz -> rgb matrix, before scaling to white. */ + + rx = (yg * zb) - (yb * zg); ry = (xb * zg) - (xg * zb); rz = (xg * yb) - (xb * yg); + gx = (yb * zr) - (yr * zb); gy = (xr * zb) - (xb * zr); gz = (xb * yr) - (xr * yb); + bx = (yr * zg) - (yg * zr); by = (xg * zr) - (xr * zg); bz = (xr * yg) - (xg * yr); + + /* White scaling factors. + Dividing by yw scales the white luminance to unity, as conventional. */ + + rw = ((rx * xw) + (ry * yw) + (rz * zw)) / yw; + gw = ((gx * xw) + (gy * yw) + (gz * zw)) / yw; + bw = ((bx * xw) + (by * yw) + (bz * zw)) / yw; + + /* xyz -> rgb matrix, correctly scaled to white. */ + + rx = rx / rw; ry = ry / rw; rz = rz / rw; + gx = gx / gw; gy = gy / gw; gz = gz / gw; + bx = bx / bw; by = by / bw; bz = bz / bw; + + /* rgb of the desired point */ + + *r = (rx * xc) + (ry * yc) + (rz * zc); + *g = (gx * xc) + (gy * yc) + (gz * zc); + *b = (bx * xc) + (by * yc) + (bz * zc); +} + +/*If the requested RGB shade contains a negative weight for + one of the primaries, it lies outside the colour gamut + accessible from the given triple of primaries. Desaturate + it by adding white, equal quantities of R, G, and B, enough + to make RGB all positive. The function returns 1 if the + components were modified, zero otherwise.*/ +int constrain_rgb(float *r, float *g, float *b) +{ + float w; + + /* Amount of white needed is w = - min(0, *r, *g, *b) */ + + w = (0 < *r) ? 0 : *r; + w = (w < *g) ? w : *g; + w = (w < *b) ? w : *b; + w = -w; + + /* Add just enough white to make r, g, b all positive. */ + + if (w > 0) { + *r += w; *g += w; *b += w; + return 1; /* Colour modified to fit RGB gamut */ + } + + return 0; /* Colour within RGB gamut */ +} + +/*Transform linear RGB values to nonlinear RGB values. Rec. + 709 is ITU-R Recommendation BT. 709 (1990) ``Basic + Parameter Values for the HDTV Standard for the Studio and + for International Programme Exchange'', formerly CCIR Rec. + 709.*/ +void gamma_correct(float *c) +{ + /* Rec. 709 gamma correction. */ + float cc = 0.018; + + if (*c < cc) { + *c *= ((1.099 * pow(cc, 0.45)) - 0.099) / cc; + } else { + *c = (1.099 * pow(*c, 0.45)) - 0.099; + } +} + +void gamma_correct_rgb(float *r, float *g, float *b) +{ + gamma_correct(r); + gamma_correct(g); + gamma_correct(b); +} + /* we define a 'cpack' here as a (3 byte color code) number that can be expressed like 0xFFAA66 or so. for that reason it is sensitive for endianness... with this function it works correctly */ Index: source/blender/blenloader/intern/readfile.c =================================================================== --- source/blender/blenloader/intern/readfile.c (revision 13152) +++ source/blender/blenloader/intern/readfile.c (working copy) @@ -2087,6 +2087,9 @@ wrld->id.flag -= LIB_NEEDLINK; } + if(wrld->sun_ob != NULL){ + wrld->sun_ob = newlibadr(fd, wrld->id.lib, wrld->sun_ob); + } wrld= wrld->id.next; } } @@ -7290,7 +7293,28 @@ } } } - + if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 13)) { + World *wrld; + + for(wrld=main->world.first; wrld; wrld= wrld->id.next) + { + wrld->sun_type = WO_SUNLOCATION; + wrld->latitude = 0.0f; + wrld->longitude = 0.0f; + wrld->standard_meridation = 0; + wrld->julian_day=1; + wrld->time_of_day=7.5; + wrld->turbidity=2.0f; + wrld->sun_theta=0.0f; + wrld->sun_phi=0.0f; + wrld->atm_distancef=1.0f; + wrld->atm_mief=1.0f; + wrld->atm_rayf=1.0f; + wrld->atm_inscatterf=1.0f; + wrld->atm_extinctionf=1.0f; + wrld->sun_ob=NULL; + } + } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */