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:
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/CMakeLists.txt1
-rw-r--r--source/blender/render/extern/include/RE_engine.h2
-rw-r--r--source/blender/render/extern/include/RE_render_ext.h3
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h12
-rw-r--r--source/blender/render/intern/include/envmap.h3
-rw-r--r--source/blender/render/intern/include/pixelshading.h2
-rw-r--r--source/blender/render/intern/include/render_types.h5
-rw-r--r--source/blender/render/intern/include/texture.h7
-rw-r--r--source/blender/render/intern/raytrace/rayobject_octree.cpp4
-rw-r--r--source/blender/render/intern/raytrace/rayobject_vbvh.cpp4
-rw-r--r--source/blender/render/intern/source/bake.c1107
-rw-r--r--source/blender/render/intern/source/convertblender.c15
-rw-r--r--source/blender/render/intern/source/envmap.c14
-rw-r--r--source/blender/render/intern/source/external_engine.c16
-rw-r--r--source/blender/render/intern/source/imagetexture.c60
-rw-r--r--source/blender/render/intern/source/multires_bake.c179
-rw-r--r--source/blender/render/intern/source/pipeline.c12
-rw-r--r--source/blender/render/intern/source/render_texture.c119
-rw-r--r--source/blender/render/intern/source/rendercore.c932
-rw-r--r--source/blender/render/intern/source/renderdatabase.c8
-rw-r--r--source/blender/render/intern/source/shadbuf.c7
-rw-r--r--source/blender/render/intern/source/shadeinput.c10
22 files changed, 1388 insertions, 1134 deletions
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index 16cba944e01..effc564fdc9 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -54,6 +54,7 @@ set(SRC
intern/raytrace/rayobject_qbvh.cpp
intern/raytrace/rayobject_rtbuild.cpp
intern/raytrace/rayobject_vbvh.cpp
+ intern/source/bake.c
intern/source/convertblender.c
intern/source/envmap.c
intern/source/external_engine.c
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index 64135a16f5d..b687acae1f7 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -62,6 +62,7 @@ struct Scene;
#define RE_ENGINE_DO_UPDATE 8
#define RE_ENGINE_RENDERING 16
#define RE_ENGINE_HIGHLIGHT_TILES 32
+#define RE_ENGINE_USED_FOR_VIEWPORT 64
extern ListBase R_engines;
@@ -105,6 +106,7 @@ typedef struct RenderEngine {
} RenderEngine;
RenderEngine *RE_engine_create(RenderEngineType *type);
+RenderEngine *RE_engine_create_ex(RenderEngineType *type, int use_for_viewport);
void RE_engine_free(RenderEngine *engine);
void RE_layer_load_from_file(struct RenderLayer *layer, struct ReportList *reports, const char *filename, int x, int y);
diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h
index 2a9a1becc42..2dfbdd0d6f5 100644
--- a/source/blender/render/extern/include/RE_render_ext.h
+++ b/source/blender/render/extern/include/RE_render_ext.h
@@ -49,10 +49,11 @@ struct RNode;
struct Render;
struct MTex;
struct ImBuf;
+struct ImagePool;
struct DerivedMesh;
/* particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */
-int externtex(struct MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread);
+int externtex(struct MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool);
/* particle.c */
void texture_rgb_blend(float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype);
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index 10045a8f7e1..d686de21517 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -184,19 +184,24 @@ typedef struct ShadeInput {
} ShadeInput;
+typedef struct BakeImBufuserData {
+ float *displacement_buffer;
+ char *mask_buffer;
+} BakeImBufuserData;
/* node shaders... */
struct Tex;
struct MTex;
struct ImBuf;
+struct ImagePool;
/* this one uses nodes */
-int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres);
+int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool);
/* nodes disabled */
-int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres);
+int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres, struct ImagePool *pool);
/* only for internal node usage */
int multitex_nodes(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres,
- const short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex);
+ const short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex, struct ImagePool *pool);
/* shaded view and bake */
struct Render;
@@ -206,6 +211,7 @@ struct Object;
int RE_bake_shade_all_selected(struct Render *re, int type, struct Object *actob, short *do_update, float *progress);
struct Image *RE_bake_shade_get_image(void);
void RE_bake_ibuf_filter(struct ImBuf *ibuf, char *mask, const int filter);
+void RE_bake_ibuf_normalize_displacement(struct ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max);
#define BAKE_RESULT_OK 0
#define BAKE_RESULT_NO_OBJECTS 1
diff --git a/source/blender/render/intern/include/envmap.h b/source/blender/render/intern/include/envmap.h
index d0f346f7402..a6c6d46e2e9 100644
--- a/source/blender/render/intern/include/envmap.h
+++ b/source/blender/render/intern/include/envmap.h
@@ -44,9 +44,10 @@
struct Render;
struct TexResult;
+struct ImagePool;
void make_envmaps(struct Render *re);
-int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres);
+int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool);
#endif /* __ENVMAP_H__ */
diff --git a/source/blender/render/intern/include/pixelshading.h b/source/blender/render/intern/include/pixelshading.h
index 30d574694b2..faf8c5f54f5 100644
--- a/source/blender/render/intern/include/pixelshading.h
+++ b/source/blender/render/intern/include/pixelshading.h
@@ -32,6 +32,8 @@
#ifndef __PIXELSHADING_H__
#define __PIXELSHADING_H__
+struct ImagePool;
+
/**
* Render the pixel at (x,y) for object ap. Apply the jitter mask.
* Output is given in float collector[4]. The type vector:
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 3b8cd3c6aa5..deba6d165f2 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -62,6 +62,7 @@ struct RayFace;
struct RenderEngine;
struct ReportList;
struct Main;
+struct ImagePool;
#define TABLEINITSIZE 1024
@@ -264,6 +265,8 @@ struct Render
RenderStats i;
struct ReportList *reports;
+
+ struct ImagePool *pool;
};
/* ------------------------------------------------------------------------- */
@@ -377,6 +380,7 @@ struct halosort {
/* ------------------------------------------------------------------------- */
struct Material;
struct MTFace;
+struct ImagePool;
typedef struct RadFace {
float unshot[3], totrad[3];
@@ -409,6 +413,7 @@ typedef struct HaloRen {
int pixels;
unsigned int lay;
struct Material *mat;
+ struct ImagePool *pool;
} HaloRen;
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h
index 4b9fa2d2042..2dc12f39db7 100644
--- a/source/blender/render/intern/include/texture.h
+++ b/source/blender/render/intern/include/texture.h
@@ -60,6 +60,7 @@ struct TexResult;
struct Tex;
struct Image;
struct ImBuf;
+struct ImagePool;
/* texture.h */
@@ -76,9 +77,9 @@ void render_realtime_texture(struct ShadeInput *shi, struct Image *ima);
/* imagetexture.h */
-int imagewraposa(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], const float dxt[2], const float dyt[2], struct TexResult *texres);
-int imagewrap(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], struct TexResult *texres);
-void image_sample(struct Image *ima, float fx, float fy, float dx, float dy, float result[4]);
+int imagewraposa(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], const float dxt[2], const float dyt[2], struct TexResult *texres, struct ImagePool *pool);
+int imagewrap(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], struct TexResult *texres, struct ImagePool *pool);
+void image_sample(struct Image *ima, float fx, float fy, float dx, float dy, float result[4], struct ImagePool *pool);
#endif /* __TEXTURE_H__ */
diff --git a/source/blender/render/intern/raytrace/rayobject_octree.cpp b/source/blender/render/intern/raytrace/rayobject_octree.cpp
index 658ab9dc091..e4fd5a6d41e 100644
--- a/source/blender/render/intern/raytrace/rayobject_octree.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_octree.cpp
@@ -667,10 +667,12 @@ static void RE_rayobject_octree_done(RayObject *tree)
oc->ocface = NULL;
MEM_freeN(oc->ro_nodes);
oc->ro_nodes = NULL;
-
+
+#if 0
printf("%f %f - %f\n", oc->min[0], oc->max[0], oc->ocfacx);
printf("%f %f - %f\n", oc->min[1], oc->max[1], oc->ocfacy);
printf("%f %f - %f\n", oc->min[2], oc->max[2], oc->ocfacz);
+#endif
}
static void RE_rayobject_octree_bb(RayObject *tree, float *min, float *max)
diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
index d03bdb74407..3e80deefecd 100644
--- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
@@ -38,12 +38,12 @@ int tot_hints = 0;
#include "MEM_guardedalloc.h"
-#include "BKE_global.h"
-
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_utildefines.h"
+#include "BKE_global.h"
+
#include "rayintersection.h"
#include "rayobject.h"
#include "rayobject_rtbuild.h"
diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c
new file mode 100644
index 00000000000..d4451d570a4
--- /dev/null
+++ b/source/blender/render/intern/source/bake.c
@@ -0,0 +1,1107 @@
+/*
+ * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributors: 2004/2005/2006 Blender Foundation, full recode
+ * Contributors: Vertex color baking, Copyright 2011 AutoCRC
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/render/intern/source/bake.c
+ * \ingroup render
+ */
+
+
+/* system includes */
+#include <stdio.h>
+#include <string.h>
+
+/* External modules: */
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_threads.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_image_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+#include "BKE_scene.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "IMB_colormanagement.h"
+
+/* local include */
+#include "rayintersection.h"
+#include "rayobject.h"
+#include "render_types.h"
+#include "renderdatabase.h"
+#include "shading.h"
+#include "zbuf.h"
+
+#include "PIL_time.h"
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
+/* only to be used here in this file, it's for speed */
+extern struct Render R;
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+
+/* ************************* bake ************************ */
+
+
+typedef struct BakeShade {
+ ShadeSample ssamp;
+ ObjectInstanceRen *obi;
+ VlakRen *vlr;
+
+ ZSpan *zspan;
+ Image *ima;
+ ImBuf *ibuf;
+
+ int rectx, recty, quad, type, vdone;
+ bool ready;
+
+ float dir[3];
+ Object *actob;
+
+ /* Output: vertex color or image data. If vcol is not NULL, rect and
+ * rect_float should be NULL. */
+ MPoly *mpoly;
+ MLoop *mloop;
+ MLoopCol *vcol;
+
+ unsigned int *rect;
+ float *rect_float;
+
+ /* displacement buffer used for normalization with unknown maximal distance */
+ bool use_displacement_buffer;
+ float *displacement_buffer;
+ float displacement_min, displacement_max;
+
+ bool use_mask;
+ char *rect_mask; /* bake pixel mask */
+
+ float dxco[3], dyco[3];
+
+ short *do_update;
+
+ struct ColorSpace *rect_colorspace;
+} BakeShade;
+
+static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int UNUSED(isect), int x, int y, float u, float v)
+{
+ if (quad)
+ shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3);
+ else
+ shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
+
+ /* cache for shadow */
+ shi->samplenr = R.shadowsamplenr[shi->thread]++;
+
+ shi->mask = 0xFFFF; /* all samples */
+
+ shi->u = -u;
+ shi->v = -v;
+ shi->xs = x;
+ shi->ys = y;
+
+ shade_input_set_uv(shi);
+ shade_input_set_normals(shi);
+
+ /* no normal flip */
+ if (shi->flippednor)
+ shade_input_flip_normals(shi);
+
+ /* set up view vector to look right at the surface (note that the normal
+ * is negated in the renderer so it does not need to be done here) */
+ shi->view[0] = shi->vn[0];
+ shi->view[1] = shi->vn[1];
+ shi->view[2] = shi->vn[2];
+}
+
+static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(quad), int x, int y, float UNUSED(u), float UNUSED(v), float *tvn, float *ttang)
+{
+ BakeShade *bs = handle;
+ ShadeSample *ssamp = &bs->ssamp;
+ ShadeResult shr;
+ VlakRen *vlr = shi->vlr;
+
+ shade_input_init_material(shi);
+
+ if (bs->type == RE_BAKE_AO) {
+ ambient_occlusion(shi);
+
+ if (R.r.bake_flag & R_BAKE_NORMALIZE) {
+ copy_v3_v3(shr.combined, shi->ao);
+ }
+ else {
+ zero_v3(shr.combined);
+ environment_lighting_apply(shi, &shr);
+ }
+ }
+ else {
+ if (bs->type == RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */
+ shi->r = shi->g = shi->b = 1.0f;
+
+ shade_input_set_shade_texco(shi);
+
+ /* only do AO for a full bake (and obviously AO bakes)
+ * AO for light bakes is a leftover and might not be needed */
+ if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT))
+ shade_samples_do_AO(ssamp);
+
+ if (shi->mat->nodetree && shi->mat->use_nodes) {
+ ntreeShaderExecTree(shi->mat->nodetree, shi, &shr);
+ shi->mat = vlr->mat; /* shi->mat is being set in nodetree */
+ }
+ else
+ shade_material_loop(shi, &shr);
+
+ if (bs->type == RE_BAKE_NORMALS) {
+ float nor[3];
+
+ copy_v3_v3(nor, shi->vn);
+
+ if (R.r.bake_normal_space == R_BAKE_SPACE_CAMERA) {
+ /* pass */
+ }
+ else if (R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) {
+ float mat[3][3], imat[3][3];
+
+ /* bitangent */
+ if (tvn && ttang) {
+ copy_v3_v3(mat[0], ttang);
+ cross_v3_v3v3(mat[1], tvn, ttang);
+ mul_v3_fl(mat[1], ttang[3]);
+ copy_v3_v3(mat[2], tvn);
+ }
+ else {
+ copy_v3_v3(mat[0], shi->nmaptang);
+ cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang);
+ mul_v3_fl(mat[1], shi->nmaptang[3]);
+ copy_v3_v3(mat[2], shi->nmapnorm);
+ }
+
+ invert_m3_m3(imat, mat);
+ mul_m3_v3(imat, nor);
+ }
+ else if (R.r.bake_normal_space == R_BAKE_SPACE_OBJECT)
+ mul_mat3_m4_v3(ob->imat_ren, nor); /* ob->imat_ren includes viewinv! */
+ else if (R.r.bake_normal_space == R_BAKE_SPACE_WORLD)
+ mul_mat3_m4_v3(R.viewinv, nor);
+
+ normalize_v3(nor); /* in case object has scaling */
+
+ /* The invert of the red channel is to make
+ * the normal map compliant with the outside world.
+ * It needs to be done because in Blender
+ * the normal used in the renderer points inward. It is generated
+ * this way in calc_vertexnormals(). Should this ever change
+ * this negate must be removed. */
+ shr.combined[0] = (-nor[0]) / 2.0f + 0.5f;
+ shr.combined[1] = nor[1] / 2.0f + 0.5f;
+ shr.combined[2] = nor[2] / 2.0f + 0.5f;
+ }
+ else if (bs->type == RE_BAKE_TEXTURE) {
+ copy_v3_v3(shr.combined, &shi->r);
+ shr.alpha = shi->alpha;
+ }
+ else if (bs->type == RE_BAKE_SHADOW) {
+ copy_v3_v3(shr.combined, shr.shad);
+ shr.alpha = shi->alpha;
+ }
+ else if (bs->type == RE_BAKE_SPEC_COLOR) {
+ copy_v3_v3(shr.combined, &shi->specr);
+ shr.alpha = 1.0f;
+ }
+ else if (bs->type == RE_BAKE_SPEC_INTENSITY) {
+ copy_v3_fl(shr.combined, shi->spec);
+ shr.alpha = 1.0f;
+ }
+ else if (bs->type == RE_BAKE_MIRROR_COLOR) {
+ copy_v3_v3(shr.combined, &shi->mirr);
+ shr.alpha = 1.0f;
+ }
+ else if (bs->type == RE_BAKE_MIRROR_INTENSITY) {
+ copy_v3_fl(shr.combined, shi->ray_mirror);
+ shr.alpha = 1.0f;
+ }
+ else if (bs->type == RE_BAKE_ALPHA) {
+ copy_v3_fl(shr.combined, shi->alpha);
+ shr.alpha = 1.0f;
+ }
+ else if (bs->type == RE_BAKE_EMIT) {
+ copy_v3_fl(shr.combined, shi->emit);
+ shr.alpha = 1.0f;
+ }
+ }
+
+ if (bs->rect_float && !bs->vcol) {
+ float *col = bs->rect_float + 4 * (bs->rectx * y + x);
+ copy_v3_v3(col, shr.combined);
+ if (bs->type == RE_BAKE_ALL || bs->type == RE_BAKE_TEXTURE) {
+ col[3] = shr.alpha;
+ }
+ else {
+ col[3] = 1.0;
+ }
+ }
+ else {
+ /* Target is char (LDR). */
+ unsigned char col[4];
+
+ if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
+ float rgb[3];
+
+ copy_v3_v3(rgb, shr.combined);
+ if (R.scene_color_manage) {
+ /* Vertex colors have no way to specify color space, so they
+ * default to sRGB. */
+ if (!bs->vcol)
+ IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace);
+ else
+ linearrgb_to_srgb_v3_v3(rgb, rgb);
+ }
+ rgb_float_to_uchar(col, rgb);
+ }
+ else {
+ rgb_float_to_uchar(col, shr.combined);
+ }
+
+ if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
+ col[3] = FTOCHAR(shr.alpha);
+ }
+ else {
+ col[3] = 255;
+ }
+
+ if (bs->vcol) {
+ /* Vertex color baking. Vcol has no useful alpha channel (it exists
+ * but is used only for vertex painting). */
+ bs->vcol->r = col[0];
+ bs->vcol->g = col[1];
+ bs->vcol->b = col[2];
+ }
+ else {
+ unsigned char *imcol = (unsigned char *)(bs->rect + bs->rectx * y + x);
+ copy_v4_v4_char((char *)imcol, (char *)col);
+ }
+
+ }
+
+ if (bs->rect_mask) {
+ bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED;
+ }
+}
+
+static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist, int x, int y)
+{
+ BakeShade *bs = handle;
+ float disp;
+
+ if (R.r.bake_flag & R_BAKE_NORMALIZE) {
+ if (R.r.bake_maxdist)
+ disp = (dist + R.r.bake_maxdist) / (R.r.bake_maxdist * 2); /* alter the range from [-bake_maxdist, bake_maxdist] to [0, 1]*/
+ else
+ disp = dist;
+ }
+ else {
+ disp = 0.5f + dist; /* alter the range from [-0.5,0.5] to [0,1]*/
+ }
+
+ if (bs->displacement_buffer) {
+ float *displacement = bs->displacement_buffer + (bs->rectx * y + x);
+ *displacement = disp;
+ bs->displacement_min = min_ff(bs->displacement_min, disp);
+ bs->displacement_max = max_ff(bs->displacement_max, disp);
+ }
+
+ if (bs->rect_float && !bs->vcol) {
+ float *col = bs->rect_float + 4 * (bs->rectx * y + x);
+ col[0] = col[1] = col[2] = disp;
+ col[3] = 1.0f;
+ }
+ else {
+ /* Target is char (LDR). */
+ unsigned char col[4];
+ col[0] = col[1] = col[2] = FTOCHAR(disp);
+ col[3] = 255;
+
+ if (bs->vcol) {
+ /* Vertex color baking. Vcol has no useful alpha channel (it exists
+ * but is used only for vertex painting). */
+ bs->vcol->r = col[0];
+ bs->vcol->g = col[1];
+ bs->vcol->b = col[2];
+ }
+ else {
+ char *imcol = (char *)(bs->rect + bs->rectx * y + x);
+ copy_v4_v4_char((char *)imcol, (char *)col);
+ }
+ }
+ if (bs->rect_mask) {
+ bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED;
+ }
+}
+
+static int bake_intersect_tree(RayObject *raytree, Isect *isect, float *start, float *dir, float sign, float *hitco, float *dist)
+{
+ float maxdist;
+ int hit;
+
+ /* might be useful to make a user setting for maxsize*/
+ if (R.r.bake_maxdist > 0.0f)
+ maxdist = R.r.bake_maxdist;
+ else
+ maxdist = RE_RAYTRACE_MAXDIST + R.r.bake_biasdist;
+
+ /* 'dir' is always normalized */
+ madd_v3_v3v3fl(isect->start, start, dir, -R.r.bake_biasdist);
+
+ mul_v3_v3fl(isect->dir, dir, sign);
+
+ isect->dist = maxdist;
+
+ hit = RE_rayobject_raycast(raytree, isect);
+ if (hit) {
+ madd_v3_v3v3fl(hitco, isect->start, isect->dir, isect->dist);
+
+ *dist = isect->dist;
+ }
+
+ return hit;
+}
+
+static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3)
+{
+ VlakRen *vlr = bs->vlr;
+ float A, d1, d2, d3, *v1, *v2, *v3;
+
+ if (bs->quad) {
+ v1 = vlr->v1->co;
+ v2 = vlr->v3->co;
+ v3 = vlr->v4->co;
+ }
+ else {
+ v1 = vlr->v1->co;
+ v2 = vlr->v2->co;
+ v3 = vlr->v3->co;
+ }
+
+ /* formula derived from barycentric coordinates:
+ * (uvArea1*v1 + uvArea2*v2 + uvArea3*v3)/uvArea
+ * then taking u and v partial derivatives to get dxco and dyco */
+ A = (uv2[0] - uv1[0]) * (uv3[1] - uv1[1]) - (uv3[0] - uv1[0]) * (uv2[1] - uv1[1]);
+
+ if (fabsf(A) > FLT_EPSILON) {
+ A = 0.5f / A;
+
+ d1 = uv2[1] - uv3[1];
+ d2 = uv3[1] - uv1[1];
+ d3 = uv1[1] - uv2[1];
+ bs->dxco[0] = (v1[0] * d1 + v2[0] * d2 + v3[0] * d3) * A;
+ bs->dxco[1] = (v1[1] * d1 + v2[1] * d2 + v3[1] * d3) * A;
+ bs->dxco[2] = (v1[2] * d1 + v2[2] * d2 + v3[2] * d3) * A;
+
+ d1 = uv3[0] - uv2[0];
+ d2 = uv1[0] - uv3[0];
+ d3 = uv2[0] - uv1[0];
+ bs->dyco[0] = (v1[0] * d1 + v2[0] * d2 + v3[0] * d3) * A;
+ bs->dyco[1] = (v1[1] * d1 + v2[1] * d2 + v3[1] * d3) * A;
+ bs->dyco[2] = (v1[2] * d1 + v2[2] * d2 + v3[2] * d3) * A;
+ }
+ else {
+ bs->dxco[0] = bs->dxco[1] = bs->dxco[2] = 0.0f;
+ bs->dyco[0] = bs->dyco[1] = bs->dyco[2] = 0.0f;
+ }
+
+ if (bs->obi->flag & R_TRANSFORMED) {
+ mul_m3_v3(bs->obi->nmat, bs->dxco);
+ mul_m3_v3(bs->obi->nmat, bs->dyco);
+ }
+}
+
+static void do_bake_shade(void *handle, int x, int y, float u, float v)
+{
+ BakeShade *bs = handle;
+ VlakRen *vlr = bs->vlr;
+ ObjectInstanceRen *obi = bs->obi;
+ Object *ob = obi->obr->ob;
+ float l, *v1, *v2, *v3, tvn[3], ttang[4];
+ int quad;
+ ShadeSample *ssamp = &bs->ssamp;
+ ShadeInput *shi = ssamp->shi;
+
+ /* fast threadsafe break test */
+ if (R.test_break(R.tbh))
+ return;
+
+ /* setup render coordinates */
+ if (bs->quad) {
+ v1 = vlr->v1->co;
+ v2 = vlr->v3->co;
+ v3 = vlr->v4->co;
+ }
+ else {
+ v1 = vlr->v1->co;
+ v2 = vlr->v2->co;
+ v3 = vlr->v3->co;
+ }
+
+ l = 1.0f - u - v;
+
+ /* shrink barycentric coordinates inwards slightly to avoid some issues
+ * where baking selected to active might just miss the other face at the
+ * near the edge of a face */
+ if (bs->actob) {
+ const float eps = 1.0f - 1e-4f;
+ float invsum;
+
+ u = (u - 0.5f) * eps + 0.5f;
+ v = (v - 0.5f) * eps + 0.5f;
+ l = (l - 0.5f) * eps + 0.5f;
+
+ invsum = 1.0f / (u + v + l);
+
+ u *= invsum;
+ v *= invsum;
+ l *= invsum;
+ }
+
+ /* renderco */
+ 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];
+
+ /* avoid self shadow with vertex bake from adjacent faces [#33729] */
+ if ((bs->vcol != NULL) && (bs->actob == NULL)) {
+ madd_v3_v3fl(shi->co, vlr->n, 0.0001f);
+ }
+
+ if (obi->flag & R_TRANSFORMED)
+ mul_m4_v3(obi->mat, shi->co);
+
+ copy_v3_v3(shi->dxco, bs->dxco);
+ copy_v3_v3(shi->dyco, bs->dyco);
+
+ quad = bs->quad;
+ bake_set_shade_input(obi, vlr, shi, quad, 0, x, y, u, v);
+
+ if (bs->type == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) {
+ shade_input_set_shade_texco(shi);
+ copy_v3_v3(tvn, shi->nmapnorm);
+ copy_v4_v4(ttang, shi->nmaptang);
+ }
+
+ /* if we are doing selected to active baking, find point on other face */
+ if (bs->actob) {
+ Isect isec, minisec;
+ float co[3], minco[3], dist, mindist = 0.0f;
+ int hit, sign, dir = 1;
+
+ /* intersect with ray going forward and backward*/
+ hit = 0;
+ memset(&minisec, 0, sizeof(minisec));
+ minco[0] = minco[1] = minco[2] = 0.0f;
+
+ copy_v3_v3(bs->dir, shi->vn);
+
+ for (sign = -1; sign <= 1; sign += 2) {
+ memset(&isec, 0, sizeof(isec));
+ isec.mode = RE_RAY_MIRROR;
+
+ isec.orig.ob = obi;
+ isec.orig.face = vlr;
+ isec.userdata = bs->actob;
+ isec.check = RE_CHECK_VLR_BAKE;
+ isec.skip = RE_SKIP_VLR_NEIGHBOUR;
+
+ if (bake_intersect_tree(R.raytree, &isec, shi->co, shi->vn, sign, co, &dist)) {
+ if (!hit || len_squared_v3v3(shi->co, co) < len_squared_v3v3(shi->co, minco)) {
+ minisec = isec;
+ mindist = dist;
+ copy_v3_v3(minco, co);
+ hit = 1;
+ dir = sign;
+ }
+ }
+ }
+
+ if (bs->type == RE_BAKE_DISPLACEMENT) {
+ if (hit)
+ bake_displacement(handle, shi, (dir == -1) ? mindist : -mindist, x, y);
+ else
+ bake_displacement(handle, shi, 0.0f, x, y);
+ return;
+ }
+
+ /* if hit, we shade from the new point, otherwise from point one starting face */
+ if (hit) {
+ obi = (ObjectInstanceRen *)minisec.hit.ob;
+ vlr = (VlakRen *)minisec.hit.face;
+ quad = (minisec.isect == 2);
+ copy_v3_v3(shi->co, minco);
+
+ u = -minisec.u;
+ v = -minisec.v;
+ bake_set_shade_input(obi, vlr, shi, quad, 1, x, y, u, v);
+ }
+ }
+
+ if (bs->type == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT)
+ bake_shade(handle, ob, shi, quad, x, y, u, v, tvn, ttang);
+ else
+ bake_shade(handle, ob, shi, quad, x, y, u, v, 0, 0);
+}
+
+static int get_next_bake_face(BakeShade *bs)
+{
+ ObjectRen *obr;
+ VlakRen *vlr;
+ MTFace *tface;
+ static int v = 0, vdone = false;
+ static ObjectInstanceRen *obi = NULL;
+
+ if (bs == NULL) {
+ vlr = NULL;
+ v = vdone = false;
+ obi = R.instancetable.first;
+ return 0;
+ }
+
+ BLI_lock_thread(LOCK_CUSTOM1);
+
+ for (; obi; obi = obi->next, v = 0) {
+ obr = obi->obr;
+
+ for (; v < obr->totvlak; v++) {
+ vlr = RE_findOrAddVlak(obr, v);
+
+ if ((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) {
+ if (R.r.bake_flag & R_BAKE_VCOL) {
+ /* Gather face data for vertex color bake */
+ Mesh *me;
+ int *origindex, vcollayer;
+ CustomDataLayer *cdl;
+
+ if (obr->ob->type != OB_MESH)
+ continue;
+ me = obr->ob->data;
+
+ origindex = RE_vlakren_get_origindex(obr, vlr, 0);
+ if (origindex == NULL)
+ continue;
+ if (*origindex >= me->totpoly) {
+ /* Small hack for Array modifier, which gives false
+ original indices - z0r */
+ continue;
+ }
+#if 0
+ /* Only shade selected faces. */
+ if ((me->mface[*origindex].flag & ME_FACE_SEL) == 0)
+ continue;
+#endif
+
+ vcollayer = CustomData_get_render_layer_index(&me->ldata, CD_MLOOPCOL);
+ if (vcollayer == -1)
+ continue;
+
+ cdl = &me->ldata.layers[vcollayer];
+ bs->mpoly = me->mpoly + *origindex;
+ bs->vcol = ((MLoopCol *)cdl->data) + bs->mpoly->loopstart;
+ bs->mloop = me->mloop + bs->mpoly->loopstart;
+
+ /* Tag mesh for reevaluation. */
+ DAG_id_tag_update(&me->id, 0);
+ }
+ else {
+ Image *ima = NULL;
+ ImBuf *ibuf = NULL;
+ const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+
+ tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
+
+ if (!tface || !tface->tpage)
+ continue;
+
+ ima = tface->tpage;
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+
+ if (ibuf == NULL)
+ continue;
+
+ if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ continue;
+ }
+
+ if (ibuf->rect_float && !(ibuf->channels == 0 || ibuf->channels == 4)) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ continue;
+ }
+
+ if (ima->flag & IMA_USED_FOR_RENDER) {
+ ima->id.flag &= ~LIB_DOIT;
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ continue;
+ }
+
+ /* find the image for the first time? */
+ if (ima->id.flag & LIB_DOIT) {
+ ima->id.flag &= ~LIB_DOIT;
+
+ /* we either fill in float or char, this ensures things go fine */
+ if (ibuf->rect_float)
+ imb_freerectImBuf(ibuf);
+ /* clear image */
+ if (R.r.bake_flag & R_BAKE_CLEAR)
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
+
+ /* might be read by UI to set active image for display */
+ R.bakebuf = ima;
+ }
+
+ /* Tag image for redraw. */
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+
+ bs->obi = obi;
+ bs->vlr = vlr;
+ bs->vdone++; /* only for error message if nothing was rendered */
+ v++;
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ return 1;
+ }
+ }
+ }
+
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ return 0;
+}
+
+static void bake_single_vertex(BakeShade *bs, VertRen *vert, float u, float v)
+{
+ int *origindex, i;
+ MLoopCol *basevcol;
+ MLoop *mloop;
+
+ origindex = RE_vertren_get_origindex(bs->obi->obr, vert, 0);
+ if (!origindex || *origindex == ORIGINDEX_NONE)
+ return;
+
+ /* Search for matching vertex index and apply shading. */
+ for (i = 0; i < bs->mpoly->totloop; i++) {
+ mloop = bs->mloop + i;
+ if (mloop->v != *origindex)
+ continue;
+ basevcol = bs->vcol;
+ bs->vcol = basevcol + i;
+ do_bake_shade(bs, 0, 0, u, v);
+ bs->vcol = basevcol;
+ break;
+ }
+}
+
+/* Bake all vertices of a face. Actually, this still works on a face-by-face
+ basis, and each vertex on each face is shaded. Vertex colors are a property
+ of loops, not vertices. */
+static void shade_verts(BakeShade *bs)
+{
+ VlakRen *vlr = bs->vlr;
+
+ /* Disable baking to image; write to vcol instead. vcol pointer is set in
+ * bake_single_vertex. */
+ bs->ima = NULL;
+ bs->rect = NULL;
+ bs->rect_float = NULL;
+ bs->displacement_buffer = NULL;
+ bs->displacement_min = FLT_MAX;
+ bs->displacement_max = -FLT_MAX;
+
+ bs->quad = 0;
+
+ /* No anti-aliasing for vertices. */
+ zero_v3(bs->dxco);
+ zero_v3(bs->dyco);
+
+ /* Shade each vertex of the face. u and v are barycentric coordinates; since
+ we're only interested in vertices, these will be 0 or 1. */
+ if ((vlr->flag & R_FACE_SPLIT) == 0) {
+ /* Processing triangle face, whole quad, or first half of split quad. */
+
+ bake_single_vertex(bs, bs->vlr->v1, 1.0f, 0.0f);
+ bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f);
+ bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f);
+
+ if (vlr->v4) {
+ bs->quad = 1;
+ bake_single_vertex(bs, bs->vlr->v4, 0.0f, 0.0f);
+ }
+ }
+ else {
+ /* Processing second half of split quad. Only one vertex to go. */
+ if (vlr->flag & R_DIVIDE_24) {
+ bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f);
+ }
+ else {
+ bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f);
+ }
+ }
+}
+
+/* already have tested for tface and ima and zspan */
+static void shade_tface(BakeShade *bs)
+{
+ VlakRen *vlr = bs->vlr;
+ ObjectInstanceRen *obi = bs->obi;
+ ObjectRen *obr = obi->obr;
+ MTFace *tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
+ Image *ima = tface->tpage;
+ float vec[4][2];
+ int a, i1, i2, i3;
+
+ /* check valid zspan */
+ if (ima != bs->ima) {
+ BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL);
+
+ bs->ima = ima;
+ bs->ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ /* note, these calls only free/fill contents of zspan struct, not zspan itself */
+ zbuf_free_span(bs->zspan);
+ zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop);
+ }
+
+ bs->rectx = bs->ibuf->x;
+ bs->recty = bs->ibuf->y;
+ bs->rect = bs->ibuf->rect;
+ bs->rect_colorspace = bs->ibuf->rect_colorspace;
+ bs->rect_float = bs->ibuf->rect_float;
+ bs->vcol = NULL;
+ bs->quad = 0;
+ bs->rect_mask = NULL;
+ bs->displacement_buffer = NULL;
+
+ if (bs->use_mask || bs->use_displacement_buffer) {
+ BakeImBufuserData *userdata = bs->ibuf->userdata;
+ if (userdata == NULL) {
+ BLI_lock_thread(LOCK_CUSTOM1);
+ userdata = bs->ibuf->userdata;
+ if (userdata == NULL) /* since the thread was locked, its possible another thread alloced the value */
+ userdata = MEM_callocN(sizeof(BakeImBufuserData), "BakeMask");
+
+ if (bs->use_mask)
+ userdata->mask_buffer = MEM_callocN(sizeof(char) * bs->rectx * bs->recty, "BakeMask");
+
+ if (bs->use_displacement_buffer)
+ userdata->displacement_buffer = MEM_callocN(sizeof(float) * bs->rectx * bs->recty, "BakeDisp");
+
+ bs->ibuf->userdata = userdata;
+
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ }
+
+ bs->rect_mask = userdata->mask_buffer;
+ bs->displacement_buffer = userdata->displacement_buffer;
+ }
+
+ /* get pixel level vertex coordinates */
+ for (a = 0; a < 4; a++) {
+ /* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests
+ * where a pixel gets in between 2 faces or the middle of a quad,
+ * camera aligned quads also have this problem but they are less common.
+ * Add a small offset to the UVs, fixes bug #18685 - Campbell */
+ vec[a][0] = tface->uv[a][0] * (float)bs->rectx - (0.5f + 0.001f);
+ vec[a][1] = tface->uv[a][1] * (float)bs->recty - (0.5f + 0.002f);
+ }
+
+ /* UV indices have to be corrected for possible quad->tria splits */
+ i1 = 0; i2 = 1; i3 = 2;
+ vlr_set_uv_indices(vlr, &i1, &i2, &i3);
+ bake_set_vlr_dxyco(bs, vec[i1], vec[i2], vec[i3]);
+ zspan_scanconvert(bs->zspan, bs, vec[i1], vec[i2], vec[i3], do_bake_shade);
+
+ if (vlr->v4) {
+ bs->quad = 1;
+ bake_set_vlr_dxyco(bs, vec[0], vec[2], vec[3]);
+ zspan_scanconvert(bs->zspan, bs, vec[0], vec[2], vec[3], do_bake_shade);
+ }
+}
+
+static void *do_bake_thread(void *bs_v)
+{
+ BakeShade *bs = bs_v;
+
+ while (get_next_bake_face(bs)) {
+ if (R.r.bake_flag & R_BAKE_VCOL) {
+ shade_verts(bs);
+ }
+ else {
+ shade_tface(bs);
+ }
+
+ /* fast threadsafe break test */
+ if (R.test_break(R.tbh))
+ break;
+
+ /* access is not threadsafe but since its just true/false probably ok
+ * only used for interactive baking */
+ if (bs->do_update) {
+ *bs->do_update = true;
+ }
+ }
+ bs->ready = true;
+
+ BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL);
+
+ return NULL;
+}
+
+void RE_bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter)
+{
+ /* must check before filtering */
+ const short is_new_alpha = (ibuf->planes != R_IMF_PLANES_RGBA) && BKE_imbuf_alpha_test(ibuf);
+
+ /* Margin */
+ if (filter) {
+ IMB_filter_extend(ibuf, mask, filter);
+ }
+
+ /* if the bake results in new alpha then change the image setting */
+ if (is_new_alpha) {
+ ibuf->planes = R_IMF_PLANES_RGBA;
+ }
+ else {
+ if (filter && ibuf->planes != R_IMF_PLANES_RGBA) {
+ /* clear alpha added by filtering */
+ IMB_rectfill_alpha(ibuf, 1.0f);
+ }
+ }
+}
+
+void RE_bake_ibuf_normalize_displacement(ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max)
+{
+ int i;
+ float *current_displacement = displacement;
+ char *current_mask = mask;
+ float max_distance;
+
+ max_distance = max_ff(fabsf(displacement_min), fabsf(displacement_max));
+
+ for (i = 0; i < ibuf->x * ibuf->y; i++) {
+ if (*current_mask == FILTER_MASK_USED) {
+ float normalized_displacement;
+
+ if (max_distance > 1e-5f)
+ normalized_displacement = (*current_displacement + max_distance) / (max_distance * 2);
+ else
+ normalized_displacement = 0.5f;
+
+ if (ibuf->rect_float) {
+ /* currently baking happens to RGBA only */
+ float *fp = ibuf->rect_float + i * 4;
+ fp[0] = fp[1] = fp[2] = normalized_displacement;
+ fp[3] = 1.0f;
+ }
+
+ if (ibuf->rect) {
+ unsigned char *cp = (unsigned char *) (ibuf->rect + i);
+ cp[0] = cp[1] = cp[2] = FTOCHAR(normalized_displacement);
+ cp[3] = 255;
+ }
+ }
+
+ current_displacement++;
+ current_mask++;
+ }
+}
+
+/* using object selection tags, the faces with UV maps get baked */
+/* render should have been setup */
+/* returns 0 if nothing was handled */
+int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_update, float *progress)
+{
+ BakeShade *handles;
+ ListBase threads;
+ Image *ima;
+ int a, vdone = false, result = BAKE_RESULT_OK;
+ bool use_mask = false;
+ bool use_displacement_buffer = false;
+
+ re->scene_color_manage = BKE_scene_check_color_management_enabled(re->scene);
+
+ /* initialize render global */
+ R = *re;
+ R.bakebuf = NULL;
+
+ /* initialize static vars */
+ get_next_bake_face(NULL);
+
+ /* do we need a mask? */
+ if (re->r.bake_filter)
+ use_mask = true;
+
+ /* do we need buffer to store displacements */
+ if (type == RE_BAKE_DISPLACEMENT) {
+ if ((R.r.bake_flag & R_BAKE_NORMALIZE) && R.r.bake_maxdist == 0.0f) {
+ use_displacement_buffer = true;
+ use_mask = true;
+ }
+ }
+
+ /* baker uses this flag to detect if image was initialized */
+ if ((R.r.bake_flag & R_BAKE_VCOL) == 0) {
+ for (ima = G.main->image.first; ima; ima = ima->id.next) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ ima->id.flag |= LIB_DOIT;
+ ima->flag &= ~IMA_USED_FOR_RENDER;
+ if (ibuf) {
+ ibuf->userdata = NULL; /* use for masking if needed */
+ }
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+ }
+
+ BLI_init_threads(&threads, do_bake_thread, re->r.threads);
+
+ handles = MEM_callocN(sizeof(BakeShade) * re->r.threads, "BakeShade");
+
+ /* get the threads running */
+ for (a = 0; a < re->r.threads; a++) {
+ /* set defaults in handles */
+ handles[a].ssamp.shi[0].lay = re->lay;
+
+ if (type == RE_BAKE_SHADOW) {
+ handles[a].ssamp.shi[0].passflag = SCE_PASS_SHADOW;
+ }
+ else {
+ handles[a].ssamp.shi[0].passflag = SCE_PASS_COMBINED;
+ }
+ handles[a].ssamp.shi[0].combinedflag = ~(SCE_PASS_SPEC);
+ handles[a].ssamp.shi[0].thread = a;
+ handles[a].ssamp.tot = 1;
+
+ handles[a].type = type;
+ handles[a].actob = actob;
+ if (R.r.bake_flag & R_BAKE_VCOL)
+ handles[a].zspan = NULL;
+ else
+ handles[a].zspan = MEM_callocN(sizeof(ZSpan), "zspan for bake");
+
+ handles[a].use_mask = use_mask;
+ handles[a].use_displacement_buffer = use_displacement_buffer;
+
+ handles[a].do_update = do_update; /* use to tell the view to update */
+
+ handles[a].displacement_min = FLT_MAX;
+ handles[a].displacement_max = -FLT_MAX;
+
+ BLI_insert_thread(&threads, &handles[a]);
+ }
+
+ /* wait for everything to be done */
+ a = 0;
+ while (a != re->r.threads) {
+ PIL_sleep_ms(50);
+
+ /* calculate progress */
+ for (vdone = false, a = 0; a < re->r.threads; a++)
+ vdone += handles[a].vdone;
+ if (progress)
+ *progress = (float)(vdone / (float)re->totvlak);
+
+ for (a = 0; a < re->r.threads; a++) {
+ if (handles[a].ready == false) {
+ break;
+ }
+ }
+ }
+
+ /* filter and refresh images */
+ if ((R.r.bake_flag & R_BAKE_VCOL) == 0) {
+ float displacement_min = FLT_MAX, displacement_max = -FLT_MAX;
+
+ if (use_displacement_buffer) {
+ for (a = 0; a < re->r.threads; a++) {
+ displacement_min = min_ff(displacement_min, handles[a].displacement_min);
+ displacement_max = max_ff(displacement_max, handles[a].displacement_max);
+ }
+ }
+
+ for (ima = G.main->image.first; ima; ima = ima->id.next) {
+ if ((ima->id.flag & LIB_DOIT) == 0) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ BakeImBufuserData *userdata;
+
+ if (ima->flag & IMA_USED_FOR_RENDER)
+ result = BAKE_RESULT_FEEDBACK_LOOP;
+
+ if (!ibuf)
+ continue;
+
+ userdata = (BakeImBufuserData *) ibuf->userdata;
+ RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, re->r.bake_filter);
+
+ if (use_displacement_buffer) {
+ RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
+ displacement_min, displacement_max);
+ }
+
+ ibuf->userflags |= IB_BITMAPDIRTY;
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+ }
+
+ /* calculate return value */
+ for (a = 0; a < re->r.threads; a++) {
+ zbuf_free_span(handles[a].zspan);
+ MEM_freeN(handles[a].zspan);
+ }
+ }
+
+ MEM_freeN(handles);
+
+ BLI_end_threads(&threads);
+
+ if (vdone == 0) {
+ result = BAKE_RESULT_NO_OBJECTS;
+ }
+
+ return result;
+}
+
+struct Image *RE_bake_shade_get_image(void)
+{
+ return R.bakebuf;
+}
+
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 74aab678ea8..9e9dff63c04 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -153,6 +153,7 @@ static HaloRen *initstar(Render *re, ObjectRen *obr, const float vec[3], float h
har->hasize= hasize;
har->zd= 0.0;
+ har->pool = re->pool;
return har;
}
@@ -4853,7 +4854,7 @@ static int allow_render_dupli_instance(Render *UNUSED(re), DupliObject *dob, Obj
if (totmaterial) {
for (a= 0; a<*totmaterial; a++) {
- ma= give_current_material(obd, a);
+ ma= give_current_material(obd, a + 1);
if (ma && (ma->material_type == MA_TYPE_HALO))
return 0;
}
@@ -5165,8 +5166,8 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
* following calls don't depend on 'RE_SetCamera' */
RE_SetCamera(re, camera);
- normalize_m4(camera->obmat);
- invert_m4_m4(mat, camera->obmat);
+ normalize_m4_m4(mat, camera->obmat);
+ invert_m4(mat);
RE_SetView(re, mat);
camera->recalc= OB_RECALC_OB; /* force correct matrix for scaled cameras */
}
@@ -5315,8 +5316,8 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la
/* if no camera, viewmat should have been set! */
if (camera) {
- normalize_m4(camera->obmat);
- invert_m4_m4(mat, camera->obmat);
+ normalize_m4_m4(mat, camera->obmat);
+ invert_m4(mat);
RE_SetView(re, mat);
}
@@ -5855,8 +5856,8 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
/* if no camera, set unit */
if (camera) {
- normalize_m4(camera->obmat);
- invert_m4_m4(mat, camera->obmat);
+ normalize_m4_m4(mat, camera->obmat);
+ invert_m4(mat);
RE_SetView(re, mat);
}
else {
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index be8b7f6c357..9adae6f49ba 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -668,7 +668,7 @@ static void set_dxtdyt(float r_dxt[3], float r_dyt[3], const float dxt[3], const
/* ------------------------------------------------------------------------- */
-int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres)
+int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool)
{
extern Render R; /* only in this call */
/* texvec should be the already reflected normal */
@@ -687,12 +687,12 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
env->ima = tex->ima;
if (env->ima && env->ima->ok) {
if (env->cube[1] == NULL) {
- ImBuf *ibuf_ima = BKE_image_acquire_ibuf(env->ima, NULL, NULL);
+ ImBuf *ibuf_ima = BKE_image_pool_acquire_ibuf(env->ima, NULL, pool);
if (ibuf_ima)
envmap_split_ima(env, ibuf_ima);
else
env->ok = 0;
- BKE_image_release_ibuf(env->ima, ibuf_ima, NULL);
+ BKE_image_pool_release_ibuf(env->ima, ibuf_ima, pool);
}
}
}
@@ -720,7 +720,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
mul_mat3_m4_v3(R.viewinv, dyt);
}
set_dxtdyt(dxts, dyts, dxt, dyt, face);
- imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres);
+ imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres, pool);
/* edges? */
@@ -737,7 +737,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
if (face != face1) {
ibuf = env->cube[face1];
set_dxtdyt(dxts, dyts, dxt, dyt, face1);
- imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1);
+ imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1, pool);
}
else texr1.tr = texr1.tg = texr1.tb = texr1.ta = 0.0;
@@ -750,7 +750,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
if (face != face1) {
ibuf = env->cube[face1];
set_dxtdyt(dxts, dyts, dxt, dyt, face1);
- imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2);
+ imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2, pool);
}
else texr2.tr = texr2.tg = texr2.tb = texr2.ta = 0.0;
@@ -766,7 +766,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
}
}
else {
- imagewrap(tex, NULL, ibuf, sco, texres);
+ imagewrap(tex, NULL, ibuf, sco, texres, pool);
}
return 1;
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 296c8b6eba8..22a49bcbbc3 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -1,4 +1,5 @@
/*
+
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -128,9 +129,20 @@ int RE_engine_is_external(Render *re)
RenderEngine *RE_engine_create(RenderEngineType *type)
{
+ return RE_engine_create_ex(type, FALSE);
+}
+
+RenderEngine *RE_engine_create_ex(RenderEngineType *type, int use_for_viewport)
+{
RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine");
engine->type = type;
+ if (use_for_viewport) {
+ engine->flag |= RE_ENGINE_USED_FOR_VIEWPORT;
+
+ BLI_begin_threaded_malloc();
+ }
+
return engine;
}
@@ -142,6 +154,10 @@ void RE_engine_free(RenderEngine *engine)
}
#endif
+ if (engine->flag & RE_ENGINE_USED_FOR_VIEWPORT) {
+ BLI_end_threaded_malloc();
+ }
+
if (engine->text)
MEM_freeN(engine->text);
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index 4aaa6247478..0a427d57ebc 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -110,7 +110,7 @@ static void ibuf_get_color(float col[4], struct ImBuf *ibuf, int x, int y)
}
}
-int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres)
+int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres, struct ImagePool *pool)
{
float fx, fy, val1, val2, val3;
int x, y, retval;
@@ -130,13 +130,13 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
return retval;
- ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+ ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
ima->flag|= IMA_USED_FOR_RENDER;
}
if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
@@ -164,14 +164,14 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
}
else {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
if ((xs+ys) & 1) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
@@ -188,14 +188,14 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
if (tex->extend == TEX_CLIPCUBE) {
if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0f || texvec[2]>1.0f) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
else if ( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
@@ -302,10 +302,10 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
texres->tg*= fx;
texres->tb*= fx;
}
-
+
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
-
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
+
BRICONTRGB;
return retval;
@@ -1045,7 +1045,7 @@ static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
}
-static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[2], float dyt[2], TexResult *texres)
+static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[2], float dyt[2], TexResult *texres, struct ImagePool *pool)
{
TexResult texr;
float fx, fy, minx, maxx, miny, maxy;
@@ -1076,12 +1076,12 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
if (ima) { /* hack for icon render */
if ((ima->ibufs.first == NULL) && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval;
- ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+ ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
}
if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
@@ -1199,12 +1199,12 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
else {
if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
fx -= xs;
@@ -1224,14 +1224,14 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
if (tex->extend == TEX_CLIPCUBE) {
if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f || texvec[2] < -1.f || texvec[2] > 1.f) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
else if (tex->extend == TEX_CLIP || tex->extend == TEX_CHECKER) {
if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
@@ -1455,7 +1455,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
}
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
BRICONTRGB;
@@ -1463,7 +1463,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
}
-int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[2], const float DYT[2], TexResult *texres)
+int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[2], const float DYT[2], TexResult *texres, struct ImagePool *pool)
{
TexResult texr;
float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[2], dyt[2];
@@ -1477,7 +1477,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
/* anisotropic filtering */
if (tex->texfilter != TXF_BOX)
- return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres);
+ return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres, pool);
texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
@@ -1493,13 +1493,13 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
return retval;
- ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+ ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
ima->flag|= IMA_USED_FOR_RENDER;
}
if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
@@ -1608,14 +1608,14 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
}
else {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
if ((xs + ys) & 1) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
@@ -1652,14 +1652,14 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
if (tex->extend == TEX_CLIPCUBE) {
if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f || texvec[2]<-1.0f || texvec[2]>1.0f) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
else if (tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
@@ -1855,17 +1855,17 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
}
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
BRICONTRGB;
return retval;
}
-void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4])
+void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4], struct ImagePool *pool)
{
TexResult texres;
- ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, NULL, pool);
if (UNLIKELY(ibuf == NULL)) {
zero_v4(result);
@@ -1884,7 +1884,7 @@ void image_sample(Image *ima, float fx, float fy, float dx, float dy, float resu
ima->flag|= IMA_USED_FOR_RENDER;
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
}
void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4])
diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c
index 091ba9589d7..89f67335c39 100644
--- a/source/blender/render/intern/source/multires_bake.c
+++ b/source/blender/render/intern/source/multires_bake.c
@@ -60,14 +60,17 @@
#include "rayobject.h"
#include "rendercore.h"
-typedef void (*MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
- ImBuf *ibuf, const int face_index, const int lvl, const float st[2],
- float tangmat[3][3], const int x, const int y);
+typedef void (*MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *thread_data,
+ void *bake_data, ImBuf *ibuf, const int face_index, const int lvl,
+ const float st[2], float tangmat[3][3], const int x, const int y);
typedef void * (*MInitBakeData)(MultiresBakeRender *bkr, Image *ima);
-typedef void (*MApplyBakeData)(void *bake_data);
typedef void (*MFreeBakeData)(void *bake_data);
+typedef struct MultiresBakeResult {
+ float height_min, height_max;
+} MultiresBakeResult;
+
typedef struct {
MVert *mvert;
MFace *mface;
@@ -79,6 +82,7 @@ typedef struct {
int i0, i1, i2;
DerivedMesh *lores_dm, *hires_dm;
int lvl;
+ void *thread_data;
void *bake_data;
ImBuf *ibuf;
MPassKnownData pass_data;
@@ -95,7 +99,6 @@ typedef struct {
typedef struct {
float *heights;
- float height_min, height_max;
Image *ima;
DerivedMesh *ssdm;
const int *orig_index_mf_to_mpoly;
@@ -161,9 +164,11 @@ static void multiresbake_get_normal(const MResolvePixelData *data, float norm[],
static void init_bake_rast(MBakeRast *bake_rast, const ImBuf *ibuf, const MResolvePixelData *data, MFlushPixel flush_pixel)
{
+ BakeImBufuserData *userdata = (BakeImBufuserData *) ibuf->userdata;
+
memset(bake_rast, 0, sizeof(MBakeRast));
- bake_rast->texels = ibuf->userdata;
+ bake_rast->texels = userdata->mask_buffer;
bake_rast->w = ibuf->x;
bake_rast->h = ibuf->y;
bake_rast->data = data;
@@ -222,7 +227,7 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
zero_m3(to_tang);
}
- data->pass_data(data->lores_dm, data->hires_dm, data->bake_data,
+ data->pass_data(data->lores_dm, data->hires_dm, data->thread_data, data->bake_data,
data->ibuf, data->face_index, data->lvl, st, to_tang, x, y);
}
@@ -348,6 +353,9 @@ typedef struct MultiresBakeThread {
/* thread-specific data */
MBakeRast bake_rast;
MResolvePixelData data;
+
+ /* displacement-specific data */
+ float height_min, height_max;
} MultiresBakeThread;
static int multires_bake_queue_next_face(MultiresBakeQueue *queue)
@@ -428,8 +436,29 @@ static void *do_multires_bake_thread(void *data_v)
return NULL;
}
+/* some of arrays inside ccgdm are lazy-initialized, which will generally
+ * require lock around accessing such data
+ * this function will ensure all arrays are allocated before threading started
+ */
+static void init_ccgdm_arrays(DerivedMesh *dm)
+{
+ CCGElem **grid_data;
+ CCGKey key;
+ int grid_size;
+ int *grid_offset;
+
+ grid_size = dm->getGridSize(dm);
+ grid_data = dm->getGridData(dm);
+ grid_offset = dm->getGridOffset(dm);
+ dm->getGridKey(dm, &key);
+
+ (void) grid_size;
+ (void) grid_data;
+ (void) grid_offset;
+}
+
static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, int require_tangent, MPassKnownData passKnownData,
- MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData)
+ MInitBakeData initBakeData, MFreeBakeData freeBakeData, MultiresBakeResult *result)
{
DerivedMesh *dm = bkr->lores_dm;
const int lvl = bkr->lvl;
@@ -467,6 +496,8 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, int require_ta
handles = MEM_callocN(tot_thread * sizeof(MultiresBakeThread), "do_multires_bake handles");
+ init_ccgdm_arrays(bkr->hires_dm);
+
/* faces queue */
queue.cur_face = 0;
queue.tot_face = tot_face;
@@ -491,9 +522,13 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, int require_ta
handle->data.hires_dm = bkr->hires_dm;
handle->data.lvl = lvl;
handle->data.pass_data = passKnownData;
+ handle->data.thread_data = handle;
handle->data.bake_data = bake_data;
handle->data.ibuf = ibuf;
+ handle->height_min = FLT_MAX;
+ handle->height_max = -FLT_MAX;
+
init_bake_rast(&handle->bake_rast, ibuf, &handle->data, flush_pixel);
if (tot_thread > 1)
@@ -506,15 +541,23 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, int require_ta
else
do_multires_bake_thread(&handles[0]);
+ /* construct bake result */
+ result->height_min = handles[0].height_min;
+ result->height_max = handles[0].height_max;
+
+ for (i = 1; i < tot_thread; i++) {
+ result->height_min = min_ff(result->height_min, handles[i].height_min);
+ result->height_max = max_ff(result->height_max, handles[i].height_max);
+ }
+
BLI_spin_end(&queue.spin);
/* finalize baking */
- if (applyBakeData)
- applyBakeData(bake_data);
-
if (freeBakeData)
freeBakeData(bake_data);
+ MEM_freeN(handles);
+
BKE_image_release_ibuf(ima, ibuf, NULL);
}
}
@@ -651,13 +694,15 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima)
MHeightBakeData *height_data;
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
DerivedMesh *lodm = bkr->lores_dm;
+ BakeImBufuserData *userdata = ibuf->userdata;
+
+ if (userdata->displacement_buffer == NULL)
+ userdata->displacement_buffer = MEM_callocN(sizeof(float) * ibuf->x * ibuf->y, "MultiresBake heights");
height_data = MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData");
height_data->ima = ima;
- height_data->heights = MEM_callocN(sizeof(float) * ibuf->x * ibuf->y, "MultiresBake heights");
- height_data->height_max = -FLT_MAX;
- height_data->height_min = FLT_MAX;
+ height_data->heights = userdata->displacement_buffer;
if (!bkr->use_lores_mesh) {
SubsurfModifierData smd = {{NULL}};
@@ -673,6 +718,7 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima)
smd.subdivType = ME_SIMPLE_SUBSURF;
height_data->ssdm = subsurf_make_derived_from_derived(bkr->lores_dm, &smd, NULL, 0);
+ init_ccgdm_arrays(height_data->ssdm);
}
}
@@ -684,48 +730,6 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima)
return (void *)height_data;
}
-static void apply_heights_data(void *bake_data)
-{
- MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
- ImBuf *ibuf = BKE_image_acquire_ibuf(height_data->ima, NULL, NULL);
- int x, y, i;
- float height, *heights = height_data->heights;
- float min = height_data->height_min, max = height_data->height_max;
-
- for (x = 0; x < ibuf->x; x++) {
- for (y = 0; y < ibuf->y; y++) {
- i = ibuf->x * y + x;
-
- if (((char *)ibuf->userdata)[i] != FILTER_MASK_USED)
- continue;
-
- if (ibuf->rect_float) {
- float *rrgbf = ibuf->rect_float + i * 4;
-
- if (max - min > 1e-5f) height = (heights[i] - min) / (max - min);
- else height = 0;
-
- rrgbf[0] = rrgbf[1] = rrgbf[2] = height;
- }
- else {
- char *rrgb = (char *)ibuf->rect + i * 4;
-
- if (max - min > 1e-5f) height = (heights[i] - min) / (max - min);
- else height = 0;
-
- rrgb[0] = rrgb[1] = rrgb[2] = FTOCHAR(height);
- }
- }
- }
-
- if (ibuf->rect_float)
- ibuf->userflags |= IB_RECT_INVALID;
-
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
-
- BKE_image_release_ibuf(height_data->ima, ibuf, NULL);
-}
-
static void free_heights_data(void *bake_data)
{
MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
@@ -733,7 +737,6 @@ static void free_heights_data(void *bake_data)
if (height_data->ssdm)
height_data->ssdm->release(height_data->ssdm);
- MEM_freeN(height_data->heights);
MEM_freeN(height_data);
}
@@ -743,13 +746,14 @@ static void free_heights_data(void *bake_data)
* - find coord of point and normal with specified UV in lo-res mesh (or subdivided lo-res
* mesh to make texture smoother) let's call this point p0 and n.
* - height wound be dot(n, p1-p0) */
-static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
+static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *thread_data_v, void *bake_data,
ImBuf *ibuf, const int face_index, const int lvl, const float st[2],
float UNUSED(tangmat[3][3]), const int x, const int y)
{
MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
MFace mface;
MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
+ MultiresBakeThread *thread_data = (MultiresBakeThread *) thread_data_v;
float uv[2], *st0, *st1, *st2, *st3;
int pixel = ibuf->x * y + x;
float vec[3], p0[3], p1[3], n[3], len;
@@ -771,12 +775,12 @@ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm,
CLAMP(uv[1], 0.0f, 1.0f);
get_ccgdm_data(lores_dm, hires_dm,
- height_data->orig_index_mf_to_mpoly, height_data->orig_index_mf_to_mpoly,
+ height_data->orig_index_mf_to_mpoly, height_data->orig_index_mp_to_orig,
lvl, face_index, uv[0], uv[1], p1, 0);
if (height_data->ssdm) {
get_ccgdm_data(lores_dm, height_data->ssdm,
- height_data->orig_index_mf_to_mpoly, height_data->orig_index_mf_to_mpoly,
+ height_data->orig_index_mf_to_mpoly, height_data->orig_index_mp_to_orig,
0, face_index, uv[0], uv[1], p0, n);
}
else {
@@ -796,15 +800,18 @@ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm,
len = dot_v3v3(n, vec);
height_data->heights[pixel] = len;
- if (len < height_data->height_min) height_data->height_min = len;
- if (len > height_data->height_max) height_data->height_max = len;
+
+ thread_data->height_min = min_ff(thread_data->height_min, len);
+ thread_data->height_max = max_ff(thread_data->height_max, len);
if (ibuf->rect_float) {
float *rrgbf = ibuf->rect_float + pixel * 4;
+ rrgbf[0] = rrgbf[1] = rrgbf[2] = len;
rrgbf[3] = 1.0f;
}
else {
char *rrgb = (char *)ibuf->rect + pixel * 4;
+ rrgb[0] = rrgb[1] = rrgb[2] = FTOCHAR(len);
rrgb[3] = 255;
}
}
@@ -836,9 +843,9 @@ static void free_normal_data(void *bake_data)
* - find coord and normal of point with specified UV in hi-res mesh
* - multiply it by tangmat
* - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */
-static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
- ImBuf *ibuf, const int face_index, const int lvl, const float st[2],
- float tangmat[3][3], const int x, const int y)
+static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *UNUSED(thread_data),
+ void *bake_data, ImBuf *ibuf, const int face_index, const int lvl,
+ const float st[2], float tangmat[3][3], const int x, const int y)
{
MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
MFace mface;
@@ -1073,9 +1080,9 @@ static int trace_ao_ray(MAOBakeData *ao_data, float ray_start[3], float ray_dire
return RE_rayobject_raycast(ao_data->raytree, &isect);
}
-static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
- ImBuf *ibuf, const int face_index, const int lvl, const float st[2],
- float UNUSED(tangmat[3][3]), const int x, const int y)
+static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *UNUSED(thread_data),
+ void *bake_data, ImBuf *ibuf, const int face_index, const int lvl,
+ const float st[2], float UNUSED(tangmat[3][3]), const int x, const int y)
{
MAOBakeData *ao_data = (MAOBakeData *) bake_data;
MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
@@ -1205,7 +1212,7 @@ static void count_images(MultiresBakeRender *bkr)
mtface[a].tpage->id.flag &= ~LIB_DOIT;
}
-static void bake_images(MultiresBakeRender *bkr)
+static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
{
LinkData *link;
@@ -1214,18 +1221,19 @@ static void bake_images(MultiresBakeRender *bkr)
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
if (ibuf->x > 0 && ibuf->y > 0) {
- ibuf->userdata = MEM_callocN(ibuf->y * ibuf->x, "MultiresBake imbuf mask");
+ BakeImBufuserData *userdata = MEM_callocN(sizeof(BakeImBufuserData), "MultiresBake userdata");
+ userdata->mask_buffer = MEM_callocN(ibuf->y * ibuf->x, "MultiresBake imbuf mask");
+ ibuf->userdata = userdata;
switch (bkr->mode) {
case RE_BAKE_NORMALS:
- do_multires_bake(bkr, ima, TRUE, apply_tangmat_callback, init_normal_data, NULL, free_normal_data);
+ do_multires_bake(bkr, ima, TRUE, apply_tangmat_callback, init_normal_data, free_normal_data, result);
break;
case RE_BAKE_DISPLACEMENT:
- do_multires_bake(bkr, ima, FALSE, apply_heights_callback, init_heights_data,
- apply_heights_data, free_heights_data);
+ do_multires_bake(bkr, ima, FALSE, apply_heights_callback, init_heights_data, free_heights_data, result);
break;
case RE_BAKE_AO:
- do_multires_bake(bkr, ima, FALSE, apply_ao_callback, init_ao_data, NULL, free_ao_data);
+ do_multires_bake(bkr, ima, FALSE, apply_ao_callback, init_ao_data, free_ao_data, result);
break;
}
}
@@ -1236,18 +1244,25 @@ static void bake_images(MultiresBakeRender *bkr)
}
}
-static void finish_images(MultiresBakeRender *bkr)
+static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
{
LinkData *link;
+ int use_displacement_buffer = bkr->mode == RE_BAKE_DISPLACEMENT;
for (link = bkr->image.first; link; link = link->next) {
Image *ima = (Image *)link->data;
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ BakeImBufuserData *userdata = (BakeImBufuserData *) ibuf->userdata;
if (ibuf->x <= 0 || ibuf->y <= 0)
continue;
- RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, bkr->bake_filter);
+ RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter);
+
+ if (use_displacement_buffer) {
+ RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
+ result->height_min, result->height_max);
+ }
ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;
@@ -1260,7 +1275,11 @@ static void finish_images(MultiresBakeRender *bkr)
}
if (ibuf->userdata) {
- MEM_freeN(ibuf->userdata);
+ if (userdata->displacement_buffer)
+ MEM_freeN(userdata->displacement_buffer);
+
+ MEM_freeN(userdata->mask_buffer);
+ MEM_freeN(userdata);
ibuf->userdata = NULL;
}
@@ -1270,7 +1289,9 @@ static void finish_images(MultiresBakeRender *bkr)
void RE_multires_bake_images(MultiresBakeRender *bkr)
{
+ MultiresBakeResult result;
+
count_images(bkr);
- bake_images(bkr);
- finish_images(bkr);
+ bake_images(bkr, &result);
+ finish_images(bkr, &result);
}
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index e37b24b13a4..866932632c2 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -474,7 +474,7 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *
re->recty = winy;
}
- if (re->rectx < 2 || re->recty < 2 || (BKE_imtype_is_movie(rd->im_format.imtype) &&
+ if (re->rectx < 1 || re->recty < 1 || (BKE_imtype_is_movie(rd->im_format.imtype) &&
(re->rectx < 16 || re->recty < 16) ))
{
BKE_report(re->reports, RPT_ERROR, "Image too small");
@@ -1879,6 +1879,8 @@ static void do_render_all_options(Render *re)
/* ensure no images are in memory from previous animated sequences */
BKE_image_all_free_anim_ibufs(re->r.cfra);
+ re->pool = BKE_image_pool_new();
+
if (RE_engine_render(re, 1)) {
/* in this case external render overrides all */
}
@@ -1903,6 +1905,9 @@ static void do_render_all_options(Render *re)
renderresult_stampinfo(re);
re->display_draw(re->ddh, re->result, NULL);
}
+
+ BKE_image_pool_free(re->pool);
+ re->pool = NULL;
}
static int check_valid_camera(Scene *scene, Object *camera_override)
@@ -2488,6 +2493,8 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
RE_InitState(re, NULL, &sce->r, NULL, winx, winy, NULL);
+ re->pool = BKE_image_pool_new();
+
re->main = bmain;
re->scene = sce;
re->scene_color_manage = BKE_scene_check_color_management_enabled(sce);
@@ -2497,6 +2504,9 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
RE_SetCamera(re, camera);
do_render_3d(re);
+
+ BKE_image_pool_free(re->pool);
+ re->pool = NULL;
}
/* note; repeated win/disprect calc... solve that nicer, also in compo */
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index e3bfd535f11..3ea94981cac 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -1099,7 +1099,7 @@ static void do_2d_mapping(MTex *mtex, float texvec[3], VlakRen *vlr, const float
/* ************************************** */
-static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, short which_output)
+static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, short which_output, struct ImagePool *pool)
{
float tmpvec[3];
int retval = 0; /* return value, int:0, col:1, nor:2, everything:3 */
@@ -1137,12 +1137,12 @@ static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int o
retval = texnoise(tex, texres);
break;
case TEX_IMAGE:
- if (osatex) retval = imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres);
- else retval = imagewrap(tex, tex->ima, NULL, texvec, texres);
+ if (osatex) retval = imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres, pool);
+ else retval = imagewrap(tex, tex->ima, NULL, texvec, texres, pool);
BKE_image_tag_time(tex->ima); /* tag image as having being used */
break;
case TEX_ENVMAP:
- retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres);
+ retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres, pool);
break;
case TEX_MUSGRAVE:
/* newnoise: musgrave types */
@@ -1214,7 +1214,7 @@ static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int o
/* this is called from the shader and texture nodes */
int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres,
- const short thread, short which_output, ShadeInput *shi, MTex *mtex)
+ const short thread, short which_output, ShadeInput *shi, MTex *mtex, struct ImagePool *pool)
{
if (tex==NULL) {
memset(texres, 0, sizeof(TexResult));
@@ -1230,16 +1230,16 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os
if (mtex) {
/* we have mtex, use it for 2d mapping images only */
do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt);
- rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output);
+ rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool);
if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
/* don't linearize float buffers, assumed to be linear */
if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace);
- BKE_image_release_ibuf(tex->ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
}
}
else {
@@ -1263,28 +1263,28 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os
}
do_2d_mapping(&localmtex, texvec_l, NULL, NULL, dxt_l, dyt_l);
- rgbnor= multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output);
+ rgbnor = multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output, pool);
{
- ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
/* don't linearize float buffers, assumed to be linear */
if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace);
- BKE_image_release_ibuf(tex->ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
}
}
return rgbnor;
}
else {
- return multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output);
+ return multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool);
}
}
/* this is called for surface shading */
-static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt[3], float dyt[3], TexResult *texres)
+static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt[3], float dyt[3], TexResult *texres, struct ImagePool *pool)
{
Tex *tex = mtex->tex;
@@ -1295,24 +1295,24 @@ static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt
tex, mtex->which_output, R.r.cfra, (R.r.scemode & R_TEXNODE_PREVIEW) != 0, shi, mtex);
}
else {
- return multitex(mtex->tex, texvec, dxt, dyt, shi->osatex, texres, shi->thread, mtex->which_output);
+ return multitex(mtex->tex, texvec, dxt, dyt, shi->osatex, texres, shi->thread, mtex->which_output, pool);
}
}
/* Warning, if the texres's values are not declared zero, check the return value to be sure
* the color values are set before using the r/g/b values, otherwise you may use uninitialized values - Campbell */
-int multitex_ext(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres)
+int multitex_ext(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool)
{
- return multitex_nodes(tex, texvec, dxt, dyt, osatex, texres, 0, 0, NULL, NULL);
+ return multitex_nodes(tex, texvec, dxt, dyt, osatex, texres, 0, 0, NULL, NULL, pool);
}
/* extern-tex doesn't support nodes (ntreeBeginExec() can't be called when rendering is going on) */
-int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres)
+int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct ImagePool *pool)
{
int use_nodes= tex->use_nodes, retval;
tex->use_nodes = FALSE;
- retval= multitex_nodes(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL);
+ retval= multitex_nodes(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL, pool);
tex->use_nodes= use_nodes;
return retval;
@@ -1699,7 +1699,8 @@ static void compatible_bump_uv_derivs(CompatibleBump *compat_bump, ShadeInput *s
}
static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres,
- float Tnor, const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3])
+ float Tnor, const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3],
+ struct ImagePool *pool)
{
TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */
float tco[3], texv[3], cd, ud, vd, du, dv, idu, idv;
@@ -1727,12 +1728,12 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
if (!shi->osatex && (tex->type == TEX_IMAGE) && tex->ima) {
/* in case we have no proper derivatives, fall back to
* computing du/dv it based on image size */
- ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
if (ibuf) {
du = 1.f/(float)ibuf->x;
dv = 1.f/(float)ibuf->y;
}
- BKE_image_release_ibuf(tex->ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
}
else if (shi->osatex) {
/* we have derivatives, can compute proper du/dv */
@@ -1752,7 +1753,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
/* center, main return value */
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool);
cd = fromrgb ? (texres->tr + texres->tg + texres->tb)*0.33333333f : texres->tin;
if (mtex->texco == TEXCO_UV) {
@@ -1766,7 +1767,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
tco[1] = co[1] + compat_bump->dvdnu*du;
tco[2] = 0.f;
texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
- multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr);
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin));
/* +v val */
@@ -1774,7 +1775,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
tco[1] = co[1] + compat_bump->dvdnv*du;
tco[2] = 0.f;
texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
- multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr);
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
vd = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin));
}
else {
@@ -1808,7 +1809,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
tco[1] = co[1] + tu[1]*du;
tco[2] = co[2] + tu[2]*du;
texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
- multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr);
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin));
/* +v val */
@@ -1816,7 +1817,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
tco[1] = co[1] + tv[1]*dv;
tco[2] = co[2] + tv[2]*dv;
texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
- multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr);
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
vd = idv*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin));
}
@@ -1858,7 +1859,7 @@ static void ntap_bump_init(NTapBump *ntap_bump)
static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres,
float Tnor, const float co[3], const float dx[3], const float dy[3],
- float texvec[3], float dxt[3], float dyt[3])
+ float texvec[3], float dxt[3], float dyt[3], struct ImagePool *pool)
{
TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */
@@ -1905,20 +1906,20 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
/* resolve image dimensions */
if (found_deriv_map || (mtex->texflag&MTEX_BUMP_TEXTURESPACE)!=0) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
if (ibuf) {
dimx = ibuf->x;
dimy = ibuf->y;
aspect = ((float) dimy) / dimx;
}
- BKE_image_release_ibuf(tex->ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
}
if (found_deriv_map) {
float dBdu, dBdv, auto_bump = 1.0f;
float s = 1; /* negate this if flipped texture coordinate */
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool);
if (shi->obr->ob->derivedFinal) {
auto_bump = shi->obr->ob->derivedFinal->auto_bump_scale;
@@ -1960,14 +1961,14 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
}
/* use texres for the center sample, set rgbnor */
- rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres);
+ rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres, pool);
Hll = (fromrgb) ? rgb_to_grayscale(&texres->tr) : texres->tin;
/* use ttexr for the other 2 taps */
- multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr);
+ multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr, pool);
Hlr = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
- multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr);
+ multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr, pool);
Hul = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
dHdx = Hscale*(Hlr - Hll);
@@ -1998,17 +1999,17 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
}
/* use texres for the center sample, set rgbnor */
- rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres);
+ rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres, pool);
/* Hc = (fromrgb) ? rgb_to_grayscale(&texres->tr) : texres->tin; */ /* UNUSED */
/* use ttexr for the other taps */
- multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr);
+ multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr, pool);
Hl = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
- multitex_mtex(shi, mtex, STr, dxt, dyt, &ttexr);
+ multitex_mtex(shi, mtex, STr, dxt, dyt, &ttexr, pool);
Hr = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
- multitex_mtex(shi, mtex, STd, dxt, dyt, &ttexr);
+ multitex_mtex(shi, mtex, STd, dxt, dyt, &ttexr, pool);
Hd = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
- multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr);
+ multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr, pool);
Hu = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
dHdx = Hscale*(Hr - Hl);
@@ -2285,20 +2286,22 @@ void do_material_tex(ShadeInput *shi, Render *re)
if (texres.nor && !((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP))) {
if (use_compat_bump) {
rgbnor = compatible_bump_compute(&compat_bump, shi, mtex, tex,
- &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt);
+ &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt,
+ re->pool);
}
else if (use_ntap_bump) {
rgbnor = ntap_bump_compute(&ntap_bump, shi, mtex, tex,
- &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt);
+ &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt,
+ re->pool);
}
else {
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool);
}
}
else {
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool);
}
/* texture output */
@@ -2402,13 +2405,13 @@ void do_material_tex(ShadeInput *shi, Render *re)
/* inverse gamma correction */
if (tex->type==TEX_IMAGE) {
Image *ima = tex->ima;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, re->pool);
/* don't linearize float buffers, assumed to be linear */
if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, re->pool);
}
if (mtex->mapto & MAP_COL) {
@@ -2737,7 +2740,7 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_
else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
}
- rgbnor= multitex(tex, texvec, NULL, NULL, 0, &texres, 0, mtex->which_output); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
+ rgbnor = multitex(tex, texvec, NULL, NULL, 0, &texres, 0, mtex->which_output, re->pool); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
/* texture output */
@@ -2904,7 +2907,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
if (mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
- rgb= multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres, 0, mtex->which_output);
+ rgb = multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres, 0, mtex->which_output, har->pool);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -2936,13 +2939,13 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
/* inverse gamma correction */
if (mtex->tex->type==TEX_IMAGE) {
Image *ima = mtex->tex->ima;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &mtex->tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &mtex->tex->iuser, har->pool);
/* don't linearize float buffers, assumed to be linear */
if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, har->pool);
}
fact= texres.tin*mtex->colfac;
@@ -3109,7 +3112,7 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
/* texture */
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);
+ rgb = multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output, R.pool);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -3157,13 +3160,13 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
/* inverse gamma correction */
if (tex->type==TEX_IMAGE) {
Image *ima = tex->ima;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, R.pool);
/* don't linearize float buffers, assumed to be linear */
if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, R.pool);
}
if (mtex->mapto & WOMAP_HORIZ) {
@@ -3324,7 +3327,7 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
}
- rgb= multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output);
+ rgb = multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output, R.pool);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -3373,13 +3376,13 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
/* inverse gamma correction */
if (tex->type==TEX_IMAGE) {
Image *ima = tex->ima;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, R.pool);
/* don't linearize float buffers, assumed to be linear */
if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, R.pool);
}
/* lamp colors were premultiplied with this */
@@ -3395,7 +3398,7 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
/* ------------------------------------------------------------------------- */
-int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread)
+int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool)
{
Tex *tex;
TexResult texr;
@@ -3421,7 +3424,7 @@ int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg,
do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
}
- rgb= multitex(tex, texvec, dxt, dyt, 0, &texr, thread, mtex->which_output);
+ rgb = multitex(tex, texvec, dxt, dyt, 0, &texr, thread, mtex->which_output, pool);
if (rgb) {
texr.tin = rgb_to_bw(&texr.tr);
@@ -3485,8 +3488,8 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
texr.nor= NULL;
- if (shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr);
- else imagewrap(tex, ima, NULL, texvec, &texr);
+ if (shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr, R.pool);
+ else imagewrap(tex, ima, NULL, texvec, &texr, R.pool);
shi->vcol[0]*= texr.tr;
shi->vcol[1]*= texr.tg;
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 14586f16478..2d0f575b3e3 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -20,7 +20,6 @@
*
* Contributors: Hos, Robert Wenzlaff.
* Contributors: 2004/2005/2006 Blender Foundation, full recode
- * Contributors: Vertex color baking, Copyright 2011 AutoCRC
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -1139,7 +1138,7 @@ static void addAlphaOverFloatMask(float *dest, float *source, unsigned short dma
dest[3]+= source[3];
return;
- }
+ }
dest[0]= (mul*dest[0]) + source[0];
dest[1]= (mul*dest[1]) + source[1];
@@ -1991,932 +1990,3 @@ void add_halo_flare(Render *re)
R.r.mode= mode;
}
-/* ************************* bake ************************ */
-
-
-typedef struct BakeShade {
- ShadeSample ssamp;
- ObjectInstanceRen *obi;
- VlakRen *vlr;
-
- ZSpan *zspan;
- Image *ima;
- ImBuf *ibuf;
-
- int rectx, recty, quad, type, vdone, ready;
-
- float dir[3];
- Object *actob;
-
- /* Output: vertex color or image data. If vcol is not NULL, rect and
- * rect_float should be NULL. */
- MPoly *mpoly;
- MLoop *mloop;
- MLoopCol *vcol;
-
- unsigned int *rect;
- float *rect_float;
-
- int use_mask;
- char *rect_mask; /* bake pixel mask */
-
- float dxco[3], dyco[3];
-
- short *do_update;
-
- struct ColorSpace *rect_colorspace;
-} BakeShade;
-
-static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int UNUSED(isect), int x, int y, float u, float v)
-{
- if (quad)
- shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3);
- else
- shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
-
- /* cache for shadow */
- shi->samplenr= R.shadowsamplenr[shi->thread]++;
-
- shi->mask= 0xFFFF; /* all samples */
-
- shi->u= -u;
- shi->v= -v;
- shi->xs= x;
- shi->ys= y;
-
- shade_input_set_uv(shi);
- shade_input_set_normals(shi);
-
- /* no normal flip */
- if (shi->flippednor)
- shade_input_flip_normals(shi);
-
- /* set up view vector to look right at the surface (note that the normal
- * is negated in the renderer so it does not need to be done here) */
- shi->view[0]= shi->vn[0];
- shi->view[1]= shi->vn[1];
- shi->view[2]= shi->vn[2];
-}
-
-static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(quad), int x, int y, float UNUSED(u), float UNUSED(v), float *tvn, float *ttang)
-{
- BakeShade *bs= handle;
- ShadeSample *ssamp= &bs->ssamp;
- ShadeResult shr;
- VlakRen *vlr= shi->vlr;
-
- shade_input_init_material(shi);
-
- if (bs->type==RE_BAKE_AO) {
- ambient_occlusion(shi);
-
- if (R.r.bake_flag & R_BAKE_NORMALIZE) {
- copy_v3_v3(shr.combined, shi->ao);
- }
- else {
- zero_v3(shr.combined);
- environment_lighting_apply(shi, &shr);
- }
- }
- else {
- if (bs->type==RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */
- shi->r = shi->g = shi->b = 1.0f;
-
- shade_input_set_shade_texco(shi);
-
- /* only do AO for a full bake (and obviously AO bakes)
- * AO for light bakes is a leftover and might not be needed */
- if ( ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT))
- shade_samples_do_AO(ssamp);
-
- if (shi->mat->nodetree && shi->mat->use_nodes) {
- ntreeShaderExecTree(shi->mat->nodetree, shi, &shr);
- shi->mat= vlr->mat; /* shi->mat is being set in nodetree */
- }
- else
- shade_material_loop(shi, &shr);
-
- if (bs->type==RE_BAKE_NORMALS) {
- float nor[3];
-
- copy_v3_v3(nor, shi->vn);
-
- if (R.r.bake_normal_space == R_BAKE_SPACE_CAMERA) {
- /* pass */
- }
- else if (R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) {
- float mat[3][3], imat[3][3];
-
- /* bitangent */
- if (tvn && ttang) {
- copy_v3_v3(mat[0], ttang);
- cross_v3_v3v3(mat[1], tvn, ttang);
- mul_v3_fl(mat[1], ttang[3]);
- copy_v3_v3(mat[2], tvn);
- }
- else {
- copy_v3_v3(mat[0], shi->nmaptang);
- cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang);
- mul_v3_fl(mat[1], shi->nmaptang[3]);
- copy_v3_v3(mat[2], shi->nmapnorm);
- }
-
- invert_m3_m3(imat, mat);
- mul_m3_v3(imat, nor);
- }
- else if (R.r.bake_normal_space == R_BAKE_SPACE_OBJECT)
- mul_mat3_m4_v3(ob->imat_ren, nor); /* ob->imat_ren includes viewinv! */
- else if (R.r.bake_normal_space == R_BAKE_SPACE_WORLD)
- mul_mat3_m4_v3(R.viewinv, nor);
-
- normalize_v3(nor); /* in case object has scaling */
-
- /* The invert of the red channel is to make
- * the normal map compliant with the outside world.
- * It needs to be done because in Blender
- * the normal used in the renderer points inward. It is generated
- * this way in calc_vertexnormals(). Should this ever change
- * this negate must be removed. */
- shr.combined[0]= (-nor[0])/2.0f + 0.5f;
- shr.combined[1]= nor[1]/2.0f + 0.5f;
- shr.combined[2]= nor[2]/2.0f + 0.5f;
- }
- else if (bs->type==RE_BAKE_TEXTURE) {
- shr.combined[0]= shi->r;
- shr.combined[1]= shi->g;
- shr.combined[2]= shi->b;
- shr.alpha = shi->alpha;
- }
- else if (bs->type==RE_BAKE_SHADOW) {
- copy_v3_v3(shr.combined, shr.shad);
- shr.alpha = shi->alpha;
- }
- else if (bs->type==RE_BAKE_SPEC_COLOR) {
- shr.combined[0]= shi->specr;
- shr.combined[1]= shi->specg;
- shr.combined[2]= shi->specb;
- shr.alpha = 1.0f;
- }
- else if (bs->type==RE_BAKE_SPEC_INTENSITY) {
- shr.combined[0]=
- shr.combined[1]=
- shr.combined[2]= shi->spec;
- shr.alpha = 1.0f;
- }
- else if (bs->type==RE_BAKE_MIRROR_COLOR) {
- shr.combined[0]= shi->mirr;
- shr.combined[1]= shi->mirg;
- shr.combined[2]= shi->mirb;
- shr.alpha = 1.0f;
- }
- else if (bs->type==RE_BAKE_MIRROR_INTENSITY) {
- shr.combined[0]=
- shr.combined[1]=
- shr.combined[2]= shi->ray_mirror;
- shr.alpha = 1.0f;
- }
- else if (bs->type==RE_BAKE_ALPHA) {
- shr.combined[0]=
- shr.combined[1]=
- shr.combined[2]= shi->alpha;
- shr.alpha = 1.0f;
- }
- else if (bs->type==RE_BAKE_EMIT) {
- shr.combined[0]=
- shr.combined[1]=
- shr.combined[2]= shi->emit;
- shr.alpha = 1.0f;
- }
- }
-
- if (bs->rect_float && !bs->vcol) {
- float *col= bs->rect_float + 4*(bs->rectx*y + x);
- copy_v3_v3(col, shr.combined);
- if (bs->type==RE_BAKE_ALL || bs->type==RE_BAKE_TEXTURE) {
- col[3]= shr.alpha;
- }
- else {
- col[3]= 1.0;
- }
- }
- else {
- /* Target is char (LDR). */
- unsigned char col[4];
-
- if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
- float rgb[3];
-
- copy_v3_v3(rgb, shr.combined);
- if (R.scene_color_manage)
- IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace);
- rgb_float_to_uchar(col, rgb);
- }
- else {
- rgb_float_to_uchar(col, shr.combined);
- }
-
- if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
- col[3]= FTOCHAR(shr.alpha);
- }
- else {
- col[3]= 255;
- }
-
- if (bs->vcol) {
- /* Vertex colour baking. Vcol has no useful alpha channel (it exists
- * but is used only for vertex painting). */
- bs->vcol->r = col[0];
- bs->vcol->g = col[1];
- bs->vcol->b = col[2];
- }
- else {
- unsigned char *imcol= (unsigned char *)(bs->rect + bs->rectx*y + x);
- copy_v4_v4_char((char *)imcol, (char *)col);
- }
-
- }
-
- if (bs->rect_mask) {
- bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED;
- }
-}
-
-static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist, int x, int y)
-{
- BakeShade *bs= handle;
- float disp;
-
- if (R.r.bake_flag & R_BAKE_NORMALIZE && R.r.bake_maxdist) {
- disp = (dist+R.r.bake_maxdist) / (R.r.bake_maxdist*2); /* alter the range from [-bake_maxdist, bake_maxdist] to [0, 1]*/
- }
- else {
- disp = 0.5f + dist; /* alter the range from [-0.5,0.5] to [0,1]*/
- }
-
- if (bs->rect_float && !bs->vcol) {
- float *col= bs->rect_float + 4*(bs->rectx*y + x);
- col[0] = col[1] = col[2] = disp;
- col[3]= 1.0f;
- }
- else {
- /* Target is char (LDR). */
- unsigned char col[4];
- col[0] = col[1] = col[2] = FTOCHAR(disp);
- col[3] = 255;
-
- if(bs->vcol) {
- /* Vertex colour baking. Vcol has no useful alpha channel (it exists
- * but is used only for vertex painting). */
- bs->vcol->r = col[0];
- bs->vcol->g = col[1];
- bs->vcol->b = col[2];
- }
- else {
- char *imcol= (char *)(bs->rect + bs->rectx*y + x);
- copy_v4_v4_char((char *)imcol, (char *)col);
- }
- }
- if (bs->rect_mask) {
- bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED;
- }
-}
-
-static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, float *dir, float sign, float *hitco, float *dist)
-{
- float maxdist;
- int hit;
-
- /* might be useful to make a user setting for maxsize*/
- if (R.r.bake_maxdist > 0.0f)
- maxdist= R.r.bake_maxdist;
- else
- maxdist= RE_RAYTRACE_MAXDIST + R.r.bake_biasdist;
-
- /* 'dir' is always normalized */
- madd_v3_v3v3fl(isect->start, start, dir, -R.r.bake_biasdist);
-
- mul_v3_v3fl(isect->dir, dir, sign);
-
- isect->dist = maxdist;
-
- hit = RE_rayobject_raycast(raytree, isect);
- if (hit) {
- madd_v3_v3v3fl(hitco, isect->start, isect->dir, isect->dist);
-
- *dist= isect->dist;
- }
-
- return hit;
-}
-
-static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3)
-{
- VlakRen *vlr= bs->vlr;
- float A, d1, d2, d3, *v1, *v2, *v3;
-
- if (bs->quad) {
- v1= vlr->v1->co;
- v2= vlr->v3->co;
- v3= vlr->v4->co;
- }
- else {
- v1= vlr->v1->co;
- v2= vlr->v2->co;
- v3= vlr->v3->co;
- }
-
- /* formula derived from barycentric coordinates:
- * (uvArea1*v1 + uvArea2*v2 + uvArea3*v3)/uvArea
- * then taking u and v partial derivatives to get dxco and dyco */
- A= (uv2[0] - uv1[0])*(uv3[1] - uv1[1]) - (uv3[0] - uv1[0])*(uv2[1] - uv1[1]);
-
- if (fabsf(A) > FLT_EPSILON) {
- A= 0.5f/A;
-
- d1= uv2[1] - uv3[1];
- d2= uv3[1] - uv1[1];
- d3= uv1[1] - uv2[1];
- bs->dxco[0]= (v1[0]*d1 + v2[0]*d2 + v3[0]*d3)*A;
- bs->dxco[1]= (v1[1]*d1 + v2[1]*d2 + v3[1]*d3)*A;
- bs->dxco[2]= (v1[2]*d1 + v2[2]*d2 + v3[2]*d3)*A;
-
- d1= uv3[0] - uv2[0];
- d2= uv1[0] - uv3[0];
- d3= uv2[0] - uv1[0];
- bs->dyco[0]= (v1[0]*d1 + v2[0]*d2 + v3[0]*d3)*A;
- bs->dyco[1]= (v1[1]*d1 + v2[1]*d2 + v3[1]*d3)*A;
- bs->dyco[2]= (v1[2]*d1 + v2[2]*d2 + v3[2]*d3)*A;
- }
- else {
- bs->dxco[0]= bs->dxco[1]= bs->dxco[2]= 0.0f;
- bs->dyco[0]= bs->dyco[1]= bs->dyco[2]= 0.0f;
- }
-
- if (bs->obi->flag & R_TRANSFORMED) {
- mul_m3_v3(bs->obi->nmat, bs->dxco);
- mul_m3_v3(bs->obi->nmat, bs->dyco);
- }
-}
-
-static void do_bake_shade(void *handle, int x, int y, float u, float v)
-{
- BakeShade *bs= handle;
- VlakRen *vlr= bs->vlr;
- ObjectInstanceRen *obi= bs->obi;
- Object *ob= obi->obr->ob;
- float l, *v1, *v2, *v3, tvn[3], ttang[4];
- int quad;
- ShadeSample *ssamp= &bs->ssamp;
- ShadeInput *shi= ssamp->shi;
-
- /* fast threadsafe break test */
- if (R.test_break(R.tbh))
- return;
-
- /* setup render coordinates */
- if (bs->quad) {
- v1= vlr->v1->co;
- v2= vlr->v3->co;
- v3= vlr->v4->co;
- }
- else {
- v1= vlr->v1->co;
- v2= vlr->v2->co;
- v3= vlr->v3->co;
- }
-
- l= 1.0f-u-v;
-
- /* shrink barycentric coordinates inwards slightly to avoid some issues
- * where baking selected to active might just miss the other face at the
- * near the edge of a face */
- if (bs->actob) {
- const float eps = 1.0f - 1e-4f;
- float invsum;
-
- u = (u - 0.5f)*eps + 0.5f;
- v = (v - 0.5f)*eps + 0.5f;
- l = (l - 0.5f)*eps + 0.5f;
-
- invsum = 1.0f/(u + v + l);
-
- u *= invsum;
- v *= invsum;
- l *= invsum;
- }
-
- /* renderco */
- 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];
-
- if (obi->flag & R_TRANSFORMED)
- mul_m4_v3(obi->mat, shi->co);
-
- copy_v3_v3(shi->dxco, bs->dxco);
- copy_v3_v3(shi->dyco, bs->dyco);
-
- quad= bs->quad;
- bake_set_shade_input(obi, vlr, shi, quad, 0, x, y, u, v);
-
- if (bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT) {
- shade_input_set_shade_texco(shi);
- copy_v3_v3(tvn, shi->nmapnorm);
- copy_v4_v4(ttang, shi->nmaptang);
- }
-
- /* if we are doing selected to active baking, find point on other face */
- if (bs->actob) {
- Isect isec, minisec;
- float co[3], minco[3], dist, mindist=0.0f;
- int hit, sign, dir=1;
-
- /* intersect with ray going forward and backward*/
- hit= 0;
- memset(&minisec, 0, sizeof(minisec));
- minco[0]= minco[1]= minco[2]= 0.0f;
-
- copy_v3_v3(bs->dir, shi->vn);
-
- for (sign=-1; sign<=1; sign+=2) {
- memset(&isec, 0, sizeof(isec));
- isec.mode= RE_RAY_MIRROR;
-
- isec.orig.ob = obi;
- isec.orig.face = vlr;
- isec.userdata= bs->actob;
- isec.check = RE_CHECK_VLR_BAKE;
- isec.skip = RE_SKIP_VLR_NEIGHBOUR;
-
- if (bake_intersect_tree(R.raytree, &isec, shi->co, shi->vn, sign, co, &dist)) {
- if (!hit || len_squared_v3v3(shi->co, co) < len_squared_v3v3(shi->co, minco)) {
- minisec= isec;
- mindist= dist;
- copy_v3_v3(minco, co);
- hit= 1;
- dir = sign;
- }
- }
- }
-
- if (bs->type==RE_BAKE_DISPLACEMENT) {
- if (hit)
- bake_displacement(handle, shi, (dir==-1)? mindist:-mindist, x, y);
- else
- bake_displacement(handle, shi, 0.0f, x, y);
- return;
- }
-
- /* if hit, we shade from the new point, otherwise from point one starting face */
- if (hit) {
- obi = (ObjectInstanceRen *)minisec.hit.ob;
- vlr = (VlakRen *)minisec.hit.face;
- quad= (minisec.isect == 2);
- copy_v3_v3(shi->co, minco);
-
- u= -minisec.u;
- v= -minisec.v;
- bake_set_shade_input(obi, vlr, shi, quad, 1, x, y, u, v);
- }
- }
-
- if (bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT)
- bake_shade(handle, ob, shi, quad, x, y, u, v, tvn, ttang);
- else
- bake_shade(handle, ob, shi, quad, x, y, u, v, 0, 0);
-}
-
-static int get_next_bake_face(BakeShade *bs)
-{
- ObjectRen *obr;
- VlakRen *vlr;
- MTFace *tface;
- static int v= 0, vdone = FALSE;
- static ObjectInstanceRen *obi= NULL;
-
- if (bs==NULL) {
- vlr= NULL;
- v= vdone = FALSE;
- obi= R.instancetable.first;
- return 0;
- }
-
- BLI_lock_thread(LOCK_CUSTOM1);
-
- for (; obi; obi=obi->next, v=0) {
- obr= obi->obr;
-
- for (; v<obr->totvlak; v++) {
- vlr= RE_findOrAddVlak(obr, v);
-
- if ((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) {
- if(R.r.bake_flag & R_BAKE_VCOL) {
- /* Gather face data for vertex colour bake */
- Mesh *me;
- int *origindex, vcollayer;
- CustomDataLayer *cdl;
-
- if(obr->ob->type != OB_MESH)
- continue;
- me = obr->ob->data;
-
- origindex = RE_vlakren_get_origindex(obr, vlr, 0);
- if(origindex == NULL)
- continue;
- if (*origindex >= me->totpoly) {
- /* Small hack for Array modifier, which gives false
- original indices - z0r */
- continue;
- }
-#if 0
- /* Only shade selected faces. */
- if((me->mface[*origindex].flag & ME_FACE_SEL) == 0)
- continue;
-#endif
-
- vcollayer = CustomData_get_render_layer_index(&me->ldata, CD_MLOOPCOL);
- if(vcollayer == -1)
- continue;
-
- cdl = &me->ldata.layers[vcollayer];
- bs->mpoly = me->mpoly + *origindex;
- bs->vcol = ((MLoopCol*)cdl->data) + bs->mpoly->loopstart;
- bs->mloop = me->mloop + bs->mpoly->loopstart;
-
- /* Tag mesh for reevaluation. */
- DAG_id_tag_update(&me->id, 0);
- }
- else {
- Image *ima = NULL;
- ImBuf *ibuf = NULL;
- const float vec_alpha[4]= {0.0f, 0.0f, 0.0f, 0.0f};
- const float vec_solid[4]= {0.0f, 0.0f, 0.0f, 1.0f};
-
- tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
-
- if (!tface || !tface->tpage)
- continue;
-
- ima = tface->tpage;
- ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
-
- if (ibuf==NULL)
- continue;
-
- if (ibuf->rect==NULL && ibuf->rect_float==NULL) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- continue;
- }
-
- if (ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4)) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- continue;
- }
-
- if (ima->flag & IMA_USED_FOR_RENDER) {
- ima->id.flag &= ~LIB_DOIT;
- BKE_image_release_ibuf(ima, ibuf, NULL);
- continue;
- }
-
- /* find the image for the first time? */
- if (ima->id.flag & LIB_DOIT) {
- ima->id.flag &= ~LIB_DOIT;
-
- /* we either fill in float or char, this ensures things go fine */
- if (ibuf->rect_float)
- imb_freerectImBuf(ibuf);
- /* clear image */
- if (R.r.bake_flag & R_BAKE_CLEAR)
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
-
- /* might be read by UI to set active image for display */
- R.bakebuf= ima;
- }
-
- /* Tag image for redraw. */
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
-
- bs->obi = obi;
- bs->vlr = vlr;
- bs->vdone++; /* only for error message if nothing was rendered */
- v++;
- BLI_unlock_thread(LOCK_CUSTOM1);
- return 1;
- }
- }
- }
-
- BLI_unlock_thread(LOCK_CUSTOM1);
- return 0;
-}
-
-static void bake_single_vertex(BakeShade *bs, VertRen *vert, float u, float v)
-{
- int *origindex, i;
- MLoopCol *basevcol;
- MLoop *mloop;
-
- origindex = RE_vertren_get_origindex(bs->obi->obr, vert, 0);
- if (!origindex || *origindex == ORIGINDEX_NONE)
- return;
-
- /* Search for matching vertex index and apply shading. */
- for (i = 0; i < bs->mpoly->totloop; i++) {
- mloop = bs->mloop + i;
- if (mloop->v != *origindex)
- continue;
- basevcol = bs->vcol;
- bs->vcol = basevcol + i;
- do_bake_shade(bs, 0, 0, u, v);
- bs->vcol = basevcol;
- break;
- }
-}
-
-/* Bake all vertices of a face. Actually, this still works on a face-by-face
- basis, and each vertex on each face is shaded. Vertex colors are a property
- of loops, not vertices. */
-static void shade_verts(BakeShade *bs)
-{
- VlakRen *vlr = bs->vlr;
-
- /* Disable baking to image; write to vcol instead. vcol pointer is set in
- * bake_single_vertex. */
- bs->ima = NULL;
- bs->rect = NULL;
- bs->rect_float = NULL;
-
- bs->quad = 0;
-
- /* No anti-aliasing for vertices. */
- zero_v3(bs->dxco);
- zero_v3(bs->dyco);
-
- /* Shade each vertex of the face. u and v are barycentric coordinates; since
- we're only interested in vertices, these will be 0 or 1. */
- if ((vlr->flag & R_FACE_SPLIT) == 0) {
- /* Processing triangle face, whole quad, or first half of split quad. */
-
- bake_single_vertex(bs, bs->vlr->v1, 1.0f, 0.0f);
- bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f);
- bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f);
-
- if (vlr->v4) {
- bs->quad = 1;
- bake_single_vertex(bs, bs->vlr->v4, 0.0f, 0.0f);
- }
- }
- else {
- /* Processing second half of split quad. Only one vertex to go. */
- if (vlr->flag & R_DIVIDE_24) {
- bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f);
- }
- else {
- bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f);
- }
- }
-}
-
-/* already have tested for tface and ima and zspan */
-static void shade_tface(BakeShade *bs)
-{
- VlakRen *vlr= bs->vlr;
- ObjectInstanceRen *obi= bs->obi;
- ObjectRen *obr= obi->obr;
- MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
- Image *ima= tface->tpage;
- float vec[4][2];
- int a, i1, i2, i3;
-
- /* check valid zspan */
- if (ima!=bs->ima) {
- BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL);
-
- bs->ima= ima;
- bs->ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
- /* note, these calls only free/fill contents of zspan struct, not zspan itself */
- zbuf_free_span(bs->zspan);
- zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop);
- }
-
- bs->rectx= bs->ibuf->x;
- bs->recty= bs->ibuf->y;
- bs->rect= bs->ibuf->rect;
- bs->rect_colorspace= bs->ibuf->rect_colorspace;
- bs->rect_float= bs->ibuf->rect_float;
- bs->vcol = NULL;
- bs->quad= 0;
-
- if (bs->use_mask) {
- if (bs->ibuf->userdata==NULL) {
- BLI_lock_thread(LOCK_CUSTOM1);
- if (bs->ibuf->userdata==NULL) /* since the thread was locked, its possible another thread alloced the value */
- bs->ibuf->userdata = (void *)MEM_callocN(sizeof(char)*bs->rectx*bs->recty, "BakeMask");
- bs->rect_mask= (char *)bs->ibuf->userdata;
- BLI_unlock_thread(LOCK_CUSTOM1);
- }
- else {
- bs->rect_mask= (char *)bs->ibuf->userdata;
- }
- }
-
- /* get pixel level vertex coordinates */
- for (a=0; a<4; a++) {
- /* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests
- * where a pixel gets in between 2 faces or the middle of a quad,
- * camera aligned quads also have this problem but they are less common.
- * Add a small offset to the UVs, fixes bug #18685 - Campbell */
- vec[a][0]= tface->uv[a][0]*(float)bs->rectx - (0.5f + 0.001f);
- vec[a][1]= tface->uv[a][1]*(float)bs->recty - (0.5f + 0.002f);
- }
-
- /* UV indices have to be corrected for possible quad->tria splits */
- i1= 0; i2= 1; i3= 2;
- vlr_set_uv_indices(vlr, &i1, &i2, &i3);
- bake_set_vlr_dxyco(bs, vec[i1], vec[i2], vec[i3]);
- zspan_scanconvert(bs->zspan, bs, vec[i1], vec[i2], vec[i3], do_bake_shade);
-
- if (vlr->v4) {
- bs->quad= 1;
- bake_set_vlr_dxyco(bs, vec[0], vec[2], vec[3]);
- zspan_scanconvert(bs->zspan, bs, vec[0], vec[2], vec[3], do_bake_shade);
- }
-}
-
-static void *do_bake_thread(void *bs_v)
-{
- BakeShade *bs= bs_v;
-
- while (get_next_bake_face(bs)) {
- if (R.r.bake_flag & R_BAKE_VCOL)
- shade_verts(bs);
- else
- shade_tface(bs);
-
- /* fast threadsafe break test */
- if (R.test_break(R.tbh))
- break;
-
- /* access is not threadsafe but since its just true/false probably ok
- * only used for interactive baking */
- if (bs->do_update)
- *bs->do_update= TRUE;
- }
- bs->ready= 1;
-
- BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL);
-
- return NULL;
-}
-
-void RE_bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter)
-{
- /* must check before filtering */
- const short is_new_alpha= (ibuf->planes != R_IMF_PLANES_RGBA) && BKE_imbuf_alpha_test(ibuf);
-
- /* Margin */
- if (filter) {
- IMB_filter_extend(ibuf, mask, filter);
- }
-
- /* if the bake results in new alpha then change the image setting */
- if (is_new_alpha) {
- ibuf->planes= R_IMF_PLANES_RGBA;
- }
- else {
- if (filter && ibuf->planes != R_IMF_PLANES_RGBA) {
- /* clear alpha added by filtering */
- IMB_rectfill_alpha(ibuf, 1.0f);
- }
- }
-}
-
-/* using object selection tags, the faces with UV maps get baked */
-/* render should have been setup */
-/* returns 0 if nothing was handled */
-int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_update, float *progress)
-{
- BakeShade *handles;
- ListBase threads;
- Image *ima;
- int a, vdone = FALSE, use_mask = FALSE, result = BAKE_RESULT_OK;
-
- re->scene_color_manage = BKE_scene_check_color_management_enabled(re->scene);
-
- /* initialize render global */
- R= *re;
- R.bakebuf= NULL;
-
- /* initialize static vars */
- get_next_bake_face(NULL);
-
- /* do we need a mask? */
- if (re->r.bake_filter)
- use_mask = TRUE;
-
- /* baker uses this flag to detect if image was initialized */
- if ((R.r.bake_flag & R_BAKE_VCOL) == 0) {
- for (ima = G.main->image.first; ima; ima = ima->id.next) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- ima->id.flag |= LIB_DOIT;
- ima->flag &= ~IMA_USED_FOR_RENDER;
- if (ibuf) {
- ibuf->userdata = NULL; /* use for masking if needed */
- }
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
- }
-
- BLI_init_threads(&threads, do_bake_thread, re->r.threads);
-
- handles= MEM_callocN(sizeof(BakeShade)*re->r.threads, "BakeShade");
-
- /* get the threads running */
- for (a=0; a<re->r.threads; a++) {
- /* set defaults in handles */
- handles[a].ssamp.shi[0].lay= re->lay;
-
- if (type==RE_BAKE_SHADOW) {
- handles[a].ssamp.shi[0].passflag= SCE_PASS_SHADOW;
- }
- else {
- handles[a].ssamp.shi[0].passflag= SCE_PASS_COMBINED;
- }
- handles[a].ssamp.shi[0].combinedflag= ~(SCE_PASS_SPEC);
- handles[a].ssamp.shi[0].thread= a;
- handles[a].ssamp.tot= 1;
-
- handles[a].type= type;
- handles[a].actob= actob;
- if (R.r.bake_flag & R_BAKE_VCOL)
- handles[a].zspan = NULL;
- else
- handles[a].zspan = MEM_callocN(sizeof(ZSpan), "zspan for bake");
-
- handles[a].use_mask = use_mask;
-
- handles[a].do_update = do_update; /* use to tell the view to update */
-
- BLI_insert_thread(&threads, &handles[a]);
- }
-
- /* wait for everything to be done */
- a= 0;
- while (a!=re->r.threads) {
- PIL_sleep_ms(50);
-
- /* calculate progress */
- for (vdone = FALSE, a=0; a<re->r.threads; a++)
- vdone+= handles[a].vdone;
- if (progress)
- *progress = (float)(vdone / (float)re->totvlak);
-
- for (a=0; a<re->r.threads; a++) {
- if (handles[a].ready==0)
- break;
- }
- }
-
- /* filter and refresh images */
- if ((R.r.bake_flag & R_BAKE_VCOL) == 0) {
- for (ima = G.main->image.first; ima; ima = ima->id.next) {
- if ((ima->id.flag & LIB_DOIT)==0) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
-
- if (ima->flag & IMA_USED_FOR_RENDER)
- result = BAKE_RESULT_FEEDBACK_LOOP;
-
- if (!ibuf)
- continue;
-
- RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, re->r.bake_filter);
-
- ibuf->userflags |= IB_BITMAPDIRTY;
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
- }
-
- /* calculate return value */
- for (a = 0; a < re->r.threads; a++) {
- zbuf_free_span(handles[a].zspan);
- MEM_freeN(handles[a].zspan);
- }
- }
-
- MEM_freeN(handles);
-
- BLI_end_threads(&threads);
-
- if (vdone==0)
- result= BAKE_RESULT_NO_OBJECTS;
-
- return result;
-}
-
-struct Image *RE_bake_shade_get_image(void)
-{
- return R.bakebuf;
-}
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index 7ca4f01ae47..b25f2f4201a 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -1051,7 +1051,7 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,
}
}
- externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
+ externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool);
yn= tin*mtex->colfac;
//zn= tin*mtex->alphafac;
@@ -1070,6 +1070,8 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,
}
}
+ har->pool = re->pool;
+
return har;
}
@@ -1180,7 +1182,7 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater
copy_v3_v3(texvec, orco);
}
- hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
+ hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool);
//yn= tin*mtex->colfac;
//zn= tin*mtex->alphafac;
@@ -1223,6 +1225,8 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater
//}
}
+ har->pool = re->pool;
+
return har;
}
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 87912f546e8..1a24055c7f4 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -38,10 +38,6 @@
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
-#include "BKE_global.h"
-#include "BKE_scene.h"
-
-
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_jitter.h"
@@ -49,6 +45,9 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_scene.h"
+
#include "PIL_time.h"
#include "renderpipeline.h"
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index db93a21de2d..bf0087d0292 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -151,6 +151,7 @@ void shade_material_loop(ShadeInput *shi, ShadeResult *shr)
/* do a shade, finish up some passes, apply mist */
void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr)
{
+ bool compat = false;
float alpha;
/* ------ main shading loop -------- */
@@ -158,10 +159,11 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr)
memset(&shi->raycounter, 0, sizeof(shi->raycounter));
#endif
- if (shi->mat->nodetree && shi->mat->use_nodes) {
- ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
- }
- else {
+ if (shi->mat->nodetree && shi->mat->use_nodes)
+ compat = ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
+
+ /* also run this when node shaders fail, due to incompatible shader nodes */
+ if (compat == false) {
/* copy all relevant material vars, note, keep this synced with render_types.h */
shade_input_init_material(shi);