diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-12-07 22:22:48 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-12-07 22:22:48 +0300 |
commit | 82ddfbf99fc0776a7fe439b81cf71bab87ceaaf9 (patch) | |
tree | fb1eda53eeeab12b093f5178693923b606708b05 /source/blender/render | |
parent | 4ca2581b77112c488938f0a2dc226042e0390b71 (diff) | |
parent | fc69c54c4ce810e6236eaa45017130f27ba3f1e2 (diff) |
Sculpt Branch:
svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r24889:25180
Diffstat (limited to 'source/blender/render')
-rw-r--r-- | source/blender/render/SConscript | 33 | ||||
-rw-r--r-- | source/blender/render/extern/include/RE_shader_ext.h | 2 | ||||
-rw-r--r-- | source/blender/render/intern/include/render_types.h | 3 | ||||
-rw-r--r-- | source/blender/render/intern/raytrace/reorganize.h | 5 | ||||
-rw-r--r-- | source/blender/render/intern/source/convertblender.c | 22 | ||||
-rw-r--r-- | source/blender/render/intern/source/occlusion.c | 246 | ||||
-rw-r--r-- | source/blender/render/intern/source/pipeline.c | 23 | ||||
-rw-r--r-- | source/blender/render/intern/source/pixelshading.c | 17 | ||||
-rw-r--r-- | source/blender/render/intern/source/shadeinput.c | 38 | ||||
-rw-r--r-- | source/blender/render/intern/source/shadeoutput.c | 1 | ||||
-rw-r--r-- | source/blender/render/intern/source/sss.c | 11 | ||||
-rw-r--r-- | source/blender/render/intern/source/strand.c | 6 | ||||
-rw-r--r-- | source/blender/render/intern/source/texture.c | 47 |
13 files changed, 283 insertions, 171 deletions
diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript index 63ef83a0cfe..2642d31bd35 100644 --- a/source/blender/render/SConscript +++ b/source/blender/render/SConscript @@ -1,18 +1,21 @@ #!/usr/bin/python Import ('env') -if env['OURPLATFORM'] in ('win32-vc', 'win64-vc', 'win32-mingw'): - # FIXME: need to set the appropriate flags for msvc, otherwise we get warnings - cflags = [] - cxxflags = [] +cflags = env['CCFLAGS'] +cxxflags = env['CXXFLAGS'] + +if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): + if env['WITH_BF_RAYOPTIMIZATION']: + cflags = env['CCFLAGS'] + ['/arch:SSE'] + +if env['OURPLATFORM'] == 'win32-mingw': + if env['WITH_BF_RAYOPTIMIZATION']: + cflags = env['CCFLAGS'] + ['-mfpmath=sse'] if env['OURPLATFORM'] == 'darwin': - if env['MACOSX_ARCHITECTURE'] in ('i386', 'x86_64'): - cflags = env['CFLAGS'] + ['-mfpmath=sse'] - cxxflags = env['CXXFLAGS'] + ['-mfpmath=sse'] - else: - cflags = env['CFLAGS'] - cxxflags = env['CXXFLAGS'] + if env['MACOSX_ARCHITECTURE'] in ('i386', 'x86_64') and env['WITH_BF_RAYOPTIMIZATION']: + cflags = env['CFLAGS'] + ['-mfpmath=sse'] + cxxflags = env['CXXFLAGS'] + ['-mfpmath=sse'] sources = env.Glob('intern/source/*.c') raysources = env.Glob('intern/raytrace/*.cpp') @@ -31,15 +34,19 @@ if env['WITH_BF_OPENEXR']: defs.append('WITH_OPENEXR') if env['OURPLATFORM'] == 'linux2': -# SSE is NOT safe all the time on linux, plus that ignores users compile flags and therefore no no +# SSE is NOT safe all the time on linux, plus that ignores users compile flags and therefore no no # cflags = ['-O2','-msse2','-mfpmath=sse', '-pthread'] # cxxflags = ['-O2','-msse2','-mfpmath=sse', '-pthread'] - cflags = env['CCFLAGS'] - cxxflags = env['CXXFLAGS'] + if env['WITH_BF_RAYOPTIMIZATION']: + cflags = env['CCFLAGS'] + ['-O2','-msse2','-mfpmath=sse', '-pthread'] + cxxflags = env['CXXFLAGS'] + ['-O2','-msse2','-mfpmath=sse', '-pthread'] incs += ' ../../../extern/binreloc/include' if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'): incs += ' ' + env['BF_PTHREADS_INC'] +if env['WITH_BF_RAYOPTIMIZATION']: + defs.append('__SSE__') + env.BlenderLib ( libname = 'bf_render', sources = sources, includes = Split(incs), defines=defs, libtype='core', priority=145, compileflags=cflags ) env.BlenderLib ( libname = 'bf_render_raytrace', sources = raysources, includes = Split(incs), defines=defs, libtype='core', priority=145, compileflags=cflags, cxx_compileflags=cxxflags ) diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index b36163f57c0..2615be1440a 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -153,7 +153,7 @@ typedef struct ShadeInput float dxstrand, dystrand; /* AO is a pre-process now */ - float ao[3]; + float ao[3], indirect[3]; int xs, ys; /* pixel to be rendered */ int mask; /* subsample mask */ diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 48bf34d0696..d41851db5ff 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -398,7 +398,8 @@ typedef struct StrandSurface { int (*face)[4]; float (*co)[3]; /* for occlusion caching */ - float (*col)[3]; + float (*ao)[3]; + float (*indirect)[3]; /* for speedvectors */ float (*prevco)[3], (*nextco)[3]; int totvert, totface; diff --git a/source/blender/render/intern/raytrace/reorganize.h b/source/blender/render/intern/raytrace/reorganize.h index bcf7f6f2078..2d4a4d15fe2 100644 --- a/source/blender/render/intern/raytrace/reorganize.h +++ b/source/blender/render/intern/raytrace/reorganize.h @@ -26,13 +26,16 @@ * * ***** END GPL LICENSE BLOCK ***** */ - #include <stdio.h> #include <algorithm> #include <math.h> #include <vector> #include <queue> +#ifdef _WIN32 +#define INFINITY FLT_MAX // in mingw math.h: (1.0F/0.0F). This generates compile error, though. +#endif + extern int tot_pushup; extern int tot_pushdown; diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index d09c6a48ef3..d0f7b2d60a5 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -4496,7 +4496,7 @@ void RE_Database_Free(Render *re) } } -static int allow_render_object(Object *ob, int nolamps, int onlyselected, Object *actob) +static int allow_render_object(Render *re, Object *ob, int nolamps, int onlyselected, Object *actob) { /* override not showing object when duplis are used with particles */ if(ob->transflag & OB_DUPLIPARTS) @@ -4504,6 +4504,10 @@ static int allow_render_object(Object *ob, int nolamps, int onlyselected, Object else if((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES)) return 0; + /* don't add non-basic meta objects, ends up having renderobjects with no geometry */ + if (ob->type == OB_MBALL && ob!=find_basis_mball(re->scene, ob)) + return 0; + if(nolamps && (ob->type==OB_LAMP)) return 0; @@ -4609,7 +4613,7 @@ static void add_group_render_dupli_obs(Render *re, Group *group, int nolamps, in if(ob->flag & OB_DONE) { if(ob->transflag & OB_RENDER_DUPLI) { - if(allow_render_object(ob, nolamps, onlyselected, actob)) { + if(allow_render_object(re, ob, nolamps, onlyselected, actob)) { init_render_object(re, ob, NULL, 0, timeoffset, vectorlay); ob->transflag &= ~OB_RENDER_DUPLI; @@ -4663,7 +4667,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp /* OB_RENDER_DUPLI means instances for it were already created, now * it still needs to create the ObjectRen containing the data */ if(ob->transflag & OB_RENDER_DUPLI) { - if(allow_render_object(ob, nolamps, onlyselected, actob)) { + if(allow_render_object(re, ob, nolamps, onlyselected, actob)) { init_render_object(re, ob, NULL, 0, timeoffset, vectorlay); ob->transflag &= ~OB_RENDER_DUPLI; } @@ -4697,7 +4701,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp if(obd->type==OB_MBALL) continue; - if(!allow_render_object(obd, nolamps, onlyselected, actob)) + if(!allow_render_object(re, obd, nolamps, onlyselected, actob)) continue; if(allow_render_dupli_instance(re, dob, obd)) { @@ -4767,10 +4771,10 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp } free_object_duplilist(lb); - if(allow_render_object(ob, nolamps, onlyselected, actob)) + if(allow_render_object(re, ob, nolamps, onlyselected, actob)) init_render_object(re, ob, NULL, 0, timeoffset, vectorlay); } - else if(allow_render_object(ob, nolamps, onlyselected, actob)) + else if(allow_render_object(re, ob, nolamps, onlyselected, actob)) init_render_object(re, ob, NULL, 0, timeoffset, vectorlay); } @@ -4848,8 +4852,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) /* still bad... doing all */ init_render_textures(re); - if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) color_manage_linearize(amb, &re->wrld.ambr); - else VECCOPY(amb, &re->wrld.ambr); + VECCOPY(amb, &re->wrld.ambr); init_render_materials(re->r.mode, amb); set_node_shader_lamp_loop(shade_material_loop); @@ -5538,8 +5541,7 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob) /* still bad... doing all */ init_render_textures(re); - if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) color_manage_linearize(amb, &re->wrld.ambr); - else VECCOPY(amb, &re->wrld.ambr); + VECCOPY(amb, &re->wrld.ambr); init_render_materials(re->r.mode, amb); set_node_shader_lamp_loop(shade_material_loop); diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c index f62668b84c0..3a5680eaf70 100644 --- a/source/blender/render/intern/source/occlusion.c +++ b/source/blender/render/intern/source/occlusion.c @@ -64,7 +64,7 @@ #define CACHE_STEP 3 typedef struct OcclusionCacheSample { - float co[3], n[3], col[3], intensity, dist2; + float co[3], n[3], ao[3], indirect[3], intensity, dist2; int x, y, filled; } OcclusionCacheSample; @@ -81,7 +81,7 @@ typedef struct OccFace { typedef struct OccNode { float co[3], area; float sh[9], dco; - float occlusion; + float occlusion, rad[3]; int childflag; union { //OccFace face; @@ -97,6 +97,7 @@ typedef struct OcclusionTree { OccFace *face; /* instance and face indices */ float *occlusion; /* occlusion for faces */ + float (*rad)[3]; /* radiance for faces */ OccNode *root; @@ -110,6 +111,7 @@ typedef struct OcclusionTree { int dothreadedbuild; int totbuildthread; + int doindirect; OcclusionCache *cache; } OcclusionTree; @@ -117,7 +119,8 @@ typedef struct OcclusionTree { typedef struct OcclusionThread { Render *re; StrandSurface *mesh; - float (*facecol)[3]; + float (*faceao)[3]; + float (*faceindirect)[3]; int begin, end; int thread; } OcclusionThread; @@ -132,7 +135,6 @@ typedef struct OcclusionBuildThread { extern Render R; // meh -#if 0 static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr, float *rad) { ShadeInput *shi= ssamp->shi; @@ -160,7 +162,7 @@ static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr, shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0]; shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1]; shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2]; - + shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2); /* set up view vector */ @@ -179,6 +181,8 @@ static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr, if(shi->flippednor) shade_input_flip_normals(shi); + madd_v3_v3fl(shi->co, shi->vn, 0.0001f); /* ugly.. */ + /* not a pretty solution, but fixes common cases */ if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) { negate_v3(shi->vn); @@ -215,12 +219,11 @@ static void occ_build_shade(Render *re, OcclusionTree *tree) for(a=0; a<tree->totface; a++) { obi= &R.objectinstance[tree->face[a].obi]; - vlr= RE_findOrAddVlak(obi->obr, tree->face[a].vlr); + vlr= RE_findOrAddVlak(obi->obr, tree->face[a].facenr); occ_shade(&ssamp, obi, vlr, tree->rad[a]); } } -#endif /* ------------------------- Spherical Harmonics --------------------------- */ @@ -352,17 +355,19 @@ static void occ_face(const OccFace *face, float *co, float *normal, float *area) static void occ_sum_occlusion(OcclusionTree *tree, OccNode *node) { OccNode *child; - float occ, area, totarea; + float occ, area, totarea, rad[3]; int a, b; occ= 0.0f; totarea= 0.0f; + zero_v3(rad); for(b=0; b<TOTCHILD; b++) { if(node->childflag & (1<<b)) { a= node->child[b].face; occ_face(&tree->face[a], 0, 0, &area); occ += area*tree->occlusion[a]; + madd_v3_v3fl(rad, tree->rad[a], area); totarea += area; } else if(node->child[b].node) { @@ -370,14 +375,18 @@ static void occ_sum_occlusion(OcclusionTree *tree, OccNode *node) occ_sum_occlusion(tree, child); occ += child->area*child->occlusion; + madd_v3_v3fl(rad, child->rad, child->area); totarea += child->area; } } - if(totarea != 0.0f) + if(totarea != 0.0f) { occ /= totarea; + mul_v3_fl(rad, 1.0f/totarea); + } node->occlusion= occ; + copy_v3_v3(node->rad, rad); } static int occ_find_bbox_axis(OcclusionTree *tree, int begin, int end, float *min, float *max) @@ -644,6 +653,7 @@ static OcclusionTree *occ_tree_build(Render *re) /* parameters */ tree->error= get_render_aosss_error(&re->r, re->wrld.ao_approx_error); tree->distfac= (re->wrld.aomode & WO_AODIST)? re->wrld.aodistfac: 0.0f; + tree->doindirect= (re->wrld.ao_indirect_energy > 0.0f && re->wrld.ao_indirect_bounces > 0); /* allocation */ tree->arena= BLI_memarena_new(0x8000 * sizeof(OccNode)); @@ -656,6 +666,9 @@ static OcclusionTree *occ_tree_build(Render *re) tree->co= MEM_callocN(sizeof(float)*3*totface, "OcclusionCo"); tree->occlusion= MEM_callocN(sizeof(float)*totface, "OcclusionOcclusion"); + if(tree->doindirect) + tree->rad= MEM_callocN(sizeof(float)*3*totface, "OcclusionRad"); + /* make array of face pointers */ for(b=0, c=0, obi=re->instancetable.first; obi; obi=obi->next, c++) { obr= obi->obr; @@ -682,12 +695,10 @@ static OcclusionTree *occ_tree_build(Render *re) tree->maxdepth= 1; occ_build_recursive(tree, tree->root, 0, totface, 1); -#if 0 if(tree->doindirect) { occ_build_shade(re, tree); occ_sum_occlusion(tree, tree->root); } -#endif MEM_freeN(tree->co); tree->co= NULL; @@ -710,8 +721,9 @@ static void occ_free_tree(OcclusionTree *tree) if(tree->stack[a]) MEM_freeN(tree->stack[a]); if(tree->occlusion) MEM_freeN(tree->occlusion); - if(tree->face) MEM_freeN(tree->face); if(tree->cache) MEM_freeN(tree->cache); + if(tree->face) MEM_freeN(tree->face); + if(tree->rad) MEM_freeN(tree->rad); MEM_freeN(tree); } } @@ -1171,13 +1183,13 @@ static float occ_form_factor(OccFace *face, float *p, float *n) return contrib; } -static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float *pp, float *pn, float *occ, float *bentn) +static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float *pp, float *pn, float *occ, float rad[3], float bentn[3]) { OccNode *node, **stack; OccFace *face; - float resultocc, v[3], p[3], n[3], co[3], invd2; + float resultocc, resultrad[3], v[3], p[3], n[3], co[3], invd2; float distfac, fac, error, d2, weight, emitarea; - int b, totstack; + int b, f, totstack; /* init variables */ VECCOPY(p, pp); @@ -1185,12 +1197,13 @@ static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float VECADDFAC(p, p, n, 1e-4f); if(bentn) - VECCOPY(bentn, n); + copy_v3_v3(bentn, n); error= tree->error; distfac= tree->distfac; resultocc= 0.0f; + zero_v3(resultrad); /* init stack */ stack= tree->stack[thread]; @@ -1217,6 +1230,10 @@ static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float /* accumulate occlusion from spherical harmonics */ invd2 = 1.0f/sqrtf(d2); weight= occ_solid_angle(node, v, d2, invd2, n); + + if(rad) + madd_v3_v3fl(resultrad, node->rad, weight*fac); + weight *= node->occlusion; if(bentn) { @@ -1231,7 +1248,8 @@ static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float /* traverse into children */ for(b=0; b<TOTCHILD; b++) { if(node->childflag & (1<<b)) { - face= tree->face+node->child[b].face; + f= node->child[b].face; + face= &tree->face[f]; /* accumulate occlusion with face form factor */ if(!exclude || !(face->obi == exclude->obi && face->facenr == exclude->facenr)) { @@ -1248,7 +1266,11 @@ static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float fac= 1.0f; weight= occ_form_factor(face, p, n); - weight *= tree->occlusion[node->child[b].face]; + + if(rad) + madd_v3_v3fl(resultrad, tree->rad[f], weight*fac); + + weight *= tree->occlusion[f]; if(bentn) { invd2= 1.0f/sqrtf(d2); @@ -1269,9 +1291,57 @@ static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float } if(occ) *occ= resultocc; + if(rad) copy_v3_v3(rad, resultrad); + /*if(rad && exclude) { + int a; + for(a=0; a<tree->totface; a++) + if((tree->face[a].obi == exclude->obi && tree->face[a].facenr == exclude->facenr)) + copy_v3_v3(rad, tree->rad[a]); + }*/ if(bentn) normalize_v3(bentn); } +static void occ_compute_bounces(Render *re, OcclusionTree *tree, int totbounce) +{ + float (*rad)[3], (*sum)[3], (*tmp)[3], co[3], n[3], occ; + int bounce, i; + + rad= MEM_callocN(sizeof(float)*3*tree->totface, "OcclusionBounceRad"); + sum= MEM_dupallocN(tree->rad); + + for(bounce=1; bounce<totbounce; bounce++) { + for(i=0; i<tree->totface; i++) { + occ_face(&tree->face[i], co, n, NULL); + madd_v3_v3fl(co, n, 1e-8f); + + occ_lookup(tree, 0, &tree->face[i], co, n, &occ, rad[i], NULL); + rad[i][0]= MAX2(rad[i][0], 0.0f); + rad[i][1]= MAX2(rad[i][1], 0.0f); + rad[i][2]= MAX2(rad[i][2], 0.0f); + add_v3_v3(sum[i], rad[i]); + + if(re->test_break(re->tbh)) + break; + } + + if(re->test_break(re->tbh)) + break; + + tmp= tree->rad; + tree->rad= rad; + rad= tmp; + + occ_sum_occlusion(tree, tree->root); + } + + MEM_freeN(rad); + MEM_freeN(tree->rad); + tree->rad= sum; + + if(!re->test_break(re->tbh)) + occ_sum_occlusion(tree, tree->root); +} + static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass) { float *occ, co[3], n[3]; @@ -1285,7 +1355,7 @@ static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass) negate_v3(n); VECADDFAC(co, co, n, 1e-8f); - occ_lookup(tree, 0, &tree->face[i], co, n, &occ[i], NULL); + occ_lookup(tree, 0, &tree->face[i], co, n, &occ[i], NULL, NULL); if(re->test_break(re->tbh)) break; } @@ -1305,9 +1375,9 @@ static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass) MEM_freeN(occ); } -static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, float *co, float *n, int thread, int onlyshadow, float *skycol) +static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, float *co, float *n, int thread, int onlyshadow, float *ao, float *indirect) { - float nn[3], bn[3], fac, occ, occlusion, correction; + float nn[3], bn[3], fac, occ, occlusion, correction, rad[3]; int aocolor; aocolor= re->wrld.aocolor; @@ -1317,7 +1387,7 @@ static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, f VECCOPY(nn, n); negate_v3(nn); - occ_lookup(tree, thread, exclude, co, nn, &occ, (aocolor)? bn: NULL); + occ_lookup(tree, thread, exclude, co, nn, &occ, (tree->doindirect)? rad: NULL, (aocolor)? bn: NULL); correction= re->wrld.ao_approx_correction; @@ -1330,9 +1400,9 @@ static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, f /* sky shading using bent normal */ if(ELEM(aocolor, WO_AOSKYCOL, WO_AOSKYTEX)) { fac= 0.5*(1.0f+bn[0]*re->grvec[0]+ bn[1]*re->grvec[1]+ bn[2]*re->grvec[2]); - skycol[0]= (1.0f-fac)*re->wrld.horr + fac*re->wrld.zenr; - skycol[1]= (1.0f-fac)*re->wrld.horg + fac*re->wrld.zeng; - skycol[2]= (1.0f-fac)*re->wrld.horb + fac*re->wrld.zenb; + ao[0]= (1.0f-fac)*re->wrld.horr + fac*re->wrld.zenr; + ao[1]= (1.0f-fac)*re->wrld.horg + fac*re->wrld.zeng; + ao[2]= (1.0f-fac)*re->wrld.horb + fac*re->wrld.zenb; } #if 0 else { /* WO_AOSKYTEX */ @@ -1343,17 +1413,20 @@ static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, f dxyview[0]= 1.0f; dxyview[1]= 1.0f; dxyview[2]= 0.0f; - shadeSkyView(skycol, co, bn, dxyview); + shadeSkyView(ao, co, bn, dxyview); } #endif - mul_v3_fl(skycol, occlusion); + mul_v3_fl(ao, occlusion); } else { - skycol[0]= occlusion; - skycol[1]= occlusion; - skycol[2]= occlusion; + ao[0]= occlusion; + ao[1]= occlusion; + ao[2]= occlusion; } + + if(tree->doindirect) copy_v3_v3(indirect, rad); + else zero_v3(indirect); } /* ---------------------------- Caching ------------------------------- */ @@ -1374,7 +1447,7 @@ static OcclusionCacheSample *find_occ_sample(OcclusionCache *cache, int x, int y return &cache->sample[y*cache->w + x]; } -static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int y, int thread, float *col) +static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int y, int thread, float *ao, float *indirect) { OcclusionCache *cache; OcclusionCacheSample *samples[4], *sample; @@ -1394,7 +1467,8 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int VECSUB(d, sample->co, co); dist2= INPR(d, d); if(dist2 < 0.5f*sample->dist2 && INPR(sample->n, n) > 0.98f) { - VECCOPY(col, sample->col); + VECCOPY(ao, sample->ao); + VECCOPY(indirect, sample->indirect); return 1; } } @@ -1420,7 +1494,8 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int return 0; /* compute weighted interpolation between samples */ - col[0]= col[1]= col[2]= 0.0f; + zero_v3(ao); + zero_v3(indirect); totw= 0.0f; x1= samples[0]->x; @@ -1446,16 +1521,14 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int w= wb[i]*wn[i]*wz[i]; totw += w; - col[0] += w*samples[i]->col[0]; - col[1] += w*samples[i]->col[1]; - col[2] += w*samples[i]->col[2]; + madd_v3_v3fl(ao, samples[i]->ao, w); + madd_v3_v3fl(indirect, samples[i]->indirect, w); } if(totw >= 0.9f) { totw= 1.0f/totw; - col[0] *= totw; - col[1] *= totw; - col[2] *= totw; + mul_v3_fl(ao, totw); + mul_v3_fl(indirect, totw); return 1; } @@ -1469,7 +1542,7 @@ static void sample_occ_surface(ShadeInput *shi) int *face, *index = RE_strandren_get_face(shi->obr, strand, 0); float w[4], *co1, *co2, *co3, *co4; - if(mesh && mesh->face && mesh->co && mesh->col && index) { + if(mesh && mesh->face && mesh->co && mesh->ao && index) { face= mesh->face[*index]; co1= mesh->co[face[0]]; @@ -1477,19 +1550,27 @@ static void sample_occ_surface(ShadeInput *shi) co3= mesh->co[face[2]]; co4= (face[3])? mesh->co[face[3]]: NULL; - interp_weights_face_v3( w,co1, co2, co3, co4, strand->vert->co); + interp_weights_face_v3(w, co1, co2, co3, co4, strand->vert->co); + + zero_v3(shi->ao); + zero_v3(shi->indirect); - shi->ao[0]= shi->ao[1]= shi->ao[2]= 0.0f; - VECADDFAC(shi->ao, shi->ao, mesh->col[face[0]], w[0]); - VECADDFAC(shi->ao, shi->ao, mesh->col[face[1]], w[1]); - VECADDFAC(shi->ao, shi->ao, mesh->col[face[2]], w[2]); - if(face[3]) - VECADDFAC(shi->ao, shi->ao, mesh->col[face[3]], w[3]); + madd_v3_v3fl(shi->ao, mesh->ao[face[0]], w[0]); + madd_v3_v3fl(shi->indirect, mesh->indirect[face[0]], w[0]); + madd_v3_v3fl(shi->ao, mesh->ao[face[1]], w[1]); + madd_v3_v3fl(shi->indirect, mesh->indirect[face[1]], w[1]); + madd_v3_v3fl(shi->ao, mesh->ao[face[2]], w[2]); + madd_v3_v3fl(shi->indirect, mesh->indirect[face[2]], w[2]); + if(face[3]) { + madd_v3_v3fl(shi->ao, mesh->ao[face[3]], w[3]); + madd_v3_v3fl(shi->indirect, mesh->indirect[face[3]], w[3]); + } } else { shi->ao[0]= 1.0f; shi->ao[1]= 1.0f; shi->ao[2]= 1.0f; + zero_v3(shi->indirect); } } @@ -1500,7 +1581,7 @@ static void *exec_strandsurface_sample(void *data) OcclusionThread *othread= (OcclusionThread*)data; Render *re= othread->re; StrandSurface *mesh= othread->mesh; - float col[3], co[3], n[3], *co1, *co2, *co3, *co4; + float ao[3], indirect[3], co[3], n[3], *co1, *co2, *co3, *co4; int a, *face; for(a=othread->begin; a<othread->end; a++) { @@ -1521,8 +1602,9 @@ static void *exec_strandsurface_sample(void *data) } negate_v3(n); - sample_occ_tree(re, re->occlusiontree, NULL, co, n, othread->thread, 0, col); - VECCOPY(othread->facecol[a], col); + sample_occ_tree(re, re->occlusiontree, NULL, co, n, othread->thread, 0, ao, indirect); + VECCOPY(othread->faceao[a], ao); + VECCOPY(othread->faceindirect[a], indirect); } return 0; @@ -1533,7 +1615,7 @@ void make_occ_tree(Render *re) OcclusionThread othreads[BLENDER_MAX_THREADS]; StrandSurface *mesh; ListBase threads; - float col[3], (*facecol)[3]; + float ao[3], indirect[3], (*faceao)[3], (*faceindirect)[3]; int a, totface, totthread, *face, *count; /* ugly, needed for occ_face */ @@ -1545,21 +1627,25 @@ void make_occ_tree(Render *re) re->occlusiontree= occ_tree_build(re); if(re->occlusiontree) { - if(re->wrld.ao_approx_passes) + if(re->wrld.ao_approx_passes > 0) occ_compute_passes(re, re->occlusiontree, re->wrld.ao_approx_passes); + if(re->wrld.ao_indirect_bounces > 1) + occ_compute_bounces(re, re->occlusiontree, re->wrld.ao_indirect_bounces); for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) { - if(!mesh->face || !mesh->co || !mesh->col) + if(!mesh->face || !mesh->co || !mesh->ao) continue; count= MEM_callocN(sizeof(int)*mesh->totvert, "OcclusionCount"); - facecol= MEM_callocN(sizeof(float)*3*mesh->totface, "StrandSurfFaceCol"); + faceao= MEM_callocN(sizeof(float)*3*mesh->totface, "StrandSurfFaceAO"); + faceindirect= MEM_callocN(sizeof(float)*3*mesh->totface, "StrandSurfFaceIndirect"); totthread= (mesh->totface > 10000)? re->r.threads: 1; totface= mesh->totface/totthread; for(a=0; a<totthread; a++) { othreads[a].re= re; - othreads[a].facecol= facecol; + othreads[a].faceao= faceao; + othreads[a].faceindirect= faceindirect; othreads[a].thread= a; othreads[a].mesh= mesh; othreads[a].begin= a*totface; @@ -1581,26 +1667,36 @@ void make_occ_tree(Render *re) for(a=0; a<mesh->totface; a++) { face= mesh->face[a]; - VECCOPY(col, facecol[a]); - VECADD(mesh->col[face[0]], mesh->col[face[0]], col); + VECCOPY(ao, faceao[a]); + VECCOPY(indirect, faceindirect[a]); + + VECADD(mesh->ao[face[0]], mesh->ao[face[0]], ao); + VECADD(mesh->indirect[face[0]], mesh->indirect[face[0]], indirect); count[face[0]]++; - VECADD(mesh->col[face[1]], mesh->col[face[1]], col); + VECADD(mesh->ao[face[1]], mesh->ao[face[1]], ao); + VECADD(mesh->indirect[face[1]], mesh->indirect[face[1]], indirect); count[face[1]]++; - VECADD(mesh->col[face[2]], mesh->col[face[2]], col); + VECADD(mesh->ao[face[2]], mesh->ao[face[2]], ao); + VECADD(mesh->indirect[face[2]], mesh->indirect[face[2]], indirect); count[face[2]]++; if(face[3]) { - VECADD(mesh->col[face[3]], mesh->col[face[3]], col); + VECADD(mesh->ao[face[3]], mesh->ao[face[3]], ao); + VECADD(mesh->indirect[face[3]], mesh->indirect[face[3]], indirect); count[face[3]]++; } } - for(a=0; a<mesh->totvert; a++) - if(count[a]) - mul_v3_fl(mesh->col[a], 1.0f/count[a]); + for(a=0; a<mesh->totvert; a++) { + if(count[a]) { + mul_v3_fl(mesh->ao[a], 1.0f/count[a]); + mul_v3_fl(mesh->indirect[a], 1.0f/count[a]); + } + } MEM_freeN(count); - MEM_freeN(facecol); + MEM_freeN(faceao); + MEM_freeN(faceindirect); } } } @@ -1626,12 +1722,12 @@ void sample_occ(Render *re, ShadeInput *shi) sample_occ_surface(shi); } /* try to get result from the cache if possible */ - else if(shi->depth!=0 || !sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao)) { + else if(shi->depth!=0 || !sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao, shi->indirect)) { /* no luck, let's sample the occlusion */ exclude.obi= shi->obi - re->objectinstance; exclude.facenr= shi->vlr->index; onlyshadow= (shi->mat->mode & MA_ONLYSHADOW); - sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao); + sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao, shi->indirect); /* fill result into sample, each time */ if(tree->cache) { @@ -1641,8 +1737,10 @@ void sample_occ(Render *re, ShadeInput *shi) sample= &cache->sample[(shi->ys-cache->y)*cache->w + (shi->xs-cache->x)]; VECCOPY(sample->co, shi->co); VECCOPY(sample->n, shi->vno); - VECCOPY(sample->col, shi->ao); - sample->intensity= MAX3(sample->col[0], sample->col[1], sample->col[2]); + VECCOPY(sample->ao, shi->ao); + VECCOPY(sample->indirect, shi->indirect); + sample->intensity= MAX3(sample->ao[0], sample->ao[1], sample->ao[2]); + sample->intensity= MAX2(sample->intensity, MAX3(sample->indirect[0], sample->indirect[1], sample->indirect[2])); sample->dist2= INPR(shi->dxco, shi->dxco) + INPR(shi->dyco, shi->dyco); sample->filled= 1; } @@ -1653,6 +1751,10 @@ void sample_occ(Render *re, ShadeInput *shi) shi->ao[0]= 1.0f; shi->ao[1]= 1.0f; shi->ao[2]= 1.0f; + + shi->indirect[0]= 0.0f; + shi->indirect[1]= 0.0f; + shi->indirect[2]= 0.0f; } } @@ -1720,12 +1822,14 @@ void cache_occ_samples(Render *re, RenderPart *pa, ShadeSample *ssamp) onlyshadow= (shi->mat->mode & MA_ONLYSHADOW); exclude.obi= shi->obi - re->objectinstance; exclude.facenr= shi->vlr->index; - sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao); + sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao, shi->indirect); VECCOPY(sample->co, shi->co); VECCOPY(sample->n, shi->vno); - VECCOPY(sample->col, shi->ao); - sample->intensity= MAX3(sample->col[0], sample->col[1], sample->col[2]); + VECCOPY(sample->ao, shi->ao); + VECCOPY(sample->indirect, shi->indirect); + sample->intensity= MAX3(sample->ao[0], sample->ao[1], sample->ao[2]); + sample->intensity= MAX2(sample->intensity, MAX3(sample->indirect[0], sample->indirect[1], sample->indirect[2])); sample->dist2= INPR(shi->dxco, shi->dxco) + INPR(shi->dyco, shi->dyco); sample->x= shi->xs; sample->y= shi->ys; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index b357a17e244..08440798826 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1065,12 +1065,25 @@ void RE_ResultGet32(Render *re, unsigned int *rect) int tot= rres.rectx*rres.recty; char *cp= (char *)rect; - for(;tot>0; tot--, cp+=4, fp+=4) { - cp[0] = FTOCHAR(fp[0]); - cp[1] = FTOCHAR(fp[1]); - cp[2] = FTOCHAR(fp[2]); - cp[3] = FTOCHAR(fp[3]); + if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) { + /* Finally convert back to sRGB rendered image */ + for(;tot>0; tot--, cp+=4, fp+=4) { + cp[0] = FTOCHAR(linearrgb_to_srgb(fp[0])); + cp[1] = FTOCHAR(linearrgb_to_srgb(fp[1])); + cp[2] = FTOCHAR(linearrgb_to_srgb(fp[2])); + cp[3] = FTOCHAR(fp[3]); + } } + else { + /* Color management is off : no conversion necessary */ + for(;tot>0; tot--, cp+=4, fp+=4) { + cp[0] = FTOCHAR(fp[0]); + cp[1] = FTOCHAR(fp[1]); + cp[2] = FTOCHAR(fp[2]); + cp[3] = FTOCHAR(fp[3]); + } + } + } else /* else fill with black */ diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c index d4b7c403f50..6fef8279c7e 100644 --- a/source/blender/render/intern/source/pixelshading.c +++ b/source/blender/render/intern/source/pixelshading.c @@ -537,15 +537,9 @@ void shadeSkyView(float *colf, float *rco, float *view, float *dxyview, short th /* the fraction of how far we are above the bottom of the screen */ blend= fabs(0.5+ view[1]); } - - if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) { - color_manage_linearize(hor, &R.wrld.horr); - color_manage_linearize(zen, &R.wrld.zenr); - } - else { - VECCOPY(hor, &R.wrld.horr); - VECCOPY(zen, &R.wrld.zenr); - } + + VECCOPY(hor, &R.wrld.horr); + VECCOPY(zen, &R.wrld.zenr); /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If */ /* SKYBLEND is active, the texture and color blend are added. */ @@ -633,10 +627,7 @@ void shadeSkyPixel(float *collector, float fx, float fy, short thread) } else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) { /* 2. solid color */ - if(R.r.color_mgt_flag & R_COLOR_MANAGEMENT) - color_manage_linearize(collector, &R.wrld.horr); - else - VECCOPY(collector, &R.wrld.horr); + VECCOPY(collector, &R.wrld.horr); collector[3] = 0.0f; } diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 396c713cfb7..fd1e27ab28a 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -91,42 +91,16 @@ extern struct Render R; * doing inverse gamma correction where applicable */ void shade_input_init_material(ShadeInput *shi) { - if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) { - color_manage_linearize(&shi->r, &shi->mat->r); - color_manage_linearize(&shi->specr, &shi->mat->specr); - color_manage_linearize(&shi->mirr, &shi->mat->mirr); - - /* material ambr / ambg / ambb is overwritten from world - color_manage_linearize(shi->ambr, shi->mat->ambr); - */ - - /* note, keep this synced with render_types.h */ - memcpy(&shi->amb, &shi->mat->amb, 11*sizeof(float)); - shi->har= shi->mat->har; - } else { - /* note, keep this synced with render_types.h */ - memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); - shi->har= shi->mat->har; - } - -} - -static void shadeinput_colors_linearize(ShadeInput *shi) -{ - color_manage_linearize(&shi->r, &shi->r); - color_manage_linearize(&shi->specr, &shi->specr); - color_manage_linearize(&shi->mirr, &shi->mirr); + /* note, keep this synced with render_types.h */ + memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); + shi->har= shi->mat->har; } /* also used as callback for nodes */ /* delivers a fully filled in ShadeResult, for all passes */ void shade_material_loop(ShadeInput *shi, ShadeResult *shr) { - /* because node materials don't have access to rendering context, - * inverse gamma correction must happen here. evil. */ - if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT && shi->nodes == 1) - shadeinput_colors_linearize(shi); - + shade_lamp_loop(shi, shr); /* clears shr */ if(shi->translucency!=0.0f) { @@ -626,7 +600,7 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) { if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE)) { - color_manage_linearize(shi->vcol, shi->vcol); + srgb_to_linearrgb_v3_v3(shi->vcol, shi->vcol); } } @@ -1291,7 +1265,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) */ if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) { if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE)) { - color_manage_linearize(shi->vcol, shi->vcol); + srgb_to_linearrgb_v3_v3(shi->vcol, shi->vcol); } } diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index f167122f497..958a2e34215 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -1041,6 +1041,7 @@ void ambient_occlusion_to_diffuse(ShadeInput *shi, float *diff) } VECMUL(diff, f); + madd_v3_v3fl(diff, shi->indirect, R.wrld.ao_indirect_energy*shi->amb); } else diff[0]= diff[1]= diff[2]= 0.0f; diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c index 25cfc0f1253..e551cf0f3d2 100644 --- a/source/blender/render/intern/source/sss.c +++ b/source/blender/render/intern/source/sss.c @@ -926,20 +926,17 @@ static void sss_create_tree_mat(Render *re, Material *mat) if(!re->test_break(re->tbh)) { SSSData *sss= MEM_callocN(sizeof(*sss), "SSSData"); float ior= mat->sss_ior, cfac= mat->sss_colfac; - float col[3], *radius= mat->sss_radius; + float *radius= mat->sss_radius; float fw= mat->sss_front, bw= mat->sss_back; float error = mat->sss_error; error= get_render_aosss_error(&re->r, error); if((re->r.scemode & R_PREVIEWBUTS) && error < 0.5f) error= 0.5f; - - if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) color_manage_linearize(col, mat->sss_col); - else VECCOPY(col, mat->sss_col); - sss->ss[0]= scatter_settings_new(col[0], radius[0], ior, cfac, fw, bw); - sss->ss[1]= scatter_settings_new(col[1], radius[1], ior, cfac, fw, bw); - sss->ss[2]= scatter_settings_new(col[2], radius[2], ior, cfac, fw, bw); + sss->ss[0]= scatter_settings_new(mat->sss_col[0], radius[0], ior, cfac, fw, bw); + sss->ss[1]= scatter_settings_new(mat->sss_col[1], radius[1], ior, cfac, fw, bw); + sss->ss[2]= scatter_settings_new(mat->sss_col[2], radius[2], ior, cfac, fw, bw); sss->tree= scatter_tree_new(sss->ss, mat->sss_scale, error, co, color, area, totpoint); diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c index 47a7c052b18..ecea7360974 100644 --- a/source/blender/render/intern/source/strand.c +++ b/source/blender/render/intern/source/strand.c @@ -959,7 +959,8 @@ StrandSurface *cache_strand_surface(Render *re, ObjectRen *obr, DerivedMesh *dm, mesh->totvert= totvert; mesh->totface= totface; mesh->face= MEM_callocN(sizeof(int)*4*mesh->totface, "StrandSurfFaces"); - mesh->col= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCol"); + mesh->ao= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfAO"); + mesh->indirect= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfIndirect"); BLI_addtail(&re->strandsurface, mesh); } @@ -997,7 +998,8 @@ void free_strand_surface(Render *re) if(mesh->co) MEM_freeN(mesh->co); if(mesh->prevco) MEM_freeN(mesh->prevco); if(mesh->nextco) MEM_freeN(mesh->nextco); - if(mesh->col) MEM_freeN(mesh->col); + if(mesh->ao) MEM_freeN(mesh->ao); + if(mesh->indirect) MEM_freeN(mesh->indirect); if(mesh->face) MEM_freeN(mesh->face); } diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index a9f6e7a53fd..16372d7a15d 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -2051,8 +2051,13 @@ void do_material_tex(ShadeInput *shi) else texres.tin= texres.ta; /* inverse gamma correction */ - if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) { - color_manage_linearize(tcol, tcol); + if (tex->type==TEX_IMAGE) { + Image *ima = tex->ima; + ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); + + /* don't linearize float buffers, assumed to be linear */ + if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT) + srgb_to_linearrgb_v3_v3(tcol, tcol); } if(mtex->mapto & MAP_COL) { @@ -2404,11 +2409,6 @@ void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, floa texres.tin= texres.ta; } - /* inverse gamma correction */ - if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) { - color_manage_linearize(tcol, tcol); - } - /* used for emit */ if((mapto_flag & MAP_EMISSION_COL) && (mtex->mapto & MAP_EMISSION_COL)) { float colemitfac= mtex->colemitfac*stencilTin; @@ -2556,8 +2556,13 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float *colf) else texres.tin= texres.ta; /* inverse gamma correction */ - if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) { - color_manage_linearize(&texres.tr, &texres.tr); + if (mtex->tex->type==TEX_IMAGE) { + Image *ima = mtex->tex->ima; + ImBuf *ibuf = BKE_image_get_ibuf(ima, &mtex->tex->iuser); + + /* don't linearize float buffers, assumed to be linear */ + if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT) + srgb_to_linearrgb_v3_v3(&texres.tr, &texres.tr); } fact= texres.tin*mtex->colfac; @@ -2605,6 +2610,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float *colf) void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, float *blend, int skyflag, short thread) { MTex *mtex; + Tex *tex; TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; float *co, fact, stencilTin=1.0; float tempvec[3], texvec[3], dxt[3], dyt[3]; @@ -2618,7 +2624,8 @@ void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, f if(R.wrld.mtex[tex_nr]) { mtex= R.wrld.mtex[tex_nr]; - if(mtex->tex==0) continue; + tex= mtex->tex; + if(tex==0) continue; /* if(mtex->mapto==0) continue; */ /* which coords */ @@ -2700,7 +2707,7 @@ void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, f else texvec[2]= mtex->size[2]*(mtex->ofs[2]); /* texture */ - if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); + if(tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); rgb= multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output); @@ -2748,8 +2755,13 @@ void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, f tcol[0]= texres.tr; tcol[1]= texres.tg; tcol[2]= texres.tb; /* inverse gamma correction */ - if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) { - color_manage_linearize(tcol, tcol); + if (tex->type==TEX_IMAGE) { + Image *ima = tex->ima; + ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); + + /* don't linearize float buffers, assumed to be linear */ + if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT) + srgb_to_linearrgb_v3_v3(tcol, tcol); } if(mtex->mapto & WOMAP_HORIZ) { @@ -2947,8 +2959,13 @@ void do_lamp_tex(LampRen *la, float *lavec, ShadeInput *shi, float *colf, int ef else texres.tin= texres.ta; /* inverse gamma correction */ - if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) { - color_manage_linearize(&texres.tr, &texres.tr); + if (tex->type==TEX_IMAGE) { + Image *ima = tex->ima; + ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); + + /* don't linearize float buffers, assumed to be linear */ + if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT) + srgb_to_linearrgb_v3_v3(&texres.tr, &texres.tr); } /* lamp colors were premultiplied with this */ |