Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2009-12-07 22:22:48 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2009-12-07 22:22:48 +0300
commit82ddfbf99fc0776a7fe439b81cf71bab87ceaaf9 (patch)
treefb1eda53eeeab12b093f5178693923b606708b05 /source/blender/render
parent4ca2581b77112c488938f0a2dc226042e0390b71 (diff)
parentfc69c54c4ce810e6236eaa45017130f27ba3f1e2 (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/SConscript33
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h2
-rw-r--r--source/blender/render/intern/include/render_types.h3
-rw-r--r--source/blender/render/intern/raytrace/reorganize.h5
-rw-r--r--source/blender/render/intern/source/convertblender.c22
-rw-r--r--source/blender/render/intern/source/occlusion.c246
-rw-r--r--source/blender/render/intern/source/pipeline.c23
-rw-r--r--source/blender/render/intern/source/pixelshading.c17
-rw-r--r--source/blender/render/intern/source/shadeinput.c38
-rw-r--r--source/blender/render/intern/source/shadeoutput.c1
-rw-r--r--source/blender/render/intern/source/sss.c11
-rw-r--r--source/blender/render/intern/source/strand.c6
-rw-r--r--source/blender/render/intern/source/texture.c47
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 */