[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [53971] trunk/blender/source/blender/ render: Multires baker: fix wrong normalization if baking happens to multiple images

Sergey Sharybin sergey.vfx at gmail.com
Mon Jan 21 19:34:27 CET 2013


Revision: 53971
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=53971
Author:   nazgul
Date:     2013-01-21 18:34:27 +0000 (Mon, 21 Jan 2013)
Log Message:
-----------
Multires baker: fix wrong normalization if baking happens to multiple images

Previously normalization will happen per image buffer individually, which
was wrong in cases different faces of the sane mesh uses different images.

Also solved possible threading issues when calculating min.max displacement.

Modified Paths:
--------------
    trunk/blender/source/blender/render/extern/include/RE_shader_ext.h
    trunk/blender/source/blender/render/intern/source/multires_bake.c
    trunk/blender/source/blender/render/intern/source/rendercore.c

Modified: trunk/blender/source/blender/render/extern/include/RE_shader_ext.h
===================================================================
--- trunk/blender/source/blender/render/extern/include/RE_shader_ext.h	2013-01-21 18:34:20 UTC (rev 53970)
+++ trunk/blender/source/blender/render/extern/include/RE_shader_ext.h	2013-01-21 18:34:27 UTC (rev 53971)
@@ -186,7 +186,6 @@
 
 typedef struct BakeImBufuserData {
 	float *displacement_buffer;
-	float displacement_min, displacement_max;
 	char *mask_buffer;
 } BakeImBufuserData;
 
@@ -212,7 +211,7 @@
 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 global_displacement_min, float global_displacement_max);
+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

Modified: trunk/blender/source/blender/render/intern/source/multires_bake.c
===================================================================
--- trunk/blender/source/blender/render/intern/source/multires_bake.c	2013-01-21 18:34:20 UTC (rev 53970)
+++ trunk/blender/source/blender/render/intern/source/multires_bake.c	2013-01-21 18:34:27 UTC (rev 53971)
@@ -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 @@
 	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 {
 	float *heights;
-	float height_min, height_max;
 	Image *ima;
 	DerivedMesh *ssdm;
 	const int *orig_index_mf_to_mpoly;
@@ -161,9 +164,11 @@
 
 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 @@
 		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 @@
 	/* 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)
@@ -450,7 +458,7 @@
 }
 
 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;
@@ -514,9 +522,13 @@
 			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)
@@ -529,12 +541,18 @@
 		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);
 
@@ -676,13 +694,15 @@
 	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}};
@@ -710,48 +730,6 @@
 	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;
@@ -759,7 +737,6 @@
 	if (height_data->ssdm)
 		height_data->ssdm->release(height_data->ssdm);
 
-	MEM_freeN(height_data->heights);
 	MEM_freeN(height_data);
 }
 
@@ -769,13 +746,14 @@
  *   - 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;
@@ -822,15 +800,18 @@
 	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;
 	}
 }
@@ -862,9 +843,9 @@
  *   - 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;
@@ -1099,9 +1080,9 @@
 	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,

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list