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:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/render
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/CMakeLists.txt124
-rw-r--r--source/blender/render/extern/include/RE_bake.h101
-rw-r--r--source/blender/render/extern/include/RE_engine.h193
-rw-r--r--source/blender/render/extern/include/RE_multires_bake.h48
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h290
-rw-r--r--source/blender/render/extern/include/RE_render_ext.h39
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h33
-rw-r--r--source/blender/render/intern/include/initrender.h1
-rw-r--r--source/blender/render/intern/include/render_result.h105
-rw-r--r--source/blender/render/intern/include/render_types.h179
-rw-r--r--source/blender/render/intern/include/renderpipeline.h5
-rw-r--r--source/blender/render/intern/include/texture.h89
-rw-r--r--source/blender/render/intern/include/zbuf.h17
-rw-r--r--source/blender/render/intern/source/bake_api.c1522
-rw-r--r--source/blender/render/intern/source/external_engine.c1055
-rw-r--r--source/blender/render/intern/source/imagetexture.c3326
-rw-r--r--source/blender/render/intern/source/initrender.c339
-rw-r--r--source/blender/render/intern/source/multires_bake.c2133
-rw-r--r--source/blender/render/intern/source/pipeline.c4193
-rw-r--r--source/blender/render/intern/source/pointdensity.c1579
-rw-r--r--source/blender/render/intern/source/render_result.c2486
-rw-r--r--source/blender/render/intern/source/render_texture.c2670
-rw-r--r--source/blender/render/intern/source/zbuf.c310
23 files changed, 10931 insertions, 9906 deletions
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index d6bbbbd3061..da82e606bda 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -20,96 +20,96 @@
set(INC
- extern/include
- intern/include
- ../blenkernel
- ../blenlib
- ../blentranslation
- ../imbuf
- ../depsgraph
- ../makesdna
- ../makesrna
- ../nodes
- ../physics
- ../draw
- ../gpu
- ../../../intern/atomic
- ../../../intern/guardedalloc
- ../../../intern/mikktspace
- ../../../intern/smoke/extern
+ extern/include
+ intern/include
+ ../blenkernel
+ ../blenlib
+ ../blentranslation
+ ../imbuf
+ ../depsgraph
+ ../makesdna
+ ../makesrna
+ ../nodes
+ ../physics
+ ../draw
+ ../gpu
+ ../../../intern/atomic
+ ../../../intern/guardedalloc
+ ../../../intern/mikktspace
+ ../../../intern/smoke/extern
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- intern/source/bake_api.c
- intern/source/external_engine.c
- intern/source/imagetexture.c
- intern/source/initrender.c
- intern/source/multires_bake.c
- intern/source/pipeline.c
- intern/source/pointdensity.c
- intern/source/render_result.c
- intern/source/render_texture.c
- intern/source/zbuf.c
+ intern/source/bake_api.c
+ intern/source/external_engine.c
+ intern/source/imagetexture.c
+ intern/source/initrender.c
+ intern/source/multires_bake.c
+ intern/source/pipeline.c
+ intern/source/pointdensity.c
+ intern/source/render_result.c
+ intern/source/render_texture.c
+ intern/source/zbuf.c
- extern/include/RE_bake.h
- extern/include/RE_engine.h
- extern/include/RE_multires_bake.h
- extern/include/RE_pipeline.h
- extern/include/RE_render_ext.h
- extern/include/RE_shader_ext.h
- intern/include/initrender.h
- intern/include/render_result.h
- intern/include/render_types.h
- intern/include/renderpipeline.h
- intern/include/texture.h
- intern/include/zbuf.h
+ extern/include/RE_bake.h
+ extern/include/RE_engine.h
+ extern/include/RE_multires_bake.h
+ extern/include/RE_pipeline.h
+ extern/include/RE_render_ext.h
+ extern/include/RE_shader_ext.h
+ intern/include/initrender.h
+ intern/include/render_result.h
+ intern/include/render_types.h
+ intern/include/renderpipeline.h
+ intern/include/texture.h
+ intern/include/zbuf.h
)
set(LIB
)
if(WITH_PYTHON)
- add_definitions(-DWITH_PYTHON)
- list(APPEND INC
- ../python
- )
+ add_definitions(-DWITH_PYTHON)
+ list(APPEND INC
+ ../python
+ )
endif()
if(WITH_IMAGE_OPENEXR)
- list(APPEND LIB
- bf_imbuf_openexr
- )
- add_definitions(-DWITH_OPENEXR)
+ list(APPEND LIB
+ bf_imbuf_openexr
+ )
+ add_definitions(-DWITH_OPENEXR)
endif()
if(WITH_MOD_SMOKE)
- add_definitions(-DWITH_SMOKE)
+ add_definitions(-DWITH_SMOKE)
endif()
if(WITH_FREESTYLE)
- list(APPEND INC
- ../freestyle
- )
- list(APPEND LIB
- bf_freestyle
- )
- add_definitions(-DWITH_FREESTYLE)
+ list(APPEND INC
+ ../freestyle
+ )
+ list(APPEND LIB
+ bf_freestyle
+ )
+ add_definitions(-DWITH_FREESTYLE)
endif()
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
if(APPLE)
- # SSE math is enabled by default on x86_64
- if(CMAKE_OSX_ARCHITECTURES MATCHES "i386")
- set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mfpmath=sse")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mfpmath=sse")
- endif()
+ # SSE math is enabled by default on x86_64
+ if(CMAKE_OSX_ARCHITECTURES MATCHES "i386")
+ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mfpmath=sse")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mfpmath=sse")
+ endif()
endif()
blender_add_lib_nolist(bf_render "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/render/extern/include/RE_bake.h b/source/blender/render/extern/include/RE_bake.h
index f04f689d114..372defbe8db 100644
--- a/source/blender/render/extern/include/RE_bake.h
+++ b/source/blender/render/extern/include/RE_bake.h
@@ -30,68 +30,93 @@ struct Mesh;
struct Render;
typedef struct BakeImage {
- struct Image *image;
- int width;
- int height;
- size_t offset;
+ struct Image *image;
+ int width;
+ int height;
+ size_t offset;
} BakeImage;
typedef struct BakeImages {
- BakeImage *data; /* all the images of an object */
- int *lookup; /* lookup table from Material to BakeImage */
- int size;
+ BakeImage *data; /* all the images of an object */
+ int *lookup; /* lookup table from Material to BakeImage */
+ int size;
} BakeImages;
typedef struct BakePixel {
- int primitive_id, object_id;
- float uv[2];
- float du_dx, du_dy;
- float dv_dx, dv_dy;
+ int primitive_id, object_id;
+ float uv[2];
+ float du_dx, du_dy;
+ float dv_dx, dv_dy;
} BakePixel;
typedef struct BakeHighPolyData {
- struct Object *ob;
- struct Object *ob_eval;
- struct Mesh *me;
- bool is_flip_object;
+ struct Object *ob;
+ struct Object *ob_eval;
+ struct Mesh *me;
+ bool is_flip_object;
- float obmat[4][4];
- float imat[4][4];
+ float obmat[4][4];
+ float imat[4][4];
} BakeHighPolyData;
/* external_engine.c */
bool RE_bake_has_engine(struct Render *re);
-bool RE_bake_engine(
- struct Render *re, struct Depsgraph *depsgraph, struct Object *object, const int object_id, const BakePixel pixel_array[],
- const size_t num_pixels, const int depth, const eScenePassType pass_type, const int pass_filter, float result[]);
+bool RE_bake_engine(struct Render *re,
+ struct Depsgraph *depsgraph,
+ struct Object *object,
+ const int object_id,
+ const BakePixel pixel_array[],
+ const size_t num_pixels,
+ const int depth,
+ const eScenePassType pass_type,
+ const int pass_filter,
+ float result[]);
/* bake.c */
int RE_pass_depth(const eScenePassType pass_type);
-bool RE_bake_pixels_populate_from_objects(
- struct Mesh *me_low, BakePixel pixel_array_from[], BakePixel pixel_array_to[],
- BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage,
- const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage);
-
-void RE_bake_pixels_populate(
- struct Mesh *me, struct BakePixel *pixel_array,
- const size_t num_pixels, const struct BakeImages *bake_images, const char *uv_layer);
+bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low,
+ BakePixel pixel_array_from[],
+ BakePixel pixel_array_to[],
+ BakeHighPolyData highpoly[],
+ const int tot_highpoly,
+ const size_t num_pixels,
+ const bool is_custom_cage,
+ const float cage_extrusion,
+ float mat_low[4][4],
+ float mat_cage[4][4],
+ struct Mesh *me_cage);
+
+void RE_bake_pixels_populate(struct Mesh *me,
+ struct BakePixel *pixel_array,
+ const size_t num_pixels,
+ const struct BakeImages *bake_images,
+ const char *uv_layer);
void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, char *mask);
void RE_bake_margin(struct ImBuf *ibuf, char *mask, const int margin);
-void RE_bake_normal_world_to_object(
- const BakePixel pixel_array[], const size_t num_pixels, const int depth, float result[],
- struct Object *ob, const eBakeNormalSwizzle normal_swizzle[3]);
-void RE_bake_normal_world_to_tangent(
- const BakePixel pixel_array[], const size_t num_pixels, const int depth, float result[],
- struct Mesh *me, const eBakeNormalSwizzle normal_swizzle[3], float mat[4][4]);
-void RE_bake_normal_world_to_world(
- const BakePixel pixel_array[], const size_t num_pixels, const int depth, float result[],
- const eBakeNormalSwizzle normal_swizzle[3]);
+void RE_bake_normal_world_to_object(const BakePixel pixel_array[],
+ const size_t num_pixels,
+ const int depth,
+ float result[],
+ struct Object *ob,
+ const eBakeNormalSwizzle normal_swizzle[3]);
+void RE_bake_normal_world_to_tangent(const BakePixel pixel_array[],
+ const size_t num_pixels,
+ const int depth,
+ float result[],
+ struct Mesh *me,
+ const eBakeNormalSwizzle normal_swizzle[3],
+ float mat[4][4]);
+void RE_bake_normal_world_to_world(const BakePixel pixel_array[],
+ const size_t num_pixels,
+ const int depth,
+ float result[],
+ const eBakeNormalSwizzle normal_swizzle[3]);
void RE_bake_ibuf_clear(struct Image *image, const bool is_tangent);
-#endif /* __RE_BAKE_H__ */
+#endif /* __RE_BAKE_H__ */
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index d22ab6d782d..1092ab553e9 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -51,107 +51,139 @@ struct bNodeTree;
/* External Engine */
/* RenderEngineType.flag */
-#define RE_INTERNAL 1
-/* #define RE_FLAG_DEPRECATED 2 */
-#define RE_USE_PREVIEW 4
-#define RE_USE_POSTPROCESS 8
-#define RE_USE_SHADING_NODES 16
-#define RE_USE_EXCLUDE_LAYERS 32
-#define RE_USE_SAVE_BUFFERS 64
-#define RE_USE_SHADING_NODES_CUSTOM 256
+#define RE_INTERNAL 1
+/* #define RE_FLAG_DEPRECATED 2 */
+#define RE_USE_PREVIEW 4
+#define RE_USE_POSTPROCESS 8
+#define RE_USE_SHADING_NODES 16
+#define RE_USE_EXCLUDE_LAYERS 32
+#define RE_USE_SAVE_BUFFERS 64
+#define RE_USE_SHADING_NODES_CUSTOM 256
#define RE_USE_SPHERICAL_STEREO 512
/* RenderEngine.flag */
-#define RE_ENGINE_ANIMATION 1
-#define RE_ENGINE_PREVIEW 2
-#define RE_ENGINE_DO_DRAW 4
-#define RE_ENGINE_DO_UPDATE 8
-#define RE_ENGINE_RENDERING 16
-#define RE_ENGINE_HIGHLIGHT_TILES 32
-#define RE_ENGINE_USED_FOR_VIEWPORT 64
+#define RE_ENGINE_ANIMATION 1
+#define RE_ENGINE_PREVIEW 2
+#define RE_ENGINE_DO_DRAW 4
+#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;
typedef struct RenderEngineType {
- struct RenderEngineType *next, *prev;
-
- /* type info */
- char idname[64]; // best keep the same size as BKE_ST_MAXNAME
- char name[64];
- int flag;
-
- void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Depsgraph *depsgraph);
- void (*render)(struct RenderEngine *engine, struct Depsgraph *depsgraph);
- void (*bake)(struct RenderEngine *engine, struct Depsgraph *depsgraph,
- struct Object *object, const int pass_type,
- const int pass_filter, const int object_id, const struct BakePixel *pixel_array, const int num_pixels,
- const int depth, void *result);
-
- void (*view_update)(struct RenderEngine *engine, const struct bContext *context);
- void (*view_draw)(struct RenderEngine *engine, const struct bContext *context);
-
- void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node);
- void (*update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer);
-
- struct DrawEngineType *draw_engine;
-
- /* RNA integration */
- ExtensionRNA ext;
+ struct RenderEngineType *next, *prev;
+
+ /* type info */
+ char idname[64]; // best keep the same size as BKE_ST_MAXNAME
+ char name[64];
+ int flag;
+
+ void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Depsgraph *depsgraph);
+ void (*render)(struct RenderEngine *engine, struct Depsgraph *depsgraph);
+ void (*bake)(struct RenderEngine *engine,
+ struct Depsgraph *depsgraph,
+ struct Object *object,
+ const int pass_type,
+ const int pass_filter,
+ const int object_id,
+ const struct BakePixel *pixel_array,
+ const int num_pixels,
+ const int depth,
+ void *result);
+
+ void (*view_update)(struct RenderEngine *engine, const struct bContext *context);
+ void (*view_draw)(struct RenderEngine *engine, const struct bContext *context);
+
+ void (*update_script_node)(struct RenderEngine *engine,
+ struct bNodeTree *ntree,
+ struct bNode *node);
+ void (*update_render_passes)(struct RenderEngine *engine,
+ struct Scene *scene,
+ struct ViewLayer *view_layer);
+
+ struct DrawEngineType *draw_engine;
+
+ /* RNA integration */
+ ExtensionRNA ext;
} RenderEngineType;
-typedef void (*update_render_passes_cb_t)(void *userdata, struct Scene *scene, struct ViewLayer *view_layer,
- const char *name, int channels, const char *chanid, int type);
+typedef void (*update_render_passes_cb_t)(void *userdata,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ const char *name,
+ int channels,
+ const char *chanid,
+ int type);
typedef struct RenderEngine {
- RenderEngineType *type;
- void *py_instance;
+ RenderEngineType *type;
+ void *py_instance;
- int flag;
- struct Object *camera_override;
- unsigned int layer_override;
+ int flag;
+ struct Object *camera_override;
+ unsigned int layer_override;
- int tile_x;
- int tile_y;
+ int tile_x;
+ int tile_y;
- struct Render *re;
- ListBase fullresult;
- char text[512]; /* IMA_MAX_RENDER_TEXT */
+ struct Render *re;
+ ListBase fullresult;
+ char text[512]; /* IMA_MAX_RENDER_TEXT */
- int resolution_x, resolution_y;
+ int resolution_x, resolution_y;
- struct ReportList *reports;
+ struct ReportList *reports;
- /* Depsgraph */
- struct Depsgraph *depsgraph;
+ /* Depsgraph */
+ struct Depsgraph *depsgraph;
- /* callback for render pass query */
- ThreadMutex update_render_passes_mutex;
- update_render_passes_cb_t update_render_passes_cb;
- void *update_render_passes_data;
+ /* callback for render pass query */
+ ThreadMutex update_render_passes_mutex;
+ update_render_passes_cb_t update_render_passes_cb;
+ void *update_render_passes_data;
- rctf last_viewplane;
- rcti last_disprect;
- float last_viewmat[4][4];
- int last_winx, last_winy;
+ rctf last_viewplane;
+ rcti last_disprect;
+ float last_viewmat[4][4];
+ int last_winx, last_winy;
} RenderEngine;
RenderEngine *RE_engine_create(RenderEngineType *type);
RenderEngine *RE_engine_create_ex(RenderEngineType *type, bool 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);
-void RE_result_load_from_file(struct RenderResult *result, struct ReportList *reports, const char *filename);
+void RE_layer_load_from_file(
+ struct RenderLayer *layer, struct ReportList *reports, const char *filename, int x, int y);
+void RE_result_load_from_file(struct RenderResult *result,
+ struct ReportList *reports,
+ const char *filename);
-struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname);
+struct RenderResult *RE_engine_begin_result(
+ RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname);
void RE_engine_update_result(RenderEngine *engine, struct RenderResult *result);
-void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername);
-void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, bool cancel, bool highlight, bool merge_results);
+void RE_engine_add_pass(RenderEngine *engine,
+ const char *name,
+ int channels,
+ const char *chan_id,
+ const char *layername);
+void RE_engine_end_result(RenderEngine *engine,
+ struct RenderResult *result,
+ bool cancel,
+ bool highlight,
+ bool merge_results);
struct RenderResult *RE_engine_get_result(struct RenderEngine *engine);
const char *RE_engine_active_view_get(RenderEngine *engine);
void RE_engine_active_view_set(RenderEngine *engine, const char *viewname);
-float RE_engine_get_camera_shift_x(RenderEngine *engine, struct Object *camera, bool use_spherical_stereo);
-void RE_engine_get_camera_model_matrix(RenderEngine *engine, struct Object *camera, bool use_spherical_stereo, float *r_modelmat);
+float RE_engine_get_camera_shift_x(RenderEngine *engine,
+ struct Object *camera,
+ bool use_spherical_stereo);
+void RE_engine_get_camera_model_matrix(RenderEngine *engine,
+ struct Object *camera,
+ bool use_spherical_stereo,
+ float *r_modelmat);
bool RE_engine_get_spherical_stereo(RenderEngine *engine, struct Object *camera);
bool RE_engine_test_break(RenderEngine *engine);
@@ -167,10 +199,18 @@ bool RE_engine_is_external(struct Render *re);
void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe);
-void RE_engine_update_render_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer,
- update_render_passes_cb_t callback, void *callback_data);
-void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer,
- const char *name, int channels, const char *chanid, int type);
+void RE_engine_update_render_passes(struct RenderEngine *engine,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ update_render_passes_cb_t callback,
+ void *callback_data);
+void RE_engine_register_pass(struct RenderEngine *engine,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ const char *name,
+ int channels,
+ const char *chanid,
+ int type);
/* Engine Types */
@@ -184,8 +224,9 @@ RenderEngineType *RE_engines_find(const char *idname);
rcti *RE_engine_get_current_tiles(struct Render *re, int *r_total_tiles, bool *r_needs_free);
struct RenderData *RE_engine_get_render_data(struct Render *re);
-void RE_bake_engine_set_engine_parameters(
- struct Render *re, struct Main *bmain, struct Scene *scene);
+void RE_bake_engine_set_engine_parameters(struct Render *re,
+ struct Main *bmain,
+ struct Scene *scene);
void RE_engine_free_blender_memory(struct RenderEngine *engine);
diff --git a/source/blender/render/extern/include/RE_multires_bake.h b/source/blender/render/extern/include/RE_multires_bake.h
index 626910701e0..6abd9be6608 100644
--- a/source/blender/render/extern/include/RE_multires_bake.h
+++ b/source/blender/render/extern/include/RE_multires_bake.h
@@ -28,37 +28,37 @@ struct MultiresBakeRender;
struct Scene;
typedef struct MultiresBakeRender {
- Scene *scene;
- DerivedMesh *lores_dm, *hires_dm;
- bool simple;
- int bake_filter; /* Bake-filter, aka margin */
- int lvl, tot_lvl;
- short mode;
- bool use_lores_mesh; /* Use low-resolution mesh when baking displacement maps */
+ Scene *scene;
+ DerivedMesh *lores_dm, *hires_dm;
+ bool simple;
+ int bake_filter; /* Bake-filter, aka margin */
+ int lvl, tot_lvl;
+ short mode;
+ bool use_lores_mesh; /* Use low-resolution mesh when baking displacement maps */
- /* material aligned image array (for per-face bake image) */
- struct {
- Image **array;
- int len;
- } ob_image;
+ /* material aligned image array (for per-face bake image) */
+ struct {
+ Image **array;
+ int len;
+ } ob_image;
- int number_of_rays; /* Number of rays to be cast when doing AO baking */
- float bias; /* Bias between object and start ray point when doing AO baking */
+ int number_of_rays; /* Number of rays to be cast when doing AO baking */
+ float bias; /* Bias between object and start ray point when doing AO baking */
- int tot_obj, tot_image;
- ListBase image;
+ int tot_obj, tot_image;
+ ListBase image;
- int baked_objects, baked_faces;
+ int baked_objects, baked_faces;
- int raytrace_structure; /* Optimization structure to be used for AO baking */
- int octree_resolution; /* Reslution of octotree when using octotree optimization structure */
- int threads; /* Number of threads to be used for baking */
+ int raytrace_structure; /* Optimization structure to be used for AO baking */
+ int octree_resolution; /* Reslution of octotree when using octotree optimization structure */
+ int threads; /* Number of threads to be used for baking */
- float user_scale; /* User scale used to scale displacement when baking derivative map. */
+ float user_scale; /* User scale used to scale displacement when baking derivative map. */
- short *stop;
- short *do_update;
- float *progress;
+ short *stop;
+ short *do_update;
+ float *progress;
} MultiresBakeRender;
void RE_multires_bake_images(struct MultiresBakeRender *bkr);
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 83217c6b009..0e7399d4a0d 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -48,7 +48,7 @@ struct bNodeTree;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* length of the scene name + passname */
-#define RE_MAXNAME ((MAX_ID_NAME - 2) + 10)
+#define RE_MAXNAME ((MAX_ID_NAME - 2) + 10)
/* only used as handle */
typedef struct Render Render;
@@ -62,118 +62,116 @@ typedef struct Render Render;
*/
typedef struct RenderView {
- struct RenderView *next, *prev;
- char name[64]; /* EXR_VIEW_MAXNAME */
+ struct RenderView *next, *prev;
+ char name[64]; /* EXR_VIEW_MAXNAME */
- /* if this exists, result of composited layers */
- float *rectf;
- /* if this exists, result of composited layers */
- float *rectz;
- /* optional, 32 bits version of picture, used for sequencer, ogl render and image curves */
- int *rect32;
+ /* if this exists, result of composited layers */
+ float *rectf;
+ /* if this exists, result of composited layers */
+ float *rectz;
+ /* optional, 32 bits version of picture, used for sequencer, ogl render and image curves */
+ int *rect32;
} RenderView;
typedef struct RenderPass {
- struct RenderPass *next, *prev;
- int channels;
- char name[64]; /* amount defined in openexr_multi.h */
- char chan_id[8]; /* amount defined in openexr_multi.h */
- float *rect;
- int rectx, recty;
-
- char fullname[64]; /* EXR_PASS_MAXNAME */
- char view[64]; /* EXR_VIEW_MAXNAME */
- int view_id; /* quick lookup */
-
- int pad;
+ struct RenderPass *next, *prev;
+ int channels;
+ char name[64]; /* amount defined in openexr_multi.h */
+ char chan_id[8]; /* amount defined in openexr_multi.h */
+ float *rect;
+ int rectx, recty;
+
+ char fullname[64]; /* EXR_PASS_MAXNAME */
+ char view[64]; /* EXR_VIEW_MAXNAME */
+ int view_id; /* quick lookup */
+
+ int pad;
} RenderPass;
-
/* a renderlayer is a full image, but with all passes and samples */
/* size of the rects is defined in RenderResult */
/* after render, the Combined pass is in combined, for renderlayers read from files it is a real pass */
typedef struct RenderLayer {
- struct RenderLayer *next, *prev;
+ struct RenderLayer *next, *prev;
- /* copy of RenderData */
- char name[RE_MAXNAME];
- int layflag, passflag, pass_xor;
+ /* copy of RenderData */
+ char name[RE_MAXNAME];
+ int layflag, passflag, pass_xor;
- /* MULTIVIEW_TODO: acolrect and scolrect are not supported by multiview at the moment.
- * If they are really required they should be in RenderView instead */
+ /* MULTIVIEW_TODO: acolrect and scolrect are not supported by multiview at the moment.
+ * If they are really required they should be in RenderView instead */
- float *acolrect; /* 4 float, optional transparent buffer, needs storage for display updates */
- float *scolrect; /* 4 float, optional strand buffer, needs storage for display updates */
- int *display_buffer; /* 4 char, optional color managed display buffer which is used when
- * Save Buffer is enabled to display combined pass of the screen. */
- int rectx, recty;
+ float *acolrect; /* 4 float, optional transparent buffer, needs storage for display updates */
+ float *scolrect; /* 4 float, optional strand buffer, needs storage for display updates */
+ int *display_buffer; /* 4 char, optional color managed display buffer which is used when
+ * Save Buffer is enabled to display combined pass of the screen. */
+ int rectx, recty;
- /* optional saved endresult on disk */
- void *exrhandle;
+ /* optional saved endresult on disk */
+ void *exrhandle;
- ListBase passes;
+ ListBase passes;
} RenderLayer;
typedef struct RenderResult {
- struct RenderResult *next, *prev;
+ struct RenderResult *next, *prev;
- /* target image size */
- int rectx, recty;
- short crop, sample_nr;
+ /* target image size */
+ int rectx, recty;
+ short crop, sample_nr;
- /* the following rect32, rectf and rectz buffers are for temporary storage only, for RenderResult structs
- * created in #RE_AcquireResultImage - which do not have RenderView */
+ /* the following rect32, rectf and rectz buffers are for temporary storage only, for RenderResult structs
+ * created in #RE_AcquireResultImage - which do not have RenderView */
- /* optional, 32 bits version of picture, used for ogl render and image curves */
- int *rect32;
- /* if this exists, a copy of one of layers, or result of composited layers */
- float *rectf;
- /* if this exists, a copy of one of layers, or result of composited layers */
- float *rectz;
+ /* optional, 32 bits version of picture, used for ogl render and image curves */
+ int *rect32;
+ /* if this exists, a copy of one of layers, or result of composited layers */
+ float *rectf;
+ /* if this exists, a copy of one of layers, or result of composited layers */
+ float *rectz;
- /* coordinates within final image (after cropping) */
- rcti tilerect;
- /* offset to apply to get a border render in full image */
- int xof, yof;
+ /* coordinates within final image (after cropping) */
+ rcti tilerect;
+ /* offset to apply to get a border render in full image */
+ int xof, yof;
- /* the main buffers */
- ListBase layers;
+ /* the main buffers */
+ ListBase layers;
- /* multiView maps to a StringVector in OpenEXR */
- ListBase views; /* RenderView */
+ /* multiView maps to a StringVector in OpenEXR */
+ ListBase views; /* RenderView */
- /* allowing live updates: */
- volatile rcti renrect;
- volatile RenderLayer *renlay;
+ /* allowing live updates: */
+ volatile rcti renrect;
+ volatile RenderLayer *renlay;
- /* optional saved endresult on disk */
- int do_exr_tile;
+ /* optional saved endresult on disk */
+ int do_exr_tile;
- /* for render results in Image, verify validity for sequences */
- int framenr;
+ /* for render results in Image, verify validity for sequences */
+ int framenr;
- /* for acquire image, to indicate if it there is a combined layer */
- int have_combined;
+ /* for acquire image, to indicate if it there is a combined layer */
+ int have_combined;
- /* render info text */
- char *text;
- char *error;
+ /* render info text */
+ char *text;
+ char *error;
- struct StampData *stamp_data;
+ struct StampData *stamp_data;
} RenderResult;
-
typedef struct RenderStats {
- int cfra;
- int totface, totvert, totstrand, tothalo, totlamp, totpart;
- short curfield, curblur, curpart, partsdone, convertdone, curfsa;
- bool localview;
- double starttime, lastframetime;
- const char *infostr, *statstr;
- char scene_name[MAX_ID_NAME - 2];
- float mem_used, mem_peak;
+ int cfra;
+ int totface, totvert, totstrand, tothalo, totlamp, totpart;
+ short curfield, curblur, curpart, partsdone, convertdone, curfsa;
+ bool localview;
+ double starttime, lastframetime;
+ const char *infostr, *statstr;
+ char scene_name[MAX_ID_NAME - 2];
+ float mem_used, mem_peak;
} RenderStats;
/* *********************** API ******************** */
@@ -217,24 +215,37 @@ void RE_ClearResult(struct Render *re);
struct RenderStats *RE_GetStats(struct Render *re);
void RE_ResultGet32(struct Render *re, unsigned int *rect);
-void RE_AcquiredResultGet32(struct Render *re, struct RenderResult *result, unsigned int *rect, const int view_id);
+void RE_AcquiredResultGet32(struct Render *re,
+ struct RenderResult *result,
+ unsigned int *rect,
+ const int view_id);
-void RE_render_result_rect_from_ibuf(
- struct RenderResult *rr, struct RenderData *rd,
- struct ImBuf *ibuf, const int view_id);
+void RE_render_result_rect_from_ibuf(struct RenderResult *rr,
+ struct RenderData *rd,
+ struct ImBuf *ibuf,
+ const int view_id);
struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name);
-float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, const char *name, const char *viewname);
+float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl,
+ const char *name,
+ const char *viewname);
bool RE_HasSingleLayer(struct Render *re);
/* add passes for grease pencil */
-struct RenderPass *RE_create_gp_pass(struct RenderResult *rr, const char *layername, const char *viewname);
+struct RenderPass *RE_create_gp_pass(struct RenderResult *rr,
+ const char *layername,
+ const char *viewname);
/* obligatory initialize call, disprect is optional */
-void RE_InitState(struct Render *re, struct Render *source, struct RenderData *rd,
- struct ListBase *render_layers, struct ViewLayer *single_layer,
- int winx, int winy, rcti *disprect);
+void RE_InitState(struct Render *re,
+ struct Render *source,
+ struct RenderData *rd,
+ struct ListBase *render_layers,
+ struct ViewLayer *single_layer,
+ int winx,
+ int winy,
+ rcti *disprect);
void RE_ChangeResolution(struct Render *re, int winx, int winy, rcti *disprect);
void RE_ChangeModeFlag(struct Render *re, int flag, bool clear);
@@ -254,22 +265,41 @@ void RE_GetViewPlane(struct Render *re, rctf *r_viewplane, rcti *r_disprect);
/* set the render threads based on the commandline and autothreads setting */
void RE_init_threadcount(Render *re);
-bool RE_WriteRenderViewsImage(
- struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, const bool stamp, char *name);
-bool RE_WriteRenderViewsMovie(
- struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, struct RenderData *rd,
- struct bMovieHandle *mh, void **movie_ctx_arr,
- const int totvideos, bool preview);
+bool RE_WriteRenderViewsImage(struct ReportList *reports,
+ struct RenderResult *rr,
+ struct Scene *scene,
+ const bool stamp,
+ char *name);
+bool RE_WriteRenderViewsMovie(struct ReportList *reports,
+ struct RenderResult *rr,
+ struct Scene *scene,
+ struct RenderData *rd,
+ struct bMovieHandle *mh,
+ void **movie_ctx_arr,
+ const int totvideos,
+ bool preview);
/* only RE_NewRender() needed, main Blender render calls */
-void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene,
- struct ViewLayer *single_layer, struct Object *camera_override,
- int frame, const bool write_still);
-void RE_BlenderAnim(struct Render *re, struct Main *bmain, struct Scene *scene,
- struct ViewLayer *single_layer, struct Object *camera_override,
- int sfra, int efra, int tfra);
+void RE_BlenderFrame(struct Render *re,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *single_layer,
+ struct Object *camera_override,
+ int frame,
+ const bool write_still);
+void RE_BlenderAnim(struct Render *re,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *single_layer,
+ struct Object *camera_override,
+ int sfra,
+ int efra,
+ int tfra);
#ifdef WITH_FREESTYLE
-void RE_RenderFreestyleStrokes(struct Render *re, struct Main *bmain, struct Scene *scene, int render);
+void RE_RenderFreestyleStrokes(struct Render *re,
+ struct Main *bmain,
+ struct Scene *scene,
+ int render);
void RE_RenderFreestyleExternal(struct Render *re);
#endif
@@ -283,24 +313,35 @@ void RE_SetReports(struct Render *re, struct ReportList *reports);
void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene);
bool RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode);
-bool RE_WriteRenderResult(
- struct ReportList *reports, RenderResult *rr, const char *filename,
- struct ImageFormatData *imf, const char *view, int layer);
+bool RE_WriteRenderResult(struct ReportList *reports,
+ RenderResult *rr,
+ const char *filename,
+ struct ImageFormatData *imf,
+ const char *view,
+ int layer);
struct RenderResult *RE_MultilayerConvert(
- void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty);
+ void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty);
/* display and event callbacks */
-void RE_display_init_cb (struct Render *re, void *handle, void (*f)(void *handle, RenderResult *rr));
-void RE_display_clear_cb(struct Render *re, void *handle, void (*f)(void *handle, RenderResult *rr));
-void RE_display_update_cb(struct Render *re, void *handle, void (*f)(void *handle, RenderResult *rr, volatile struct rcti *rect));
-void RE_stats_draw_cb (struct Render *re, void *handle, void (*f)(void *handle, RenderStats *rs));
-void RE_progress_cb (struct Render *re, void *handle, void (*f)(void *handle, float));
-void RE_draw_lock_cb (struct Render *re, void *handle, void (*f)(void *handle, int));
-void RE_test_break_cb (struct Render *re, void *handle, int (*f)(void *handle));
-void RE_current_scene_update_cb(struct Render *re, void *handle, void (*f)(void *handle, struct Scene *scene));
-
-void RE_gl_context_create(Render *re);
-void RE_gl_context_destroy(Render *re);
+void RE_display_init_cb(struct Render *re,
+ void *handle,
+ void (*f)(void *handle, RenderResult *rr));
+void RE_display_clear_cb(struct Render *re,
+ void *handle,
+ void (*f)(void *handle, RenderResult *rr));
+void RE_display_update_cb(struct Render *re,
+ void *handle,
+ void (*f)(void *handle, RenderResult *rr, volatile struct rcti *rect));
+void RE_stats_draw_cb(struct Render *re, void *handle, void (*f)(void *handle, RenderStats *rs));
+void RE_progress_cb(struct Render *re, void *handle, void (*f)(void *handle, float));
+void RE_draw_lock_cb(struct Render *re, void *handle, void (*f)(void *handle, int));
+void RE_test_break_cb(struct Render *re, void *handle, int (*f)(void *handle));
+void RE_current_scene_update_cb(struct Render *re,
+ void *handle,
+ void (*f)(void *handle, struct Scene *scene));
+
+void RE_gl_context_create(Render *re);
+void RE_gl_context_destroy(Render *re);
void *RE_gl_context_get(Render *re);
void *RE_gpu_context_get(Render *re);
@@ -312,13 +353,17 @@ int RE_seq_render_active(struct Scene *scene, struct RenderData *rd);
bool RE_layers_have_name(struct RenderResult *result);
bool RE_passes_have_name(struct RenderLayer *rl);
-struct RenderPass *RE_pass_find_by_name(volatile struct RenderLayer *rl, const char *name, const char *viewname);
-struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname);
+struct RenderPass *RE_pass_find_by_name(volatile struct RenderLayer *rl,
+ const char *name,
+ const char *viewname);
+struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl,
+ int passtype,
+ const char *viewname);
/* shaded view or baking options */
-#define RE_BAKE_NORMALS 0
-#define RE_BAKE_DISPLACEMENT 1
-#define RE_BAKE_AO 2
+#define RE_BAKE_NORMALS 0
+#define RE_BAKE_DISPLACEMENT 1
+#define RE_BAKE_AO 2
void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[4][4]);
void RE_GetCameraWindowWithOverscan(struct Render *re, float mat[4][4], float overscan);
@@ -326,7 +371,10 @@ void RE_GetCameraModelMatrix(struct Render *re, struct Object *camera, float r_m
struct Scene *RE_GetScene(struct Render *re);
void RE_SetScene(struct Render *re, struct Scene *sce);
-bool RE_is_rendering_allowed(struct Scene *scene, struct ViewLayer *single_layer, struct Object *camera_override, struct ReportList *reports);
+bool RE_is_rendering_allowed(struct Scene *scene,
+ struct ViewLayer *single_layer,
+ struct Object *camera_override,
+ struct ReportList *reports);
bool RE_allow_render_generic_object(struct Object *ob);
diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h
index dd457751545..6771eb53abd 100644
--- a/source/blender/render/extern/include/RE_render_ext.h
+++ b/source/blender/render/extern/include/RE_render_ext.h
@@ -20,7 +20,6 @@
* \ingroup render
*/
-
#ifndef __RE_RENDER_EXT_H__
#define __RE_RENDER_EXT_H__
@@ -38,10 +37,19 @@ struct ViewLayer;
/* render_texture.c */
/* used by particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */
-int externtex(
- const struct MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta,
- const int thread, struct ImagePool *pool, const bool skip_load_image, const bool texnode_preview);
-void texture_rgb_blend(float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype);
+int externtex(const struct MTex *mtex,
+ const float vec[3],
+ float *tin,
+ float *tr,
+ float *tg,
+ float *tb,
+ float *ta,
+ const int thread,
+ struct ImagePool *pool,
+ const bool skip_load_image,
+ const bool texnode_preview);
+void texture_rgb_blend(
+ float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype);
float texture_value_blend(float tex, float out, float fact, float facg, int blendtype);
void RE_texture_rng_init(void);
@@ -53,20 +61,17 @@ void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, flo
/* pointdensity.c */
struct PointDensity;
-void RE_point_density_cache(
- struct Depsgraph *depsgraph,
- struct PointDensity *pd);
+void RE_point_density_cache(struct Depsgraph *depsgraph, struct PointDensity *pd);
-void RE_point_density_minmax(
- struct Depsgraph *depsgraph,
- struct PointDensity *pd,
- float r_min[3], float r_max[3]);
+void RE_point_density_minmax(struct Depsgraph *depsgraph,
+ struct PointDensity *pd,
+ float r_min[3],
+ float r_max[3]);
-void RE_point_density_sample(
- struct Depsgraph *depsgraph,
- struct PointDensity *pd,
- const int resolution,
- float *values);
+void RE_point_density_sample(struct Depsgraph *depsgraph,
+ struct PointDensity *pd,
+ const int resolution,
+ float *values);
void RE_point_density_free(struct PointDensity *pd);
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index 5fc9431af3d..c5e3575d1f9 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -20,7 +20,6 @@
* \ingroup render
*/
-
#ifndef __RE_SHADER_EXT_H__
#define __RE_SHADER_EXT_H__
@@ -31,14 +30,14 @@
/* localized texture result data */
/* note; tr tg tb ta has to remain in this order */
typedef struct TexResult {
- float tin, tr, tg, tb, ta;
- int talpha;
- float *nor;
+ float tin, tr, tg, tb, ta;
+ int talpha;
+ float *nor;
} TexResult;
typedef struct BakeImBufuserData {
- float *displacement_buffer;
- char *mask_buffer;
+ float *displacement_buffer;
+ char *mask_buffer;
} BakeImBufuserData;
/* node shaders... */
@@ -51,7 +50,8 @@ struct Tex;
/* this one uses nodes */
int multitex_ext(struct Tex *tex,
float texvec[3],
- float dxt[3], float dyt[3],
+ float dxt[3],
+ float dyt[3],
int osatex,
struct TexResult *texres,
const short thread,
@@ -59,9 +59,22 @@ int multitex_ext(struct Tex *tex,
bool scene_color_manage,
const bool skip_load_image);
/* nodes disabled */
-int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image);
+int multitex_ext_safe(struct Tex *tex,
+ float texvec[3],
+ struct TexResult *texres,
+ struct ImagePool *pool,
+ bool scene_color_manage,
+ const bool skip_load_image);
/* 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 MTex *mtex, struct ImagePool *pool);
+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 MTex *mtex,
+ struct ImagePool *pool);
#endif /* __RE_SHADER_EXT_H__ */
diff --git a/source/blender/render/intern/include/initrender.h b/source/blender/render/intern/include/initrender.h
index 1c290084fbc..99282a8e703 100644
--- a/source/blender/render/intern/include/initrender.h
+++ b/source/blender/render/intern/include/initrender.h
@@ -21,7 +21,6 @@
* \ingroup render
*/
-
#ifndef __INITRENDER_H__
#define __INITRENDER_H__
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
index d7636a150ef..24356194f5d 100644
--- a/source/blender/render/intern/include/render_result.h
+++ b/source/blender/render/intern/include/render_result.h
@@ -24,13 +24,13 @@
#ifndef __RENDER_RESULT_H__
#define __RENDER_RESULT_H__
-#define PASS_VECTOR_MAX 10000.0f
+#define PASS_VECTOR_MAX 10000.0f
-#define RR_USE_MEM 0
-#define RR_USE_EXR 1
+#define RR_USE_MEM 0
+#define RR_USE_EXR 1
-#define RR_ALL_LAYERS NULL
-#define RR_ALL_VIEWS NULL
+#define RR_ALL_LAYERS NULL
+#define RR_ALL_VIEWS NULL
struct ColorManagedDisplaySettings;
struct ColorManagedViewSettings;
@@ -47,9 +47,14 @@ struct rcti;
/* New */
struct RenderResult *render_result_new(struct Render *re,
- struct rcti *partrct, int crop, int savebuffers, const char *layername, const char *viewname);
+ struct rcti *partrct,
+ int crop,
+ int savebuffers,
+ const char *layername,
+ const char *viewname);
-struct RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty);
+struct RenderResult *render_result_new_from_exr(
+ void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty);
void render_result_view_new(struct RenderResult *rr, const char *viewname);
void render_result_views_new(struct RenderResult *rr, struct RenderData *rd);
@@ -61,7 +66,12 @@ void render_result_merge(struct RenderResult *rr, struct RenderResult *rrpart);
/* Add Passes */
void render_result_clone_passes(struct Render *re, struct RenderResult *rr, const char *viewname);
-void render_result_add_pass(struct RenderResult *rr, const char *name, int channels, const char *chan_id, const char *layername, const char *viewname);
+void render_result_add_pass(struct RenderResult *rr,
+ const char *name,
+ int channels,
+ const char *chan_id,
+ const char *layername,
+ const char *viewname);
/* Free */
@@ -80,12 +90,23 @@ void render_result_exr_file_begin(struct Render *re, struct RenderEngine *engine
void render_result_exr_file_end(struct Render *re, struct RenderEngine *engine);
/* render pass wrapper for gpencil */
-struct RenderPass *gp_add_pass(struct RenderResult *rr, struct RenderLayer *rl, int channels, const char *name, const char *viewname);
-
-void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart, const char *viewname);
-
-void render_result_exr_file_path(struct Scene *scene, const char *layname, int sample, char *filepath);
-int render_result_exr_file_read_path(struct RenderResult *rr, struct RenderLayer *rl_single, const char *filepath);
+struct RenderPass *gp_add_pass(struct RenderResult *rr,
+ struct RenderLayer *rl,
+ int channels,
+ const char *name,
+ const char *viewname);
+
+void render_result_exr_file_merge(struct RenderResult *rr,
+ struct RenderResult *rrpart,
+ const char *viewname);
+
+void render_result_exr_file_path(struct Scene *scene,
+ const char *layname,
+ int sample,
+ char *filepath);
+int render_result_exr_file_read_path(struct RenderResult *rr,
+ struct RenderLayer *rl_single,
+ const char *filepath);
/* EXR cache */
@@ -94,40 +115,42 @@ bool render_result_exr_file_cache_read(struct Render *re);
/* Combined Pixel Rect */
-struct ImBuf *render_result_rect_to_ibuf(struct RenderResult *rr, struct RenderData *rd, const int view_id);
+struct ImBuf *render_result_rect_to_ibuf(struct RenderResult *rr,
+ struct RenderData *rd,
+ const int view_id);
void render_result_rect_fill_zero(struct RenderResult *rr, const int view_id);
void render_result_rect_get_pixels(struct RenderResult *rr,
- unsigned int *rect, int rectx, int recty,
- const struct ColorManagedViewSettings *view_settings,
- const struct ColorManagedDisplaySettings *display_settings,
- const int view_id);
+ unsigned int *rect,
+ int rectx,
+ int recty,
+ const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings,
+ const int view_id);
void render_result_views_shallowcopy(struct RenderResult *dst, struct RenderResult *src);
void render_result_views_shallowdelete(struct RenderResult *rr);
bool render_result_has_views(struct RenderResult *rr);
-#define FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re_, iter_) \
-{ \
- int nr_; \
- ViewLayer *iter_; \
- for (nr_ = 0, iter_ = (re_)->view_layers.first; \
- iter_ != NULL; \
- iter_ = iter_->next, nr_++) \
- { \
- if (!G.background && (re_)->r.scemode & R_SINGLE_LAYER) { \
- if (nr_ != re->active_view_layer) { \
- continue; \
- } \
- } \
- else { \
- if ((iter_->flag & VIEW_LAYER_RENDER) == 0) { \
- continue; \
- } \
- }
-
-#define FOREACH_VIEW_LAYER_TO_RENDER_END \
- } \
-} ((void)0)
+#define FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re_, iter_) \
+ { \
+ int nr_; \
+ ViewLayer *iter_; \
+ for (nr_ = 0, iter_ = (re_)->view_layers.first; iter_ != NULL; iter_ = iter_->next, nr_++) { \
+ if (!G.background && (re_)->r.scemode & R_SINGLE_LAYER) { \
+ if (nr_ != re->active_view_layer) { \
+ continue; \
+ } \
+ } \
+ else { \
+ if ((iter_->flag & VIEW_LAYER_RENDER) == 0) { \
+ continue; \
+ } \
+ }
+
+#define FOREACH_VIEW_LAYER_TO_RENDER_END \
+ } \
+ } \
+ ((void)0)
#endif /* __RENDER_RESULT_H__ */
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index a4533c6cdec..69e2ea991dd 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -21,7 +21,6 @@
* \ingroup render
*/
-
#ifndef __RENDER_TYPES_H__
#define __RENDER_TYPES_H__
@@ -45,118 +44,118 @@ struct ReportList;
/* this is handed over to threaded hiding/passes/shading engine */
typedef struct RenderPart {
- struct RenderPart *next, *prev;
+ struct RenderPart *next, *prev;
- RenderResult *result; /* result of part rendering */
- ListBase fullresult; /* optional full sample buffers */
+ RenderResult *result; /* result of part rendering */
+ ListBase fullresult; /* optional full sample buffers */
- rcti disprect; /* part coordinates within total picture */
- int rectx, recty; /* the size */
- int nr; /* nr is partnr */
- short status;
+ rcti disprect; /* part coordinates within total picture */
+ int rectx, recty; /* the size */
+ int nr; /* nr is partnr */
+ short status;
} RenderPart;
enum {
- PART_STATUS_NONE = 0,
- PART_STATUS_IN_PROGRESS = 1,
- PART_STATUS_RENDERED = 2,
- PART_STATUS_MERGED = 3,
+ PART_STATUS_NONE = 0,
+ PART_STATUS_IN_PROGRESS = 1,
+ PART_STATUS_RENDERED = 2,
+ PART_STATUS_MERGED = 3,
};
/* controls state of render, everything that's read-only during render stage */
struct Render {
- struct Render *next, *prev;
- char name[RE_MAXNAME];
- int slot;
-
- /* state settings */
- short flag, ok, result_ok;
-
- /* result of rendering */
- RenderResult *result;
- /* if render with single-layer option, other rendered layers are stored here */
- RenderResult *pushedresult;
- /* a list of RenderResults, for fullsample */
- ListBase fullresult;
- /* read/write mutex, all internal code that writes to re->result must use a
- * write lock, all external code must use a read lock. internal code is assumed
- * to not conflict with writes, so no lock used for that */
- ThreadRWMutex resultmutex;
-
- /* window size, display rect, viewplane */
- int winx, winy; /* buffer width and height with percentage applied
- * without border & crop. convert to long before multiplying together to avoid overflow. */
- rcti disprect; /* part within winx winy */
- rctf viewplane; /* mapped on winx winy */
-
- /* final picture width and height (within disprect) */
- int rectx, recty;
-
- /* real maximum size of parts after correction for minimum
- * partx*xparts can be larger than rectx, in that case last part is smaller */
- int partx, party;
-
- /* Camera transform, only used by Freestyle. */
- float winmat[4][4];
-
- /* clippping */
- float clip_start;
- float clip_end;
-
- /* main, scene, and its full copy of renderdata and world */
- struct Main *main;
- Scene *scene;
- RenderData r;
- ListBase view_layers;
- int active_view_layer;
- struct Object *camera_override;
-
- ThreadRWMutex partsmutex;
- ListBase parts;
-
- /* render engine */
- struct RenderEngine *engine;
+ struct Render *next, *prev;
+ char name[RE_MAXNAME];
+ int slot;
+
+ /* state settings */
+ short flag, ok, result_ok;
+
+ /* result of rendering */
+ RenderResult *result;
+ /* if render with single-layer option, other rendered layers are stored here */
+ RenderResult *pushedresult;
+ /* a list of RenderResults, for fullsample */
+ ListBase fullresult;
+ /* read/write mutex, all internal code that writes to re->result must use a
+ * write lock, all external code must use a read lock. internal code is assumed
+ * to not conflict with writes, so no lock used for that */
+ ThreadRWMutex resultmutex;
+
+ /* window size, display rect, viewplane */
+ int winx, winy; /* buffer width and height with percentage applied
+ * without border & crop. convert to long before multiplying together to avoid overflow. */
+ rcti disprect; /* part within winx winy */
+ rctf viewplane; /* mapped on winx winy */
+
+ /* final picture width and height (within disprect) */
+ int rectx, recty;
+
+ /* real maximum size of parts after correction for minimum
+ * partx*xparts can be larger than rectx, in that case last part is smaller */
+ int partx, party;
+
+ /* Camera transform, only used by Freestyle. */
+ float winmat[4][4];
+
+ /* clippping */
+ float clip_start;
+ float clip_end;
+
+ /* main, scene, and its full copy of renderdata and world */
+ struct Main *main;
+ Scene *scene;
+ RenderData r;
+ ListBase view_layers;
+ int active_view_layer;
+ struct Object *camera_override;
+
+ ThreadRWMutex partsmutex;
+ ListBase parts;
+
+ /* render engine */
+ struct RenderEngine *engine;
#ifdef WITH_FREESTYLE
- struct Main *freestyle_bmain;
- ListBase freestyle_renders;
+ struct Main *freestyle_bmain;
+ ListBase freestyle_renders;
#endif
- /* callbacks */
- void (*display_init)(void *handle, RenderResult *rr);
- void *dih;
- void (*display_clear)(void *handle, RenderResult *rr);
- void *dch;
- void (*display_update)(void *handle, RenderResult *rr, volatile rcti *rect);
- void *duh;
- void (*current_scene_update)(void *handle, struct Scene *scene);
- void *suh;
+ /* callbacks */
+ void (*display_init)(void *handle, RenderResult *rr);
+ void *dih;
+ void (*display_clear)(void *handle, RenderResult *rr);
+ void *dch;
+ void (*display_update)(void *handle, RenderResult *rr, volatile rcti *rect);
+ void *duh;
+ void (*current_scene_update)(void *handle, struct Scene *scene);
+ void *suh;
- void (*stats_draw)(void *handle, RenderStats *ri);
- void *sdh;
- void (*progress)(void *handle, float i);
- void *prh;
+ void (*stats_draw)(void *handle, RenderStats *ri);
+ void *sdh;
+ void (*progress)(void *handle, float i);
+ void *prh;
- void (*draw_lock)(void *handle, int i);
- void *dlh;
- int (*test_break)(void *handle);
- void *tbh;
+ void (*draw_lock)(void *handle, int i);
+ void *dlh;
+ int (*test_break)(void *handle);
+ void *tbh;
- RenderStats i;
+ RenderStats i;
- struct ReportList *reports;
+ struct ReportList *reports;
- void **movie_ctx_arr;
- char viewname[MAX_NAME];
+ void **movie_ctx_arr;
+ char viewname[MAX_NAME];
- /* TODO replace by a whole draw manager. */
- void *gl_context;
- void *gpu_context;
+ /* TODO replace by a whole draw manager. */
+ void *gl_context;
+ void *gpu_context;
};
/* **************** defines ********************* */
/* R.flag */
-#define R_ANIMATION 1
+#define R_ANIMATION 1
#endif /* __RENDER_TYPES_H__ */
diff --git a/source/blender/render/intern/include/renderpipeline.h b/source/blender/render/intern/include/renderpipeline.h
index 7479de8b707..12b231ef55f 100644
--- a/source/blender/render/intern/include/renderpipeline.h
+++ b/source/blender/render/intern/include/renderpipeline.h
@@ -21,7 +21,6 @@
* \ingroup render
*/
-
#ifndef __RENDERPIPELINE_H__
#define __RENDERPIPELINE_H__
@@ -32,7 +31,9 @@ struct RenderLayer;
struct RenderResult;
struct RenderLayer *render_get_active_layer(struct Render *re, struct RenderResult *rr);
-void render_update_anim_renderdata(struct Render *re, struct RenderData *rd, struct ListBase *render_layers);
+void render_update_anim_renderdata(struct Render *re,
+ struct RenderData *rd,
+ struct ListBase *render_layers);
void render_copy_renderdata(struct RenderData *to, struct RenderData *from);
#endif /* __RENDERPIPELINE_H__ */
diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h
index 7c86f700652..d783263c8b8 100644
--- a/source/blender/render/intern/include/texture.h
+++ b/source/blender/render/intern/include/texture.h
@@ -21,39 +21,44 @@
* \ingroup render
*/
-
#ifndef __TEXTURE_H__
#define __TEXTURE_H__
-#define BRICONT \
- texres->tin= (texres->tin-0.5f) * tex->contrast+tex->bright-0.5f; \
- if (!(tex->flag & TEX_NO_CLAMP)) { \
- if (texres->tin < 0.0f) texres->tin= 0.0f; \
- else if (texres->tin > 1.0f) texres->tin= 1.0f; \
- } \
+#define BRICONT \
+ texres->tin = (texres->tin - 0.5f) * tex->contrast + tex->bright - 0.5f; \
+ if (!(tex->flag & TEX_NO_CLAMP)) { \
+ if (texres->tin < 0.0f) \
+ texres->tin = 0.0f; \
+ else if (texres->tin > 1.0f) \
+ texres->tin = 1.0f; \
+ }
-#define BRICONTRGB \
- texres->tr= tex->rfac*((texres->tr-0.5f)*tex->contrast+tex->bright-0.5f); \
- texres->tg= tex->gfac*((texres->tg-0.5f)*tex->contrast+tex->bright-0.5f); \
- texres->tb= tex->bfac*((texres->tb-0.5f)*tex->contrast+tex->bright-0.5f); \
- if (!(tex->flag & TEX_NO_CLAMP)) { \
- if (texres->tr < 0.0f) texres->tr= 0.0f; \
- if (texres->tg < 0.0f) texres->tg= 0.0f; \
- if (texres->tb < 0.0f) texres->tb= 0.0f; \
- } \
- if (tex->saturation != 1.0f) { \
- float _hsv[3]; \
- rgb_to_hsv(texres->tr, texres->tg, texres->tb, \
- _hsv, _hsv+1, _hsv+2); \
- _hsv[1] *= tex->saturation; \
- hsv_to_rgb(_hsv[0], _hsv[1], _hsv[2], \
- &texres->tr, &texres->tg, &texres->tb); \
- if ((tex->saturation > 1.0f) && !(tex->flag & TEX_NO_CLAMP)) { \
- if (texres->tr < 0.0f) texres->tr= 0.0f; \
- if (texres->tg < 0.0f) texres->tg= 0.0f; \
- if (texres->tb < 0.0f) texres->tb= 0.0f; \
- } \
- } \
+#define BRICONTRGB \
+ texres->tr = tex->rfac * ((texres->tr - 0.5f) * tex->contrast + tex->bright - 0.5f); \
+ texres->tg = tex->gfac * ((texres->tg - 0.5f) * tex->contrast + tex->bright - 0.5f); \
+ texres->tb = tex->bfac * ((texres->tb - 0.5f) * tex->contrast + tex->bright - 0.5f); \
+ if (!(tex->flag & TEX_NO_CLAMP)) { \
+ if (texres->tr < 0.0f) \
+ texres->tr = 0.0f; \
+ if (texres->tg < 0.0f) \
+ texres->tg = 0.0f; \
+ if (texres->tb < 0.0f) \
+ texres->tb = 0.0f; \
+ } \
+ if (tex->saturation != 1.0f) { \
+ float _hsv[3]; \
+ rgb_to_hsv(texres->tr, texres->tg, texres->tb, _hsv, _hsv + 1, _hsv + 2); \
+ _hsv[1] *= tex->saturation; \
+ hsv_to_rgb(_hsv[0], _hsv[1], _hsv[2], &texres->tr, &texres->tg, &texres->tb); \
+ if ((tex->saturation > 1.0f) && !(tex->flag & TEX_NO_CLAMP)) { \
+ if (texres->tr < 0.0f) \
+ texres->tr = 0.0f; \
+ if (texres->tg < 0.0f) \
+ texres->tg = 0.0f; \
+ if (texres->tb < 0.0f) \
+ texres->tb = 0.0f; \
+ } \
+ }
struct ImBuf;
struct Image;
@@ -63,8 +68,28 @@ struct TexResult;
/* 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, struct ImagePool *pool, const bool skip_load_image);
-int imagewrap(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], struct TexResult *texres, struct ImagePool *pool, const bool skip_load_image);
-void image_sample(struct Image *ima, float fx, float fy, float dx, float dy, float result[4], struct ImagePool *pool);
+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,
+ const bool skip_load_image);
+int imagewrap(struct Tex *tex,
+ struct Image *ima,
+ struct ImBuf *ibuf,
+ const float texvec[3],
+ struct TexResult *texres,
+ struct ImagePool *pool,
+ const bool skip_load_image);
+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/include/zbuf.h b/source/blender/render/intern/include/zbuf.h
index b5f4fffb0a9..bc6addd6c5f 100644
--- a/source/blender/render/intern/include/zbuf.h
+++ b/source/blender/render/intern/include/zbuf.h
@@ -18,23 +18,26 @@
* \ingroup render
*/
-
#ifndef __ZBUF_H__
#define __ZBUF_H__
/* span fill in method, is also used to localize data for zbuffering */
typedef struct ZSpan {
- int rectx, recty; /* range for clipping */
+ int rectx, recty; /* range for clipping */
- int miny1, maxy1, miny2, maxy2; /* actual filled in range */
- const float *minp1, *maxp1, *minp2, *maxp2; /* vertex pointers detect min/max range in */
- float *span1, *span2;
+ int miny1, maxy1, miny2, maxy2; /* actual filled in range */
+ const float *minp1, *maxp1, *minp2, *maxp2; /* vertex pointers detect min/max range in */
+ float *span1, *span2;
} ZSpan;
void zbuf_alloc_span(struct ZSpan *zspan, int rectx, int recty);
void zbuf_free_span(struct ZSpan *zspan);
-void zspan_scanconvert(struct ZSpan *zpan, void *handle, float *v1, float *v2, float *v3,
- void (*func)(void *, int, int, float, float) );
+void zspan_scanconvert(struct ZSpan *zpan,
+ void *handle,
+ float *v1,
+ float *v2,
+ float *v3,
+ void (*func)(void *, int, int, float, float));
#endif
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c
index 5e63f76ca80..bc0c73fd11f 100644
--- a/source/blender/render/intern/source/bake_api.c
+++ b/source/blender/render/intern/source/bake_api.c
@@ -86,611 +86,660 @@
#include "zbuf.h"
typedef struct BakeDataZSpan {
- BakePixel *pixel_array;
- int primitive_id;
- BakeImage *bk_image;
- ZSpan *zspan;
- float du_dx, du_dy;
- float dv_dx, dv_dy;
+ BakePixel *pixel_array;
+ int primitive_id;
+ BakeImage *bk_image;
+ ZSpan *zspan;
+ float du_dx, du_dy;
+ float dv_dx, dv_dy;
} BakeDataZSpan;
/**
* struct wrapping up tangent space data
*/
typedef struct TSpace {
- float tangent[3];
- float sign;
+ float tangent[3];
+ float sign;
} TSpace;
typedef struct TriTessFace {
- const MVert *mverts[3];
- const TSpace *tspace[3];
- float normal[3]; /* for flat faces */
- bool is_smooth;
+ const MVert *mverts[3];
+ const TSpace *tspace[3];
+ float normal[3]; /* for flat faces */
+ bool is_smooth;
} TriTessFace;
static void store_bake_pixel(void *handle, int x, int y, float u, float v)
{
- BakeDataZSpan *bd = (BakeDataZSpan *)handle;
- BakePixel *pixel;
+ BakeDataZSpan *bd = (BakeDataZSpan *)handle;
+ BakePixel *pixel;
- const int width = bd->bk_image->width;
- const size_t offset = bd->bk_image->offset;
- const int i = offset + y * width + x;
+ const int width = bd->bk_image->width;
+ const size_t offset = bd->bk_image->offset;
+ const int i = offset + y * width + x;
- pixel = &bd->pixel_array[i];
- pixel->primitive_id = bd->primitive_id;
+ pixel = &bd->pixel_array[i];
+ pixel->primitive_id = bd->primitive_id;
- /* At this point object_id is always 0, since this function runs for the
- * lowpoly mesh only. The object_id lookup indices are set afterwards. */
+ /* At this point object_id is always 0, since this function runs for the
+ * lowpoly mesh only. The object_id lookup indices are set afterwards. */
- copy_v2_fl2(pixel->uv, u, v);
+ copy_v2_fl2(pixel->uv, u, v);
- pixel->du_dx = bd->du_dx;
- pixel->du_dy = bd->du_dy;
- pixel->dv_dx = bd->dv_dx;
- pixel->dv_dy = bd->dv_dy;
- pixel->object_id = 0;
+ pixel->du_dx = bd->du_dx;
+ pixel->du_dy = bd->du_dy;
+ pixel->dv_dx = bd->dv_dx;
+ pixel->dv_dy = bd->dv_dy;
+ pixel->object_id = 0;
}
void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, char *mask)
{
- size_t i;
- if (!mask)
- return;
-
- /* only extend to pixels outside the mask area */
- for (i = 0; i < num_pixels; i++) {
- if (pixel_array[i].primitive_id != -1) {
- mask[i] = FILTER_MASK_USED;
- }
- }
+ size_t i;
+ if (!mask)
+ return;
+
+ /* only extend to pixels outside the mask area */
+ for (i = 0; i < num_pixels; i++) {
+ if (pixel_array[i].primitive_id != -1) {
+ mask[i] = FILTER_MASK_USED;
+ }
+ }
}
void RE_bake_margin(ImBuf *ibuf, char *mask, const int margin)
{
- /* margin */
- IMB_filter_extend(ibuf, mask, margin);
+ /* margin */
+ IMB_filter_extend(ibuf, mask, margin);
- if (ibuf->planes != R_IMF_PLANES_RGBA)
- /* clear alpha added by filtering */
- IMB_rectfill_alpha(ibuf, 1.0f);
+ if (ibuf->planes != R_IMF_PLANES_RGBA)
+ /* clear alpha added by filtering */
+ IMB_rectfill_alpha(ibuf, 1.0f);
}
-
/**
* This function returns the coordinate and normal of a barycentric u,v for a face defined by the primitive_id index.
* The returned normal is actually the direction from the same barycentric coordinate in the cage to the base mesh
* The returned coordinate is the point in the cage mesh
*/
-static void calc_point_from_barycentric_cage(
- TriTessFace *triangles_low, TriTessFace *triangles_cage,
- float mat_low[4][4], float mat_cage[4][4],
- int primitive_id, float u, float v,
- float r_co[3], float r_dir[3])
+static void calc_point_from_barycentric_cage(TriTessFace *triangles_low,
+ TriTessFace *triangles_cage,
+ float mat_low[4][4],
+ float mat_cage[4][4],
+ int primitive_id,
+ float u,
+ float v,
+ float r_co[3],
+ float r_dir[3])
{
- float data[2][3][3];
- float coord[2][3];
- float dir[3];
- int i;
+ float data[2][3][3];
+ float coord[2][3];
+ float dir[3];
+ int i;
- TriTessFace *triangle[2];
+ TriTessFace *triangle[2];
- triangle[0] = &triangles_low[primitive_id];
- triangle[1] = &triangles_cage[primitive_id];
+ triangle[0] = &triangles_low[primitive_id];
+ triangle[1] = &triangles_cage[primitive_id];
- for (i = 0; i < 2; i++) {
- copy_v3_v3(data[i][0], triangle[i]->mverts[0]->co);
- copy_v3_v3(data[i][1], triangle[i]->mverts[1]->co);
- copy_v3_v3(data[i][2], triangle[i]->mverts[2]->co);
- interp_barycentric_tri_v3(data[i], u, v, coord[i]);
- }
+ for (i = 0; i < 2; i++) {
+ copy_v3_v3(data[i][0], triangle[i]->mverts[0]->co);
+ copy_v3_v3(data[i][1], triangle[i]->mverts[1]->co);
+ copy_v3_v3(data[i][2], triangle[i]->mverts[2]->co);
+ interp_barycentric_tri_v3(data[i], u, v, coord[i]);
+ }
- /* convert from local to world space */
- mul_m4_v3(mat_low, coord[0]);
- mul_m4_v3(mat_cage, coord[1]);
+ /* convert from local to world space */
+ mul_m4_v3(mat_low, coord[0]);
+ mul_m4_v3(mat_cage, coord[1]);
- sub_v3_v3v3(dir, coord[0], coord[1]);
- normalize_v3(dir);
+ sub_v3_v3v3(dir, coord[0], coord[1]);
+ normalize_v3(dir);
- copy_v3_v3(r_co, coord[1]);
- copy_v3_v3(r_dir, dir);
+ copy_v3_v3(r_co, coord[1]);
+ copy_v3_v3(r_dir, dir);
}
/**
* This function returns the coordinate and normal of a barycentric u,v for a face defined by the primitive_id index.
* The returned coordinate is extruded along the normal by cage_extrusion
*/
-static void calc_point_from_barycentric_extrusion(
- TriTessFace *triangles,
- float mat[4][4], float imat[4][4],
- int primitive_id, float u, float v,
- float cage_extrusion,
- float r_co[3], float r_dir[3],
- const bool is_cage)
+static void calc_point_from_barycentric_extrusion(TriTessFace *triangles,
+ float mat[4][4],
+ float imat[4][4],
+ int primitive_id,
+ float u,
+ float v,
+ float cage_extrusion,
+ float r_co[3],
+ float r_dir[3],
+ const bool is_cage)
{
- float data[3][3];
- float coord[3];
- float dir[3];
- float cage[3];
- bool is_smooth;
-
- TriTessFace *triangle = &triangles[primitive_id];
- is_smooth = triangle->is_smooth || is_cage;
-
- copy_v3_v3(data[0], triangle->mverts[0]->co);
- copy_v3_v3(data[1], triangle->mverts[1]->co);
- copy_v3_v3(data[2], triangle->mverts[2]->co);
-
- interp_barycentric_tri_v3(data, u, v, coord);
-
- if (is_smooth) {
- normal_short_to_float_v3(data[0], triangle->mverts[0]->no);
- normal_short_to_float_v3(data[1], triangle->mverts[1]->no);
- normal_short_to_float_v3(data[2], triangle->mverts[2]->no);
-
- interp_barycentric_tri_v3(data, u, v, dir);
- normalize_v3(dir);
- }
- else {
- copy_v3_v3(dir, triangle->normal);
- }
-
- mul_v3_v3fl(cage, dir, cage_extrusion);
- add_v3_v3(coord, cage);
-
- normalize_v3(dir);
- negate_v3(dir);
-
- /* convert from local to world space */
- mul_m4_v3(mat, coord);
- mul_transposed_mat3_m4_v3(imat, dir);
- normalize_v3(dir);
-
- copy_v3_v3(r_co, coord);
- copy_v3_v3(r_dir, dir);
+ float data[3][3];
+ float coord[3];
+ float dir[3];
+ float cage[3];
+ bool is_smooth;
+
+ TriTessFace *triangle = &triangles[primitive_id];
+ is_smooth = triangle->is_smooth || is_cage;
+
+ copy_v3_v3(data[0], triangle->mverts[0]->co);
+ copy_v3_v3(data[1], triangle->mverts[1]->co);
+ copy_v3_v3(data[2], triangle->mverts[2]->co);
+
+ interp_barycentric_tri_v3(data, u, v, coord);
+
+ if (is_smooth) {
+ normal_short_to_float_v3(data[0], triangle->mverts[0]->no);
+ normal_short_to_float_v3(data[1], triangle->mverts[1]->no);
+ normal_short_to_float_v3(data[2], triangle->mverts[2]->no);
+
+ interp_barycentric_tri_v3(data, u, v, dir);
+ normalize_v3(dir);
+ }
+ else {
+ copy_v3_v3(dir, triangle->normal);
+ }
+
+ mul_v3_v3fl(cage, dir, cage_extrusion);
+ add_v3_v3(coord, cage);
+
+ normalize_v3(dir);
+ negate_v3(dir);
+
+ /* convert from local to world space */
+ mul_m4_v3(mat, coord);
+ mul_transposed_mat3_m4_v3(imat, dir);
+ normalize_v3(dir);
+
+ copy_v3_v3(r_co, coord);
+ copy_v3_v3(r_dir, dir);
}
-static void barycentric_differentials_from_position(
- const float co[3], const float v1[3], const float v2[3], const float v3[3],
- const float dxco[3], const float dyco[3], const float facenor[3], const bool differentials,
- float *u, float *v, float *dx_u, float *dx_v, float *dy_u, float *dy_v)
+static void barycentric_differentials_from_position(const float co[3],
+ const float v1[3],
+ const float v2[3],
+ const float v3[3],
+ const float dxco[3],
+ const float dyco[3],
+ const float facenor[3],
+ const bool differentials,
+ float *u,
+ float *v,
+ float *dx_u,
+ float *dx_v,
+ float *dy_u,
+ float *dy_v)
{
- /* find most stable axis to project */
- int axis1, axis2;
- axis_dominant_v3(&axis1, &axis2, facenor);
-
- /* compute u,v and derivatives */
- float t00 = v3[axis1] - v1[axis1];
- float t01 = v3[axis2] - v1[axis2];
- float t10 = v3[axis1] - v2[axis1];
- float t11 = v3[axis2] - v2[axis2];
-
- float detsh = (t00 * t11 - t10 * t01);
- detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f;
- t00 *= detsh; t01 *= detsh;
- t10 *= detsh; t11 *= detsh;
-
- *u = (v3[axis1] - co[axis1]) * t11 - (v3[axis2] - co[axis2]) * t10;
- *v = (v3[axis2] - co[axis2]) * t00 - (v3[axis1] - co[axis1]) * t01;
- if (differentials) {
- *dx_u = dxco[axis1] * t11 - dxco[axis2] * t10;
- *dx_v = dxco[axis2] * t00 - dxco[axis1] * t01;
- *dy_u = dyco[axis1] * t11 - dyco[axis2] * t10;
- *dy_v = dyco[axis2] * t00 - dyco[axis1] * t01;
- }
+ /* find most stable axis to project */
+ int axis1, axis2;
+ axis_dominant_v3(&axis1, &axis2, facenor);
+
+ /* compute u,v and derivatives */
+ float t00 = v3[axis1] - v1[axis1];
+ float t01 = v3[axis2] - v1[axis2];
+ float t10 = v3[axis1] - v2[axis1];
+ float t11 = v3[axis2] - v2[axis2];
+
+ float detsh = (t00 * t11 - t10 * t01);
+ detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f;
+ t00 *= detsh;
+ t01 *= detsh;
+ t10 *= detsh;
+ t11 *= detsh;
+
+ *u = (v3[axis1] - co[axis1]) * t11 - (v3[axis2] - co[axis2]) * t10;
+ *v = (v3[axis2] - co[axis2]) * t00 - (v3[axis1] - co[axis1]) * t01;
+ if (differentials) {
+ *dx_u = dxco[axis1] * t11 - dxco[axis2] * t10;
+ *dx_v = dxco[axis2] * t00 - dxco[axis1] * t01;
+ *dy_u = dyco[axis1] * t11 - dyco[axis2] * t10;
+ *dy_v = dyco[axis2] * t00 - dyco[axis1] * t01;
+ }
}
/**
* This function populates pixel_array and returns TRUE if things are correct
*/
-static bool cast_ray_highpoly(
- BVHTreeFromMesh *treeData, TriTessFace *triangle_low, TriTessFace *triangles[],
- BakePixel *pixel_array_low, BakePixel *pixel_array, float mat_low[4][4], BakeHighPolyData *highpoly,
- const float co[3], const float dir[3], const int pixel_id, const int tot_highpoly)
+static bool cast_ray_highpoly(BVHTreeFromMesh *treeData,
+ TriTessFace *triangle_low,
+ TriTessFace *triangles[],
+ BakePixel *pixel_array_low,
+ BakePixel *pixel_array,
+ float mat_low[4][4],
+ BakeHighPolyData *highpoly,
+ const float co[3],
+ const float dir[3],
+ const int pixel_id,
+ const int tot_highpoly)
{
- int i;
- int hit_mesh = -1;
- float hit_distance = FLT_MAX;
-
- BVHTreeRayHit *hits;
- hits = MEM_mallocN(sizeof(BVHTreeRayHit) * tot_highpoly, "Bake Highpoly to Lowpoly: BVH Rays");
-
- for (i = 0; i < tot_highpoly; i++) {
- float co_high[3], dir_high[3];
-
- hits[i].index = -1;
- /* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */
- hits[i].dist = BVH_RAYCAST_DIST_MAX;
-
- /* transform the ray from the world space to the highpoly space */
- mul_v3_m4v3(co_high, highpoly[i].imat, co);
-
- /* rotates */
- mul_v3_mat3_m4v3(dir_high, highpoly[i].imat, dir);
- normalize_v3(dir_high);
-
- /* cast ray */
- if (treeData[i].tree) {
- BLI_bvhtree_ray_cast(treeData[i].tree, co_high, dir_high, 0.0f, &hits[i], treeData[i].raycast_callback, &treeData[i]);
- }
-
- if (hits[i].index != -1) {
- float distance;
- float hit_world[3];
-
- /* distance comparison in world space */
- mul_v3_m4v3(hit_world, highpoly[i].obmat, hits[i].co);
- distance = len_squared_v3v3(hit_world, co);
-
- if (distance < hit_distance) {
- hit_mesh = i;
- hit_distance = distance;
- }
- }
- }
-
- if (hit_mesh != -1) {
- int primitive_id_high = hits[hit_mesh].index;
- TriTessFace *triangle_high = &triangles[hit_mesh][primitive_id_high];
- BakePixel *pixel_low = &pixel_array_low[pixel_id];
- BakePixel *pixel_high = &pixel_array[pixel_id];
-
- pixel_high->primitive_id = primitive_id_high;
- pixel_high->object_id = hit_mesh;
-
- /* ray direction in high poly object space */
- float dir_high[3];
- mul_v3_mat3_m4v3(dir_high, highpoly[hit_mesh].imat, dir);
- normalize_v3(dir_high);
-
- /* compute position differentials on low poly object */
- float duco_low[3], dvco_low[3], dxco[3], dyco[3];
- sub_v3_v3v3(duco_low, triangle_low->mverts[0]->co, triangle_low->mverts[2]->co);
- sub_v3_v3v3(dvco_low, triangle_low->mverts[1]->co, triangle_low->mverts[2]->co);
-
- mul_v3_v3fl(dxco, duco_low, pixel_low->du_dx);
- madd_v3_v3fl(dxco, dvco_low, pixel_low->dv_dx);
- mul_v3_v3fl(dyco, duco_low, pixel_low->du_dy);
- madd_v3_v3fl(dyco, dvco_low, pixel_low->dv_dy);
-
- /* transform from low poly to high poly object space */
- mul_mat3_m4_v3(mat_low, dxco);
- mul_mat3_m4_v3(mat_low, dyco);
- mul_mat3_m4_v3(highpoly[hit_mesh].imat, dxco);
- mul_mat3_m4_v3(highpoly[hit_mesh].imat, dyco);
-
- /* transfer position differentials */
- float tmp[3];
- mul_v3_v3fl(tmp, dir_high, 1.0f / dot_v3v3(dir_high, triangle_high->normal));
- madd_v3_v3fl(dxco, tmp, -dot_v3v3(dxco, triangle_high->normal));
- madd_v3_v3fl(dyco, tmp, -dot_v3v3(dyco, triangle_high->normal));
-
- /* compute barycentric differentials from position differentials */
- barycentric_differentials_from_position(
- hits[hit_mesh].co, triangle_high->mverts[0]->co,
- triangle_high->mverts[1]->co, triangle_high->mverts[2]->co,
- dxco, dyco, triangle_high->normal, true,
- &pixel_high->uv[0], &pixel_high->uv[1],
- &pixel_high->du_dx, &pixel_high->dv_dx,
- &pixel_high->du_dy, &pixel_high->dv_dy);
-
- /* verify we have valid uvs */
- BLI_assert(pixel_high->uv[0] >= -1e-3f &&
- pixel_high->uv[1] >= -1e-3f &&
- pixel_high->uv[0] + pixel_high->uv[1] <= 1.0f + 1e-3f);
- }
- else {
- pixel_array[pixel_id].primitive_id = -1;
- pixel_array[pixel_id].object_id = -1;
- }
-
- MEM_freeN(hits);
- return hit_mesh != -1;
+ int i;
+ int hit_mesh = -1;
+ float hit_distance = FLT_MAX;
+
+ BVHTreeRayHit *hits;
+ hits = MEM_mallocN(sizeof(BVHTreeRayHit) * tot_highpoly, "Bake Highpoly to Lowpoly: BVH Rays");
+
+ for (i = 0; i < tot_highpoly; i++) {
+ float co_high[3], dir_high[3];
+
+ hits[i].index = -1;
+ /* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */
+ hits[i].dist = BVH_RAYCAST_DIST_MAX;
+
+ /* transform the ray from the world space to the highpoly space */
+ mul_v3_m4v3(co_high, highpoly[i].imat, co);
+
+ /* rotates */
+ mul_v3_mat3_m4v3(dir_high, highpoly[i].imat, dir);
+ normalize_v3(dir_high);
+
+ /* cast ray */
+ if (treeData[i].tree) {
+ BLI_bvhtree_ray_cast(treeData[i].tree,
+ co_high,
+ dir_high,
+ 0.0f,
+ &hits[i],
+ treeData[i].raycast_callback,
+ &treeData[i]);
+ }
+
+ if (hits[i].index != -1) {
+ float distance;
+ float hit_world[3];
+
+ /* distance comparison in world space */
+ mul_v3_m4v3(hit_world, highpoly[i].obmat, hits[i].co);
+ distance = len_squared_v3v3(hit_world, co);
+
+ if (distance < hit_distance) {
+ hit_mesh = i;
+ hit_distance = distance;
+ }
+ }
+ }
+
+ if (hit_mesh != -1) {
+ int primitive_id_high = hits[hit_mesh].index;
+ TriTessFace *triangle_high = &triangles[hit_mesh][primitive_id_high];
+ BakePixel *pixel_low = &pixel_array_low[pixel_id];
+ BakePixel *pixel_high = &pixel_array[pixel_id];
+
+ pixel_high->primitive_id = primitive_id_high;
+ pixel_high->object_id = hit_mesh;
+
+ /* ray direction in high poly object space */
+ float dir_high[3];
+ mul_v3_mat3_m4v3(dir_high, highpoly[hit_mesh].imat, dir);
+ normalize_v3(dir_high);
+
+ /* compute position differentials on low poly object */
+ float duco_low[3], dvco_low[3], dxco[3], dyco[3];
+ sub_v3_v3v3(duco_low, triangle_low->mverts[0]->co, triangle_low->mverts[2]->co);
+ sub_v3_v3v3(dvco_low, triangle_low->mverts[1]->co, triangle_low->mverts[2]->co);
+
+ mul_v3_v3fl(dxco, duco_low, pixel_low->du_dx);
+ madd_v3_v3fl(dxco, dvco_low, pixel_low->dv_dx);
+ mul_v3_v3fl(dyco, duco_low, pixel_low->du_dy);
+ madd_v3_v3fl(dyco, dvco_low, pixel_low->dv_dy);
+
+ /* transform from low poly to high poly object space */
+ mul_mat3_m4_v3(mat_low, dxco);
+ mul_mat3_m4_v3(mat_low, dyco);
+ mul_mat3_m4_v3(highpoly[hit_mesh].imat, dxco);
+ mul_mat3_m4_v3(highpoly[hit_mesh].imat, dyco);
+
+ /* transfer position differentials */
+ float tmp[3];
+ mul_v3_v3fl(tmp, dir_high, 1.0f / dot_v3v3(dir_high, triangle_high->normal));
+ madd_v3_v3fl(dxco, tmp, -dot_v3v3(dxco, triangle_high->normal));
+ madd_v3_v3fl(dyco, tmp, -dot_v3v3(dyco, triangle_high->normal));
+
+ /* compute barycentric differentials from position differentials */
+ barycentric_differentials_from_position(hits[hit_mesh].co,
+ triangle_high->mverts[0]->co,
+ triangle_high->mverts[1]->co,
+ triangle_high->mverts[2]->co,
+ dxco,
+ dyco,
+ triangle_high->normal,
+ true,
+ &pixel_high->uv[0],
+ &pixel_high->uv[1],
+ &pixel_high->du_dx,
+ &pixel_high->dv_dx,
+ &pixel_high->du_dy,
+ &pixel_high->dv_dy);
+
+ /* verify we have valid uvs */
+ BLI_assert(pixel_high->uv[0] >= -1e-3f && pixel_high->uv[1] >= -1e-3f &&
+ pixel_high->uv[0] + pixel_high->uv[1] <= 1.0f + 1e-3f);
+ }
+ else {
+ pixel_array[pixel_id].primitive_id = -1;
+ pixel_array[pixel_id].object_id = -1;
+ }
+
+ MEM_freeN(hits);
+ return hit_mesh != -1;
}
/**
* This function populates an array of verts for the triangles of a mesh
* Tangent and Normals are also stored
*/
-static TriTessFace *mesh_calc_tri_tessface(
- Mesh *me, bool tangent, Mesh *me_eval)
+static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval)
{
- int i;
- MVert *mvert;
- TSpace *tspace;
-
- const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
- MLoopTri *looptri;
- TriTessFace *triangles;
-
- /* calculate normal for each polygon only once */
- unsigned int mpoly_prev = UINT_MAX;
- float no[3];
-
- mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
- looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
- triangles = MEM_mallocN(sizeof(TriTessFace) * tottri, __func__);
-
- if (tangent) {
- BKE_mesh_ensure_normals_for_display(me_eval);
- BKE_mesh_calc_loop_tangents(me_eval, true, NULL, 0);
-
- tspace = CustomData_get_layer(&me_eval->ldata, CD_TANGENT);
- BLI_assert(tspace);
- }
-
- BKE_mesh_recalc_looptri(
- me->mloop, me->mpoly,
- me->mvert,
- me->totloop, me->totpoly,
- looptri);
-
- const float *precomputed_normals = CustomData_get_layer(&me->pdata, CD_NORMAL);
- const bool calculate_normal = precomputed_normals ? false : true;
-
- for (i = 0; i < tottri; i++) {
- const MLoopTri *lt = &looptri[i];
- const MPoly *mp = &me->mpoly[lt->poly];
-
- triangles[i].mverts[0] = &mvert[me->mloop[lt->tri[0]].v];
- triangles[i].mverts[1] = &mvert[me->mloop[lt->tri[1]].v];
- triangles[i].mverts[2] = &mvert[me->mloop[lt->tri[2]].v];
- triangles[i].is_smooth = (mp->flag & ME_SMOOTH) != 0;
-
- if (tangent) {
- triangles[i].tspace[0] = &tspace[lt->tri[0]];
- triangles[i].tspace[1] = &tspace[lt->tri[1]];
- triangles[i].tspace[2] = &tspace[lt->tri[2]];
- }
-
- if (calculate_normal) {
- if (lt->poly != mpoly_prev) {
- BKE_mesh_calc_poly_normal(mp, &me->mloop[mp->loopstart], me->mvert, no);
- mpoly_prev = lt->poly;
- }
- copy_v3_v3(triangles[i].normal, no);
- }
- else {
- copy_v3_v3(triangles[i].normal, &precomputed_normals[lt->poly]);
- }
- }
-
- MEM_freeN(looptri);
-
- return triangles;
+ int i;
+ MVert *mvert;
+ TSpace *tspace;
+
+ const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
+ MLoopTri *looptri;
+ TriTessFace *triangles;
+
+ /* calculate normal for each polygon only once */
+ unsigned int mpoly_prev = UINT_MAX;
+ float no[3];
+
+ mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
+ looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
+ triangles = MEM_mallocN(sizeof(TriTessFace) * tottri, __func__);
+
+ if (tangent) {
+ BKE_mesh_ensure_normals_for_display(me_eval);
+ BKE_mesh_calc_loop_tangents(me_eval, true, NULL, 0);
+
+ tspace = CustomData_get_layer(&me_eval->ldata, CD_TANGENT);
+ BLI_assert(tspace);
+ }
+
+ BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
+
+ const float *precomputed_normals = CustomData_get_layer(&me->pdata, CD_NORMAL);
+ const bool calculate_normal = precomputed_normals ? false : true;
+
+ for (i = 0; i < tottri; i++) {
+ const MLoopTri *lt = &looptri[i];
+ const MPoly *mp = &me->mpoly[lt->poly];
+
+ triangles[i].mverts[0] = &mvert[me->mloop[lt->tri[0]].v];
+ triangles[i].mverts[1] = &mvert[me->mloop[lt->tri[1]].v];
+ triangles[i].mverts[2] = &mvert[me->mloop[lt->tri[2]].v];
+ triangles[i].is_smooth = (mp->flag & ME_SMOOTH) != 0;
+
+ if (tangent) {
+ triangles[i].tspace[0] = &tspace[lt->tri[0]];
+ triangles[i].tspace[1] = &tspace[lt->tri[1]];
+ triangles[i].tspace[2] = &tspace[lt->tri[2]];
+ }
+
+ if (calculate_normal) {
+ if (lt->poly != mpoly_prev) {
+ BKE_mesh_calc_poly_normal(mp, &me->mloop[mp->loopstart], me->mvert, no);
+ mpoly_prev = lt->poly;
+ }
+ copy_v3_v3(triangles[i].normal, no);
+ }
+ else {
+ copy_v3_v3(triangles[i].normal, &precomputed_normals[lt->poly]);
+ }
+ }
+
+ MEM_freeN(looptri);
+
+ return triangles;
}
-bool RE_bake_pixels_populate_from_objects(
- struct Mesh *me_low, BakePixel pixel_array_from[], BakePixel pixel_array_to[],
- BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage,
- const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage)
+bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low,
+ BakePixel pixel_array_from[],
+ BakePixel pixel_array_to[],
+ BakeHighPolyData highpoly[],
+ const int tot_highpoly,
+ const size_t num_pixels,
+ const bool is_custom_cage,
+ const float cage_extrusion,
+ float mat_low[4][4],
+ float mat_cage[4][4],
+ struct Mesh *me_cage)
{
- size_t i;
- int primitive_id;
- float u, v;
- float imat_low[4][4];
- bool is_cage = me_cage != NULL;
- bool result = true;
-
- Mesh *me_eval_low = NULL;
- Mesh **me_highpoly;
- BVHTreeFromMesh *treeData;
-
- /* Note: all coordinates are in local space */
- TriTessFace *tris_low = NULL;
- TriTessFace *tris_cage = NULL;
- TriTessFace **tris_high;
-
- /* assume all lowpoly tessfaces can be quads */
- tris_high = MEM_callocN(sizeof(TriTessFace *) * tot_highpoly, "MVerts Highpoly Mesh Array");
-
- /* assume all highpoly tessfaces are triangles */
- me_highpoly = MEM_mallocN(sizeof(Mesh *) * tot_highpoly, "Highpoly Derived Meshes");
- treeData = MEM_callocN(sizeof(BVHTreeFromMesh) * tot_highpoly, "Highpoly BVH Trees");
-
- if (!is_cage) {
- me_eval_low = BKE_mesh_copy_for_eval(me_low, false);
- tris_low = mesh_calc_tri_tessface(me_low, true, me_eval_low);
- }
- else if (is_custom_cage) {
- tris_low = mesh_calc_tri_tessface(me_low, false, NULL);
- tris_cage = mesh_calc_tri_tessface(me_cage, false, NULL);
- }
- else {
- tris_cage = mesh_calc_tri_tessface(me_cage, false, NULL);
- }
-
- invert_m4_m4(imat_low, mat_low);
-
- for (i = 0; i < tot_highpoly; i++) {
- tris_high[i] = mesh_calc_tri_tessface(highpoly[i].me, false, NULL);
-
- me_highpoly[i] = highpoly[i].me;
- BKE_mesh_runtime_looptri_ensure(me_highpoly[i]);
-
- if (me_highpoly[i]->runtime.looptris.len != 0) {
- /* Create a bvh-tree for each highpoly object */
- BKE_bvhtree_from_mesh_get(&treeData[i], me_highpoly[i], BVHTREE_FROM_LOOPTRI, 2);
-
- if (treeData[i].tree == NULL) {
- printf("Baking: out of memory while creating BHVTree for object \"%s\"\n", highpoly[i].ob->id.name + 2);
- result = false;
- goto cleanup;
- }
- }
- }
-
- for (i = 0; i < num_pixels; i++) {
- float co[3];
- float dir[3];
- TriTessFace *tri_low;
-
- primitive_id = pixel_array_from[i].primitive_id;
-
- if (primitive_id == -1) {
- pixel_array_to[i].primitive_id = -1;
- continue;
- }
-
- u = pixel_array_from[i].uv[0];
- v = pixel_array_from[i].uv[1];
-
- /* calculate from low poly mesh cage */
- if (is_custom_cage) {
- calc_point_from_barycentric_cage(tris_low, tris_cage, mat_low, mat_cage, primitive_id, u, v, co, dir);
- tri_low = &tris_cage[primitive_id];
- }
- else if (is_cage) {
- calc_point_from_barycentric_extrusion(tris_cage, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, true);
- tri_low = &tris_cage[primitive_id];
- }
- else {
- calc_point_from_barycentric_extrusion(tris_low, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, false);
- tri_low = &tris_low[primitive_id];
- }
-
- /* cast ray */
- if (!cast_ray_highpoly(treeData, tri_low, tris_high,
- pixel_array_from, pixel_array_to, mat_low,
- highpoly, co, dir, i, tot_highpoly))
- {
- /* if it fails mask out the original pixel array */
- pixel_array_from[i].primitive_id = -1;
- }
- }
-
-
- /* garbage collection */
+ size_t i;
+ int primitive_id;
+ float u, v;
+ float imat_low[4][4];
+ bool is_cage = me_cage != NULL;
+ bool result = true;
+
+ Mesh *me_eval_low = NULL;
+ Mesh **me_highpoly;
+ BVHTreeFromMesh *treeData;
+
+ /* Note: all coordinates are in local space */
+ TriTessFace *tris_low = NULL;
+ TriTessFace *tris_cage = NULL;
+ TriTessFace **tris_high;
+
+ /* assume all lowpoly tessfaces can be quads */
+ tris_high = MEM_callocN(sizeof(TriTessFace *) * tot_highpoly, "MVerts Highpoly Mesh Array");
+
+ /* assume all highpoly tessfaces are triangles */
+ me_highpoly = MEM_mallocN(sizeof(Mesh *) * tot_highpoly, "Highpoly Derived Meshes");
+ treeData = MEM_callocN(sizeof(BVHTreeFromMesh) * tot_highpoly, "Highpoly BVH Trees");
+
+ if (!is_cage) {
+ me_eval_low = BKE_mesh_copy_for_eval(me_low, false);
+ tris_low = mesh_calc_tri_tessface(me_low, true, me_eval_low);
+ }
+ else if (is_custom_cage) {
+ tris_low = mesh_calc_tri_tessface(me_low, false, NULL);
+ tris_cage = mesh_calc_tri_tessface(me_cage, false, NULL);
+ }
+ else {
+ tris_cage = mesh_calc_tri_tessface(me_cage, false, NULL);
+ }
+
+ invert_m4_m4(imat_low, mat_low);
+
+ for (i = 0; i < tot_highpoly; i++) {
+ tris_high[i] = mesh_calc_tri_tessface(highpoly[i].me, false, NULL);
+
+ me_highpoly[i] = highpoly[i].me;
+ BKE_mesh_runtime_looptri_ensure(me_highpoly[i]);
+
+ if (me_highpoly[i]->runtime.looptris.len != 0) {
+ /* Create a bvh-tree for each highpoly object */
+ BKE_bvhtree_from_mesh_get(&treeData[i], me_highpoly[i], BVHTREE_FROM_LOOPTRI, 2);
+
+ if (treeData[i].tree == NULL) {
+ printf("Baking: out of memory while creating BHVTree for object \"%s\"\n",
+ highpoly[i].ob->id.name + 2);
+ result = false;
+ goto cleanup;
+ }
+ }
+ }
+
+ for (i = 0; i < num_pixels; i++) {
+ float co[3];
+ float dir[3];
+ TriTessFace *tri_low;
+
+ primitive_id = pixel_array_from[i].primitive_id;
+
+ if (primitive_id == -1) {
+ pixel_array_to[i].primitive_id = -1;
+ continue;
+ }
+
+ u = pixel_array_from[i].uv[0];
+ v = pixel_array_from[i].uv[1];
+
+ /* calculate from low poly mesh cage */
+ if (is_custom_cage) {
+ calc_point_from_barycentric_cage(
+ tris_low, tris_cage, mat_low, mat_cage, primitive_id, u, v, co, dir);
+ tri_low = &tris_cage[primitive_id];
+ }
+ else if (is_cage) {
+ calc_point_from_barycentric_extrusion(
+ tris_cage, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, true);
+ tri_low = &tris_cage[primitive_id];
+ }
+ else {
+ calc_point_from_barycentric_extrusion(
+ tris_low, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, false);
+ tri_low = &tris_low[primitive_id];
+ }
+
+ /* cast ray */
+ if (!cast_ray_highpoly(treeData,
+ tri_low,
+ tris_high,
+ pixel_array_from,
+ pixel_array_to,
+ mat_low,
+ highpoly,
+ co,
+ dir,
+ i,
+ tot_highpoly)) {
+ /* if it fails mask out the original pixel array */
+ pixel_array_from[i].primitive_id = -1;
+ }
+ }
+
+ /* garbage collection */
cleanup:
- for (i = 0; i < tot_highpoly; i++) {
- free_bvhtree_from_mesh(&treeData[i]);
-
- if (tris_high[i]) {
- MEM_freeN(tris_high[i]);
- }
- }
-
- MEM_freeN(tris_high);
- MEM_freeN(treeData);
- MEM_freeN(me_highpoly);
-
- if (me_eval_low) {
- BKE_id_free(NULL, me_eval_low);
- }
- if (tris_low) {
- MEM_freeN(tris_low);
- }
- if (tris_cage) {
- MEM_freeN(tris_cage);
- }
-
- return result;
+ for (i = 0; i < tot_highpoly; i++) {
+ free_bvhtree_from_mesh(&treeData[i]);
+
+ if (tris_high[i]) {
+ MEM_freeN(tris_high[i]);
+ }
+ }
+
+ MEM_freeN(tris_high);
+ MEM_freeN(treeData);
+ MEM_freeN(me_highpoly);
+
+ if (me_eval_low) {
+ BKE_id_free(NULL, me_eval_low);
+ }
+ if (tris_low) {
+ MEM_freeN(tris_low);
+ }
+ if (tris_cage) {
+ MEM_freeN(tris_cage);
+ }
+
+ return result;
}
-static void bake_differentials(BakeDataZSpan *bd, const float *uv1, const float *uv2, const float *uv3)
+static void bake_differentials(BakeDataZSpan *bd,
+ const float *uv1,
+ const float *uv2,
+ const float *uv3)
{
- float A;
+ float A;
- /* assumes dPdu = P1 - P3 and dPdv = P2 - P3 */
- A = (uv2[0] - uv1[0]) * (uv3[1] - uv1[1]) - (uv3[0] - uv1[0]) * (uv2[1] - uv1[1]);
+ /* assumes dPdu = P1 - P3 and dPdv = P2 - P3 */
+ 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;
+ if (fabsf(A) > FLT_EPSILON) {
+ A = 0.5f / A;
- bd->du_dx = (uv2[1] - uv3[1]) * A;
- bd->dv_dx = (uv3[1] - uv1[1]) * A;
+ bd->du_dx = (uv2[1] - uv3[1]) * A;
+ bd->dv_dx = (uv3[1] - uv1[1]) * A;
- bd->du_dy = (uv3[0] - uv2[0]) * A;
- bd->dv_dy = (uv1[0] - uv3[0]) * A;
- }
- else {
- bd->du_dx = bd->du_dy = 0.0f;
- bd->dv_dx = bd->dv_dy = 0.0f;
- }
+ bd->du_dy = (uv3[0] - uv2[0]) * A;
+ bd->dv_dy = (uv1[0] - uv3[0]) * A;
+ }
+ else {
+ bd->du_dx = bd->du_dy = 0.0f;
+ bd->dv_dx = bd->dv_dy = 0.0f;
+ }
}
-void RE_bake_pixels_populate(
- Mesh *me, BakePixel pixel_array[],
- const size_t num_pixels, const BakeImages *bake_images, const char *uv_layer)
+void RE_bake_pixels_populate(Mesh *me,
+ BakePixel pixel_array[],
+ const size_t num_pixels,
+ const BakeImages *bake_images,
+ const char *uv_layer)
{
- BakeDataZSpan bd;
- size_t i;
- int a, p_id;
-
- const MLoopUV *mloopuv;
- const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
- MLoopTri *looptri;
-
- if ((uv_layer == NULL) || (uv_layer[0] == '\0')) {
- mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
- }
- else {
- int uv_id = CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer);
- mloopuv = CustomData_get_layer_n(&me->ldata, CD_MTFACE, uv_id);
- }
-
- if (mloopuv == NULL)
- return;
-
-
- bd.pixel_array = pixel_array;
- bd.zspan = MEM_callocN(sizeof(ZSpan) * bake_images->size, "bake zspan");
-
- /* initialize all pixel arrays so we know which ones are 'blank' */
- for (i = 0; i < num_pixels; i++) {
- pixel_array[i].primitive_id = -1;
- pixel_array[i].object_id = 0;
- }
-
- for (i = 0; i < bake_images->size; i++) {
- zbuf_alloc_span(&bd.zspan[i], bake_images->data[i].width, bake_images->data[i].height);
- }
-
- looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
-
- BKE_mesh_recalc_looptri(
- me->mloop, me->mpoly,
- me->mvert,
- me->totloop, me->totpoly,
- looptri);
-
- p_id = -1;
- for (i = 0; i < tottri; i++) {
- const MLoopTri *lt = &looptri[i];
- const MPoly *mp = &me->mpoly[lt->poly];
- float vec[3][2];
- int mat_nr = mp->mat_nr;
- int image_id = bake_images->lookup[mat_nr];
-
- if (image_id < 0) {
- continue;
- }
-
- bd.bk_image = &bake_images->data[image_id];
- bd.primitive_id = ++p_id;
-
- for (a = 0; a < 3; a++) {
- const float *uv = mloopuv[lt->tri[a]].uv;
-
- /* 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] = uv[0] * (float)bd.bk_image->width - (0.5f + 0.001f);
- vec[a][1] = uv[1] * (float)bd.bk_image->height - (0.5f + 0.002f);
- }
-
- bake_differentials(&bd, vec[0], vec[1], vec[2]);
- zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[1], vec[2], store_bake_pixel);
- }
-
- for (i = 0; i < bake_images->size; i++) {
- zbuf_free_span(&bd.zspan[i]);
- }
-
- MEM_freeN(looptri);
- MEM_freeN(bd.zspan);
+ BakeDataZSpan bd;
+ size_t i;
+ int a, p_id;
+
+ const MLoopUV *mloopuv;
+ const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
+ MLoopTri *looptri;
+
+ if ((uv_layer == NULL) || (uv_layer[0] == '\0')) {
+ mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
+ }
+ else {
+ int uv_id = CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer);
+ mloopuv = CustomData_get_layer_n(&me->ldata, CD_MTFACE, uv_id);
+ }
+
+ if (mloopuv == NULL)
+ return;
+
+ bd.pixel_array = pixel_array;
+ bd.zspan = MEM_callocN(sizeof(ZSpan) * bake_images->size, "bake zspan");
+
+ /* initialize all pixel arrays so we know which ones are 'blank' */
+ for (i = 0; i < num_pixels; i++) {
+ pixel_array[i].primitive_id = -1;
+ pixel_array[i].object_id = 0;
+ }
+
+ for (i = 0; i < bake_images->size; i++) {
+ zbuf_alloc_span(&bd.zspan[i], bake_images->data[i].width, bake_images->data[i].height);
+ }
+
+ looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
+
+ BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
+
+ p_id = -1;
+ for (i = 0; i < tottri; i++) {
+ const MLoopTri *lt = &looptri[i];
+ const MPoly *mp = &me->mpoly[lt->poly];
+ float vec[3][2];
+ int mat_nr = mp->mat_nr;
+ int image_id = bake_images->lookup[mat_nr];
+
+ if (image_id < 0) {
+ continue;
+ }
+
+ bd.bk_image = &bake_images->data[image_id];
+ bd.primitive_id = ++p_id;
+
+ for (a = 0; a < 3; a++) {
+ const float *uv = mloopuv[lt->tri[a]].uv;
+
+ /* 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] = uv[0] * (float)bd.bk_image->width - (0.5f + 0.001f);
+ vec[a][1] = uv[1] * (float)bd.bk_image->height - (0.5f + 0.002f);
+ }
+
+ bake_differentials(&bd, vec[0], vec[1], vec[2]);
+ zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[1], vec[2], store_bake_pixel);
+ }
+
+ for (i = 0; i < bake_images->size; i++) {
+ zbuf_free_span(&bd.zspan[i]);
+ }
+
+ MEM_freeN(looptri);
+ MEM_freeN(bd.zspan);
}
/* ******************** NORMALS ************************ */
@@ -701,277 +750,284 @@ void RE_bake_pixels_populate(
*/
static void normal_uncompress(float out[3], const float in[3])
{
- int i;
- for (i = 0; i < 3; i++)
- out[i] = 2.0f * in[i] - 1.0f;
+ int i;
+ for (i = 0; i < 3; i++)
+ out[i] = 2.0f * in[i] - 1.0f;
}
-static void normal_compress(float out[3], const float in[3], const eBakeNormalSwizzle normal_swizzle[3])
+static void normal_compress(float out[3],
+ const float in[3],
+ const eBakeNormalSwizzle normal_swizzle[3])
{
- const int swizzle_index[6] = {
- 0, /* R_BAKE_POSX */
- 1, /* R_BAKE_POSY */
- 2, /* R_BAKE_POSZ */
- 0, /* R_BAKE_NEGX */
- 1, /* R_BAKE_NEGY */
- 2, /* R_BAKE_NEGZ */
- };
- const float swizzle_sign[6] = {
- +1.0f, /* R_BAKE_POSX */
- +1.0f, /* R_BAKE_POSY */
- +1.0f, /* R_BAKE_POSZ */
- -1.0f, /* R_BAKE_NEGX */
- -1.0f, /* R_BAKE_NEGY */
- -1.0f, /* R_BAKE_NEGZ */
- };
-
- int i;
-
- for (i = 0; i < 3; i++) {
- int index;
- float sign;
-
- sign = swizzle_sign[normal_swizzle[i]];
- index = swizzle_index[normal_swizzle[i]];
-
- /*
- * There is a small 1e-5f bias for precision issues. otherwise
- * we randomly get 127 or 128 for neutral colors in tangent maps.
- * we choose 128 because it is the convention flat color. *
- */
-
- out[i] = sign * in[index] / 2.0f + 0.5f + 1e-5f;
- }
+ const int swizzle_index[6] = {
+ 0, /* R_BAKE_POSX */
+ 1, /* R_BAKE_POSY */
+ 2, /* R_BAKE_POSZ */
+ 0, /* R_BAKE_NEGX */
+ 1, /* R_BAKE_NEGY */
+ 2, /* R_BAKE_NEGZ */
+ };
+ const float swizzle_sign[6] = {
+ +1.0f, /* R_BAKE_POSX */
+ +1.0f, /* R_BAKE_POSY */
+ +1.0f, /* R_BAKE_POSZ */
+ -1.0f, /* R_BAKE_NEGX */
+ -1.0f, /* R_BAKE_NEGY */
+ -1.0f, /* R_BAKE_NEGZ */
+ };
+
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ int index;
+ float sign;
+
+ sign = swizzle_sign[normal_swizzle[i]];
+ index = swizzle_index[normal_swizzle[i]];
+
+ /*
+ * There is a small 1e-5f bias for precision issues. otherwise
+ * we randomly get 127 or 128 for neutral colors in tangent maps.
+ * we choose 128 because it is the convention flat color. *
+ */
+
+ out[i] = sign * in[index] / 2.0f + 0.5f + 1e-5f;
+ }
}
/**
* This function converts an object space normal map to a tangent space normal map for a given low poly mesh
*/
-void RE_bake_normal_world_to_tangent(
- const BakePixel pixel_array[], const size_t num_pixels, const int depth,
- float result[], Mesh *me, const eBakeNormalSwizzle normal_swizzle[3],
- float mat[4][4])
+void RE_bake_normal_world_to_tangent(const BakePixel pixel_array[],
+ const size_t num_pixels,
+ const int depth,
+ float result[],
+ Mesh *me,
+ const eBakeNormalSwizzle normal_swizzle[3],
+ float mat[4][4])
{
- size_t i;
+ size_t i;
- TriTessFace *triangles;
+ TriTessFace *triangles;
- Mesh *me_eval = BKE_mesh_copy_for_eval(me, false);
+ Mesh *me_eval = BKE_mesh_copy_for_eval(me, false);
- triangles = mesh_calc_tri_tessface(me, true, me_eval);
+ triangles = mesh_calc_tri_tessface(me, true, me_eval);
- BLI_assert(num_pixels >= 3);
+ BLI_assert(num_pixels >= 3);
- for (i = 0; i < num_pixels; i++) {
- TriTessFace *triangle;
- float tangents[3][3];
- float normals[3][3];
- float signs[3];
- int j;
+ for (i = 0; i < num_pixels; i++) {
+ TriTessFace *triangle;
+ float tangents[3][3];
+ float normals[3][3];
+ float signs[3];
+ int j;
- float tangent[3];
- float normal[3];
- float binormal[3];
- float sign;
- float u, v, w;
+ float tangent[3];
+ float normal[3];
+ float binormal[3];
+ float sign;
+ float u, v, w;
- float tsm[3][3]; /* tangent space matrix */
- float itsm[3][3];
+ float tsm[3][3]; /* tangent space matrix */
+ float itsm[3][3];
- size_t offset;
- float nor[3]; /* texture normal */
+ size_t offset;
+ float nor[3]; /* texture normal */
- bool is_smooth;
+ bool is_smooth;
- int primitive_id = pixel_array[i].primitive_id;
+ int primitive_id = pixel_array[i].primitive_id;
- offset = i * depth;
+ offset = i * depth;
- if (primitive_id == -1) {
- if (depth == 4)
- copy_v4_fl4(&result[offset], 0.5f, 0.5f, 1.0f, 1.0f);
- else
- copy_v3_fl3(&result[offset], 0.5f, 0.5f, 1.0f);
- continue;
- }
+ if (primitive_id == -1) {
+ if (depth == 4)
+ copy_v4_fl4(&result[offset], 0.5f, 0.5f, 1.0f, 1.0f);
+ else
+ copy_v3_fl3(&result[offset], 0.5f, 0.5f, 1.0f);
+ continue;
+ }
- triangle = &triangles[primitive_id];
- is_smooth = triangle->is_smooth;
+ triangle = &triangles[primitive_id];
+ is_smooth = triangle->is_smooth;
- for (j = 0; j < 3; j++) {
- const TSpace *ts;
+ for (j = 0; j < 3; j++) {
+ const TSpace *ts;
- if (is_smooth)
- normal_short_to_float_v3(normals[j], triangle->mverts[j]->no);
- else
- normal[j] = triangle->normal[j];
+ if (is_smooth)
+ normal_short_to_float_v3(normals[j], triangle->mverts[j]->no);
+ else
+ normal[j] = triangle->normal[j];
- ts = triangle->tspace[j];
- copy_v3_v3(tangents[j], ts->tangent);
- signs[j] = ts->sign;
- }
+ ts = triangle->tspace[j];
+ copy_v3_v3(tangents[j], ts->tangent);
+ signs[j] = ts->sign;
+ }
- u = pixel_array[i].uv[0];
- v = pixel_array[i].uv[1];
- w = 1.0f - u - v;
+ u = pixel_array[i].uv[0];
+ v = pixel_array[i].uv[1];
+ w = 1.0f - u - v;
- /* normal */
- if (is_smooth)
- interp_barycentric_tri_v3(normals, u, v, normal);
+ /* normal */
+ if (is_smooth)
+ interp_barycentric_tri_v3(normals, u, v, normal);
- /* tangent */
- interp_barycentric_tri_v3(tangents, u, v, tangent);
+ /* tangent */
+ interp_barycentric_tri_v3(tangents, u, v, tangent);
- /* sign */
- /* The sign is the same at all face vertices for any non degenerate face.
- * Just in case we clamp the interpolated value though. */
- sign = (signs[0] * u + signs[1] * v + signs[2] * w) < 0 ? (-1.0f) : 1.0f;
+ /* sign */
+ /* The sign is the same at all face vertices for any non degenerate face.
+ * Just in case we clamp the interpolated value though. */
+ sign = (signs[0] * u + signs[1] * v + signs[2] * w) < 0 ? (-1.0f) : 1.0f;
- /* binormal */
- /* B = sign * cross(N, T) */
- cross_v3_v3v3(binormal, normal, tangent);
- mul_v3_fl(binormal, sign);
+ /* binormal */
+ /* B = sign * cross(N, T) */
+ cross_v3_v3v3(binormal, normal, tangent);
+ mul_v3_fl(binormal, sign);
- /* populate tangent space matrix */
- copy_v3_v3(tsm[0], tangent);
- copy_v3_v3(tsm[1], binormal);
- copy_v3_v3(tsm[2], normal);
+ /* populate tangent space matrix */
+ copy_v3_v3(tsm[0], tangent);
+ copy_v3_v3(tsm[1], binormal);
+ copy_v3_v3(tsm[2], normal);
- /* texture values */
- normal_uncompress(nor, &result[offset]);
+ /* texture values */
+ normal_uncompress(nor, &result[offset]);
- /* converts from world space to local space */
- mul_transposed_mat3_m4_v3(mat, nor);
+ /* converts from world space to local space */
+ mul_transposed_mat3_m4_v3(mat, nor);
- invert_m3_m3(itsm, tsm);
- mul_m3_v3(itsm, nor);
- normalize_v3(nor);
+ invert_m3_m3(itsm, tsm);
+ mul_m3_v3(itsm, nor);
+ normalize_v3(nor);
- /* save back the values */
- normal_compress(&result[offset], nor, normal_swizzle);
- }
+ /* save back the values */
+ normal_compress(&result[offset], nor, normal_swizzle);
+ }
- /* garbage collection */
- MEM_freeN(triangles);
+ /* garbage collection */
+ MEM_freeN(triangles);
- if (me_eval) {
- BKE_id_free(NULL, me_eval);
- }
+ if (me_eval) {
+ BKE_id_free(NULL, me_eval);
+ }
}
-void RE_bake_normal_world_to_object(
- const BakePixel pixel_array[], const size_t num_pixels, const int depth,
- float result[], struct Object *ob, const eBakeNormalSwizzle normal_swizzle[3])
+void RE_bake_normal_world_to_object(const BakePixel pixel_array[],
+ const size_t num_pixels,
+ const int depth,
+ float result[],
+ struct Object *ob,
+ const eBakeNormalSwizzle normal_swizzle[3])
{
- size_t i;
- float iobmat[4][4];
+ size_t i;
+ float iobmat[4][4];
- invert_m4_m4(iobmat, ob->obmat);
+ invert_m4_m4(iobmat, ob->obmat);
- for (i = 0; i < num_pixels; i++) {
- size_t offset;
- float nor[3];
+ for (i = 0; i < num_pixels; i++) {
+ size_t offset;
+ float nor[3];
- if (pixel_array[i].primitive_id == -1)
- continue;
+ if (pixel_array[i].primitive_id == -1)
+ continue;
- offset = i * depth;
- normal_uncompress(nor, &result[offset]);
+ offset = i * depth;
+ normal_uncompress(nor, &result[offset]);
- /* rotates only without translation */
- mul_mat3_m4_v3(iobmat, nor);
- normalize_v3(nor);
+ /* rotates only without translation */
+ mul_mat3_m4_v3(iobmat, nor);
+ normalize_v3(nor);
- /* save back the values */
- normal_compress(&result[offset], nor, normal_swizzle);
- }
+ /* save back the values */
+ normal_compress(&result[offset], nor, normal_swizzle);
+ }
}
-void RE_bake_normal_world_to_world(
- const BakePixel pixel_array[], const size_t num_pixels, const int depth,
- float result[], const eBakeNormalSwizzle normal_swizzle[3])
+void RE_bake_normal_world_to_world(const BakePixel pixel_array[],
+ const size_t num_pixels,
+ const int depth,
+ float result[],
+ const eBakeNormalSwizzle normal_swizzle[3])
{
- size_t i;
+ size_t i;
- for (i = 0; i < num_pixels; i++) {
- size_t offset;
- float nor[3];
+ for (i = 0; i < num_pixels; i++) {
+ size_t offset;
+ float nor[3];
- if (pixel_array[i].primitive_id == -1)
- continue;
+ if (pixel_array[i].primitive_id == -1)
+ continue;
- offset = i * depth;
- normal_uncompress(nor, &result[offset]);
+ offset = i * depth;
+ normal_uncompress(nor, &result[offset]);
- /* save back the values */
- normal_compress(&result[offset], nor, normal_swizzle);
- }
+ /* save back the values */
+ normal_compress(&result[offset], nor, normal_swizzle);
+ }
}
void RE_bake_ibuf_clear(Image *image, const bool is_tangent)
{
- ImBuf *ibuf;
- void *lock;
+ ImBuf *ibuf;
+ void *lock;
- 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};
- const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f};
- const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f};
+ 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};
+ const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f};
+ const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f};
- ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
- BLI_assert(ibuf);
+ ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+ BLI_assert(ibuf);
- if (is_tangent)
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
- else
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
+ if (is_tangent)
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
+ else
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
- BKE_image_release_ibuf(image, ibuf, lock);
+ BKE_image_release_ibuf(image, ibuf, lock);
}
/* ************************************************************* */
int RE_pass_depth(const eScenePassType pass_type)
{
- /* IMB_buffer_byte_from_float assumes 4 channels
- * making it work for now - XXX */
- return 4;
-
- switch (pass_type) {
- case SCE_PASS_Z:
- case SCE_PASS_AO:
- case SCE_PASS_MIST:
- {
- return 1;
- }
- case SCE_PASS_UV:
- {
- return 2;
- }
- case SCE_PASS_COMBINED:
- case SCE_PASS_SHADOW:
- case SCE_PASS_NORMAL:
- case SCE_PASS_VECTOR:
- case SCE_PASS_INDEXOB: /* XXX double check */
- case SCE_PASS_RAYHITS: /* XXX double check */
- case SCE_PASS_EMIT:
- case SCE_PASS_ENVIRONMENT:
- case SCE_PASS_INDEXMA:
- case SCE_PASS_DIFFUSE_DIRECT:
- case SCE_PASS_DIFFUSE_INDIRECT:
- case SCE_PASS_DIFFUSE_COLOR:
- case SCE_PASS_GLOSSY_DIRECT:
- case SCE_PASS_GLOSSY_INDIRECT:
- case SCE_PASS_GLOSSY_COLOR:
- case SCE_PASS_TRANSM_DIRECT:
- case SCE_PASS_TRANSM_INDIRECT:
- case SCE_PASS_TRANSM_COLOR:
- case SCE_PASS_SUBSURFACE_DIRECT:
- case SCE_PASS_SUBSURFACE_INDIRECT:
- case SCE_PASS_SUBSURFACE_COLOR:
- default:
- {
- return 3;
- }
- }
+ /* IMB_buffer_byte_from_float assumes 4 channels
+ * making it work for now - XXX */
+ return 4;
+
+ switch (pass_type) {
+ case SCE_PASS_Z:
+ case SCE_PASS_AO:
+ case SCE_PASS_MIST: {
+ return 1;
+ }
+ case SCE_PASS_UV: {
+ return 2;
+ }
+ case SCE_PASS_COMBINED:
+ case SCE_PASS_SHADOW:
+ case SCE_PASS_NORMAL:
+ case SCE_PASS_VECTOR:
+ case SCE_PASS_INDEXOB: /* XXX double check */
+ case SCE_PASS_RAYHITS: /* XXX double check */
+ case SCE_PASS_EMIT:
+ case SCE_PASS_ENVIRONMENT:
+ case SCE_PASS_INDEXMA:
+ case SCE_PASS_DIFFUSE_DIRECT:
+ case SCE_PASS_DIFFUSE_INDIRECT:
+ case SCE_PASS_DIFFUSE_COLOR:
+ case SCE_PASS_GLOSSY_DIRECT:
+ case SCE_PASS_GLOSSY_INDIRECT:
+ case SCE_PASS_GLOSSY_COLOR:
+ case SCE_PASS_TRANSM_DIRECT:
+ case SCE_PASS_TRANSM_INDIRECT:
+ case SCE_PASS_TRANSM_COLOR:
+ case SCE_PASS_SUBSURFACE_DIRECT:
+ case SCE_PASS_SUBSURFACE_INDIRECT:
+ case SCE_PASS_SUBSURFACE_COLOR:
+ default: {
+ return 3;
+ }
+ }
}
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index a9bf80a6aa0..c4eef235b5d 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -50,7 +50,7 @@
#include "RNA_access.h"
#ifdef WITH_PYTHON
-#include "BPY_extern.h"
+# include "BPY_extern.h"
#endif
#include "RE_engine.h"
@@ -70,766 +70,785 @@ ListBase R_engines = {NULL, NULL};
void RE_engines_init(void)
{
- DRW_engines_register();
+ DRW_engines_register();
}
void RE_engines_exit(void)
{
- RenderEngineType *type, *next;
+ RenderEngineType *type, *next;
- DRW_engines_free();
+ DRW_engines_free();
- for (type = R_engines.first; type; type = next) {
- next = type->next;
+ for (type = R_engines.first; type; type = next) {
+ next = type->next;
- BLI_remlink(&R_engines, type);
+ BLI_remlink(&R_engines, type);
- if (!(type->flag & RE_INTERNAL)) {
- if (type->ext.free)
- type->ext.free(type->ext.data);
+ if (!(type->flag & RE_INTERNAL)) {
+ if (type->ext.free)
+ type->ext.free(type->ext.data);
- MEM_freeN(type);
- }
- }
+ MEM_freeN(type);
+ }
+ }
}
void RE_engines_register(RenderEngineType *render_type)
{
- if (render_type->draw_engine) {
- DRW_engine_register(render_type->draw_engine);
- }
- BLI_addtail(&R_engines, render_type);
+ if (render_type->draw_engine) {
+ DRW_engine_register(render_type->draw_engine);
+ }
+ BLI_addtail(&R_engines, render_type);
}
RenderEngineType *RE_engines_find(const char *idname)
{
- RenderEngineType *type;
+ RenderEngineType *type;
- type = BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname));
- if (!type)
- type = BLI_findstring(&R_engines, "BLENDER_EEVEE", offsetof(RenderEngineType, idname));
+ type = BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname));
+ if (!type)
+ type = BLI_findstring(&R_engines, "BLENDER_EEVEE", offsetof(RenderEngineType, idname));
- return type;
+ return type;
}
bool RE_engine_is_external(Render *re)
{
- return (re->engine && re->engine->type && re->engine->type->render);
+ return (re->engine && re->engine->type && re->engine->type->render);
}
bool RE_engine_is_opengl(RenderEngineType *render_type)
{
- /* TODO refine? Can we have ogl render engine without ogl render pipeline? */
- return (render_type->draw_engine != NULL) &&
- DRW_engine_render_support(render_type->draw_engine);
+ /* TODO refine? Can we have ogl render engine without ogl render pipeline? */
+ return (render_type->draw_engine != NULL) && DRW_engine_render_support(render_type->draw_engine);
}
/* Create, Free */
RenderEngine *RE_engine_create(RenderEngineType *type)
{
- return RE_engine_create_ex(type, false);
+ return RE_engine_create_ex(type, false);
}
RenderEngine *RE_engine_create_ex(RenderEngineType *type, bool use_for_viewport)
{
- RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine");
- engine->type = type;
+ RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine");
+ engine->type = type;
- if (use_for_viewport) {
- engine->flag |= RE_ENGINE_USED_FOR_VIEWPORT;
+ if (use_for_viewport) {
+ engine->flag |= RE_ENGINE_USED_FOR_VIEWPORT;
- BLI_threaded_malloc_begin();
- }
+ BLI_threaded_malloc_begin();
+ }
- BLI_mutex_init(&engine->update_render_passes_mutex);
+ BLI_mutex_init(&engine->update_render_passes_mutex);
- return engine;
+ return engine;
}
void RE_engine_free(RenderEngine *engine)
{
#ifdef WITH_PYTHON
- if (engine->py_instance) {
- BPY_DECREF_RNA_INVALIDATE(engine->py_instance);
- }
+ if (engine->py_instance) {
+ BPY_DECREF_RNA_INVALIDATE(engine->py_instance);
+ }
#endif
- if (engine->flag & RE_ENGINE_USED_FOR_VIEWPORT) {
- BLI_threaded_malloc_end();
- }
+ if (engine->flag & RE_ENGINE_USED_FOR_VIEWPORT) {
+ BLI_threaded_malloc_end();
+ }
- BLI_mutex_end(&engine->update_render_passes_mutex);
+ BLI_mutex_end(&engine->update_render_passes_mutex);
- MEM_freeN(engine);
+ MEM_freeN(engine);
}
/* Render Results */
static RenderPart *get_part_from_result(Render *re, RenderResult *result)
{
- RenderPart *pa;
+ RenderPart *pa;
- for (pa = re->parts.first; pa; pa = pa->next) {
- if (result->tilerect.xmin == pa->disprect.xmin - re->disprect.xmin &&
- result->tilerect.ymin == pa->disprect.ymin - re->disprect.ymin &&
- result->tilerect.xmax == pa->disprect.xmax - re->disprect.xmin &&
- result->tilerect.ymax == pa->disprect.ymax - re->disprect.ymin)
- {
- return pa;
- }
- }
+ for (pa = re->parts.first; pa; pa = pa->next) {
+ if (result->tilerect.xmin == pa->disprect.xmin - re->disprect.xmin &&
+ result->tilerect.ymin == pa->disprect.ymin - re->disprect.ymin &&
+ result->tilerect.xmax == pa->disprect.xmax - re->disprect.xmin &&
+ result->tilerect.ymax == pa->disprect.ymax - re->disprect.ymin) {
+ return pa;
+ }
+ }
- return NULL;
+ return NULL;
}
RenderResult *RE_engine_begin_result(
- RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
+ RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
{
- Render *re = engine->re;
- RenderResult *result;
- rcti disprect;
+ Render *re = engine->re;
+ RenderResult *result;
+ rcti disprect;
- /* ensure the coordinates are within the right limits */
- CLAMP(x, 0, re->result->rectx);
- CLAMP(y, 0, re->result->recty);
- CLAMP(w, 0, re->result->rectx);
- CLAMP(h, 0, re->result->recty);
+ /* ensure the coordinates are within the right limits */
+ CLAMP(x, 0, re->result->rectx);
+ CLAMP(y, 0, re->result->recty);
+ CLAMP(w, 0, re->result->rectx);
+ CLAMP(h, 0, re->result->recty);
- if (x + w > re->result->rectx)
- w = re->result->rectx - x;
- if (y + h > re->result->recty)
- h = re->result->recty - y;
+ if (x + w > re->result->rectx)
+ w = re->result->rectx - x;
+ if (y + h > re->result->recty)
+ h = re->result->recty - y;
- /* allocate a render result */
- disprect.xmin = x;
- disprect.xmax = x + w;
- disprect.ymin = y;
- disprect.ymax = y + h;
+ /* allocate a render result */
+ disprect.xmin = x;
+ disprect.xmax = x + w;
+ disprect.ymin = y;
+ disprect.ymax = y + h;
- result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername, viewname);
+ result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername, viewname);
- /* todo: make this thread safe */
+ /* todo: make this thread safe */
- /* can be NULL if we CLAMP the width or height to 0 */
- if (result) {
- render_result_clone_passes(re, result, viewname);
+ /* can be NULL if we CLAMP the width or height to 0 */
+ if (result) {
+ render_result_clone_passes(re, result, viewname);
- RenderPart *pa;
+ RenderPart *pa;
- /* Copy EXR tile settings, so pipeline knows whether this is a result
- * for Save Buffers enabled rendering.
- */
- result->do_exr_tile = re->result->do_exr_tile;
+ /* Copy EXR tile settings, so pipeline knows whether this is a result
+ * for Save Buffers enabled rendering.
+ */
+ result->do_exr_tile = re->result->do_exr_tile;
- BLI_addtail(&engine->fullresult, result);
+ BLI_addtail(&engine->fullresult, result);
- result->tilerect.xmin += re->disprect.xmin;
- result->tilerect.xmax += re->disprect.xmin;
- result->tilerect.ymin += re->disprect.ymin;
- result->tilerect.ymax += re->disprect.ymin;
+ result->tilerect.xmin += re->disprect.xmin;
+ result->tilerect.xmax += re->disprect.xmin;
+ result->tilerect.ymin += re->disprect.ymin;
+ result->tilerect.ymax += re->disprect.ymin;
- pa = get_part_from_result(re, result);
+ pa = get_part_from_result(re, result);
- if (pa)
- pa->status = PART_STATUS_IN_PROGRESS;
- }
+ if (pa)
+ pa->status = PART_STATUS_IN_PROGRESS;
+ }
- return result;
+ return result;
}
void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
{
- Render *re = engine->re;
+ Render *re = engine->re;
- if (result) {
- result->renlay = result->layers.first; /* weak, draws first layer always */
- re->display_update(re->duh, result, NULL);
- }
+ if (result) {
+ result->renlay = result->layers.first; /* weak, draws first layer always */
+ re->display_update(re->duh, result, NULL);
+ }
}
-void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername)
+void RE_engine_add_pass(RenderEngine *engine,
+ const char *name,
+ int channels,
+ const char *chan_id,
+ const char *layername)
{
- Render *re = engine->re;
+ Render *re = engine->re;
- if (!re || !re->result) {
- return;
- }
+ if (!re || !re->result) {
+ return;
+ }
- render_result_add_pass(re->result, name, channels, chan_id, layername, NULL);
+ render_result_add_pass(re->result, name, channels, chan_id, layername, NULL);
}
-void RE_engine_end_result(RenderEngine *engine, RenderResult *result, bool cancel, bool highlight, bool merge_results)
+void RE_engine_end_result(
+ RenderEngine *engine, RenderResult *result, bool cancel, bool highlight, bool merge_results)
{
- Render *re = engine->re;
+ Render *re = engine->re;
- if (!result) {
- return;
- }
+ if (!result) {
+ return;
+ }
- /* merge. on break, don't merge in result for preview renders, looks nicer */
- if (!highlight) {
- /* for exr tile render, detect tiles that are done */
- RenderPart *pa = get_part_from_result(re, result);
+ /* merge. on break, don't merge in result for preview renders, looks nicer */
+ if (!highlight) {
+ /* for exr tile render, detect tiles that are done */
+ RenderPart *pa = get_part_from_result(re, result);
- if (pa) {
- pa->status = (!cancel && merge_results) ? PART_STATUS_MERGED : PART_STATUS_RENDERED;
- }
- else if (re->result->do_exr_tile) {
- /* if written result does not match any tile and we are using save
- * buffers, we are going to get openexr save errors */
- fprintf(stderr, "RenderEngine.end_result: dimensions do not match any OpenEXR tile.\n");
- }
- }
+ if (pa) {
+ pa->status = (!cancel && merge_results) ? PART_STATUS_MERGED : PART_STATUS_RENDERED;
+ }
+ else if (re->result->do_exr_tile) {
+ /* if written result does not match any tile and we are using save
+ * buffers, we are going to get openexr save errors */
+ fprintf(stderr, "RenderEngine.end_result: dimensions do not match any OpenEXR tile.\n");
+ }
+ }
- if (!cancel || merge_results) {
- if (re->result->do_exr_tile) {
- if (!cancel && merge_results) {
- render_result_exr_file_merge(re->result, result, re->viewname);
- }
- }
- else if (!(re->test_break(re->tbh) && (re->r.scemode & R_BUTS_PREVIEW)))
- render_result_merge(re->result, result);
+ if (!cancel || merge_results) {
+ if (re->result->do_exr_tile) {
+ if (!cancel && merge_results) {
+ render_result_exr_file_merge(re->result, result, re->viewname);
+ }
+ }
+ else if (!(re->test_break(re->tbh) && (re->r.scemode & R_BUTS_PREVIEW)))
+ render_result_merge(re->result, result);
- /* draw */
- if (!re->test_break(re->tbh)) {
- result->renlay = result->layers.first; /* weak, draws first layer always */
- re->display_update(re->duh, result, NULL);
- }
- }
+ /* draw */
+ if (!re->test_break(re->tbh)) {
+ result->renlay = result->layers.first; /* weak, draws first layer always */
+ re->display_update(re->duh, result, NULL);
+ }
+ }
- /* free */
- BLI_remlink(&engine->fullresult, result);
- render_result_free(result);
+ /* free */
+ BLI_remlink(&engine->fullresult, result);
+ render_result_free(result);
}
RenderResult *RE_engine_get_result(RenderEngine *engine)
{
- return engine->re->result;
+ return engine->re->result;
}
/* Cancel */
bool RE_engine_test_break(RenderEngine *engine)
{
- Render *re = engine->re;
+ Render *re = engine->re;
- if (re)
- return re->test_break(re->tbh);
+ if (re)
+ return re->test_break(re->tbh);
- return 0;
+ return 0;
}
/* Statistics */
void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
{
- Render *re = engine->re;
+ Render *re = engine->re;
- /* stats draw callback */
- if (re) {
- re->i.statstr = stats;
- re->i.infostr = info;
- re->stats_draw(re->sdh, &re->i);
- re->i.infostr = NULL;
- re->i.statstr = NULL;
- }
+ /* stats draw callback */
+ if (re) {
+ re->i.statstr = stats;
+ re->i.infostr = info;
+ re->stats_draw(re->sdh, &re->i);
+ re->i.infostr = NULL;
+ re->i.statstr = NULL;
+ }
- /* set engine text */
- engine->text[0] = '\0';
+ /* set engine text */
+ engine->text[0] = '\0';
- if (stats && stats[0] && info && info[0])
- BLI_snprintf(engine->text, sizeof(engine->text), "%s | %s", stats, info);
- else if (info && info[0])
- BLI_strncpy(engine->text, info, sizeof(engine->text));
- else if (stats && stats[0])
- BLI_strncpy(engine->text, stats, sizeof(engine->text));
+ if (stats && stats[0] && info && info[0])
+ BLI_snprintf(engine->text, sizeof(engine->text), "%s | %s", stats, info);
+ else if (info && info[0])
+ BLI_strncpy(engine->text, info, sizeof(engine->text));
+ else if (stats && stats[0])
+ BLI_strncpy(engine->text, stats, sizeof(engine->text));
}
void RE_engine_update_progress(RenderEngine *engine, float progress)
{
- Render *re = engine->re;
+ Render *re = engine->re;
- if (re) {
- CLAMP(progress, 0.0f, 1.0f);
- re->progress(re->prh, progress);
- }
+ if (re) {
+ CLAMP(progress, 0.0f, 1.0f);
+ re->progress(re->prh, progress);
+ }
}
void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float mem_peak)
{
- Render *re = engine->re;
+ Render *re = engine->re;
- if (re) {
- re->i.mem_used = mem_used;
- re->i.mem_peak = mem_peak;
- }
+ if (re) {
+ re->i.mem_used = mem_used;
+ re->i.mem_peak = mem_peak;
+ }
}
void RE_engine_report(RenderEngine *engine, int type, const char *msg)
{
- Render *re = engine->re;
+ Render *re = engine->re;
- if (re)
- BKE_report(engine->re->reports, type, msg);
- else if (engine->reports)
- BKE_report(engine->reports, type, msg);
+ if (re)
+ BKE_report(engine->re->reports, type, msg);
+ else if (engine->reports)
+ BKE_report(engine->reports, type, msg);
}
void RE_engine_set_error_message(RenderEngine *engine, const char *msg)
{
- Render *re = engine->re;
- if (re != NULL) {
- RenderResult *rr = RE_AcquireResultRead(re);
- if (rr) {
- if (rr->error != NULL) {
- MEM_freeN(rr->error);
- }
- rr->error = BLI_strdup(msg);
- }
- RE_ReleaseResult(re);
- }
+ Render *re = engine->re;
+ if (re != NULL) {
+ RenderResult *rr = RE_AcquireResultRead(re);
+ if (rr) {
+ if (rr->error != NULL) {
+ MEM_freeN(rr->error);
+ }
+ rr->error = BLI_strdup(msg);
+ }
+ RE_ReleaseResult(re);
+ }
}
const char *RE_engine_active_view_get(RenderEngine *engine)
{
- Render *re = engine->re;
- return RE_GetActiveRenderView(re);
+ Render *re = engine->re;
+ return RE_GetActiveRenderView(re);
}
void RE_engine_active_view_set(RenderEngine *engine, const char *viewname)
{
- Render *re = engine->re;
- RE_SetActiveRenderView(re, viewname);
+ Render *re = engine->re;
+ RE_SetActiveRenderView(re, viewname);
}
float RE_engine_get_camera_shift_x(RenderEngine *engine, Object *camera, bool use_spherical_stereo)
{
- Render *re = engine->re;
+ Render *re = engine->re;
- /* when using spherical stereo, get camera shift without multiview, leaving stereo to be handled by the engine */
- if (use_spherical_stereo)
- re = NULL;
+ /* when using spherical stereo, get camera shift without multiview, leaving stereo to be handled by the engine */
+ if (use_spherical_stereo)
+ re = NULL;
- return BKE_camera_multiview_shift_x(re ? &re->r : NULL, camera, re->viewname);
+ return BKE_camera_multiview_shift_x(re ? &re->r : NULL, camera, re->viewname);
}
-void RE_engine_get_camera_model_matrix(
- RenderEngine *engine, Object *camera, bool use_spherical_stereo, float *r_modelmat)
+void RE_engine_get_camera_model_matrix(RenderEngine *engine,
+ Object *camera,
+ bool use_spherical_stereo,
+ float *r_modelmat)
{
- Render *re = engine->re;
+ Render *re = engine->re;
- /* when using spherical stereo, get model matrix without multiview, leaving stereo to be handled by the engine */
- if (use_spherical_stereo)
- re = NULL;
+ /* when using spherical stereo, get model matrix without multiview, leaving stereo to be handled by the engine */
+ if (use_spherical_stereo)
+ re = NULL;
- BKE_camera_multiview_model_matrix(re ? &re->r : NULL, camera, re->viewname, (float (*)[4])r_modelmat);
+ BKE_camera_multiview_model_matrix(
+ re ? &re->r : NULL, camera, re->viewname, (float(*)[4])r_modelmat);
}
bool RE_engine_get_spherical_stereo(RenderEngine *engine, Object *camera)
{
- Render *re = engine->re;
- return BKE_camera_multiview_spherical_stereo(re ? &re->r : NULL, camera) ? 1 : 0;
+ Render *re = engine->re;
+ return BKE_camera_multiview_spherical_stereo(re ? &re->r : NULL, camera) ? 1 : 0;
}
rcti *RE_engine_get_current_tiles(Render *re, int *r_total_tiles, bool *r_needs_free)
{
- static rcti tiles_static[BLENDER_MAX_THREADS];
- const int allocation_step = BLENDER_MAX_THREADS;
- RenderPart *pa;
- int total_tiles = 0;
- rcti *tiles = tiles_static;
- int allocation_size = BLENDER_MAX_THREADS;
-
- BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_READ);
-
- *r_needs_free = false;
-
- if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
- *r_total_tiles = 0;
- BLI_rw_mutex_unlock(&re->partsmutex);
- return NULL;
- }
-
- for (pa = re->parts.first; pa; pa = pa->next) {
- if (pa->status == PART_STATUS_IN_PROGRESS) {
- if (total_tiles >= allocation_size) {
- /* Just in case we're using crazy network rendering with more
- * workers than BLENDER_MAX_THREADS.
- */
- allocation_size += allocation_step;
- if (tiles == tiles_static) {
- /* Can not realloc yet, tiles are pointing to a
- * stack memory.
- */
- tiles = MEM_mallocN(allocation_size * sizeof(rcti), "current engine tiles");
- }
- else {
- tiles = MEM_reallocN(tiles, allocation_size * sizeof(rcti));
- }
- *r_needs_free = true;
- }
- tiles[total_tiles] = pa->disprect;
-
- total_tiles++;
- }
- }
- BLI_rw_mutex_unlock(&re->partsmutex);
- *r_total_tiles = total_tiles;
- return tiles;
+ static rcti tiles_static[BLENDER_MAX_THREADS];
+ const int allocation_step = BLENDER_MAX_THREADS;
+ RenderPart *pa;
+ int total_tiles = 0;
+ rcti *tiles = tiles_static;
+ int allocation_size = BLENDER_MAX_THREADS;
+
+ BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_READ);
+
+ *r_needs_free = false;
+
+ if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
+ *r_total_tiles = 0;
+ BLI_rw_mutex_unlock(&re->partsmutex);
+ return NULL;
+ }
+
+ for (pa = re->parts.first; pa; pa = pa->next) {
+ if (pa->status == PART_STATUS_IN_PROGRESS) {
+ if (total_tiles >= allocation_size) {
+ /* Just in case we're using crazy network rendering with more
+ * workers than BLENDER_MAX_THREADS.
+ */
+ allocation_size += allocation_step;
+ if (tiles == tiles_static) {
+ /* Can not realloc yet, tiles are pointing to a
+ * stack memory.
+ */
+ tiles = MEM_mallocN(allocation_size * sizeof(rcti), "current engine tiles");
+ }
+ else {
+ tiles = MEM_reallocN(tiles, allocation_size * sizeof(rcti));
+ }
+ *r_needs_free = true;
+ }
+ tiles[total_tiles] = pa->disprect;
+
+ total_tiles++;
+ }
+ }
+ BLI_rw_mutex_unlock(&re->partsmutex);
+ *r_total_tiles = total_tiles;
+ return tiles;
}
RenderData *RE_engine_get_render_data(Render *re)
{
- return &re->r;
+ return &re->r;
}
/* Depsgraph */
static void engine_depsgraph_init(RenderEngine *engine, ViewLayer *view_layer)
{
- Main *bmain = engine->re->main;
- Scene *scene = engine->re->scene;
+ Main *bmain = engine->re->main;
+ Scene *scene = engine->re->scene;
- engine->depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
- DEG_debug_name_set(engine->depsgraph, "RENDER");
+ engine->depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
+ DEG_debug_name_set(engine->depsgraph, "RENDER");
- BKE_scene_graph_update_for_newframe(engine->depsgraph, bmain);
+ BKE_scene_graph_update_for_newframe(engine->depsgraph, bmain);
}
static void engine_depsgraph_free(RenderEngine *engine)
{
- DEG_graph_free(engine->depsgraph);
+ DEG_graph_free(engine->depsgraph);
- engine->depsgraph = NULL;
+ engine->depsgraph = NULL;
}
void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
{
- if (!engine->depsgraph) {
- return;
- }
+ if (!engine->depsgraph) {
+ return;
+ }
#ifdef WITH_PYTHON
- BPy_BEGIN_ALLOW_THREADS;
+ BPy_BEGIN_ALLOW_THREADS;
#endif
- Render *re = engine->re;
- double cfra = (double)frame + (double)subframe;
+ Render *re = engine->re;
+ double cfra = (double)frame + (double)subframe;
- CLAMP(cfra, MINAFRAME, MAXFRAME);
- BKE_scene_frame_set(re->scene, cfra);
- BKE_scene_graph_update_for_newframe(engine->depsgraph, re->main);
+ CLAMP(cfra, MINAFRAME, MAXFRAME);
+ BKE_scene_frame_set(re->scene, cfra);
+ BKE_scene_graph_update_for_newframe(engine->depsgraph, re->main);
- BKE_scene_camera_switch_update(re->scene);
+ BKE_scene_camera_switch_update(re->scene);
#ifdef WITH_PYTHON
- BPy_END_ALLOW_THREADS;
+ BPy_END_ALLOW_THREADS;
#endif
}
/* Bake */
void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Scene *scene)
{
- re->scene = scene;
- re->main = bmain;
- render_copy_renderdata(&re->r, &scene->r);
+ re->scene = scene;
+ re->main = bmain;
+ render_copy_renderdata(&re->r, &scene->r);
}
bool RE_bake_has_engine(Render *re)
{
- RenderEngineType *type = RE_engines_find(re->r.engine);
- return (type->bake != NULL);
+ RenderEngineType *type = RE_engines_find(re->r.engine);
+ return (type->bake != NULL);
}
-bool RE_bake_engine(
- Render *re, Depsgraph *depsgraph, Object *object,
- const int object_id, const BakePixel pixel_array[],
- const size_t num_pixels, const int depth,
- const eScenePassType pass_type, const int pass_filter,
- float result[])
+bool RE_bake_engine(Render *re,
+ Depsgraph *depsgraph,
+ Object *object,
+ const int object_id,
+ const BakePixel pixel_array[],
+ const size_t num_pixels,
+ const int depth,
+ const eScenePassType pass_type,
+ const int pass_filter,
+ float result[])
{
- RenderEngineType *type = RE_engines_find(re->r.engine);
- RenderEngine *engine;
- bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
+ RenderEngineType *type = RE_engines_find(re->r.engine);
+ RenderEngine *engine;
+ bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
- /* set render info */
- re->i.cfra = re->scene->r.cfra;
- BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name) - 2);
- re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
+ /* set render info */
+ re->i.cfra = re->scene->r.cfra;
+ BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name) - 2);
+ re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
- /* render */
- engine = re->engine;
+ /* render */
+ engine = re->engine;
- if (!engine) {
- engine = RE_engine_create(type);
- re->engine = engine;
- }
+ if (!engine) {
+ engine = RE_engine_create(type);
+ re->engine = engine;
+ }
- engine->flag |= RE_ENGINE_RENDERING;
+ engine->flag |= RE_ENGINE_RENDERING;
- /* TODO: actually link to a parent which shouldn't happen */
- engine->re = re;
+ /* TODO: actually link to a parent which shouldn't happen */
+ engine->re = re;
- engine->resolution_x = re->winx;
- engine->resolution_y = re->winy;
+ engine->resolution_x = re->winx;
+ engine->resolution_y = re->winy;
- RE_parts_init(re);
- engine->tile_x = re->r.tilex;
- engine->tile_y = re->r.tiley;
+ RE_parts_init(re);
+ engine->tile_x = re->r.tilex;
+ engine->tile_y = re->r.tiley;
- if (type->bake) {
- engine->depsgraph = depsgraph;
+ if (type->bake) {
+ engine->depsgraph = depsgraph;
- /* update is only called so we create the engine.session */
- if (type->update)
- type->update(engine, re->main, engine->depsgraph);
+ /* update is only called so we create the engine.session */
+ if (type->update)
+ type->update(engine, re->main, engine->depsgraph);
- type->bake(engine,
- engine->depsgraph,
- object,
- pass_type,
- pass_filter,
- object_id,
- pixel_array,
- num_pixels,
- depth,
- result);
+ type->bake(engine,
+ engine->depsgraph,
+ object,
+ pass_type,
+ pass_filter,
+ object_id,
+ pixel_array,
+ num_pixels,
+ depth,
+ result);
- engine->depsgraph = NULL;
- }
+ engine->depsgraph = NULL;
+ }
- engine->tile_x = 0;
- engine->tile_y = 0;
- engine->flag &= ~RE_ENGINE_RENDERING;
+ engine->tile_x = 0;
+ engine->tile_y = 0;
+ engine->flag &= ~RE_ENGINE_RENDERING;
- BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
+ BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
- /* re->engine becomes zero if user changed active render engine during render */
- if (!persistent_data || !re->engine) {
- RE_engine_free(engine);
- re->engine = NULL;
- }
+ /* re->engine becomes zero if user changed active render engine during render */
+ if (!persistent_data || !re->engine) {
+ RE_engine_free(engine);
+ re->engine = NULL;
+ }
- RE_parts_free(re);
- BLI_rw_mutex_unlock(&re->partsmutex);
+ RE_parts_free(re);
+ BLI_rw_mutex_unlock(&re->partsmutex);
- if (BKE_reports_contain(re->reports, RPT_ERROR))
- G.is_break = true;
+ if (BKE_reports_contain(re->reports, RPT_ERROR))
+ G.is_break = true;
- return true;
+ return true;
}
/* Render */
int RE_engine_render(Render *re, int do_all)
{
- RenderEngineType *type = RE_engines_find(re->r.engine);
- RenderEngine *engine;
- bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
-
- /* verify if we can render */
- if (!type->render)
- return 0;
- if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW))
- return 0;
- if (do_all && !(type->flag & RE_USE_POSTPROCESS))
- return 0;
- if (!do_all && (type->flag & RE_USE_POSTPROCESS))
- return 0;
-
- /* Lock drawing in UI during data phase. */
- if (re->draw_lock) {
- re->draw_lock(re->dlh, 1);
- }
-
- /* update animation here so any render layer animation is applied before
- * creating the render result */
- if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) {
- render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers);
- }
-
- /* create render result */
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- if (re->result == NULL || !(re->r.scemode & R_BUTS_PREVIEW)) {
- int savebuffers = RR_USE_MEM;
-
- if (re->result)
- render_result_free(re->result);
-
- if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE))
- savebuffers = RR_USE_EXR;
- re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS, RR_ALL_VIEWS);
- }
- BLI_rw_mutex_unlock(&re->resultmutex);
-
- if (re->result == NULL) {
- /* Clear UI drawing locks. */
- if (re->draw_lock) {
- re->draw_lock(re->dlh, 0);
- }
- /* Too small image is handled earlier, here it could only happen if
- * there was no sufficient memory to allocate all passes.
- */
- BKE_report(re->reports, RPT_ERROR, "Failed allocate render result, out of memory");
- G.is_break = true;
- return 1;
- }
-
- /* set render info */
- re->i.cfra = re->scene->r.cfra;
- BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name));
- re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
-
- /* render */
- engine = re->engine;
-
- if (!engine) {
- engine = RE_engine_create(type);
- re->engine = engine;
- }
-
- engine->flag |= RE_ENGINE_RENDERING;
-
- /* TODO: actually link to a parent which shouldn't happen */
- engine->re = re;
-
- if (re->flag & R_ANIMATION)
- engine->flag |= RE_ENGINE_ANIMATION;
- if (re->r.scemode & R_BUTS_PREVIEW)
- engine->flag |= RE_ENGINE_PREVIEW;
- engine->camera_override = re->camera_override;
-
- engine->resolution_x = re->winx;
- engine->resolution_y = re->winy;
-
- RE_parts_init(re);
- engine->tile_x = re->partx;
- engine->tile_y = re->party;
-
- if (re->result->do_exr_tile)
- render_result_exr_file_begin(re, engine);
-
- /* Clear UI drawing locks. */
- if (re->draw_lock) {
- re->draw_lock(re->dlh, 0);
- }
-
- if (type->render) {
- FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re, view_layer_iter)
- {
- if (re->draw_lock) {
- re->draw_lock(re->dlh, 1);
- }
-
- ViewLayer *view_layer = BLI_findstring(&re->scene->view_layers, view_layer_iter->name, offsetof(ViewLayer, name));
- engine_depsgraph_init(engine, view_layer);
-
- if (type->update) {
- type->update(engine, re->main, engine->depsgraph);
- }
-
- if (re->draw_lock) {
- re->draw_lock(re->dlh, 0);
- }
-
- type->render(engine, engine->depsgraph);
-
- /* Grease pencil render over previous render result.
- *
- * NOTE: External engine might have been requested to free its
- * dependency graph, which is only allowed if there is no grease
- * pencil (pipeline is taking care of that).
- */
- if (!RE_engine_test_break(engine) && engine->depsgraph != NULL) {
- DRW_render_gpencil(engine, engine->depsgraph);
- }
-
- engine_depsgraph_free(engine);
-
- if (RE_engine_test_break(engine)) {
- break;
- }
- }
- FOREACH_VIEW_LAYER_TO_RENDER_END;
- }
-
- engine->tile_x = 0;
- engine->tile_y = 0;
- engine->flag &= ~RE_ENGINE_RENDERING;
-
- render_result_free_list(&engine->fullresult, engine->fullresult.first);
-
- BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
-
- if (re->result->do_exr_tile) {
- render_result_exr_file_end(re, engine);
- }
-
- /* re->engine becomes zero if user changed active render engine during render */
- if (!persistent_data || !re->engine) {
- RE_engine_free(engine);
- re->engine = NULL;
- }
-
- if (re->r.scemode & R_EXR_CACHE_FILE) {
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- render_result_exr_file_cache_write(re);
- BLI_rw_mutex_unlock(&re->resultmutex);
- }
+ RenderEngineType *type = RE_engines_find(re->r.engine);
+ RenderEngine *engine;
+ bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
+
+ /* verify if we can render */
+ if (!type->render)
+ return 0;
+ if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW))
+ return 0;
+ if (do_all && !(type->flag & RE_USE_POSTPROCESS))
+ return 0;
+ if (!do_all && (type->flag & RE_USE_POSTPROCESS))
+ return 0;
+
+ /* Lock drawing in UI during data phase. */
+ if (re->draw_lock) {
+ re->draw_lock(re->dlh, 1);
+ }
+
+ /* update animation here so any render layer animation is applied before
+ * creating the render result */
+ if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) {
+ render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers);
+ }
+
+ /* create render result */
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ if (re->result == NULL || !(re->r.scemode & R_BUTS_PREVIEW)) {
+ int savebuffers = RR_USE_MEM;
+
+ if (re->result)
+ render_result_free(re->result);
+
+ if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE))
+ savebuffers = RR_USE_EXR;
+ re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS, RR_ALL_VIEWS);
+ }
+ BLI_rw_mutex_unlock(&re->resultmutex);
+
+ if (re->result == NULL) {
+ /* Clear UI drawing locks. */
+ if (re->draw_lock) {
+ re->draw_lock(re->dlh, 0);
+ }
+ /* Too small image is handled earlier, here it could only happen if
+ * there was no sufficient memory to allocate all passes.
+ */
+ BKE_report(re->reports, RPT_ERROR, "Failed allocate render result, out of memory");
+ G.is_break = true;
+ return 1;
+ }
+
+ /* set render info */
+ re->i.cfra = re->scene->r.cfra;
+ BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name));
+ re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
+
+ /* render */
+ engine = re->engine;
+
+ if (!engine) {
+ engine = RE_engine_create(type);
+ re->engine = engine;
+ }
+
+ engine->flag |= RE_ENGINE_RENDERING;
+
+ /* TODO: actually link to a parent which shouldn't happen */
+ engine->re = re;
+
+ if (re->flag & R_ANIMATION)
+ engine->flag |= RE_ENGINE_ANIMATION;
+ if (re->r.scemode & R_BUTS_PREVIEW)
+ engine->flag |= RE_ENGINE_PREVIEW;
+ engine->camera_override = re->camera_override;
+
+ engine->resolution_x = re->winx;
+ engine->resolution_y = re->winy;
+
+ RE_parts_init(re);
+ engine->tile_x = re->partx;
+ engine->tile_y = re->party;
+
+ if (re->result->do_exr_tile)
+ render_result_exr_file_begin(re, engine);
+
+ /* Clear UI drawing locks. */
+ if (re->draw_lock) {
+ re->draw_lock(re->dlh, 0);
+ }
+
+ if (type->render) {
+ FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer_iter) {
+ if (re->draw_lock) {
+ re->draw_lock(re->dlh, 1);
+ }
+
+ ViewLayer *view_layer = BLI_findstring(
+ &re->scene->view_layers, view_layer_iter->name, offsetof(ViewLayer, name));
+ engine_depsgraph_init(engine, view_layer);
+
+ if (type->update) {
+ type->update(engine, re->main, engine->depsgraph);
+ }
+
+ if (re->draw_lock) {
+ re->draw_lock(re->dlh, 0);
+ }
+
+ type->render(engine, engine->depsgraph);
+
+ /* Grease pencil render over previous render result.
+ *
+ * NOTE: External engine might have been requested to free its
+ * dependency graph, which is only allowed if there is no grease
+ * pencil (pipeline is taking care of that).
+ */
+ if (!RE_engine_test_break(engine) && engine->depsgraph != NULL) {
+ DRW_render_gpencil(engine, engine->depsgraph);
+ }
+
+ engine_depsgraph_free(engine);
+
+ if (RE_engine_test_break(engine)) {
+ break;
+ }
+ }
+ FOREACH_VIEW_LAYER_TO_RENDER_END;
+ }
+
+ engine->tile_x = 0;
+ engine->tile_y = 0;
+ engine->flag &= ~RE_ENGINE_RENDERING;
+
+ render_result_free_list(&engine->fullresult, engine->fullresult.first);
+
+ BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
+
+ if (re->result->do_exr_tile) {
+ render_result_exr_file_end(re, engine);
+ }
+
+ /* re->engine becomes zero if user changed active render engine during render */
+ if (!persistent_data || !re->engine) {
+ RE_engine_free(engine);
+ re->engine = NULL;
+ }
+
+ if (re->r.scemode & R_EXR_CACHE_FILE) {
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ render_result_exr_file_cache_write(re);
+ BLI_rw_mutex_unlock(&re->resultmutex);
+ }
- RE_parts_free(re);
- BLI_rw_mutex_unlock(&re->partsmutex);
+ RE_parts_free(re);
+ BLI_rw_mutex_unlock(&re->partsmutex);
- if (BKE_reports_contain(re->reports, RPT_ERROR))
- G.is_break = true;
+ if (BKE_reports_contain(re->reports, RPT_ERROR))
+ G.is_break = true;
#ifdef WITH_FREESTYLE
- if (re->r.mode & R_EDGE_FRS)
- RE_RenderFreestyleExternal(re);
+ if (re->r.mode & R_EDGE_FRS)
+ RE_RenderFreestyleExternal(re);
#endif
- return 1;
+ return 1;
}
-void RE_engine_update_render_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer,
- update_render_passes_cb_t callback, void *callback_data)
+void RE_engine_update_render_passes(struct RenderEngine *engine,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ update_render_passes_cb_t callback,
+ void *callback_data)
{
- if (!(scene && view_layer && engine && callback && engine->type->update_render_passes)) {
- return;
- }
+ if (!(scene && view_layer && engine && callback && engine->type->update_render_passes)) {
+ return;
+ }
- BLI_mutex_lock(&engine->update_render_passes_mutex);
+ BLI_mutex_lock(&engine->update_render_passes_mutex);
- engine->update_render_passes_cb = callback;
- engine->update_render_passes_data = callback_data;
- engine->type->update_render_passes(engine, scene, view_layer);
- engine->update_render_passes_cb = NULL;
- engine->update_render_passes_data = NULL;
+ engine->update_render_passes_cb = callback;
+ engine->update_render_passes_data = callback_data;
+ engine->type->update_render_passes(engine, scene, view_layer);
+ engine->update_render_passes_cb = NULL;
+ engine->update_render_passes_data = NULL;
- BLI_mutex_unlock(&engine->update_render_passes_mutex);
+ BLI_mutex_unlock(&engine->update_render_passes_mutex);
}
-void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer,
- const char *name, int channels, const char *chanid, int type)
+void RE_engine_register_pass(struct RenderEngine *engine,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ const char *name,
+ int channels,
+ const char *chanid,
+ int type)
{
- if (!(scene && view_layer && engine && engine->update_render_passes_cb)) {
- return;
- }
+ if (!(scene && view_layer && engine && engine->update_render_passes_cb)) {
+ return;
+ }
- engine->update_render_passes_cb(engine->update_render_passes_data, scene, view_layer, name, channels, chanid, type);
+ engine->update_render_passes_cb(
+ engine->update_render_passes_data, scene, view_layer, name, channels, chanid, type);
}
void RE_engine_free_blender_memory(RenderEngine *engine)
{
- /* Weak way to save memory, but not crash grease pencil.
- *
- * TODO(sergey): Find better solution for this.
- * TODO(sergey): Try to find solution which does not involve looping over
- * all the objects.
- */
- if (DRW_render_check_grease_pencil(engine->depsgraph)) {
- return;
- }
- DEG_graph_free(engine->depsgraph);
- engine->depsgraph = NULL;
+ /* Weak way to save memory, but not crash grease pencil.
+ *
+ * TODO(sergey): Find better solution for this.
+ * TODO(sergey): Try to find solution which does not involve looping over
+ * all the objects.
+ */
+ if (DRW_render_check_grease_pencil(engine->depsgraph)) {
+ return;
+ }
+ DEG_graph_free(engine->depsgraph);
+ engine->depsgraph = NULL;
}
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index e67a07e791e..a9b06edf558 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -27,9 +27,9 @@
#include <math.h>
#include <float.h>
#ifndef WIN32
-#include <unistd.h>
+# include <unistd.h>
#else
-#include <io.h>
+# include <io.h>
#endif
#include "IMB_imbuf_types.h"
@@ -52,585 +52,634 @@
#include "render_types.h"
#include "texture.h"
-static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend);
+static void boxsample(ImBuf *ibuf,
+ float minx,
+ float miny,
+ float maxx,
+ float maxy,
+ TexResult *texres,
+ const short imaprepeat,
+ const short imapextend);
/* *********** IMAGEWRAPPING ****************** */
-
/* x and y have to be checked for image size */
static void ibuf_get_color(float col[4], struct ImBuf *ibuf, int x, int y)
{
- int ofs = y * ibuf->x + x;
-
- if (ibuf->rect_float) {
- if (ibuf->channels == 4) {
- const float *fp = ibuf->rect_float + 4 * ofs;
- copy_v4_v4(col, fp);
- }
- else if (ibuf->channels == 3) {
- const float *fp = ibuf->rect_float + 3 * ofs;
- copy_v3_v3(col, fp);
- col[3] = 1.0f;
- }
- else {
- const float *fp = ibuf->rect_float + ofs;
- col[0] = col[1] = col[2] = col[3] = *fp;
- }
- }
- else {
- const char *rect = (char *)(ibuf->rect + ofs);
-
- col[0] = ((float)rect[0]) * (1.0f / 255.0f);
- col[1] = ((float)rect[1]) * (1.0f / 255.0f);
- col[2] = ((float)rect[2]) * (1.0f / 255.0f);
- col[3] = ((float)rect[3]) * (1.0f / 255.0f);
-
- /* bytes are internally straight, however render pipeline seems to expect premul */
- col[0] *= col[3];
- col[1] *= col[3];
- col[2] *= col[3];
- }
+ int ofs = y * ibuf->x + x;
+
+ if (ibuf->rect_float) {
+ if (ibuf->channels == 4) {
+ const float *fp = ibuf->rect_float + 4 * ofs;
+ copy_v4_v4(col, fp);
+ }
+ else if (ibuf->channels == 3) {
+ const float *fp = ibuf->rect_float + 3 * ofs;
+ copy_v3_v3(col, fp);
+ col[3] = 1.0f;
+ }
+ else {
+ const float *fp = ibuf->rect_float + ofs;
+ col[0] = col[1] = col[2] = col[3] = *fp;
+ }
+ }
+ else {
+ const char *rect = (char *)(ibuf->rect + ofs);
+
+ col[0] = ((float)rect[0]) * (1.0f / 255.0f);
+ col[1] = ((float)rect[1]) * (1.0f / 255.0f);
+ col[2] = ((float)rect[2]) * (1.0f / 255.0f);
+ col[3] = ((float)rect[3]) * (1.0f / 255.0f);
+
+ /* bytes are internally straight, however render pipeline seems to expect premul */
+ col[0] *= col[3];
+ col[1] *= col[3];
+ col[2] *= col[3];
+ }
}
-int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres, struct ImagePool *pool, const bool skip_load_image)
+int imagewrap(Tex *tex,
+ Image *ima,
+ ImBuf *ibuf,
+ const float texvec[3],
+ TexResult *texres,
+ struct ImagePool *pool,
+ const bool skip_load_image)
{
- float fx, fy, val1, val2, val3;
- int x, y, retval;
- int xi, yi; /* original values */
-
- texres->tin = texres->ta = texres->tr = texres->tg = texres->tb = 0.0f;
-
- /* we need to set retval OK, otherwise texture code generates normals itself... */
- retval = texres->nor ? 3 : 1;
-
- /* quick tests */
- if (ibuf == NULL && ima == NULL)
- return retval;
- if (ima) {
-
- /* hack for icon render */
- if (skip_load_image && !BKE_image_has_loaded_ibuf(ima))
- return retval;
-
- 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_pool_release_ibuf(ima, ibuf, pool);
- return retval;
- }
-
- /* setup mapping */
- if (tex->imaflag & TEX_IMAROT) {
- fy = texvec[0];
- fx = texvec[1];
- }
- else {
- fx = texvec[0];
- fy = texvec[1];
- }
-
- if (tex->extend == TEX_CHECKER) {
- int xs, ys;
-
- xs = (int)floor(fx);
- ys = (int)floor(fy);
- fx -= xs;
- fy -= ys;
-
- if ( (tex->flag & TEX_CHECKER_ODD) == 0) {
- if ((xs + ys) & 1) {
- /* pass */
- }
- else {
- if (ima)
- 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_pool_release_ibuf(ima, ibuf, pool);
- return retval;
- }
- }
- /* scale around center, (0.5, 0.5) */
- if (tex->checkerdist < 1.0f) {
- fx = (fx - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
- fy = (fy - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
- }
- }
-
- x = xi = (int)floorf(fx * ibuf->x);
- y = yi = (int)floorf(fy * ibuf->y);
-
- 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_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_pool_release_ibuf(ima, ibuf, pool);
- return retval;
- }
- }
- else {
- if (tex->extend == TEX_EXTEND) {
- if (x >= ibuf->x) x = ibuf->x - 1;
- else if (x < 0) x = 0;
- }
- else {
- x = x % ibuf->x;
- if (x < 0) x += ibuf->x;
- }
- if (tex->extend == TEX_EXTEND) {
- if (y >= ibuf->y) y = ibuf->y - 1;
- else if (y < 0) y = 0;
- }
- else {
- y = y % ibuf->y;
- if (y < 0) y += ibuf->y;
- }
- }
-
- /* keep this before interpolation [#29761] */
- if (ima) {
- if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
- if ((tex->imaflag & TEX_CALCALPHA) == 0) {
- texres->talpha = true;
- }
- }
- }
-
- /* interpolate */
- if (tex->imaflag & TEX_INTERPOL) {
- float filterx, filtery;
- filterx = (0.5f * tex->filtersize) / ibuf->x;
- filtery = (0.5f * tex->filtersize) / ibuf->y;
-
- /* important that this value is wrapped [#27782]
- * this applies the modifications made by the checks above,
- * back to the floating point values */
- fx -= (float)(xi - x) / (float)ibuf->x;
- fy -= (float)(yi - y) / (float)ibuf->y;
-
- boxsample(ibuf, fx - filterx, fy - filtery, fx + filterx, fy + filtery, texres, (tex->extend == TEX_REPEAT), (tex->extend == TEX_EXTEND));
- }
- else { /* no filtering */
- ibuf_get_color(&texres->tr, ibuf, x, y);
- }
-
- if (texres->nor) {
- if (tex->imaflag & TEX_NORMALMAP) {
- /* qdn: normal from color
- * 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. */
- texres->nor[0] = -2.f * (texres->tr - 0.5f);
- texres->nor[1] = 2.f * (texres->tg - 0.5f);
- texres->nor[2] = 2.f * (texres->tb - 0.5f);
- }
- else {
- /* bump: take three samples */
- val1 = texres->tr + texres->tg + texres->tb;
-
- if (x < ibuf->x - 1) {
- float col[4];
- ibuf_get_color(col, ibuf, x + 1, y);
- val2 = (col[0] + col[1] + col[2]);
- }
- else {
- val2 = val1;
- }
-
- if (y < ibuf->y - 1) {
- float col[4];
- ibuf_get_color(col, ibuf, x, y + 1);
- val3 = (col[0] + col[1] + col[2]);
- }
- else {
- val3 = val1;
- }
-
- /* do not mix up x and y here! */
- texres->nor[0] = (val1 - val2);
- texres->nor[1] = (val1 - val3);
- }
- }
-
- if (texres->talpha) {
- texres->tin = texres->ta;
- }
- else if (tex->imaflag & TEX_CALCALPHA) {
- texres->ta = texres->tin = max_fff(texres->tr, texres->tg, texres->tb);
- }
- else {
- texres->ta = texres->tin = 1.0;
- }
-
- if (tex->flag & TEX_NEGALPHA) {
- texres->ta = 1.0f - texres->ta;
- }
-
- /* de-premul, this is being premulled in shade_input_do_shade()
- * do not de-premul for generated alpha, it is already in straight */
- if (texres->ta != 1.0f && texres->ta > 1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
- fx = 1.0f / texres->ta;
- texres->tr *= fx;
- texres->tg *= fx;
- texres->tb *= fx;
- }
-
- if (ima)
- BKE_image_pool_release_ibuf(ima, ibuf, pool);
-
- BRICONTRGB;
-
- return retval;
+ float fx, fy, val1, val2, val3;
+ int x, y, retval;
+ int xi, yi; /* original values */
+
+ texres->tin = texres->ta = texres->tr = texres->tg = texres->tb = 0.0f;
+
+ /* we need to set retval OK, otherwise texture code generates normals itself... */
+ retval = texres->nor ? 3 : 1;
+
+ /* quick tests */
+ if (ibuf == NULL && ima == NULL)
+ return retval;
+ if (ima) {
+
+ /* hack for icon render */
+ if (skip_load_image && !BKE_image_has_loaded_ibuf(ima))
+ return retval;
+
+ 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_pool_release_ibuf(ima, ibuf, pool);
+ return retval;
+ }
+
+ /* setup mapping */
+ if (tex->imaflag & TEX_IMAROT) {
+ fy = texvec[0];
+ fx = texvec[1];
+ }
+ else {
+ fx = texvec[0];
+ fy = texvec[1];
+ }
+
+ if (tex->extend == TEX_CHECKER) {
+ int xs, ys;
+
+ xs = (int)floor(fx);
+ ys = (int)floor(fy);
+ fx -= xs;
+ fy -= ys;
+
+ if ((tex->flag & TEX_CHECKER_ODD) == 0) {
+ if ((xs + ys) & 1) {
+ /* pass */
+ }
+ else {
+ if (ima)
+ 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_pool_release_ibuf(ima, ibuf, pool);
+ return retval;
+ }
+ }
+ /* scale around center, (0.5, 0.5) */
+ if (tex->checkerdist < 1.0f) {
+ fx = (fx - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
+ fy = (fy - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
+ }
+ }
+
+ x = xi = (int)floorf(fx * ibuf->x);
+ y = yi = (int)floorf(fy * ibuf->y);
+
+ 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_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_pool_release_ibuf(ima, ibuf, pool);
+ return retval;
+ }
+ }
+ else {
+ if (tex->extend == TEX_EXTEND) {
+ if (x >= ibuf->x)
+ x = ibuf->x - 1;
+ else if (x < 0)
+ x = 0;
+ }
+ else {
+ x = x % ibuf->x;
+ if (x < 0)
+ x += ibuf->x;
+ }
+ if (tex->extend == TEX_EXTEND) {
+ if (y >= ibuf->y)
+ y = ibuf->y - 1;
+ else if (y < 0)
+ y = 0;
+ }
+ else {
+ y = y % ibuf->y;
+ if (y < 0)
+ y += ibuf->y;
+ }
+ }
+
+ /* keep this before interpolation [#29761] */
+ if (ima) {
+ if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
+ if ((tex->imaflag & TEX_CALCALPHA) == 0) {
+ texres->talpha = true;
+ }
+ }
+ }
+
+ /* interpolate */
+ if (tex->imaflag & TEX_INTERPOL) {
+ float filterx, filtery;
+ filterx = (0.5f * tex->filtersize) / ibuf->x;
+ filtery = (0.5f * tex->filtersize) / ibuf->y;
+
+ /* important that this value is wrapped [#27782]
+ * this applies the modifications made by the checks above,
+ * back to the floating point values */
+ fx -= (float)(xi - x) / (float)ibuf->x;
+ fy -= (float)(yi - y) / (float)ibuf->y;
+
+ boxsample(ibuf,
+ fx - filterx,
+ fy - filtery,
+ fx + filterx,
+ fy + filtery,
+ texres,
+ (tex->extend == TEX_REPEAT),
+ (tex->extend == TEX_EXTEND));
+ }
+ else { /* no filtering */
+ ibuf_get_color(&texres->tr, ibuf, x, y);
+ }
+
+ if (texres->nor) {
+ if (tex->imaflag & TEX_NORMALMAP) {
+ /* qdn: normal from color
+ * 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. */
+ texres->nor[0] = -2.f * (texres->tr - 0.5f);
+ texres->nor[1] = 2.f * (texres->tg - 0.5f);
+ texres->nor[2] = 2.f * (texres->tb - 0.5f);
+ }
+ else {
+ /* bump: take three samples */
+ val1 = texres->tr + texres->tg + texres->tb;
+
+ if (x < ibuf->x - 1) {
+ float col[4];
+ ibuf_get_color(col, ibuf, x + 1, y);
+ val2 = (col[0] + col[1] + col[2]);
+ }
+ else {
+ val2 = val1;
+ }
+
+ if (y < ibuf->y - 1) {
+ float col[4];
+ ibuf_get_color(col, ibuf, x, y + 1);
+ val3 = (col[0] + col[1] + col[2]);
+ }
+ else {
+ val3 = val1;
+ }
+
+ /* do not mix up x and y here! */
+ texres->nor[0] = (val1 - val2);
+ texres->nor[1] = (val1 - val3);
+ }
+ }
+
+ if (texres->talpha) {
+ texres->tin = texres->ta;
+ }
+ else if (tex->imaflag & TEX_CALCALPHA) {
+ texres->ta = texres->tin = max_fff(texres->tr, texres->tg, texres->tb);
+ }
+ else {
+ texres->ta = texres->tin = 1.0;
+ }
+
+ if (tex->flag & TEX_NEGALPHA) {
+ texres->ta = 1.0f - texres->ta;
+ }
+
+ /* de-premul, this is being premulled in shade_input_do_shade()
+ * do not de-premul for generated alpha, it is already in straight */
+ if (texres->ta != 1.0f && texres->ta > 1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
+ fx = 1.0f / texres->ta;
+ texres->tr *= fx;
+ texres->tg *= fx;
+ texres->tb *= fx;
+ }
+
+ if (ima)
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
+
+ BRICONTRGB;
+
+ return retval;
}
static void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2)
{
- rctf *rf, *newrct;
- short a;
-
- a = *count;
- rf = stack;
- for (; a > 0; a--) {
- if (rf->xmin < x1) {
- if (rf->xmax < x1) {
- rf->xmin += (x2 - x1);
- rf->xmax += (x2 - x1);
- }
- else {
- if (rf->xmax > x2) rf->xmax = x2;
- newrct = stack + *count;
- (*count)++;
-
- newrct->xmax = x2;
- newrct->xmin = rf->xmin + (x2 - x1);
- newrct->ymin = rf->ymin;
- newrct->ymax = rf->ymax;
-
- if (newrct->xmin == newrct->xmax) (*count)--;
-
- rf->xmin = x1;
- }
- }
- else if (rf->xmax > x2) {
- if (rf->xmin > x2) {
- rf->xmin -= (x2 - x1);
- rf->xmax -= (x2 - x1);
- }
- else {
- if (rf->xmin < x1) rf->xmin = x1;
- newrct = stack + *count;
- (*count)++;
-
- newrct->xmin = x1;
- newrct->xmax = rf->xmax - (x2 - x1);
- newrct->ymin = rf->ymin;
- newrct->ymax = rf->ymax;
-
- if (newrct->xmin == newrct->xmax) (*count)--;
-
- rf->xmax = x2;
- }
- }
- rf++;
- }
-
+ rctf *rf, *newrct;
+ short a;
+
+ a = *count;
+ rf = stack;
+ for (; a > 0; a--) {
+ if (rf->xmin < x1) {
+ if (rf->xmax < x1) {
+ rf->xmin += (x2 - x1);
+ rf->xmax += (x2 - x1);
+ }
+ else {
+ if (rf->xmax > x2)
+ rf->xmax = x2;
+ newrct = stack + *count;
+ (*count)++;
+
+ newrct->xmax = x2;
+ newrct->xmin = rf->xmin + (x2 - x1);
+ newrct->ymin = rf->ymin;
+ newrct->ymax = rf->ymax;
+
+ if (newrct->xmin == newrct->xmax)
+ (*count)--;
+
+ rf->xmin = x1;
+ }
+ }
+ else if (rf->xmax > x2) {
+ if (rf->xmin > x2) {
+ rf->xmin -= (x2 - x1);
+ rf->xmax -= (x2 - x1);
+ }
+ else {
+ if (rf->xmin < x1)
+ rf->xmin = x1;
+ newrct = stack + *count;
+ (*count)++;
+
+ newrct->xmin = x1;
+ newrct->xmax = rf->xmax - (x2 - x1);
+ newrct->ymin = rf->ymin;
+ newrct->ymax = rf->ymax;
+
+ if (newrct->xmin == newrct->xmax)
+ (*count)--;
+
+ rf->xmax = x2;
+ }
+ }
+ rf++;
+ }
}
static void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2)
{
- rctf *rf, *newrct;
- short a;
-
- a = *count;
- rf = stack;
- for (; a > 0; a--) {
- if (rf->ymin < y1) {
- if (rf->ymax < y1) {
- rf->ymin += (y2 - y1);
- rf->ymax += (y2 - y1);
- }
- else {
- if (rf->ymax > y2) rf->ymax = y2;
- newrct = stack + *count;
- (*count)++;
-
- newrct->ymax = y2;
- newrct->ymin = rf->ymin + (y2 - y1);
- newrct->xmin = rf->xmin;
- newrct->xmax = rf->xmax;
-
- if (newrct->ymin == newrct->ymax) (*count)--;
-
- rf->ymin = y1;
- }
- }
- else if (rf->ymax > y2) {
- if (rf->ymin > y2) {
- rf->ymin -= (y2 - y1);
- rf->ymax -= (y2 - y1);
- }
- else {
- if (rf->ymin < y1) rf->ymin = y1;
- newrct = stack + *count;
- (*count)++;
-
- newrct->ymin = y1;
- newrct->ymax = rf->ymax - (y2 - y1);
- newrct->xmin = rf->xmin;
- newrct->xmax = rf->xmax;
-
- if (newrct->ymin == newrct->ymax) (*count)--;
-
- rf->ymax = y2;
- }
- }
- rf++;
- }
+ rctf *rf, *newrct;
+ short a;
+
+ a = *count;
+ rf = stack;
+ for (; a > 0; a--) {
+ if (rf->ymin < y1) {
+ if (rf->ymax < y1) {
+ rf->ymin += (y2 - y1);
+ rf->ymax += (y2 - y1);
+ }
+ else {
+ if (rf->ymax > y2)
+ rf->ymax = y2;
+ newrct = stack + *count;
+ (*count)++;
+
+ newrct->ymax = y2;
+ newrct->ymin = rf->ymin + (y2 - y1);
+ newrct->xmin = rf->xmin;
+ newrct->xmax = rf->xmax;
+
+ if (newrct->ymin == newrct->ymax)
+ (*count)--;
+
+ rf->ymin = y1;
+ }
+ }
+ else if (rf->ymax > y2) {
+ if (rf->ymin > y2) {
+ rf->ymin -= (y2 - y1);
+ rf->ymax -= (y2 - y1);
+ }
+ else {
+ if (rf->ymin < y1)
+ rf->ymin = y1;
+ newrct = stack + *count;
+ (*count)++;
+
+ newrct->ymin = y1;
+ newrct->ymax = rf->ymax - (y2 - y1);
+ newrct->xmin = rf->xmin;
+ newrct->xmax = rf->xmax;
+
+ if (newrct->ymin == newrct->ymax)
+ (*count)--;
+
+ rf->ymax = y2;
+ }
+ }
+ rf++;
+ }
}
static float square_rctf(rctf *rf)
{
- float x, y;
+ float x, y;
- x = BLI_rctf_size_x(rf);
- y = BLI_rctf_size_y(rf);
- return x * y;
+ x = BLI_rctf_size_x(rf);
+ y = BLI_rctf_size_y(rf);
+ return x * y;
}
static float clipx_rctf(rctf *rf, float x1, float x2)
{
- float size;
-
- size = BLI_rctf_size_x(rf);
-
- if (rf->xmin < x1) {
- rf->xmin = x1;
- }
- if (rf->xmax > x2) {
- rf->xmax = x2;
- }
- if (rf->xmin > rf->xmax) {
- rf->xmin = rf->xmax;
- return 0.0;
- }
- else if (size != 0.0f) {
- return BLI_rctf_size_x(rf) / size;
- }
- return 1.0;
+ float size;
+
+ size = BLI_rctf_size_x(rf);
+
+ if (rf->xmin < x1) {
+ rf->xmin = x1;
+ }
+ if (rf->xmax > x2) {
+ rf->xmax = x2;
+ }
+ if (rf->xmin > rf->xmax) {
+ rf->xmin = rf->xmax;
+ return 0.0;
+ }
+ else if (size != 0.0f) {
+ return BLI_rctf_size_x(rf) / size;
+ }
+ return 1.0;
}
static float clipy_rctf(rctf *rf, float y1, float y2)
{
- float size;
-
- size = BLI_rctf_size_y(rf);
-
- if (rf->ymin < y1) {
- rf->ymin = y1;
- }
- if (rf->ymax > y2) {
- rf->ymax = y2;
- }
-
- if (rf->ymin > rf->ymax) {
- rf->ymin = rf->ymax;
- return 0.0;
- }
- else if (size != 0.0f) {
- return BLI_rctf_size_y(rf) / size;
- }
- return 1.0;
-
+ float size;
+
+ size = BLI_rctf_size_y(rf);
+
+ if (rf->ymin < y1) {
+ rf->ymin = y1;
+ }
+ if (rf->ymax > y2) {
+ rf->ymax = y2;
+ }
+
+ if (rf->ymin > rf->ymax) {
+ rf->ymin = rf->ymax;
+ return 0.0;
+ }
+ else if (size != 0.0f) {
+ return BLI_rctf_size_y(rf) / size;
+ }
+ return 1.0;
}
static void boxsampleclip(struct ImBuf *ibuf, rctf *rf, TexResult *texres)
{
- /* sample box, is clipped already, and minx etc. have been set at ibuf size.
- * Enlarge with antialiased edges of the pixels */
-
- float muly, mulx, div, col[4];
- int x, y, startx, endx, starty, endy;
-
- startx = (int)floor(rf->xmin);
- endx = (int)floor(rf->xmax);
- starty = (int)floor(rf->ymin);
- endy = (int)floor(rf->ymax);
-
- if (startx < 0) startx = 0;
- if (starty < 0) starty = 0;
- if (endx >= ibuf->x) endx = ibuf->x - 1;
- if (endy >= ibuf->y) endy = ibuf->y - 1;
-
- if (starty == endy && startx == endx) {
- ibuf_get_color(&texres->tr, ibuf, startx, starty);
- }
- else {
- div = texres->tr = texres->tg = texres->tb = texres->ta = 0.0;
- for (y = starty; y <= endy; y++) {
-
- muly = 1.0;
-
- if (starty == endy) {
- /* pass */
- }
- else {
- if (y == starty) muly = 1.0f - (rf->ymin - y);
- if (y == endy) muly = (rf->ymax - y);
- }
-
- if (startx == endx) {
- mulx = muly;
-
- ibuf_get_color(col, ibuf, startx, y);
-
- texres->ta += mulx * col[3];
- texres->tr += mulx * col[0];
- texres->tg += mulx * col[1];
- texres->tb += mulx * col[2];
- div += mulx;
- }
- else {
- for (x = startx; x <= endx; x++) {
- mulx = muly;
- if (x == startx) mulx *= 1.0f - (rf->xmin - x);
- if (x == endx) mulx *= (rf->xmax - x);
-
- ibuf_get_color(col, ibuf, x, y);
-
- if (mulx == 1.0f) {
- texres->ta += col[3];
- texres->tr += col[0];
- texres->tg += col[1];
- texres->tb += col[2];
- div += 1.0f;
- }
- else {
- texres->ta += mulx * col[3];
- texres->tr += mulx * col[0];
- texres->tg += mulx * col[1];
- texres->tb += mulx * col[2];
- div += mulx;
- }
- }
- }
- }
-
- if (div != 0.0f) {
- div = 1.0f / div;
- texres->tb *= div;
- texres->tg *= div;
- texres->tr *= div;
- texres->ta *= div;
- }
- else {
- texres->tr = texres->tg = texres->tb = texres->ta = 0.0f;
- }
- }
+ /* sample box, is clipped already, and minx etc. have been set at ibuf size.
+ * Enlarge with antialiased edges of the pixels */
+
+ float muly, mulx, div, col[4];
+ int x, y, startx, endx, starty, endy;
+
+ startx = (int)floor(rf->xmin);
+ endx = (int)floor(rf->xmax);
+ starty = (int)floor(rf->ymin);
+ endy = (int)floor(rf->ymax);
+
+ if (startx < 0)
+ startx = 0;
+ if (starty < 0)
+ starty = 0;
+ if (endx >= ibuf->x)
+ endx = ibuf->x - 1;
+ if (endy >= ibuf->y)
+ endy = ibuf->y - 1;
+
+ if (starty == endy && startx == endx) {
+ ibuf_get_color(&texres->tr, ibuf, startx, starty);
+ }
+ else {
+ div = texres->tr = texres->tg = texres->tb = texres->ta = 0.0;
+ for (y = starty; y <= endy; y++) {
+
+ muly = 1.0;
+
+ if (starty == endy) {
+ /* pass */
+ }
+ else {
+ if (y == starty)
+ muly = 1.0f - (rf->ymin - y);
+ if (y == endy)
+ muly = (rf->ymax - y);
+ }
+
+ if (startx == endx) {
+ mulx = muly;
+
+ ibuf_get_color(col, ibuf, startx, y);
+
+ texres->ta += mulx * col[3];
+ texres->tr += mulx * col[0];
+ texres->tg += mulx * col[1];
+ texres->tb += mulx * col[2];
+ div += mulx;
+ }
+ else {
+ for (x = startx; x <= endx; x++) {
+ mulx = muly;
+ if (x == startx)
+ mulx *= 1.0f - (rf->xmin - x);
+ if (x == endx)
+ mulx *= (rf->xmax - x);
+
+ ibuf_get_color(col, ibuf, x, y);
+
+ if (mulx == 1.0f) {
+ texres->ta += col[3];
+ texres->tr += col[0];
+ texres->tg += col[1];
+ texres->tb += col[2];
+ div += 1.0f;
+ }
+ else {
+ texres->ta += mulx * col[3];
+ texres->tr += mulx * col[0];
+ texres->tg += mulx * col[1];
+ texres->tb += mulx * col[2];
+ div += mulx;
+ }
+ }
+ }
+ }
+
+ if (div != 0.0f) {
+ div = 1.0f / div;
+ texres->tb *= div;
+ texres->tg *= div;
+ texres->tr *= div;
+ texres->ta *= div;
+ }
+ else {
+ texres->tr = texres->tg = texres->tb = texres->ta = 0.0f;
+ }
+ }
}
-static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend)
+static void boxsample(ImBuf *ibuf,
+ float minx,
+ float miny,
+ float maxx,
+ float maxy,
+ TexResult *texres,
+ const short imaprepeat,
+ const short imapextend)
{
- /* Sample box, performs clip. minx etc are in range 0.0 - 1.0 .
- * Enlarge with antialiased edges of pixels.
- * If variable 'imaprepeat' has been set, the
- * clipped-away parts are sampled as well.
- */
- /* note: actually minx etc isn't in the proper range... this due to filter size and offset vectors for bump */
- /* note: talpha must be initialized */
- /* note: even when 'imaprepeat' is set, this can only repeat once in any direction.
- * the point which min/max is derived from is assumed to be wrapped */
- TexResult texr;
- rctf *rf, stack[8];
- float opp, tot, alphaclip = 1.0;
- short count = 1;
-
- rf = stack;
- rf->xmin = minx * (ibuf->x);
- rf->xmax = maxx * (ibuf->x);
- rf->ymin = miny * (ibuf->y);
- rf->ymax = maxy * (ibuf->y);
-
- texr.talpha = texres->talpha; /* is read by boxsample_clip */
-
- if (imapextend) {
- CLAMP(rf->xmin, 0.0f, ibuf->x - 1);
- CLAMP(rf->xmax, 0.0f, ibuf->x - 1);
- }
- else if (imaprepeat)
- clipx_rctf_swap(stack, &count, 0.0, (float)(ibuf->x));
- else {
- alphaclip = clipx_rctf(rf, 0.0, (float)(ibuf->x));
-
- if (alphaclip <= 0.0f) {
- texres->tr = texres->tb = texres->tg = texres->ta = 0.0;
- return;
- }
- }
-
- if (imapextend) {
- CLAMP(rf->ymin, 0.0f, ibuf->y - 1);
- CLAMP(rf->ymax, 0.0f, ibuf->y - 1);
- }
- else if (imaprepeat)
- clipy_rctf_swap(stack, &count, 0.0, (float)(ibuf->y));
- else {
- alphaclip *= clipy_rctf(rf, 0.0, (float)(ibuf->y));
-
- if (alphaclip <= 0.0f) {
- texres->tr = texres->tb = texres->tg = texres->ta = 0.0;
- return;
- }
- }
-
- if (count > 1) {
- tot = texres->tr = texres->tb = texres->tg = texres->ta = 0.0;
- while (count--) {
- boxsampleclip(ibuf, rf, &texr);
-
- opp = square_rctf(rf);
- tot += opp;
-
- texres->tr += opp * texr.tr;
- texres->tg += opp * texr.tg;
- texres->tb += opp * texr.tb;
- if (texres->talpha) texres->ta += opp * texr.ta;
- rf++;
- }
- if (tot != 0.0f) {
- texres->tr /= tot;
- texres->tg /= tot;
- texres->tb /= tot;
- if (texres->talpha) texres->ta /= tot;
- }
- }
- else
- boxsampleclip(ibuf, rf, texres);
-
- if (texres->talpha == 0) texres->ta = 1.0;
-
- if (alphaclip != 1.0f) {
- /* premul it all */
- texres->tr *= alphaclip;
- texres->tg *= alphaclip;
- texres->tb *= alphaclip;
- texres->ta *= alphaclip;
- }
+ /* Sample box, performs clip. minx etc are in range 0.0 - 1.0 .
+ * Enlarge with antialiased edges of pixels.
+ * If variable 'imaprepeat' has been set, the
+ * clipped-away parts are sampled as well.
+ */
+ /* note: actually minx etc isn't in the proper range... this due to filter size and offset vectors for bump */
+ /* note: talpha must be initialized */
+ /* note: even when 'imaprepeat' is set, this can only repeat once in any direction.
+ * the point which min/max is derived from is assumed to be wrapped */
+ TexResult texr;
+ rctf *rf, stack[8];
+ float opp, tot, alphaclip = 1.0;
+ short count = 1;
+
+ rf = stack;
+ rf->xmin = minx * (ibuf->x);
+ rf->xmax = maxx * (ibuf->x);
+ rf->ymin = miny * (ibuf->y);
+ rf->ymax = maxy * (ibuf->y);
+
+ texr.talpha = texres->talpha; /* is read by boxsample_clip */
+
+ if (imapextend) {
+ CLAMP(rf->xmin, 0.0f, ibuf->x - 1);
+ CLAMP(rf->xmax, 0.0f, ibuf->x - 1);
+ }
+ else if (imaprepeat)
+ clipx_rctf_swap(stack, &count, 0.0, (float)(ibuf->x));
+ else {
+ alphaclip = clipx_rctf(rf, 0.0, (float)(ibuf->x));
+
+ if (alphaclip <= 0.0f) {
+ texres->tr = texres->tb = texres->tg = texres->ta = 0.0;
+ return;
+ }
+ }
+
+ if (imapextend) {
+ CLAMP(rf->ymin, 0.0f, ibuf->y - 1);
+ CLAMP(rf->ymax, 0.0f, ibuf->y - 1);
+ }
+ else if (imaprepeat)
+ clipy_rctf_swap(stack, &count, 0.0, (float)(ibuf->y));
+ else {
+ alphaclip *= clipy_rctf(rf, 0.0, (float)(ibuf->y));
+
+ if (alphaclip <= 0.0f) {
+ texres->tr = texres->tb = texres->tg = texres->ta = 0.0;
+ return;
+ }
+ }
+
+ if (count > 1) {
+ tot = texres->tr = texres->tb = texres->tg = texres->ta = 0.0;
+ while (count--) {
+ boxsampleclip(ibuf, rf, &texr);
+
+ opp = square_rctf(rf);
+ tot += opp;
+
+ texres->tr += opp * texr.tr;
+ texres->tg += opp * texr.tg;
+ texres->tb += opp * texr.tb;
+ if (texres->talpha)
+ texres->ta += opp * texr.ta;
+ rf++;
+ }
+ if (tot != 0.0f) {
+ texres->tr /= tot;
+ texres->tg /= tot;
+ texres->tb /= tot;
+ if (texres->talpha)
+ texres->ta /= tot;
+ }
+ }
+ else
+ boxsampleclip(ibuf, rf, texres);
+
+ if (texres->talpha == 0)
+ texres->ta = 1.0;
+
+ if (alphaclip != 1.0f) {
+ /* premul it all */
+ texres->tr *= alphaclip;
+ texres->tg *= alphaclip;
+ texres->tb *= alphaclip;
+ texres->ta *= alphaclip;
+ }
}
/*-----------------------------------------------------------------------------------------------------------------
@@ -638,1100 +687,1217 @@ static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float max
/* anisotropic filters, data struct used instead of long line of (possibly unused) func args */
typedef struct afdata_t {
- float dxt[2], dyt[2];
- int intpol, extflag;
- /* feline only */
- float majrad, minrad, theta;
- int iProbes;
- float dusc, dvsc;
+ float dxt[2], dyt[2];
+ int intpol, extflag;
+ /* feline only */
+ float majrad, minrad, theta;
+ int iProbes;
+ float dusc, dvsc;
} afdata_t;
/* this only used here to make it easier to pass extend flags as single int */
-enum {TXC_XMIR = 1, TXC_YMIR, TXC_REPT, TXC_EXTD};
+enum { TXC_XMIR = 1, TXC_YMIR, TXC_REPT, TXC_EXTD };
/* similar to ibuf_get_color() but clips/wraps coords according to repeat/extend flags
* returns true if out of range in clipmode */
static int ibuf_get_color_clip(float col[4], ImBuf *ibuf, int x, int y, int extflag)
{
- int clip = 0;
- switch (extflag) {
- case TXC_XMIR: /* y rep */
- x %= 2 * ibuf->x;
- x += x < 0 ? 2 * ibuf->x : 0;
- x = x >= ibuf->x ? 2 * ibuf->x - x - 1 : x;
- y %= ibuf->y;
- y += y < 0 ? ibuf->y : 0;
- break;
- case TXC_YMIR: /* x rep */
- x %= ibuf->x;
- x += x < 0 ? ibuf->x : 0;
- y %= 2 * ibuf->y;
- y += y < 0 ? 2 * ibuf->y : 0;
- y = y >= ibuf->y ? 2 * ibuf->y - y - 1 : y;
- break;
- case TXC_EXTD:
- x = (x < 0) ? 0 : ((x >= ibuf->x) ? (ibuf->x - 1) : x);
- y = (y < 0) ? 0 : ((y >= ibuf->y) ? (ibuf->y - 1) : y);
- break;
- case TXC_REPT:
- x %= ibuf->x;
- x += (x < 0) ? ibuf->x : 0;
- y %= ibuf->y;
- y += (y < 0) ? ibuf->y : 0;
- break;
- default:
- { /* as extend, if clipped, set alpha to 0.0 */
- if (x < 0) { x = 0; } /* TXF alpha: clip = 1; } */
- if (x >= ibuf->x) { x = ibuf->x - 1; } /* TXF alpha: clip = 1; } */
- if (y < 0) { y = 0; } /* TXF alpha: clip = 1; } */
- if (y >= ibuf->y) { y = ibuf->y - 1; } /* TXF alpha: clip = 1; } */
- }
- }
-
- if (ibuf->rect_float) {
- const float *fp = ibuf->rect_float + (x + y * ibuf->x) * ibuf->channels;
- if (ibuf->channels == 1)
- col[0] = col[1] = col[2] = col[3] = *fp;
- else {
- col[0] = fp[0];
- col[1] = fp[1];
- col[2] = fp[2];
- col[3] = clip ? 0.f : (ibuf->channels == 4 ? fp[3] : 1.f);
- }
- }
- else {
- const char *rect = (char *)(ibuf->rect + x + y * ibuf->x);
- float inv_alpha_fac = (1.0f / 255.0f) * rect[3] * (1.0f / 255.0f);
- col[0] = rect[0] * inv_alpha_fac;
- col[1] = rect[1] * inv_alpha_fac;
- col[2] = rect[2] * inv_alpha_fac;
- col[3] = clip ? 0.f : rect[3] * (1.f / 255.f);
- }
- return clip;
+ int clip = 0;
+ switch (extflag) {
+ case TXC_XMIR: /* y rep */
+ x %= 2 * ibuf->x;
+ x += x < 0 ? 2 * ibuf->x : 0;
+ x = x >= ibuf->x ? 2 * ibuf->x - x - 1 : x;
+ y %= ibuf->y;
+ y += y < 0 ? ibuf->y : 0;
+ break;
+ case TXC_YMIR: /* x rep */
+ x %= ibuf->x;
+ x += x < 0 ? ibuf->x : 0;
+ y %= 2 * ibuf->y;
+ y += y < 0 ? 2 * ibuf->y : 0;
+ y = y >= ibuf->y ? 2 * ibuf->y - y - 1 : y;
+ break;
+ case TXC_EXTD:
+ x = (x < 0) ? 0 : ((x >= ibuf->x) ? (ibuf->x - 1) : x);
+ y = (y < 0) ? 0 : ((y >= ibuf->y) ? (ibuf->y - 1) : y);
+ break;
+ case TXC_REPT:
+ x %= ibuf->x;
+ x += (x < 0) ? ibuf->x : 0;
+ y %= ibuf->y;
+ y += (y < 0) ? ibuf->y : 0;
+ break;
+ default: { /* as extend, if clipped, set alpha to 0.0 */
+ if (x < 0) {
+ x = 0;
+ } /* TXF alpha: clip = 1; } */
+ if (x >= ibuf->x) {
+ x = ibuf->x - 1;
+ } /* TXF alpha: clip = 1; } */
+ if (y < 0) {
+ y = 0;
+ } /* TXF alpha: clip = 1; } */
+ if (y >= ibuf->y) {
+ y = ibuf->y - 1;
+ } /* TXF alpha: clip = 1; } */
+ }
+ }
+
+ if (ibuf->rect_float) {
+ const float *fp = ibuf->rect_float + (x + y * ibuf->x) * ibuf->channels;
+ if (ibuf->channels == 1)
+ col[0] = col[1] = col[2] = col[3] = *fp;
+ else {
+ col[0] = fp[0];
+ col[1] = fp[1];
+ col[2] = fp[2];
+ col[3] = clip ? 0.f : (ibuf->channels == 4 ? fp[3] : 1.f);
+ }
+ }
+ else {
+ const char *rect = (char *)(ibuf->rect + x + y * ibuf->x);
+ float inv_alpha_fac = (1.0f / 255.0f) * rect[3] * (1.0f / 255.0f);
+ col[0] = rect[0] * inv_alpha_fac;
+ col[1] = rect[1] * inv_alpha_fac;
+ col[2] = rect[2] * inv_alpha_fac;
+ col[3] = clip ? 0.f : rect[3] * (1.f / 255.f);
+ }
+ return clip;
}
/* as above + bilerp */
-static int ibuf_get_color_clip_bilerp(float col[4], ImBuf *ibuf, float u, float v, int intpol, int extflag)
+static int ibuf_get_color_clip_bilerp(
+ float col[4], ImBuf *ibuf, float u, float v, int intpol, int extflag)
{
- if (intpol) {
- float c00[4], c01[4], c10[4], c11[4];
- const float ufl = floorf(u -= 0.5f), vfl = floorf(v -= 0.5f);
- const float uf = u - ufl, vf = v - vfl;
- const float w00 = (1.f - uf) * (1.f - vf), w10 = uf * (1.f - vf), w01 = (1.f - uf) * vf, w11 = uf * vf;
- const int x1 = (int)ufl, y1 = (int)vfl, x2 = x1 + 1, y2 = y1 + 1;
- int clip = ibuf_get_color_clip(c00, ibuf, x1, y1, extflag);
- clip |= ibuf_get_color_clip(c10, ibuf, x2, y1, extflag);
- clip |= ibuf_get_color_clip(c01, ibuf, x1, y2, extflag);
- clip |= ibuf_get_color_clip(c11, ibuf, x2, y2, extflag);
- col[0] = w00 * c00[0] + w10 * c10[0] + w01 * c01[0] + w11 * c11[0];
- col[1] = w00 * c00[1] + w10 * c10[1] + w01 * c01[1] + w11 * c11[1];
- col[2] = w00 * c00[2] + w10 * c10[2] + w01 * c01[2] + w11 * c11[2];
- col[3] = clip ? 0.f : w00 * c00[3] + w10 * c10[3] + w01 * c01[3] + w11 * c11[3];
- return clip;
- }
- return ibuf_get_color_clip(col, ibuf, (int)u, (int)v, extflag);
+ if (intpol) {
+ float c00[4], c01[4], c10[4], c11[4];
+ const float ufl = floorf(u -= 0.5f), vfl = floorf(v -= 0.5f);
+ const float uf = u - ufl, vf = v - vfl;
+ const float w00 = (1.f - uf) * (1.f - vf), w10 = uf * (1.f - vf), w01 = (1.f - uf) * vf,
+ w11 = uf * vf;
+ const int x1 = (int)ufl, y1 = (int)vfl, x2 = x1 + 1, y2 = y1 + 1;
+ int clip = ibuf_get_color_clip(c00, ibuf, x1, y1, extflag);
+ clip |= ibuf_get_color_clip(c10, ibuf, x2, y1, extflag);
+ clip |= ibuf_get_color_clip(c01, ibuf, x1, y2, extflag);
+ clip |= ibuf_get_color_clip(c11, ibuf, x2, y2, extflag);
+ col[0] = w00 * c00[0] + w10 * c10[0] + w01 * c01[0] + w11 * c11[0];
+ col[1] = w00 * c00[1] + w10 * c10[1] + w01 * c01[1] + w11 * c11[1];
+ col[2] = w00 * c00[2] + w10 * c10[2] + w01 * c01[2] + w11 * c11[2];
+ col[3] = clip ? 0.f : w00 * c00[3] + w10 * c10[3] + w01 * c01[3] + w11 * c11[3];
+ return clip;
+ }
+ return ibuf_get_color_clip(col, ibuf, (int)u, (int)v, extflag);
}
static void area_sample(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
{
- int xs, ys, clip = 0;
- float tc[4], xsd, ysd, cw = 0.f;
- const float ux = ibuf->x * AFD->dxt[0], uy = ibuf->y * AFD->dxt[1];
- const float vx = ibuf->x * AFD->dyt[0], vy = ibuf->y * AFD->dyt[1];
- int xsam = (int)(0.5f * sqrtf(ux * ux + uy * uy) + 0.5f);
- int ysam = (int)(0.5f * sqrtf(vx * vx + vy * vy) + 0.5f);
- const int minsam = AFD->intpol ? 2 : 4;
- xsam = CLAMPIS(xsam, minsam, ibuf->x * 2);
- ysam = CLAMPIS(ysam, minsam, ibuf->y * 2);
- xsd = 1.f / xsam;
- ysd = 1.f / ysam;
- texr->tr = texr->tg = texr->tb = texr->ta = 0.f;
- for (ys = 0; ys < ysam; ++ys) {
- for (xs = 0; xs < xsam; ++xs) {
- const float su = (xs + ((ys & 1) + 0.5f) * 0.5f) * xsd - 0.5f;
- const float sv = (ys + ((xs & 1) + 0.5f) * 0.5f) * ysd - 0.5f;
- const float pu = fx + su * AFD->dxt[0] + sv * AFD->dyt[0];
- const float pv = fy + su * AFD->dxt[1] + sv * AFD->dyt[1];
- const int out = ibuf_get_color_clip_bilerp(tc, ibuf, pu * ibuf->x, pv * ibuf->y, AFD->intpol, AFD->extflag);
- clip |= out;
- cw += out ? 0.f : 1.f;
- texr->tr += tc[0];
- texr->tg += tc[1];
- texr->tb += tc[2];
- texr->ta += texr->talpha ? tc[3] : 0.f;
- }
- }
- xsd *= ysd;
- texr->tr *= xsd;
- texr->tg *= xsd;
- texr->tb *= xsd;
- /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */
- texr->ta = texr->talpha ? texr->ta * xsd : (clip ? cw * xsd : 1.f);
+ int xs, ys, clip = 0;
+ float tc[4], xsd, ysd, cw = 0.f;
+ const float ux = ibuf->x * AFD->dxt[0], uy = ibuf->y * AFD->dxt[1];
+ const float vx = ibuf->x * AFD->dyt[0], vy = ibuf->y * AFD->dyt[1];
+ int xsam = (int)(0.5f * sqrtf(ux * ux + uy * uy) + 0.5f);
+ int ysam = (int)(0.5f * sqrtf(vx * vx + vy * vy) + 0.5f);
+ const int minsam = AFD->intpol ? 2 : 4;
+ xsam = CLAMPIS(xsam, minsam, ibuf->x * 2);
+ ysam = CLAMPIS(ysam, minsam, ibuf->y * 2);
+ xsd = 1.f / xsam;
+ ysd = 1.f / ysam;
+ texr->tr = texr->tg = texr->tb = texr->ta = 0.f;
+ for (ys = 0; ys < ysam; ++ys) {
+ for (xs = 0; xs < xsam; ++xs) {
+ const float su = (xs + ((ys & 1) + 0.5f) * 0.5f) * xsd - 0.5f;
+ const float sv = (ys + ((xs & 1) + 0.5f) * 0.5f) * ysd - 0.5f;
+ const float pu = fx + su * AFD->dxt[0] + sv * AFD->dyt[0];
+ const float pv = fy + su * AFD->dxt[1] + sv * AFD->dyt[1];
+ const int out = ibuf_get_color_clip_bilerp(
+ tc, ibuf, pu * ibuf->x, pv * ibuf->y, AFD->intpol, AFD->extflag);
+ clip |= out;
+ cw += out ? 0.f : 1.f;
+ texr->tr += tc[0];
+ texr->tg += tc[1];
+ texr->tb += tc[2];
+ texr->ta += texr->talpha ? tc[3] : 0.f;
+ }
+ }
+ xsd *= ysd;
+ texr->tr *= xsd;
+ texr->tg *= xsd;
+ texr->tb *= xsd;
+ /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */
+ texr->ta = texr->talpha ? texr->ta * xsd : (clip ? cw * xsd : 1.f);
}
typedef struct ReadEWAData {
- ImBuf *ibuf;
- afdata_t *AFD;
+ ImBuf *ibuf;
+ afdata_t *AFD;
} ReadEWAData;
static void ewa_read_pixel_cb(void *userdata, int x, int y, float result[4])
{
- ReadEWAData *data = (ReadEWAData *)userdata;
- ibuf_get_color_clip(result, data->ibuf, x, y, data->AFD->extflag);
+ ReadEWAData *data = (ReadEWAData *)userdata;
+ ibuf_get_color_clip(result, data->ibuf, x, y, data->AFD->extflag);
}
static void ewa_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
{
- ReadEWAData data;
- float uv[2] = {fx, fy};
- data.ibuf = ibuf;
- data.AFD = AFD;
- BLI_ewa_filter(ibuf->x, ibuf->y,
- AFD->intpol != 0,
- texr->talpha,
- uv, AFD->dxt, AFD->dyt,
- ewa_read_pixel_cb,
- &data,
- &texr->tr);
-
+ ReadEWAData data;
+ float uv[2] = {fx, fy};
+ data.ibuf = ibuf;
+ data.AFD = AFD;
+ BLI_ewa_filter(ibuf->x,
+ ibuf->y,
+ AFD->intpol != 0,
+ texr->talpha,
+ uv,
+ AFD->dxt,
+ AFD->dyt,
+ ewa_read_pixel_cb,
+ &data,
+ &texr->tr);
}
static void feline_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
{
- const int maxn = AFD->iProbes - 1;
- const float ll = ((AFD->majrad == AFD->minrad) ? 2.f * AFD->majrad : 2.f * (AFD->majrad - AFD->minrad)) / (maxn ? (float)maxn : 1.f);
- float du = maxn ? cosf(AFD->theta) * ll : 0.f;
- float dv = maxn ? sinf(AFD->theta) * ll : 0.f;
- /* const float D = -0.5f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad); */
- const float D = (EWA_MAXIDX + 1) * 0.25f * (du * du + dv * dv) / (AFD->majrad * AFD->majrad);
- float d; /* TXF alpha: cw = 0.f; */
- int n; /* TXF alpha: clip = 0; */
- /* have to use same scaling for du/dv here as for Ux/Vx/Uy/Vy (*after* D calc.) */
- du *= AFD->dusc;
- dv *= AFD->dvsc;
- d = texr->tr = texr->tb = texr->tg = texr->ta = 0.f;
- for (n = -maxn; n <= maxn; n += 2) {
- float tc[4];
- const float hn = n * 0.5f;
- const float u = fx + hn * du, v = fy + hn * dv;
- /*const float wt = expf(n*n*D);
- * can use ewa table here too */
- const float wt = EWA_WTS[(int)(n * n * D)];
- /*const int out =*/ ibuf_get_color_clip_bilerp(tc, ibuf, ibuf->x * u, ibuf->y * v, AFD->intpol, AFD->extflag);
- /* TXF alpha: clip |= out;
- * TXF alpha: cw += out ? 0.f : wt; */
- texr->tr += tc[0] * wt;
- texr->tg += tc[1] * wt;
- texr->tb += tc[2] * wt;
- texr->ta += texr->talpha ? tc[3] * wt : 0.f;
- d += wt;
- }
-
- d = 1.f / d;
- texr->tr *= d;
- texr->tg *= d;
- texr->tb *= d;
- /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */
- texr->ta = texr->talpha ? texr->ta * d : 1.f; // TXF alpha: (clip ? cw*d : 1.f);
+ const int maxn = AFD->iProbes - 1;
+ const float ll = ((AFD->majrad == AFD->minrad) ? 2.f * AFD->majrad :
+ 2.f * (AFD->majrad - AFD->minrad)) /
+ (maxn ? (float)maxn : 1.f);
+ float du = maxn ? cosf(AFD->theta) * ll : 0.f;
+ float dv = maxn ? sinf(AFD->theta) * ll : 0.f;
+ /* const float D = -0.5f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad); */
+ const float D = (EWA_MAXIDX + 1) * 0.25f * (du * du + dv * dv) / (AFD->majrad * AFD->majrad);
+ float d; /* TXF alpha: cw = 0.f; */
+ int n; /* TXF alpha: clip = 0; */
+ /* have to use same scaling for du/dv here as for Ux/Vx/Uy/Vy (*after* D calc.) */
+ du *= AFD->dusc;
+ dv *= AFD->dvsc;
+ d = texr->tr = texr->tb = texr->tg = texr->ta = 0.f;
+ for (n = -maxn; n <= maxn; n += 2) {
+ float tc[4];
+ const float hn = n * 0.5f;
+ const float u = fx + hn * du, v = fy + hn * dv;
+ /*const float wt = expf(n*n*D);
+ * can use ewa table here too */
+ const float wt = EWA_WTS[(int)(n * n * D)];
+ /*const int out =*/ibuf_get_color_clip_bilerp(
+ tc, ibuf, ibuf->x * u, ibuf->y * v, AFD->intpol, AFD->extflag);
+ /* TXF alpha: clip |= out;
+ * TXF alpha: cw += out ? 0.f : wt; */
+ texr->tr += tc[0] * wt;
+ texr->tg += tc[1] * wt;
+ texr->tb += tc[2] * wt;
+ texr->ta += texr->talpha ? tc[3] * wt : 0.f;
+ d += wt;
+ }
+
+ d = 1.f / d;
+ texr->tr *= d;
+ texr->tg *= d;
+ texr->tb *= d;
+ /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */
+ texr->ta = texr->talpha ? texr->ta * d : 1.f; // TXF alpha: (clip ? cw*d : 1.f);
}
#undef EWA_MAXIDX
-static void alpha_clip_aniso(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, int extflag, TexResult *texres)
+static void alpha_clip_aniso(
+ ImBuf *ibuf, float minx, float miny, float maxx, float maxy, int extflag, TexResult *texres)
{
- float alphaclip;
- rctf rf;
-
- /* TXF apha: we're doing the same alphaclip here as boxsample, but i'm doubting
- * if this is actually correct for the all the filtering algorithms .. */
-
- if (!(extflag == TXC_REPT || extflag == TXC_EXTD)) {
- rf.xmin = minx * (ibuf->x);
- rf.xmax = maxx * (ibuf->x);
- rf.ymin = miny * (ibuf->y);
- rf.ymax = maxy * (ibuf->y);
-
- alphaclip = clipx_rctf(&rf, 0.0, (float)(ibuf->x));
- alphaclip *= clipy_rctf(&rf, 0.0, (float)(ibuf->y));
- alphaclip = max_ff(alphaclip, 0.0f);
-
- if (alphaclip != 1.0f) {
- /* premul it all */
- texres->tr *= alphaclip;
- texres->tg *= alphaclip;
- texres->tb *= alphaclip;
- texres->ta *= alphaclip;
- }
- }
+ float alphaclip;
+ rctf rf;
+
+ /* TXF apha: we're doing the same alphaclip here as boxsample, but i'm doubting
+ * if this is actually correct for the all the filtering algorithms .. */
+
+ if (!(extflag == TXC_REPT || extflag == TXC_EXTD)) {
+ rf.xmin = minx * (ibuf->x);
+ rf.xmax = maxx * (ibuf->x);
+ rf.ymin = miny * (ibuf->y);
+ rf.ymax = maxy * (ibuf->y);
+
+ alphaclip = clipx_rctf(&rf, 0.0, (float)(ibuf->x));
+ alphaclip *= clipy_rctf(&rf, 0.0, (float)(ibuf->y));
+ alphaclip = max_ff(alphaclip, 0.0f);
+
+ if (alphaclip != 1.0f) {
+ /* premul it all */
+ texres->tr *= alphaclip;
+ texres->tg *= alphaclip;
+ texres->tb *= alphaclip;
+ texres->ta *= alphaclip;
+ }
+ }
}
static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
{
- if (tex->imaflag & TEX_MIPMAP) {
- if (ibuf->mipmap[0] && (ibuf->userflags & IB_MIPMAP_INVALID)) {
- BLI_thread_lock(LOCK_IMAGE);
- if (ibuf->userflags & IB_MIPMAP_INVALID) {
- IMB_remakemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
- ibuf->userflags &= ~IB_MIPMAP_INVALID;
- }
- BLI_thread_unlock(LOCK_IMAGE);
- }
- if (ibuf->mipmap[0] == NULL) {
- BLI_thread_lock(LOCK_IMAGE);
- if (ibuf->mipmap[0] == NULL)
- IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
- BLI_thread_unlock(LOCK_IMAGE);
- }
- /* if no mipmap could be made, fall back on non-mipmap render */
- if (ibuf->mipmap[0] == NULL) {
- tex->imaflag &= ~TEX_MIPMAP;
- }
- }
+ if (tex->imaflag & TEX_MIPMAP) {
+ if (ibuf->mipmap[0] && (ibuf->userflags & IB_MIPMAP_INVALID)) {
+ BLI_thread_lock(LOCK_IMAGE);
+ if (ibuf->userflags & IB_MIPMAP_INVALID) {
+ IMB_remakemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
+ ibuf->userflags &= ~IB_MIPMAP_INVALID;
+ }
+ BLI_thread_unlock(LOCK_IMAGE);
+ }
+ if (ibuf->mipmap[0] == NULL) {
+ BLI_thread_lock(LOCK_IMAGE);
+ if (ibuf->mipmap[0] == NULL)
+ IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
+ BLI_thread_unlock(LOCK_IMAGE);
+ }
+ /* if no mipmap could be made, fall back on non-mipmap render */
+ if (ibuf->mipmap[0] == NULL) {
+ tex->imaflag &= ~TEX_MIPMAP;
+ }
+ }
}
-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, const bool skip_load_image)
+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,
+ const bool skip_load_image)
{
- TexResult texr;
- float fx, fy, minx, maxx, miny, maxy;
- float maxd, val1, val2, val3;
- int curmap, retval, intpol, extflag = 0;
- afdata_t AFD;
-
- void (*filterfunc)(TexResult *, ImBuf *, float, float, afdata_t *);
- switch (tex->texfilter) {
- case TXF_EWA:
- filterfunc = ewa_eval;
- break;
- case TXF_FELINE:
- filterfunc = feline_eval;
- break;
- case TXF_AREA:
- default:
- filterfunc = area_sample;
- }
-
- texres->tin = texres->ta = texres->tr = texres->tg = texres->tb = 0.f;
-
- /* we need to set retval OK, otherwise texture code generates normals itself... */
- retval = texres->nor ? 3 : 1;
-
- /* quick tests */
- if (ibuf == NULL && ima == NULL) return retval;
-
- if (ima) { /* hack for icon render */
- if (skip_load_image && !BKE_image_has_loaded_ibuf(ima)) {
- return retval;
- }
- ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
- }
-
- if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) {
- if (ima)
- BKE_image_pool_release_ibuf(ima, ibuf, pool);
- return retval;
- }
-
- if (ima) {
- ima->flag |= IMA_USED_FOR_RENDER;
- }
-
- /* mipmap test */
- image_mipmap_test(tex, ibuf);
-
- if (ima) {
- if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
- if ((tex->imaflag & TEX_CALCALPHA) == 0) {
- texres->talpha = 1;
- }
- }
- }
- texr.talpha = texres->talpha;
-
- if (tex->imaflag & TEX_IMAROT) {
- fy = texvec[0];
- fx = texvec[1];
- }
- else {
- fx = texvec[0];
- fy = texvec[1];
- }
-
- /* pixel coordinates */
- minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
- maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
- miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
- maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
-
- /* tex_sharper has been removed */
- minx = (maxx - minx) * 0.5f;
- miny = (maxy - miny) * 0.5f;
-
- if (tex->imaflag & TEX_FILTER_MIN) {
- /* make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) */
- const float addval = (0.5f * tex->filtersize) / (float)MIN2(ibuf->x, ibuf->y);
- if (addval > minx) minx = addval;
- if (addval > miny) miny = addval;
- }
- else if (tex->filtersize != 1.f) {
- minx *= tex->filtersize;
- miny *= tex->filtersize;
- dxt[0] *= tex->filtersize;
- dxt[1] *= tex->filtersize;
- dyt[0] *= tex->filtersize;
- dyt[1] *= tex->filtersize;
- }
-
- if (tex->imaflag & TEX_IMAROT) {
- float t;
- SWAP(float, minx, miny);
- /* must rotate dxt/dyt 90 deg
- * yet another blender problem is that swapping X/Y axes (or any tex proj switches) should do something similar,
- * but it doesn't, it only swaps coords, so filter area will be incorrect in those cases. */
- t = dxt[0];
- dxt[0] = dxt[1];
- dxt[1] = -t;
- t = dyt[0];
- dyt[0] = dyt[1];
- dyt[1] = -t;
- }
-
- /* side faces of unit-cube */
- minx = (minx > 0.25f) ? 0.25f : ((minx < 1e-5f) ? 1e-5f : minx);
- miny = (miny > 0.25f) ? 0.25f : ((miny < 1e-5f) ? 1e-5f : miny);
-
- /* repeat and clip */
-
- if (tex->extend == TEX_REPEAT) {
- if ((tex->flag & (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) == (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR))
- extflag = TXC_EXTD;
- else if (tex->flag & TEX_REPEAT_XMIR)
- extflag = TXC_XMIR;
- else if (tex->flag & TEX_REPEAT_YMIR)
- extflag = TXC_YMIR;
- else
- extflag = TXC_REPT;
- }
- else if (tex->extend == TEX_EXTEND)
- extflag = TXC_EXTD;
-
- if (tex->extend == TEX_CHECKER) {
- int xs = (int)floorf(fx), ys = (int)floorf(fy);
- /* both checkers available, no boundary exceptions, checkerdist will eat aliasing */
- if ((tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN)) {
- fx -= xs;
- fy -= ys;
- }
- else if ((tex->flag & TEX_CHECKER_ODD) == 0 &&
- (tex->flag & TEX_CHECKER_EVEN) == 0)
- {
- if (ima)
- BKE_image_pool_release_ibuf(ima, ibuf, pool);
- return retval;
- }
- else {
- int xs1 = (int)floorf(fx - minx);
- int ys1 = (int)floorf(fy - miny);
- int xs2 = (int)floorf(fx + minx);
- int ys2 = (int)floorf(fy + miny);
- if ((xs1 != xs2) || (ys1 != ys2)) {
- if (tex->flag & TEX_CHECKER_ODD) {
- fx -= ((xs1 + ys) & 1) ? xs2 : xs1;
- fy -= ((ys1 + xs) & 1) ? ys2 : ys1;
- }
- if (tex->flag & TEX_CHECKER_EVEN) {
- fx -= ((xs1 + ys) & 1) ? xs1 : xs2;
- fy -= ((ys1 + xs) & 1) ? ys1 : ys2;
- }
- }
- else {
- if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) {
- if (ima)
- BKE_image_pool_release_ibuf(ima, ibuf, pool);
- return retval;
- }
- if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) {
- if (ima)
- BKE_image_pool_release_ibuf(ima, ibuf, pool);
- return retval;
- }
- fx -= xs;
- fy -= ys;
- }
- }
- /* scale around center, (0.5, 0.5) */
- if (tex->checkerdist < 1.f) {
- const float omcd = 1.f / (1.f - tex->checkerdist);
- fx = (fx - 0.5f) * omcd + 0.5f;
- fy = (fy - 0.5f) * omcd + 0.5f;
- minx *= omcd;
- miny *= omcd;
- }
- }
-
- 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_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_pool_release_ibuf(ima, ibuf, pool);
- return retval;
- }
- }
- else {
- if (tex->extend == TEX_EXTEND) {
- fx = (fx > 1.f) ? 1.f : ((fx < 0.f) ? 0.f : fx);
- fy = (fy > 1.f) ? 1.f : ((fy < 0.f) ? 0.f : fy);
- }
- else {
- fx -= floorf(fx);
- fy -= floorf(fy);
- }
- }
-
- intpol = tex->imaflag & TEX_INTERPOL;
-
- /* struct common data */
- copy_v2_v2(AFD.dxt, dxt);
- copy_v2_v2(AFD.dyt, dyt);
- AFD.intpol = intpol;
- AFD.extflag = extflag;
-
- /* brecht: added stupid clamping here, large dx/dy can give very large
- * filter sizes which take ages to render, it may be better to do this
- * more intelligently later in the code .. probably it's not noticeable */
- if (AFD.dxt[0] * AFD.dxt[0] + AFD.dxt[1] * AFD.dxt[1] > 2.0f * 2.0f)
- mul_v2_fl(AFD.dxt, 2.0f / len_v2(AFD.dxt));
- if (AFD.dyt[0] * AFD.dyt[0] + AFD.dyt[1] * AFD.dyt[1] > 2.0f * 2.0f)
- mul_v2_fl(AFD.dyt, 2.0f / len_v2(AFD.dyt));
-
- /* choice: */
- if (tex->imaflag & TEX_MIPMAP) {
- ImBuf *previbuf, *curibuf;
- float levf;
- int maxlev;
- ImBuf *mipmaps[IMB_MIPMAP_LEVELS + 1];
-
- /* modify ellipse minor axis if too eccentric, use for area sampling as well
- * scaling dxt/dyt as done in pbrt is not the same
- * (as in ewa_eval(), scale by sqrt(ibuf->x) to maximize precision) */
- const float ff = sqrtf(ibuf->x), q = ibuf->y / ff;
- const float Ux = dxt[0] * ff, Vx = dxt[1] * q, Uy = dyt[0] * ff, Vy = dyt[1] * q;
- const float A = Vx * Vx + Vy * Vy;
- const float B = -2.f * (Ux * Vx + Uy * Vy);
- const float C = Ux * Ux + Uy * Uy;
- const float F = A * C - B * B * 0.25f;
- float a, b, th, ecc;
- BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
- if (tex->texfilter == TXF_FELINE) {
- float fProbes;
- a *= ff;
- b *= ff;
- a = max_ff(a, 1.0f);
- b = max_ff(b, 1.0f);
- fProbes = 2.f * (a / b) - 1.f;
- AFD.iProbes = round_fl_to_int(fProbes);
- AFD.iProbes = MIN2(AFD.iProbes, tex->afmax);
- if (AFD.iProbes < fProbes)
- b = 2.f * a / (float)(AFD.iProbes + 1);
- AFD.majrad = a / ff;
- AFD.minrad = b / ff;
- AFD.theta = th;
- AFD.dusc = 1.f / ff;
- AFD.dvsc = ff / (float)ibuf->y;
- }
- else { /* EWA & area */
- if (ecc > (float)tex->afmax) b = a / (float)tex->afmax;
- b *= ff;
- }
- maxd = max_ff(b, 1e-8f);
- levf = ((float)M_LOG2E) * logf(maxd);
-
- curmap = 0;
- maxlev = 1;
- mipmaps[0] = ibuf;
- while (curmap < IMB_MIPMAP_LEVELS) {
- mipmaps[curmap + 1] = ibuf->mipmap[curmap];
- if (ibuf->mipmap[curmap]) maxlev++;
- curmap++;
- }
-
- /* mipmap level */
- if (levf < 0.f) { /* original image only */
- previbuf = curibuf = mipmaps[0];
- levf = 0.f;
- }
- else if (levf >= maxlev - 1) {
- previbuf = curibuf = mipmaps[maxlev - 1];
- levf = 0.f;
- if (tex->texfilter == TXF_FELINE) AFD.iProbes = 1;
- }
- else {
- const int lev = isnan(levf) ? 0 : (int)levf;
- curibuf = mipmaps[lev];
- previbuf = mipmaps[lev + 1];
- levf -= floorf(levf);
- }
-
- /* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */
-
- if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
- /* color & normal */
- filterfunc(texres, curibuf, fx, fy, &AFD);
- val1 = texres->tr + texres->tg + texres->tb;
- filterfunc(&texr, curibuf, fx + dxt[0], fy + dxt[1], &AFD);
- val2 = texr.tr + texr.tg + texr.tb;
- filterfunc(&texr, curibuf, fx + dyt[0], fy + dyt[1], &AFD);
- val3 = texr.tr + texr.tg + texr.tb;
- /* don't switch x or y! */
- texres->nor[0] = val1 - val2;
- texres->nor[1] = val1 - val3;
- if (previbuf != curibuf) { /* interpolate */
- filterfunc(&texr, previbuf, fx, fy, &AFD);
- /* rgb */
- texres->tr += levf * (texr.tr - texres->tr);
- texres->tg += levf * (texr.tg - texres->tg);
- texres->tb += levf * (texr.tb - texres->tb);
- texres->ta += levf * (texr.ta - texres->ta);
- /* normal */
- val1 += levf * ((texr.tr + texr.tg + texr.tb) - val1);
- filterfunc(&texr, previbuf, fx + dxt[0], fy + dxt[1], &AFD);
- val2 += levf * ((texr.tr + texr.tg + texr.tb) - val2);
- filterfunc(&texr, previbuf, fx + dyt[0], fy + dyt[1], &AFD);
- val3 += levf * ((texr.tr + texr.tg + texr.tb) - val3);
- texres->nor[0] = val1 - val2; /* vals have been interpolated above! */
- texres->nor[1] = val1 - val3;
- }
- }
- else { /* color */
- filterfunc(texres, curibuf, fx, fy, &AFD);
- if (previbuf != curibuf) { /* interpolate */
- filterfunc(&texr, previbuf, fx, fy, &AFD);
- texres->tr += levf * (texr.tr - texres->tr);
- texres->tg += levf * (texr.tg - texres->tg);
- texres->tb += levf * (texr.tb - texres->tb);
- texres->ta += levf * (texr.ta - texres->ta);
- }
-
- if (tex->texfilter != TXF_EWA) {
- alpha_clip_aniso(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, extflag, texres);
- }
- }
- }
- else { /* no mipmap */
- /* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */
- if (tex->texfilter == TXF_FELINE) {
- const float ff = sqrtf(ibuf->x), q = ibuf->y / ff;
- const float Ux = dxt[0] * ff, Vx = dxt[1] * q, Uy = dyt[0] * ff, Vy = dyt[1] * q;
- const float A = Vx * Vx + Vy * Vy;
- const float B = -2.f * (Ux * Vx + Uy * Vy);
- const float C = Ux * Ux + Uy * Uy;
- const float F = A * C - B * B * 0.25f;
- float a, b, th, ecc, fProbes;
- BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
- a *= ff;
- b *= ff;
- a = max_ff(a, 1.0f);
- b = max_ff(b, 1.0f);
- fProbes = 2.f * (a / b) - 1.f;
- /* no limit to number of Probes here */
- AFD.iProbes = round_fl_to_int(fProbes);
- if (AFD.iProbes < fProbes) b = 2.f * a / (float)(AFD.iProbes + 1);
- AFD.majrad = a / ff;
- AFD.minrad = b / ff;
- AFD.theta = th;
- AFD.dusc = 1.f / ff;
- AFD.dvsc = ff / (float)ibuf->y;
- }
- if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
- /* color & normal */
- filterfunc(texres, ibuf, fx, fy, &AFD);
- val1 = texres->tr + texres->tg + texres->tb;
- filterfunc(&texr, ibuf, fx + dxt[0], fy + dxt[1], &AFD);
- val2 = texr.tr + texr.tg + texr.tb;
- filterfunc(&texr, ibuf, fx + dyt[0], fy + dyt[1], &AFD);
- val3 = texr.tr + texr.tg + texr.tb;
- /* don't switch x or y! */
- texres->nor[0] = val1 - val2;
- texres->nor[1] = val1 - val3;
- }
- else {
- filterfunc(texres, ibuf, fx, fy, &AFD);
- if (tex->texfilter != TXF_EWA) {
- alpha_clip_aniso(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, extflag, texres);
- }
- }
- }
-
- if (tex->imaflag & TEX_CALCALPHA)
- texres->ta = texres->tin = texres->ta * max_fff(texres->tr, texres->tg, texres->tb);
- else
- texres->tin = texres->ta;
- if (tex->flag & TEX_NEGALPHA) texres->ta = 1.f - texres->ta;
-
- if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) { /* normal from color */
- /* 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. */
- texres->nor[0] = -2.f * (texres->tr - 0.5f);
- texres->nor[1] = 2.f * (texres->tg - 0.5f);
- texres->nor[2] = 2.f * (texres->tb - 0.5f);
- }
-
- /* de-premul, this is being premulled in shade_input_do_shade()
- * TXF: this currently does not (yet?) work properly, destroys edge AA in clip/checker mode, so for now commented out
- * also disabled in imagewraposa() to be able to compare results with blender's default texture filtering */
-
- /* brecht: tried to fix this, see "TXF alpha" comments */
-
- /* do not de-premul for generated alpha, it is already in straight */
- if (texres->ta != 1.0f && texres->ta > 1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
- fx = 1.f / texres->ta;
- texres->tr *= fx;
- texres->tg *= fx;
- texres->tb *= fx;
- }
-
- if (ima)
- BKE_image_pool_release_ibuf(ima, ibuf, pool);
-
- BRICONTRGB;
-
- return retval;
+ TexResult texr;
+ float fx, fy, minx, maxx, miny, maxy;
+ float maxd, val1, val2, val3;
+ int curmap, retval, intpol, extflag = 0;
+ afdata_t AFD;
+
+ void (*filterfunc)(TexResult *, ImBuf *, float, float, afdata_t *);
+ switch (tex->texfilter) {
+ case TXF_EWA:
+ filterfunc = ewa_eval;
+ break;
+ case TXF_FELINE:
+ filterfunc = feline_eval;
+ break;
+ case TXF_AREA:
+ default:
+ filterfunc = area_sample;
+ }
+
+ texres->tin = texres->ta = texres->tr = texres->tg = texres->tb = 0.f;
+
+ /* we need to set retval OK, otherwise texture code generates normals itself... */
+ retval = texres->nor ? 3 : 1;
+
+ /* quick tests */
+ if (ibuf == NULL && ima == NULL)
+ return retval;
+
+ if (ima) { /* hack for icon render */
+ if (skip_load_image && !BKE_image_has_loaded_ibuf(ima)) {
+ return retval;
+ }
+ ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
+ }
+
+ if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) {
+ if (ima)
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
+ return retval;
+ }
+
+ if (ima) {
+ ima->flag |= IMA_USED_FOR_RENDER;
+ }
+
+ /* mipmap test */
+ image_mipmap_test(tex, ibuf);
+
+ if (ima) {
+ if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
+ if ((tex->imaflag & TEX_CALCALPHA) == 0) {
+ texres->talpha = 1;
+ }
+ }
+ }
+ texr.talpha = texres->talpha;
+
+ if (tex->imaflag & TEX_IMAROT) {
+ fy = texvec[0];
+ fx = texvec[1];
+ }
+ else {
+ fx = texvec[0];
+ fy = texvec[1];
+ }
+
+ /* pixel coordinates */
+ minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
+ maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
+ miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
+ maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
+
+ /* tex_sharper has been removed */
+ minx = (maxx - minx) * 0.5f;
+ miny = (maxy - miny) * 0.5f;
+
+ if (tex->imaflag & TEX_FILTER_MIN) {
+ /* make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) */
+ const float addval = (0.5f * tex->filtersize) / (float)MIN2(ibuf->x, ibuf->y);
+ if (addval > minx)
+ minx = addval;
+ if (addval > miny)
+ miny = addval;
+ }
+ else if (tex->filtersize != 1.f) {
+ minx *= tex->filtersize;
+ miny *= tex->filtersize;
+ dxt[0] *= tex->filtersize;
+ dxt[1] *= tex->filtersize;
+ dyt[0] *= tex->filtersize;
+ dyt[1] *= tex->filtersize;
+ }
+
+ if (tex->imaflag & TEX_IMAROT) {
+ float t;
+ SWAP(float, minx, miny);
+ /* must rotate dxt/dyt 90 deg
+ * yet another blender problem is that swapping X/Y axes (or any tex proj switches) should do something similar,
+ * but it doesn't, it only swaps coords, so filter area will be incorrect in those cases. */
+ t = dxt[0];
+ dxt[0] = dxt[1];
+ dxt[1] = -t;
+ t = dyt[0];
+ dyt[0] = dyt[1];
+ dyt[1] = -t;
+ }
+
+ /* side faces of unit-cube */
+ minx = (minx > 0.25f) ? 0.25f : ((minx < 1e-5f) ? 1e-5f : minx);
+ miny = (miny > 0.25f) ? 0.25f : ((miny < 1e-5f) ? 1e-5f : miny);
+
+ /* repeat and clip */
+
+ if (tex->extend == TEX_REPEAT) {
+ if ((tex->flag & (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) == (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR))
+ extflag = TXC_EXTD;
+ else if (tex->flag & TEX_REPEAT_XMIR)
+ extflag = TXC_XMIR;
+ else if (tex->flag & TEX_REPEAT_YMIR)
+ extflag = TXC_YMIR;
+ else
+ extflag = TXC_REPT;
+ }
+ else if (tex->extend == TEX_EXTEND)
+ extflag = TXC_EXTD;
+
+ if (tex->extend == TEX_CHECKER) {
+ int xs = (int)floorf(fx), ys = (int)floorf(fy);
+ /* both checkers available, no boundary exceptions, checkerdist will eat aliasing */
+ if ((tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN)) {
+ fx -= xs;
+ fy -= ys;
+ }
+ else if ((tex->flag & TEX_CHECKER_ODD) == 0 && (tex->flag & TEX_CHECKER_EVEN) == 0) {
+ if (ima)
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
+ return retval;
+ }
+ else {
+ int xs1 = (int)floorf(fx - minx);
+ int ys1 = (int)floorf(fy - miny);
+ int xs2 = (int)floorf(fx + minx);
+ int ys2 = (int)floorf(fy + miny);
+ if ((xs1 != xs2) || (ys1 != ys2)) {
+ if (tex->flag & TEX_CHECKER_ODD) {
+ fx -= ((xs1 + ys) & 1) ? xs2 : xs1;
+ fy -= ((ys1 + xs) & 1) ? ys2 : ys1;
+ }
+ if (tex->flag & TEX_CHECKER_EVEN) {
+ fx -= ((xs1 + ys) & 1) ? xs1 : xs2;
+ fy -= ((ys1 + xs) & 1) ? ys1 : ys2;
+ }
+ }
+ else {
+ if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) {
+ if (ima)
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
+ return retval;
+ }
+ if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) {
+ if (ima)
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
+ return retval;
+ }
+ fx -= xs;
+ fy -= ys;
+ }
+ }
+ /* scale around center, (0.5, 0.5) */
+ if (tex->checkerdist < 1.f) {
+ const float omcd = 1.f / (1.f - tex->checkerdist);
+ fx = (fx - 0.5f) * omcd + 0.5f;
+ fy = (fy - 0.5f) * omcd + 0.5f;
+ minx *= omcd;
+ miny *= omcd;
+ }
+ }
+
+ 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_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_pool_release_ibuf(ima, ibuf, pool);
+ return retval;
+ }
+ }
+ else {
+ if (tex->extend == TEX_EXTEND) {
+ fx = (fx > 1.f) ? 1.f : ((fx < 0.f) ? 0.f : fx);
+ fy = (fy > 1.f) ? 1.f : ((fy < 0.f) ? 0.f : fy);
+ }
+ else {
+ fx -= floorf(fx);
+ fy -= floorf(fy);
+ }
+ }
+
+ intpol = tex->imaflag & TEX_INTERPOL;
+
+ /* struct common data */
+ copy_v2_v2(AFD.dxt, dxt);
+ copy_v2_v2(AFD.dyt, dyt);
+ AFD.intpol = intpol;
+ AFD.extflag = extflag;
+
+ /* brecht: added stupid clamping here, large dx/dy can give very large
+ * filter sizes which take ages to render, it may be better to do this
+ * more intelligently later in the code .. probably it's not noticeable */
+ if (AFD.dxt[0] * AFD.dxt[0] + AFD.dxt[1] * AFD.dxt[1] > 2.0f * 2.0f)
+ mul_v2_fl(AFD.dxt, 2.0f / len_v2(AFD.dxt));
+ if (AFD.dyt[0] * AFD.dyt[0] + AFD.dyt[1] * AFD.dyt[1] > 2.0f * 2.0f)
+ mul_v2_fl(AFD.dyt, 2.0f / len_v2(AFD.dyt));
+
+ /* choice: */
+ if (tex->imaflag & TEX_MIPMAP) {
+ ImBuf *previbuf, *curibuf;
+ float levf;
+ int maxlev;
+ ImBuf *mipmaps[IMB_MIPMAP_LEVELS + 1];
+
+ /* modify ellipse minor axis if too eccentric, use for area sampling as well
+ * scaling dxt/dyt as done in pbrt is not the same
+ * (as in ewa_eval(), scale by sqrt(ibuf->x) to maximize precision) */
+ const float ff = sqrtf(ibuf->x), q = ibuf->y / ff;
+ const float Ux = dxt[0] * ff, Vx = dxt[1] * q, Uy = dyt[0] * ff, Vy = dyt[1] * q;
+ const float A = Vx * Vx + Vy * Vy;
+ const float B = -2.f * (Ux * Vx + Uy * Vy);
+ const float C = Ux * Ux + Uy * Uy;
+ const float F = A * C - B * B * 0.25f;
+ float a, b, th, ecc;
+ BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
+ if (tex->texfilter == TXF_FELINE) {
+ float fProbes;
+ a *= ff;
+ b *= ff;
+ a = max_ff(a, 1.0f);
+ b = max_ff(b, 1.0f);
+ fProbes = 2.f * (a / b) - 1.f;
+ AFD.iProbes = round_fl_to_int(fProbes);
+ AFD.iProbes = MIN2(AFD.iProbes, tex->afmax);
+ if (AFD.iProbes < fProbes)
+ b = 2.f * a / (float)(AFD.iProbes + 1);
+ AFD.majrad = a / ff;
+ AFD.minrad = b / ff;
+ AFD.theta = th;
+ AFD.dusc = 1.f / ff;
+ AFD.dvsc = ff / (float)ibuf->y;
+ }
+ else { /* EWA & area */
+ if (ecc > (float)tex->afmax)
+ b = a / (float)tex->afmax;
+ b *= ff;
+ }
+ maxd = max_ff(b, 1e-8f);
+ levf = ((float)M_LOG2E) * logf(maxd);
+
+ curmap = 0;
+ maxlev = 1;
+ mipmaps[0] = ibuf;
+ while (curmap < IMB_MIPMAP_LEVELS) {
+ mipmaps[curmap + 1] = ibuf->mipmap[curmap];
+ if (ibuf->mipmap[curmap])
+ maxlev++;
+ curmap++;
+ }
+
+ /* mipmap level */
+ if (levf < 0.f) { /* original image only */
+ previbuf = curibuf = mipmaps[0];
+ levf = 0.f;
+ }
+ else if (levf >= maxlev - 1) {
+ previbuf = curibuf = mipmaps[maxlev - 1];
+ levf = 0.f;
+ if (tex->texfilter == TXF_FELINE)
+ AFD.iProbes = 1;
+ }
+ else {
+ const int lev = isnan(levf) ? 0 : (int)levf;
+ curibuf = mipmaps[lev];
+ previbuf = mipmaps[lev + 1];
+ levf -= floorf(levf);
+ }
+
+ /* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */
+
+ if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
+ /* color & normal */
+ filterfunc(texres, curibuf, fx, fy, &AFD);
+ val1 = texres->tr + texres->tg + texres->tb;
+ filterfunc(&texr, curibuf, fx + dxt[0], fy + dxt[1], &AFD);
+ val2 = texr.tr + texr.tg + texr.tb;
+ filterfunc(&texr, curibuf, fx + dyt[0], fy + dyt[1], &AFD);
+ val3 = texr.tr + texr.tg + texr.tb;
+ /* don't switch x or y! */
+ texres->nor[0] = val1 - val2;
+ texres->nor[1] = val1 - val3;
+ if (previbuf != curibuf) { /* interpolate */
+ filterfunc(&texr, previbuf, fx, fy, &AFD);
+ /* rgb */
+ texres->tr += levf * (texr.tr - texres->tr);
+ texres->tg += levf * (texr.tg - texres->tg);
+ texres->tb += levf * (texr.tb - texres->tb);
+ texres->ta += levf * (texr.ta - texres->ta);
+ /* normal */
+ val1 += levf * ((texr.tr + texr.tg + texr.tb) - val1);
+ filterfunc(&texr, previbuf, fx + dxt[0], fy + dxt[1], &AFD);
+ val2 += levf * ((texr.tr + texr.tg + texr.tb) - val2);
+ filterfunc(&texr, previbuf, fx + dyt[0], fy + dyt[1], &AFD);
+ val3 += levf * ((texr.tr + texr.tg + texr.tb) - val3);
+ texres->nor[0] = val1 - val2; /* vals have been interpolated above! */
+ texres->nor[1] = val1 - val3;
+ }
+ }
+ else { /* color */
+ filterfunc(texres, curibuf, fx, fy, &AFD);
+ if (previbuf != curibuf) { /* interpolate */
+ filterfunc(&texr, previbuf, fx, fy, &AFD);
+ texres->tr += levf * (texr.tr - texres->tr);
+ texres->tg += levf * (texr.tg - texres->tg);
+ texres->tb += levf * (texr.tb - texres->tb);
+ texres->ta += levf * (texr.ta - texres->ta);
+ }
+
+ if (tex->texfilter != TXF_EWA) {
+ alpha_clip_aniso(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, extflag, texres);
+ }
+ }
+ }
+ else { /* no mipmap */
+ /* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */
+ if (tex->texfilter == TXF_FELINE) {
+ const float ff = sqrtf(ibuf->x), q = ibuf->y / ff;
+ const float Ux = dxt[0] * ff, Vx = dxt[1] * q, Uy = dyt[0] * ff, Vy = dyt[1] * q;
+ const float A = Vx * Vx + Vy * Vy;
+ const float B = -2.f * (Ux * Vx + Uy * Vy);
+ const float C = Ux * Ux + Uy * Uy;
+ const float F = A * C - B * B * 0.25f;
+ float a, b, th, ecc, fProbes;
+ BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
+ a *= ff;
+ b *= ff;
+ a = max_ff(a, 1.0f);
+ b = max_ff(b, 1.0f);
+ fProbes = 2.f * (a / b) - 1.f;
+ /* no limit to number of Probes here */
+ AFD.iProbes = round_fl_to_int(fProbes);
+ if (AFD.iProbes < fProbes)
+ b = 2.f * a / (float)(AFD.iProbes + 1);
+ AFD.majrad = a / ff;
+ AFD.minrad = b / ff;
+ AFD.theta = th;
+ AFD.dusc = 1.f / ff;
+ AFD.dvsc = ff / (float)ibuf->y;
+ }
+ if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
+ /* color & normal */
+ filterfunc(texres, ibuf, fx, fy, &AFD);
+ val1 = texres->tr + texres->tg + texres->tb;
+ filterfunc(&texr, ibuf, fx + dxt[0], fy + dxt[1], &AFD);
+ val2 = texr.tr + texr.tg + texr.tb;
+ filterfunc(&texr, ibuf, fx + dyt[0], fy + dyt[1], &AFD);
+ val3 = texr.tr + texr.tg + texr.tb;
+ /* don't switch x or y! */
+ texres->nor[0] = val1 - val2;
+ texres->nor[1] = val1 - val3;
+ }
+ else {
+ filterfunc(texres, ibuf, fx, fy, &AFD);
+ if (tex->texfilter != TXF_EWA) {
+ alpha_clip_aniso(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, extflag, texres);
+ }
+ }
+ }
+
+ if (tex->imaflag & TEX_CALCALPHA)
+ texres->ta = texres->tin = texres->ta * max_fff(texres->tr, texres->tg, texres->tb);
+ else
+ texres->tin = texres->ta;
+ if (tex->flag & TEX_NEGALPHA)
+ texres->ta = 1.f - texres->ta;
+
+ if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) { /* normal from color */
+ /* 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. */
+ texres->nor[0] = -2.f * (texres->tr - 0.5f);
+ texres->nor[1] = 2.f * (texres->tg - 0.5f);
+ texres->nor[2] = 2.f * (texres->tb - 0.5f);
+ }
+
+ /* de-premul, this is being premulled in shade_input_do_shade()
+ * TXF: this currently does not (yet?) work properly, destroys edge AA in clip/checker mode, so for now commented out
+ * also disabled in imagewraposa() to be able to compare results with blender's default texture filtering */
+
+ /* brecht: tried to fix this, see "TXF alpha" comments */
+
+ /* do not de-premul for generated alpha, it is already in straight */
+ if (texres->ta != 1.0f && texres->ta > 1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
+ fx = 1.f / texres->ta;
+ texres->tr *= fx;
+ texres->tg *= fx;
+ texres->tb *= fx;
+ }
+
+ if (ima)
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
+
+ BRICONTRGB;
+
+ return retval;
}
-
-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, const bool skip_load_image)
+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,
+ const bool skip_load_image)
{
- TexResult texr;
- float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[2], dyt[2];
- float maxd, pixsize, val1, val2, val3;
- int curmap, retval, imaprepeat, imapextend;
-
- /* TXF: since dxt/dyt might be modified here and since they might be needed after imagewraposa() call,
- * make a local copy here so that original vecs remain untouched */
- copy_v2_v2(dxt, DXT);
- copy_v2_v2(dyt, DYT);
-
- /* anisotropic filtering */
- if (tex->texfilter != TXF_BOX)
- return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres, pool, skip_load_image);
-
- texres->tin = texres->ta = texres->tr = texres->tg = texres->tb = 0.0f;
-
- /* we need to set retval OK, otherwise texture code generates normals itself... */
- retval = texres->nor ? 3 : 1;
-
- /* quick tests */
- if (ibuf == NULL && ima == NULL)
- return retval;
- if (ima) {
-
- /* hack for icon render */
- if (skip_load_image && !BKE_image_has_loaded_ibuf(ima))
- return retval;
-
- 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_pool_release_ibuf(ima, ibuf, pool);
- return retval;
- }
-
- /* mipmap test */
- image_mipmap_test(tex, ibuf);
-
- if (ima) {
- if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
- if ((tex->imaflag & TEX_CALCALPHA) == 0) {
- texres->talpha = true;
- }
- }
- }
-
- texr.talpha = texres->talpha;
-
- if (tex->imaflag & TEX_IMAROT) {
- fy = texvec[0];
- fx = texvec[1];
- }
- else {
- fx = texvec[0];
- fy = texvec[1];
- }
-
- /* pixel coordinates */
-
- minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
- maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
- miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
- maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
-
- /* tex_sharper has been removed */
- minx = (maxx - minx) / 2.0f;
- miny = (maxy - miny) / 2.0f;
-
- if (tex->imaflag & TEX_FILTER_MIN) {
- /* make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) */
- float addval = (0.5f * tex->filtersize) / (float)MIN2(ibuf->x, ibuf->y);
-
- if (addval > minx)
- minx = addval;
- if (addval > miny)
- miny = addval;
- }
- else if (tex->filtersize != 1.0f) {
- minx *= tex->filtersize;
- miny *= tex->filtersize;
-
- dxt[0] *= tex->filtersize;
- dxt[1] *= tex->filtersize;
- dyt[0] *= tex->filtersize;
- dyt[1] *= tex->filtersize;
- }
-
- if (tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny);
-
- if (minx > 0.25f) minx = 0.25f;
- else if (minx < 0.00001f) minx = 0.00001f; /* side faces of unit-cube */
- if (miny > 0.25f) miny = 0.25f;
- else if (miny < 0.00001f) miny = 0.00001f;
-
-
- /* repeat and clip */
- imaprepeat = (tex->extend == TEX_REPEAT);
- imapextend = (tex->extend == TEX_EXTEND);
-
- if (tex->extend == TEX_REPEAT) {
- if (tex->flag & (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) {
- imaprepeat = 0;
- imapextend = 1;
- }
- }
-
- if (tex->extend == TEX_CHECKER) {
- int xs, ys, xs1, ys1, xs2, ys2, boundary;
-
- xs = (int)floor(fx);
- ys = (int)floor(fy);
-
- /* both checkers available, no boundary exceptions, checkerdist will eat aliasing */
- if ( (tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN) ) {
- fx -= xs;
- fy -= ys;
- }
- else if ((tex->flag & TEX_CHECKER_ODD) == 0 &&
- (tex->flag & TEX_CHECKER_EVEN) == 0)
- {
- if (ima)
- BKE_image_pool_release_ibuf(ima, ibuf, pool);
- return retval;
- }
- else {
-
- xs1 = (int)floor(fx - minx);
- ys1 = (int)floor(fy - miny);
- xs2 = (int)floor(fx + minx);
- ys2 = (int)floor(fy + miny);
- boundary = (xs1 != xs2) || (ys1 != ys2);
-
- if (boundary == 0) {
- if ( (tex->flag & TEX_CHECKER_ODD) == 0) {
- if ((xs + ys) & 1) {
- /* pass */
- }
- else {
- if (ima)
- 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_pool_release_ibuf(ima, ibuf, pool);
- return retval;
- }
- }
- fx -= xs;
- fy -= ys;
- }
- else {
- if (tex->flag & TEX_CHECKER_ODD) {
- if ((xs1 + ys) & 1) fx -= xs2;
- else fx -= xs1;
-
- if ((ys1 + xs) & 1) fy -= ys2;
- else fy -= ys1;
- }
- if (tex->flag & TEX_CHECKER_EVEN) {
- if ((xs1 + ys) & 1) fx -= xs1;
- else fx -= xs2;
-
- if ((ys1 + xs) & 1) fy -= ys1;
- else fy -= ys2;
- }
- }
- }
-
- /* scale around center, (0.5, 0.5) */
- if (tex->checkerdist < 1.0f) {
- fx = (fx - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
- fy = (fy - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
- minx /= (1.0f - tex->checkerdist);
- miny /= (1.0f - tex->checkerdist);
- }
- }
-
- 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_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_pool_release_ibuf(ima, ibuf, pool);
- return retval;
- }
- }
- else {
- if (imapextend) {
- if (fx > 1.0f) fx = 1.0f;
- else if (fx < 0.0f) fx = 0.0f;
- }
- else {
- if (fx > 1.0f) fx -= (int)(fx);
- else if (fx < 0.0f) fx += 1 - (int)(fx);
- }
-
- if (imapextend) {
- if (fy > 1.0f) fy = 1.0f;
- else if (fy < 0.0f) fy = 0.0f;
- }
- else {
- if (fy > 1.0f) fy -= (int)(fy);
- else if (fy < 0.0f) fy += 1 - (int)(fy);
- }
- }
-
- /* choice: */
- if (tex->imaflag & TEX_MIPMAP) {
- ImBuf *previbuf, *curibuf;
- float bumpscale;
-
- dx = minx;
- dy = miny;
- maxd = max_ff(dx, dy);
- if (maxd > 0.5f) maxd = 0.5f;
-
- pixsize = 1.0f / (float)MIN2(ibuf->x, ibuf->y);
-
- bumpscale = pixsize / maxd;
- if (bumpscale > 1.0f) bumpscale = 1.0f;
- else bumpscale *= bumpscale;
-
- curmap = 0;
- previbuf = curibuf = ibuf;
- while (curmap < IMB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) {
- if (maxd < pixsize) break;
- previbuf = curibuf;
- curibuf = ibuf->mipmap[curmap];
- pixsize = 1.0f / (float)MIN2(curibuf->x, curibuf->y);
- curmap++;
- }
-
- if (previbuf != curibuf || (tex->imaflag & TEX_INTERPOL)) {
- /* sample at least 1 pixel */
- if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x;
- if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y;
- }
-
- if (texres->nor && (tex->imaflag & TEX_NORMALMAP) == 0) {
- /* a bit extra filter */
- //minx*= 1.35f;
- //miny*= 1.35f;
-
- boxsample(curibuf, fx - minx, fy - miny, fx + minx, fy + miny, texres, imaprepeat, imapextend);
- val1 = texres->tr + texres->tg + texres->tb;
- boxsample(curibuf, fx - minx + dxt[0], fy - miny + dxt[1], fx + minx + dxt[0], fy + miny + dxt[1], &texr, imaprepeat, imapextend);
- val2 = texr.tr + texr.tg + texr.tb;
- boxsample(curibuf, fx - minx + dyt[0], fy - miny + dyt[1], fx + minx + dyt[0], fy + miny + dyt[1], &texr, imaprepeat, imapextend);
- val3 = texr.tr + texr.tg + texr.tb;
-
- /* don't switch x or y! */
- texres->nor[0] = (val1 - val2);
- texres->nor[1] = (val1 - val3);
-
- if (previbuf != curibuf) { /* interpolate */
-
- boxsample(previbuf, fx - minx, fy - miny, fx + minx, fy + miny, &texr, imaprepeat, imapextend);
-
- /* calc rgb */
- dx = 2.0f * (pixsize - maxd) / pixsize;
- if (dx >= 1.0f) {
- texres->ta = texr.ta; texres->tb = texr.tb;
- texres->tg = texr.tg; texres->tr = texr.tr;
- }
- else {
- dy = 1.0f - dx;
- texres->tb = dy * texres->tb + dx * texr.tb;
- texres->tg = dy * texres->tg + dx * texr.tg;
- texres->tr = dy * texres->tr + dx * texr.tr;
- texres->ta = dy * texres->ta + dx * texr.ta;
- }
-
- val1 = dy * val1 + dx * (texr.tr + texr.tg + texr.tb);
- boxsample(previbuf, fx - minx + dxt[0], fy - miny + dxt[1], fx + minx + dxt[0], fy + miny + dxt[1], &texr, imaprepeat, imapextend);
- val2 = dy * val2 + dx * (texr.tr + texr.tg + texr.tb);
- boxsample(previbuf, fx - minx + dyt[0], fy - miny + dyt[1], fx + minx + dyt[0], fy + miny + dyt[1], &texr, imaprepeat, imapextend);
- val3 = dy * val3 + dx * (texr.tr + texr.tg + texr.tb);
-
- texres->nor[0] = (val1 - val2); /* vals have been interpolated above! */
- texres->nor[1] = (val1 - val3);
-
- if (dx < 1.0f) {
- dy = 1.0f - dx;
- texres->tb = dy * texres->tb + dx * texr.tb;
- texres->tg = dy * texres->tg + dx * texr.tg;
- texres->tr = dy * texres->tr + dx * texr.tr;
- texres->ta = dy * texres->ta + dx * texr.ta;
- }
- }
- texres->nor[0] *= bumpscale;
- texres->nor[1] *= bumpscale;
- }
- else {
- maxx = fx + minx;
- minx = fx - minx;
- maxy = fy + miny;
- miny = fy - miny;
-
- boxsample(curibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend);
-
- if (previbuf != curibuf) { /* interpolate */
- boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend);
-
- fx = 2.0f * (pixsize - maxd) / pixsize;
-
- if (fx >= 1.0f) {
- texres->ta = texr.ta; texres->tb = texr.tb;
- texres->tg = texr.tg; texres->tr = texr.tr;
- }
- else {
- fy = 1.0f - fx;
- texres->tb = fy * texres->tb + fx * texr.tb;
- texres->tg = fy * texres->tg + fx * texr.tg;
- texres->tr = fy * texres->tr + fx * texr.tr;
- texres->ta = fy * texres->ta + fx * texr.ta;
- }
- }
- }
- }
- else {
- const int intpol = tex->imaflag & TEX_INTERPOL;
- if (intpol) {
- /* sample 1 pixel minimum */
- if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x;
- if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y;
- }
-
- if (texres->nor && (tex->imaflag & TEX_NORMALMAP) == 0) {
- boxsample(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, texres, imaprepeat, imapextend);
- val1 = texres->tr + texres->tg + texres->tb;
- boxsample(ibuf, fx - minx + dxt[0], fy - miny + dxt[1], fx + minx + dxt[0], fy + miny + dxt[1], &texr, imaprepeat, imapextend);
- val2 = texr.tr + texr.tg + texr.tb;
- boxsample(ibuf, fx - minx + dyt[0], fy - miny + dyt[1], fx + minx + dyt[0], fy + miny + dyt[1], &texr, imaprepeat, imapextend);
- val3 = texr.tr + texr.tg + texr.tb;
-
- /* don't switch x or y! */
- texres->nor[0] = (val1 - val2);
- texres->nor[1] = (val1 - val3);
- }
- else
- boxsample(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, texres, imaprepeat, imapextend);
- }
-
- if (tex->imaflag & TEX_CALCALPHA) {
- texres->ta = texres->tin = texres->ta * max_fff(texres->tr, texres->tg, texres->tb);
- }
- else {
- texres->tin = texres->ta;
- }
-
- if (tex->flag & TEX_NEGALPHA) texres->ta = 1.0f - texres->ta;
-
- if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) {
- /* qdn: normal from color
- * 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. */
- texres->nor[0] = -2.f * (texres->tr - 0.5f);
- texres->nor[1] = 2.f * (texres->tg - 0.5f);
- texres->nor[2] = 2.f * (texres->tb - 0.5f);
- }
-
- /* de-premul, this is being premulled in shade_input_do_shade() */
- /* do not de-premul for generated alpha, it is already in straight */
- if (texres->ta != 1.0f && texres->ta > 1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
- mul_v3_fl(&texres->tr, 1.0f / texres->ta);
- }
-
- if (ima)
- BKE_image_pool_release_ibuf(ima, ibuf, pool);
-
- BRICONTRGB;
-
- return retval;
+ TexResult texr;
+ float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[2], dyt[2];
+ float maxd, pixsize, val1, val2, val3;
+ int curmap, retval, imaprepeat, imapextend;
+
+ /* TXF: since dxt/dyt might be modified here and since they might be needed after imagewraposa() call,
+ * make a local copy here so that original vecs remain untouched */
+ copy_v2_v2(dxt, DXT);
+ copy_v2_v2(dyt, DYT);
+
+ /* anisotropic filtering */
+ if (tex->texfilter != TXF_BOX)
+ return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres, pool, skip_load_image);
+
+ texres->tin = texres->ta = texres->tr = texres->tg = texres->tb = 0.0f;
+
+ /* we need to set retval OK, otherwise texture code generates normals itself... */
+ retval = texres->nor ? 3 : 1;
+
+ /* quick tests */
+ if (ibuf == NULL && ima == NULL)
+ return retval;
+ if (ima) {
+
+ /* hack for icon render */
+ if (skip_load_image && !BKE_image_has_loaded_ibuf(ima))
+ return retval;
+
+ 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_pool_release_ibuf(ima, ibuf, pool);
+ return retval;
+ }
+
+ /* mipmap test */
+ image_mipmap_test(tex, ibuf);
+
+ if (ima) {
+ if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
+ if ((tex->imaflag & TEX_CALCALPHA) == 0) {
+ texres->talpha = true;
+ }
+ }
+ }
+
+ texr.talpha = texres->talpha;
+
+ if (tex->imaflag & TEX_IMAROT) {
+ fy = texvec[0];
+ fx = texvec[1];
+ }
+ else {
+ fx = texvec[0];
+ fy = texvec[1];
+ }
+
+ /* pixel coordinates */
+
+ minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
+ maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
+ miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
+ maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
+
+ /* tex_sharper has been removed */
+ minx = (maxx - minx) / 2.0f;
+ miny = (maxy - miny) / 2.0f;
+
+ if (tex->imaflag & TEX_FILTER_MIN) {
+ /* make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) */
+ float addval = (0.5f * tex->filtersize) / (float)MIN2(ibuf->x, ibuf->y);
+
+ if (addval > minx)
+ minx = addval;
+ if (addval > miny)
+ miny = addval;
+ }
+ else if (tex->filtersize != 1.0f) {
+ minx *= tex->filtersize;
+ miny *= tex->filtersize;
+
+ dxt[0] *= tex->filtersize;
+ dxt[1] *= tex->filtersize;
+ dyt[0] *= tex->filtersize;
+ dyt[1] *= tex->filtersize;
+ }
+
+ if (tex->imaflag & TEX_IMAROT)
+ SWAP(float, minx, miny);
+
+ if (minx > 0.25f)
+ minx = 0.25f;
+ else if (minx < 0.00001f)
+ minx = 0.00001f; /* side faces of unit-cube */
+ if (miny > 0.25f)
+ miny = 0.25f;
+ else if (miny < 0.00001f)
+ miny = 0.00001f;
+
+ /* repeat and clip */
+ imaprepeat = (tex->extend == TEX_REPEAT);
+ imapextend = (tex->extend == TEX_EXTEND);
+
+ if (tex->extend == TEX_REPEAT) {
+ if (tex->flag & (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) {
+ imaprepeat = 0;
+ imapextend = 1;
+ }
+ }
+
+ if (tex->extend == TEX_CHECKER) {
+ int xs, ys, xs1, ys1, xs2, ys2, boundary;
+
+ xs = (int)floor(fx);
+ ys = (int)floor(fy);
+
+ /* both checkers available, no boundary exceptions, checkerdist will eat aliasing */
+ if ((tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN)) {
+ fx -= xs;
+ fy -= ys;
+ }
+ else if ((tex->flag & TEX_CHECKER_ODD) == 0 && (tex->flag & TEX_CHECKER_EVEN) == 0) {
+ if (ima)
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
+ return retval;
+ }
+ else {
+
+ xs1 = (int)floor(fx - minx);
+ ys1 = (int)floor(fy - miny);
+ xs2 = (int)floor(fx + minx);
+ ys2 = (int)floor(fy + miny);
+ boundary = (xs1 != xs2) || (ys1 != ys2);
+
+ if (boundary == 0) {
+ if ((tex->flag & TEX_CHECKER_ODD) == 0) {
+ if ((xs + ys) & 1) {
+ /* pass */
+ }
+ else {
+ if (ima)
+ 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_pool_release_ibuf(ima, ibuf, pool);
+ return retval;
+ }
+ }
+ fx -= xs;
+ fy -= ys;
+ }
+ else {
+ if (tex->flag & TEX_CHECKER_ODD) {
+ if ((xs1 + ys) & 1)
+ fx -= xs2;
+ else
+ fx -= xs1;
+
+ if ((ys1 + xs) & 1)
+ fy -= ys2;
+ else
+ fy -= ys1;
+ }
+ if (tex->flag & TEX_CHECKER_EVEN) {
+ if ((xs1 + ys) & 1)
+ fx -= xs1;
+ else
+ fx -= xs2;
+
+ if ((ys1 + xs) & 1)
+ fy -= ys1;
+ else
+ fy -= ys2;
+ }
+ }
+ }
+
+ /* scale around center, (0.5, 0.5) */
+ if (tex->checkerdist < 1.0f) {
+ fx = (fx - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
+ fy = (fy - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
+ minx /= (1.0f - tex->checkerdist);
+ miny /= (1.0f - tex->checkerdist);
+ }
+ }
+
+ 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_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_pool_release_ibuf(ima, ibuf, pool);
+ return retval;
+ }
+ }
+ else {
+ if (imapextend) {
+ if (fx > 1.0f)
+ fx = 1.0f;
+ else if (fx < 0.0f)
+ fx = 0.0f;
+ }
+ else {
+ if (fx > 1.0f)
+ fx -= (int)(fx);
+ else if (fx < 0.0f)
+ fx += 1 - (int)(fx);
+ }
+
+ if (imapextend) {
+ if (fy > 1.0f)
+ fy = 1.0f;
+ else if (fy < 0.0f)
+ fy = 0.0f;
+ }
+ else {
+ if (fy > 1.0f)
+ fy -= (int)(fy);
+ else if (fy < 0.0f)
+ fy += 1 - (int)(fy);
+ }
+ }
+
+ /* choice: */
+ if (tex->imaflag & TEX_MIPMAP) {
+ ImBuf *previbuf, *curibuf;
+ float bumpscale;
+
+ dx = minx;
+ dy = miny;
+ maxd = max_ff(dx, dy);
+ if (maxd > 0.5f)
+ maxd = 0.5f;
+
+ pixsize = 1.0f / (float)MIN2(ibuf->x, ibuf->y);
+
+ bumpscale = pixsize / maxd;
+ if (bumpscale > 1.0f)
+ bumpscale = 1.0f;
+ else
+ bumpscale *= bumpscale;
+
+ curmap = 0;
+ previbuf = curibuf = ibuf;
+ while (curmap < IMB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) {
+ if (maxd < pixsize)
+ break;
+ previbuf = curibuf;
+ curibuf = ibuf->mipmap[curmap];
+ pixsize = 1.0f / (float)MIN2(curibuf->x, curibuf->y);
+ curmap++;
+ }
+
+ if (previbuf != curibuf || (tex->imaflag & TEX_INTERPOL)) {
+ /* sample at least 1 pixel */
+ if (minx < 0.5f / ibuf->x)
+ minx = 0.5f / ibuf->x;
+ if (miny < 0.5f / ibuf->y)
+ miny = 0.5f / ibuf->y;
+ }
+
+ if (texres->nor && (tex->imaflag & TEX_NORMALMAP) == 0) {
+ /* a bit extra filter */
+ //minx*= 1.35f;
+ //miny*= 1.35f;
+
+ boxsample(
+ curibuf, fx - minx, fy - miny, fx + minx, fy + miny, texres, imaprepeat, imapextend);
+ val1 = texres->tr + texres->tg + texres->tb;
+ boxsample(curibuf,
+ fx - minx + dxt[0],
+ fy - miny + dxt[1],
+ fx + minx + dxt[0],
+ fy + miny + dxt[1],
+ &texr,
+ imaprepeat,
+ imapextend);
+ val2 = texr.tr + texr.tg + texr.tb;
+ boxsample(curibuf,
+ fx - minx + dyt[0],
+ fy - miny + dyt[1],
+ fx + minx + dyt[0],
+ fy + miny + dyt[1],
+ &texr,
+ imaprepeat,
+ imapextend);
+ val3 = texr.tr + texr.tg + texr.tb;
+
+ /* don't switch x or y! */
+ texres->nor[0] = (val1 - val2);
+ texres->nor[1] = (val1 - val3);
+
+ if (previbuf != curibuf) { /* interpolate */
+
+ boxsample(
+ previbuf, fx - minx, fy - miny, fx + minx, fy + miny, &texr, imaprepeat, imapextend);
+
+ /* calc rgb */
+ dx = 2.0f * (pixsize - maxd) / pixsize;
+ if (dx >= 1.0f) {
+ texres->ta = texr.ta;
+ texres->tb = texr.tb;
+ texres->tg = texr.tg;
+ texres->tr = texr.tr;
+ }
+ else {
+ dy = 1.0f - dx;
+ texres->tb = dy * texres->tb + dx * texr.tb;
+ texres->tg = dy * texres->tg + dx * texr.tg;
+ texres->tr = dy * texres->tr + dx * texr.tr;
+ texres->ta = dy * texres->ta + dx * texr.ta;
+ }
+
+ val1 = dy * val1 + dx * (texr.tr + texr.tg + texr.tb);
+ boxsample(previbuf,
+ fx - minx + dxt[0],
+ fy - miny + dxt[1],
+ fx + minx + dxt[0],
+ fy + miny + dxt[1],
+ &texr,
+ imaprepeat,
+ imapextend);
+ val2 = dy * val2 + dx * (texr.tr + texr.tg + texr.tb);
+ boxsample(previbuf,
+ fx - minx + dyt[0],
+ fy - miny + dyt[1],
+ fx + minx + dyt[0],
+ fy + miny + dyt[1],
+ &texr,
+ imaprepeat,
+ imapextend);
+ val3 = dy * val3 + dx * (texr.tr + texr.tg + texr.tb);
+
+ texres->nor[0] = (val1 - val2); /* vals have been interpolated above! */
+ texres->nor[1] = (val1 - val3);
+
+ if (dx < 1.0f) {
+ dy = 1.0f - dx;
+ texres->tb = dy * texres->tb + dx * texr.tb;
+ texres->tg = dy * texres->tg + dx * texr.tg;
+ texres->tr = dy * texres->tr + dx * texr.tr;
+ texres->ta = dy * texres->ta + dx * texr.ta;
+ }
+ }
+ texres->nor[0] *= bumpscale;
+ texres->nor[1] *= bumpscale;
+ }
+ else {
+ maxx = fx + minx;
+ minx = fx - minx;
+ maxy = fy + miny;
+ miny = fy - miny;
+
+ boxsample(curibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend);
+
+ if (previbuf != curibuf) { /* interpolate */
+ boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend);
+
+ fx = 2.0f * (pixsize - maxd) / pixsize;
+
+ if (fx >= 1.0f) {
+ texres->ta = texr.ta;
+ texres->tb = texr.tb;
+ texres->tg = texr.tg;
+ texres->tr = texr.tr;
+ }
+ else {
+ fy = 1.0f - fx;
+ texres->tb = fy * texres->tb + fx * texr.tb;
+ texres->tg = fy * texres->tg + fx * texr.tg;
+ texres->tr = fy * texres->tr + fx * texr.tr;
+ texres->ta = fy * texres->ta + fx * texr.ta;
+ }
+ }
+ }
+ }
+ else {
+ const int intpol = tex->imaflag & TEX_INTERPOL;
+ if (intpol) {
+ /* sample 1 pixel minimum */
+ if (minx < 0.5f / ibuf->x)
+ minx = 0.5f / ibuf->x;
+ if (miny < 0.5f / ibuf->y)
+ miny = 0.5f / ibuf->y;
+ }
+
+ if (texres->nor && (tex->imaflag & TEX_NORMALMAP) == 0) {
+ boxsample(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, texres, imaprepeat, imapextend);
+ val1 = texres->tr + texres->tg + texres->tb;
+ boxsample(ibuf,
+ fx - minx + dxt[0],
+ fy - miny + dxt[1],
+ fx + minx + dxt[0],
+ fy + miny + dxt[1],
+ &texr,
+ imaprepeat,
+ imapextend);
+ val2 = texr.tr + texr.tg + texr.tb;
+ boxsample(ibuf,
+ fx - minx + dyt[0],
+ fy - miny + dyt[1],
+ fx + minx + dyt[0],
+ fy + miny + dyt[1],
+ &texr,
+ imaprepeat,
+ imapextend);
+ val3 = texr.tr + texr.tg + texr.tb;
+
+ /* don't switch x or y! */
+ texres->nor[0] = (val1 - val2);
+ texres->nor[1] = (val1 - val3);
+ }
+ else
+ boxsample(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, texres, imaprepeat, imapextend);
+ }
+
+ if (tex->imaflag & TEX_CALCALPHA) {
+ texres->ta = texres->tin = texres->ta * max_fff(texres->tr, texres->tg, texres->tb);
+ }
+ else {
+ texres->tin = texres->ta;
+ }
+
+ if (tex->flag & TEX_NEGALPHA)
+ texres->ta = 1.0f - texres->ta;
+
+ if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) {
+ /* qdn: normal from color
+ * 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. */
+ texres->nor[0] = -2.f * (texres->tr - 0.5f);
+ texres->nor[1] = 2.f * (texres->tg - 0.5f);
+ texres->nor[2] = 2.f * (texres->tb - 0.5f);
+ }
+
+ /* de-premul, this is being premulled in shade_input_do_shade() */
+ /* do not de-premul for generated alpha, it is already in straight */
+ if (texres->ta != 1.0f && texres->ta > 1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
+ mul_v3_fl(&texres->tr, 1.0f / texres->ta);
+ }
+
+ if (ima)
+ 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], struct ImagePool *pool)
+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_pool_acquire_ibuf(ima, NULL, pool);
+ TexResult texres;
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, NULL, pool);
- if (UNLIKELY(ibuf == NULL)) {
- zero_v4(result);
- return;
- }
+ if (UNLIKELY(ibuf == NULL)) {
+ zero_v4(result);
+ return;
+ }
- texres.talpha = true; /* boxsample expects to be initialized */
- boxsample(ibuf, fx, fy, fx + dx, fy + dy, &texres, 0, 1);
- copy_v4_v4(result, &texres.tr);
+ texres.talpha = true; /* boxsample expects to be initialized */
+ boxsample(ibuf, fx, fy, fx + dx, fy + dy, &texres, 0, 1);
+ copy_v4_v4(result, &texres.tr);
- ima->flag |= IMA_USED_FOR_RENDER;
+ ima->flag |= IMA_USED_FOR_RENDER;
- BKE_image_pool_release_ibuf(ima, ibuf, pool);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
}
void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4])
{
- TexResult texres = {0};
- afdata_t AFD;
+ TexResult texres = {0};
+ afdata_t AFD;
- AFD.dxt[0] = dx; AFD.dxt[1] = dx;
- AFD.dyt[0] = dy; AFD.dyt[1] = dy;
- //copy_v2_v2(AFD.dxt, dx);
- //copy_v2_v2(AFD.dyt, dy);
+ AFD.dxt[0] = dx;
+ AFD.dxt[1] = dx;
+ AFD.dyt[0] = dy;
+ AFD.dyt[1] = dy;
+ //copy_v2_v2(AFD.dxt, dx);
+ //copy_v2_v2(AFD.dyt, dy);
- AFD.intpol = 1;
- AFD.extflag = TXC_EXTD;
+ AFD.intpol = 1;
+ AFD.extflag = TXC_EXTD;
- ewa_eval(&texres, ibuf, fx, fy, &AFD);
+ ewa_eval(&texres, ibuf, fx, fy, &AFD);
- copy_v4_v4(result, &texres.tr);
+ copy_v4_v4(result, &texres.tr);
}
diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c
index ff0d2867426..e23d839297a 100644
--- a/source/blender/render/intern/source/initrender.c
+++ b/source/blender/render/intern/source/initrender.c
@@ -45,253 +45,266 @@
/* Own includes */
#include "initrender.h"
-
/* ****************** MASKS and LUTS **************** */
static float filt_quadratic(float x)
{
- if (x < 0.0f) x = -x;
- if (x < 0.5f) return 0.75f - (x * x);
- if (x < 1.5f) return 0.50f * (x - 1.5f) * (x - 1.5f);
- return 0.0f;
+ if (x < 0.0f)
+ x = -x;
+ if (x < 0.5f)
+ return 0.75f - (x * x);
+ if (x < 1.5f)
+ return 0.50f * (x - 1.5f) * (x - 1.5f);
+ return 0.0f;
}
-
static float filt_cubic(float x)
{
- float x2 = x * x;
+ float x2 = x * x;
- if (x < 0.0f) x = -x;
+ if (x < 0.0f)
+ x = -x;
- if (x < 1.0f) return 0.5f * x * x2 - x2 + 2.0f / 3.0f;
- if (x < 2.0f) return (2.0f - x) * (2.0f - x) * (2.0f - x) / 6.0f;
- return 0.0f;
+ if (x < 1.0f)
+ return 0.5f * x * x2 - x2 + 2.0f / 3.0f;
+ if (x < 2.0f)
+ return (2.0f - x) * (2.0f - x) * (2.0f - x) / 6.0f;
+ return 0.0f;
}
-
static float filt_catrom(float x)
{
- float x2 = x * x;
-
- if (x < 0.0f) x = -x;
- if (x < 1.0f) return 1.5f * x2 * x - 2.5f * x2 + 1.0f;
- if (x < 2.0f) return -0.5f * x2 * x + 2.5f * x2 - 4.0f * x + 2.0f;
- return 0.0f;
+ float x2 = x * x;
+
+ if (x < 0.0f)
+ x = -x;
+ if (x < 1.0f)
+ return 1.5f * x2 * x - 2.5f * x2 + 1.0f;
+ if (x < 2.0f)
+ return -0.5f * x2 * x + 2.5f * x2 - 4.0f * x + 2.0f;
+ return 0.0f;
}
static float filt_mitchell(float x) /* Mitchell & Netravali's two-param cubic */
{
- float b = 1.0f / 3.0f, c = 1.0f / 3.0f;
- float p0 = ( 6.0f - 2.0f * b) / 6.0f;
- float p2 = (-18.0f + 12.0f * b + 6.0f * c) / 6.0f;
- float p3 = ( 12.0f - 9.0f * b - 6.0f * c) / 6.0f;
- float q0 = ( 8.0f * b + 24.0f * c) / 6.0f;
- float q1 = ( -12.0f * b - 48.0f * c) / 6.0f;
- float q2 = ( 6.0f * b + 30.0f * c) / 6.0f;
- float q3 = ( -b - 6.0f * c) / 6.0f;
-
- if (x < -2.0f) return 0.0f;
- if (x < -1.0f) return (q0 - x * (q1 - x * (q2 - x * q3)));
- if (x < 0.0f) return (p0 + x * x * (p2 - x * p3));
- if (x < 1.0f) return (p0 + x * x * (p2 + x * p3));
- if (x < 2.0f) return (q0 + x * (q1 + x * (q2 + x * q3)));
- return 0.0f;
+ float b = 1.0f / 3.0f, c = 1.0f / 3.0f;
+ float p0 = (6.0f - 2.0f * b) / 6.0f;
+ float p2 = (-18.0f + 12.0f * b + 6.0f * c) / 6.0f;
+ float p3 = (12.0f - 9.0f * b - 6.0f * c) / 6.0f;
+ float q0 = (8.0f * b + 24.0f * c) / 6.0f;
+ float q1 = (-12.0f * b - 48.0f * c) / 6.0f;
+ float q2 = (6.0f * b + 30.0f * c) / 6.0f;
+ float q3 = (-b - 6.0f * c) / 6.0f;
+
+ if (x < -2.0f)
+ return 0.0f;
+ if (x < -1.0f)
+ return (q0 - x * (q1 - x * (q2 - x * q3)));
+ if (x < 0.0f)
+ return (p0 + x * x * (p2 - x * p3));
+ if (x < 1.0f)
+ return (p0 + x * x * (p2 + x * p3));
+ if (x < 2.0f)
+ return (q0 + x * (q1 + x * (q2 + x * q3)));
+ return 0.0f;
}
/* x ranges from -1 to 1 */
float RE_filter_value(int type, float x)
{
- float gaussfac = 1.6f;
+ float gaussfac = 1.6f;
- x = ABS(x);
+ x = ABS(x);
- switch (type) {
- case R_FILTER_BOX:
- if (x > 1.0f) return 0.0f;
- return 1.0f;
+ switch (type) {
+ case R_FILTER_BOX:
+ if (x > 1.0f)
+ return 0.0f;
+ return 1.0f;
- case R_FILTER_TENT:
- if (x > 1.0f) return 0.0f;
- return 1.0f - x;
+ case R_FILTER_TENT:
+ if (x > 1.0f)
+ return 0.0f;
+ return 1.0f - x;
- case R_FILTER_GAUSS:
- {
- const float two_gaussfac2 = 2.0f * gaussfac * gaussfac;
- x *= 3.0f * gaussfac;
- return 1.0f / sqrtf((float)M_PI * two_gaussfac2) * expf(-x * x / two_gaussfac2);
- }
+ case R_FILTER_GAUSS: {
+ const float two_gaussfac2 = 2.0f * gaussfac * gaussfac;
+ x *= 3.0f * gaussfac;
+ return 1.0f / sqrtf((float)M_PI * two_gaussfac2) * expf(-x * x / two_gaussfac2);
+ }
- case R_FILTER_MITCH:
- return filt_mitchell(x * gaussfac);
+ case R_FILTER_MITCH:
+ return filt_mitchell(x * gaussfac);
- case R_FILTER_QUAD:
- return filt_quadratic(x * gaussfac);
+ case R_FILTER_QUAD:
+ return filt_quadratic(x * gaussfac);
- case R_FILTER_CUBIC:
- return filt_cubic(x * gaussfac);
+ case R_FILTER_CUBIC:
+ return filt_cubic(x * gaussfac);
- case R_FILTER_CATROM:
- return filt_catrom(x * gaussfac);
- }
- return 0.0f;
+ case R_FILTER_CATROM:
+ return filt_catrom(x * gaussfac);
+ }
+ return 0.0f;
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
struct Object *RE_GetCamera(Render *re)
{
- Object *camera = re->camera_override ? re->camera_override : re->scene->camera;
- return BKE_camera_multiview_render(re->scene, camera, re->viewname);
+ Object *camera = re->camera_override ? re->camera_override : re->scene->camera;
+ return BKE_camera_multiview_render(re->scene, camera, re->viewname);
}
static void re_camera_params_get(Render *re, CameraParams *params)
{
- copy_m4_m4(re->winmat, params->winmat);
+ copy_m4_m4(re->winmat, params->winmat);
- re->clip_start = params->clip_start;
- re->clip_end = params->clip_end;
+ re->clip_start = params->clip_start;
+ re->clip_end = params->clip_end;
- re->viewplane = params->viewplane;
+ re->viewplane = params->viewplane;
}
void RE_SetOverrideCamera(Render *re, Object *camera)
{
- re->camera_override = camera;
+ re->camera_override = camera;
}
static void re_camera_params_stereo3d(Render *re, CameraParams *params, Object *cam_ob)
{
- BKE_camera_multiview_params(&re->r, params, cam_ob, re->viewname);
+ BKE_camera_multiview_params(&re->r, params, cam_ob, re->viewname);
}
/* call this after InitState() */
/* per render, there's one persistent viewplane. Parts will set their own viewplanes */
void RE_SetCamera(Render *re, Object *cam_ob)
{
- CameraParams params;
+ CameraParams params;
- /* setup parameters */
- BKE_camera_params_init(&params);
- BKE_camera_params_from_object(&params, cam_ob);
- re_camera_params_stereo3d(re, &params, cam_ob);
+ /* setup parameters */
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_object(&params, cam_ob);
+ re_camera_params_stereo3d(re, &params, cam_ob);
- /* compute matrix, viewplane, .. */
- BKE_camera_params_compute_viewplane(&params, re->winx, re->winy, re->r.xasp, re->r.yasp);
- BKE_camera_params_compute_matrix(&params);
+ /* compute matrix, viewplane, .. */
+ BKE_camera_params_compute_viewplane(&params, re->winx, re->winy, re->r.xasp, re->r.yasp);
+ BKE_camera_params_compute_matrix(&params);
- /* extract results */
- re_camera_params_get(re, &params);
+ /* extract results */
+ re_camera_params_get(re, &params);
}
void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[4][4])
{
- re->r.cfra = frame;
- RE_SetCamera(re, camera);
- copy_m4_m4(mat, re->winmat);
+ re->r.cfra = frame;
+ RE_SetCamera(re, camera);
+ copy_m4_m4(mat, re->winmat);
}
/* Must be called after RE_GetCameraWindow(), does not change re->winmat. */
void RE_GetCameraWindowWithOverscan(struct Render *re, float mat[4][4], float overscan)
{
- CameraParams params;
- params.is_ortho = re->winmat[3][3] != 0.0f;
- params.clip_start = re->clip_start;
- params.clip_end = re->clip_end;
- params.viewplane = re->viewplane;
-
- overscan *= max_ff(BLI_rctf_size_x(&params.viewplane), BLI_rctf_size_y(&params.viewplane));
-
- params.viewplane.xmin -= overscan;
- params.viewplane.xmax += overscan;
- params.viewplane.ymin -= overscan;
- params.viewplane.ymax += overscan;
- BKE_camera_params_compute_matrix(&params);
- copy_m4_m4(mat, params.winmat);
+ CameraParams params;
+ params.is_ortho = re->winmat[3][3] != 0.0f;
+ params.clip_start = re->clip_start;
+ params.clip_end = re->clip_end;
+ params.viewplane = re->viewplane;
+
+ overscan *= max_ff(BLI_rctf_size_x(&params.viewplane), BLI_rctf_size_y(&params.viewplane));
+
+ params.viewplane.xmin -= overscan;
+ params.viewplane.xmax += overscan;
+ params.viewplane.ymin -= overscan;
+ params.viewplane.ymax += overscan;
+ BKE_camera_params_compute_matrix(&params);
+ copy_m4_m4(mat, params.winmat);
}
void RE_GetCameraModelMatrix(Render *re, struct Object *camera, float r_mat[4][4])
{
- BKE_camera_multiview_model_matrix(&re->r, camera, re->viewname, r_mat);
+ BKE_camera_multiview_model_matrix(&re->r, camera, re->viewname, r_mat);
}
/* ~~~~~~~~~~~~~~~~ part (tile) calculus ~~~~~~~~~~~~~~~~~~~~~~ */
-
void RE_parts_free(Render *re)
{
- BLI_freelistN(&re->parts);
+ BLI_freelistN(&re->parts);
}
void RE_parts_clamp(Render *re)
{
- /* part size */
- re->partx = max_ii(1, min_ii(re->r.tilex, re->rectx));
- re->party = max_ii(1, min_ii(re->r.tiley, re->recty));
+ /* part size */
+ re->partx = max_ii(1, min_ii(re->r.tilex, re->rectx));
+ re->party = max_ii(1, min_ii(re->r.tiley, re->recty));
}
void RE_parts_init(Render *re)
{
- int nr, xd, yd, partx, party, xparts, yparts;
- int xminb, xmaxb, yminb, ymaxb;
-
- RE_parts_free(re);
-
- /* this is render info for caller, is not reset when parts are freed! */
- re->i.totpart = 0;
- re->i.curpart = 0;
- re->i.partsdone = 0;
-
- /* just for readable code.. */
- xminb = re->disprect.xmin;
- yminb = re->disprect.ymin;
- xmaxb = re->disprect.xmax;
- ymaxb = re->disprect.ymax;
-
- RE_parts_clamp(re);
-
- partx = re->partx;
- party = re->party;
- /* part count */
- xparts = (re->rectx + partx - 1) / partx;
- yparts = (re->recty + party - 1) / party;
-
- for (nr = 0; nr < xparts * yparts; nr++) {
- rcti disprect;
- int rectx, recty;
-
- xd = (nr % xparts);
- yd = (nr - xd) / xparts;
-
- disprect.xmin = xminb + xd * partx;
- disprect.ymin = yminb + yd * party;
-
- /* ensure we cover the entire picture, so last parts go to end */
- if (xd < xparts - 1) {
- disprect.xmax = disprect.xmin + partx;
- if (disprect.xmax > xmaxb)
- disprect.xmax = xmaxb;
- }
- else disprect.xmax = xmaxb;
-
- if (yd < yparts - 1) {
- disprect.ymax = disprect.ymin + party;
- if (disprect.ymax > ymaxb)
- disprect.ymax = ymaxb;
- }
- else disprect.ymax = ymaxb;
-
- rectx = BLI_rcti_size_x(&disprect);
- recty = BLI_rcti_size_y(&disprect);
-
- /* so, now can we add this part? */
- if (rectx > 0 && recty > 0) {
- RenderPart *pa = MEM_callocN(sizeof(RenderPart), "new part");
-
- pa->disprect = disprect;
- pa->rectx = rectx;
- pa->recty = recty;
-
- BLI_addtail(&re->parts, pa);
- re->i.totpart++;
- }
- }
+ int nr, xd, yd, partx, party, xparts, yparts;
+ int xminb, xmaxb, yminb, ymaxb;
+
+ RE_parts_free(re);
+
+ /* this is render info for caller, is not reset when parts are freed! */
+ re->i.totpart = 0;
+ re->i.curpart = 0;
+ re->i.partsdone = 0;
+
+ /* just for readable code.. */
+ xminb = re->disprect.xmin;
+ yminb = re->disprect.ymin;
+ xmaxb = re->disprect.xmax;
+ ymaxb = re->disprect.ymax;
+
+ RE_parts_clamp(re);
+
+ partx = re->partx;
+ party = re->party;
+ /* part count */
+ xparts = (re->rectx + partx - 1) / partx;
+ yparts = (re->recty + party - 1) / party;
+
+ for (nr = 0; nr < xparts * yparts; nr++) {
+ rcti disprect;
+ int rectx, recty;
+
+ xd = (nr % xparts);
+ yd = (nr - xd) / xparts;
+
+ disprect.xmin = xminb + xd * partx;
+ disprect.ymin = yminb + yd * party;
+
+ /* ensure we cover the entire picture, so last parts go to end */
+ if (xd < xparts - 1) {
+ disprect.xmax = disprect.xmin + partx;
+ if (disprect.xmax > xmaxb)
+ disprect.xmax = xmaxb;
+ }
+ else
+ disprect.xmax = xmaxb;
+
+ if (yd < yparts - 1) {
+ disprect.ymax = disprect.ymin + party;
+ if (disprect.ymax > ymaxb)
+ disprect.ymax = ymaxb;
+ }
+ else
+ disprect.ymax = ymaxb;
+
+ rectx = BLI_rcti_size_x(&disprect);
+ recty = BLI_rcti_size_y(&disprect);
+
+ /* so, now can we add this part? */
+ if (rectx > 0 && recty > 0) {
+ RenderPart *pa = MEM_callocN(sizeof(RenderPart), "new part");
+
+ pa->disprect = disprect;
+ pa->rectx = rectx;
+ pa->recty = recty;
+
+ BLI_addtail(&re->parts, pa);
+ re->i.totpart++;
+ }
+ }
}
diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c
index 8a8e4bbbb2a..1358b7a9438 100644
--- a/source/blender/render/intern/source/multires_bake.c
+++ b/source/blender/render/intern/source/multires_bake.c
@@ -51,340 +51,377 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-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 (*MFreeBakeData)(void *bake_data);
+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 (*MFreeBakeData)(void *bake_data);
typedef struct MultiresBakeResult {
- float height_min, height_max;
+ float height_min, height_max;
} MultiresBakeResult;
typedef struct {
- MVert *mvert;
- MPoly *mpoly;
- MLoop *mloop;
- MLoopUV *mloopuv;
- const MLoopTri *mlooptri;
- float *pvtangent;
- const float *precomputed_normals;
- int w, h;
- int tri_index;
- DerivedMesh *lores_dm, *hires_dm;
- int lvl;
- void *thread_data;
- void *bake_data;
- ImBuf *ibuf;
- MPassKnownData pass_data;
- /* material aligned UV array */
- Image **image_array;
+ MVert *mvert;
+ MPoly *mpoly;
+ MLoop *mloop;
+ MLoopUV *mloopuv;
+ const MLoopTri *mlooptri;
+ float *pvtangent;
+ const float *precomputed_normals;
+ int w, h;
+ int tri_index;
+ DerivedMesh *lores_dm, *hires_dm;
+ int lvl;
+ void *thread_data;
+ void *bake_data;
+ ImBuf *ibuf;
+ MPassKnownData pass_data;
+ /* material aligned UV array */
+ Image **image_array;
} MResolvePixelData;
typedef void (*MFlushPixel)(const MResolvePixelData *data, const int x, const int y);
typedef struct {
- int w, h;
- char *texels;
- const MResolvePixelData *data;
- MFlushPixel flush_pixel;
- short *do_update;
+ int w, h;
+ char *texels;
+ const MResolvePixelData *data;
+ MFlushPixel flush_pixel;
+ short *do_update;
} MBakeRast;
typedef struct {
- float *heights;
- Image *ima;
- DerivedMesh *ssdm;
- const int *orig_index_mp_to_orig;
+ float *heights;
+ Image *ima;
+ DerivedMesh *ssdm;
+ const int *orig_index_mp_to_orig;
} MHeightBakeData;
typedef struct {
- const int *orig_index_mp_to_orig;
+ const int *orig_index_mp_to_orig;
} MNormalBakeData;
-static void multiresbake_get_normal(const MResolvePixelData *data, float norm[], const int tri_num, const int vert_index)
+static void multiresbake_get_normal(const MResolvePixelData *data,
+ float norm[],
+ const int tri_num,
+ const int vert_index)
{
- const int poly_index = data->mlooptri[tri_num].poly;
- const MPoly *mp = &data->mpoly[poly_index];
- const bool smoothnormal = (mp->flag & ME_SMOOTH) != 0;
-
- if (!smoothnormal) { /* flat */
- if (data->precomputed_normals) {
- copy_v3_v3(norm, &data->precomputed_normals[poly_index]);
- }
- else {
- BKE_mesh_calc_poly_normal(mp, &data->mloop[mp->loopstart], data->mvert, norm);
- }
- }
- else {
- const int vi = data->mloop[data->mlooptri[tri_num].tri[vert_index]].v;
- const short *no = data->mvert[vi].no;
-
- normal_short_to_float_v3(norm, no);
- normalize_v3(norm);
- }
+ const int poly_index = data->mlooptri[tri_num].poly;
+ const MPoly *mp = &data->mpoly[poly_index];
+ const bool smoothnormal = (mp->flag & ME_SMOOTH) != 0;
+
+ if (!smoothnormal) { /* flat */
+ if (data->precomputed_normals) {
+ copy_v3_v3(norm, &data->precomputed_normals[poly_index]);
+ }
+ else {
+ BKE_mesh_calc_poly_normal(mp, &data->mloop[mp->loopstart], data->mvert, norm);
+ }
+ }
+ else {
+ const int vi = data->mloop[data->mlooptri[tri_num].tri[vert_index]].v;
+ const short *no = data->mvert[vi].no;
+
+ normal_short_to_float_v3(norm, no);
+ normalize_v3(norm);
+ }
}
-static void init_bake_rast(MBakeRast *bake_rast, const ImBuf *ibuf, const MResolvePixelData *data,
- MFlushPixel flush_pixel, short *do_update)
+static void init_bake_rast(MBakeRast *bake_rast,
+ const ImBuf *ibuf,
+ const MResolvePixelData *data,
+ MFlushPixel flush_pixel,
+ short *do_update)
{
- BakeImBufuserData *userdata = (BakeImBufuserData *)ibuf->userdata;
+ BakeImBufuserData *userdata = (BakeImBufuserData *)ibuf->userdata;
- memset(bake_rast, 0, sizeof(MBakeRast));
+ memset(bake_rast, 0, sizeof(MBakeRast));
- bake_rast->texels = userdata->mask_buffer;
- bake_rast->w = ibuf->x;
- bake_rast->h = ibuf->y;
- bake_rast->data = data;
- bake_rast->flush_pixel = flush_pixel;
- bake_rast->do_update = do_update;
+ bake_rast->texels = userdata->mask_buffer;
+ bake_rast->w = ibuf->x;
+ bake_rast->h = ibuf->y;
+ bake_rast->data = data;
+ bake_rast->flush_pixel = flush_pixel;
+ bake_rast->do_update = do_update;
}
static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
{
- float st[2] = {(x + 0.5f) / data->w, (y + 0.5f) / data->h};
- const float *st0, *st1, *st2;
- const float *tang0, *tang1, *tang2;
- float no0[3], no1[3], no2[3];
- float fUV[2], from_tang[3][3], to_tang[3][3];
- float u, v, w, sign;
- int r;
-
- st0 = data->mloopuv[data->mlooptri[data->tri_index].tri[0]].uv;
- st1 = data->mloopuv[data->mlooptri[data->tri_index].tri[1]].uv;
- st2 = data->mloopuv[data->mlooptri[data->tri_index].tri[2]].uv;
-
- multiresbake_get_normal(data, no0, data->tri_index, 0); /* can optimize these 3 into one call */
- multiresbake_get_normal(data, no1, data->tri_index, 1);
- multiresbake_get_normal(data, no2, data->tri_index, 2);
-
- resolve_tri_uv_v2(fUV, st, st0, st1, st2);
-
- u = fUV[0];
- v = fUV[1];
- w = 1 - u - v;
-
- if (data->pvtangent) {
- tang0 = data->pvtangent + data->mlooptri[data->tri_index].tri[0] * 4;
- tang1 = data->pvtangent + data->mlooptri[data->tri_index].tri[1] * 4;
- tang2 = data->pvtangent + data->mlooptri[data->tri_index].tri[2] * 4;
-
- /* the sign is the same at all face vertices for any non degenerate face.
- * Just in case we clamp the interpolated value though. */
- sign = (tang0[3] * u + tang1[3] * v + tang2[3] * w) < 0 ? (-1.0f) : 1.0f;
-
- /* this sequence of math is designed specifically as is with great care
- * to be compatible with our shader. Please don't change without good reason. */
- for (r = 0; r < 3; r++) {
- from_tang[0][r] = tang0[r] * u + tang1[r] * v + tang2[r] * w;
- from_tang[2][r] = no0[r] * u + no1[r] * v + no2[r] * w;
- }
-
- cross_v3_v3v3(from_tang[1], from_tang[2], from_tang[0]); /* B = sign * cross(N, T) */
- mul_v3_fl(from_tang[1], sign);
- invert_m3_m3(to_tang, from_tang);
- }
- else {
- zero_m3(to_tang);
- }
-
- data->pass_data(data->lores_dm, data->hires_dm, data->thread_data, data->bake_data,
- data->ibuf, data->tri_index, data->lvl, st, to_tang, x, y);
+ float st[2] = {(x + 0.5f) / data->w, (y + 0.5f) / data->h};
+ const float *st0, *st1, *st2;
+ const float *tang0, *tang1, *tang2;
+ float no0[3], no1[3], no2[3];
+ float fUV[2], from_tang[3][3], to_tang[3][3];
+ float u, v, w, sign;
+ int r;
+
+ st0 = data->mloopuv[data->mlooptri[data->tri_index].tri[0]].uv;
+ st1 = data->mloopuv[data->mlooptri[data->tri_index].tri[1]].uv;
+ st2 = data->mloopuv[data->mlooptri[data->tri_index].tri[2]].uv;
+
+ multiresbake_get_normal(data, no0, data->tri_index, 0); /* can optimize these 3 into one call */
+ multiresbake_get_normal(data, no1, data->tri_index, 1);
+ multiresbake_get_normal(data, no2, data->tri_index, 2);
+
+ resolve_tri_uv_v2(fUV, st, st0, st1, st2);
+
+ u = fUV[0];
+ v = fUV[1];
+ w = 1 - u - v;
+
+ if (data->pvtangent) {
+ tang0 = data->pvtangent + data->mlooptri[data->tri_index].tri[0] * 4;
+ tang1 = data->pvtangent + data->mlooptri[data->tri_index].tri[1] * 4;
+ tang2 = data->pvtangent + data->mlooptri[data->tri_index].tri[2] * 4;
+
+ /* the sign is the same at all face vertices for any non degenerate face.
+ * Just in case we clamp the interpolated value though. */
+ sign = (tang0[3] * u + tang1[3] * v + tang2[3] * w) < 0 ? (-1.0f) : 1.0f;
+
+ /* this sequence of math is designed specifically as is with great care
+ * to be compatible with our shader. Please don't change without good reason. */
+ for (r = 0; r < 3; r++) {
+ from_tang[0][r] = tang0[r] * u + tang1[r] * v + tang2[r] * w;
+ from_tang[2][r] = no0[r] * u + no1[r] * v + no2[r] * w;
+ }
+
+ cross_v3_v3v3(from_tang[1], from_tang[2], from_tang[0]); /* B = sign * cross(N, T) */
+ mul_v3_fl(from_tang[1], sign);
+ invert_m3_m3(to_tang, from_tang);
+ }
+ else {
+ zero_m3(to_tang);
+ }
+
+ data->pass_data(data->lores_dm,
+ data->hires_dm,
+ data->thread_data,
+ data->bake_data,
+ data->ibuf,
+ data->tri_index,
+ data->lvl,
+ st,
+ to_tang,
+ x,
+ y);
}
static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int y)
{
- const int w = bake_rast->w;
- const int h = bake_rast->h;
-
- if (x >= 0 && x < w && y >= 0 && y < h) {
- if ((bake_rast->texels[y * w + x]) == 0) {
- bake_rast->texels[y * w + x] = FILTER_MASK_USED;
- flush_pixel(bake_rast->data, x, y);
- if (bake_rast->do_update) {
- *bake_rast->do_update = true;
- }
- }
- }
+ const int w = bake_rast->w;
+ const int h = bake_rast->h;
+
+ if (x >= 0 && x < w && y >= 0 && y < h) {
+ if ((bake_rast->texels[y * w + x]) == 0) {
+ bake_rast->texels[y * w + x] = FILTER_MASK_USED;
+ flush_pixel(bake_rast->data, x, y);
+ if (bake_rast->do_update) {
+ *bake_rast->do_update = true;
+ }
+ }
+ }
}
static void rasterize_half(const MBakeRast *bake_rast,
- const float s0_s, const float t0_s, const float s1_s, const float t1_s,
- const float s0_l, const float t0_l, const float s1_l, const float t1_l,
- const int y0_in, const int y1_in, const int is_mid_right)
+ const float s0_s,
+ const float t0_s,
+ const float s1_s,
+ const float t1_s,
+ const float s0_l,
+ const float t0_l,
+ const float s1_l,
+ const float t1_l,
+ const int y0_in,
+ const int y1_in,
+ const int is_mid_right)
{
- const int s_stable = fabsf(t1_s - t0_s) > FLT_EPSILON ? 1 : 0;
- const int l_stable = fabsf(t1_l - t0_l) > FLT_EPSILON ? 1 : 0;
- const int w = bake_rast->w;
- const int h = bake_rast->h;
- int y, y0, y1;
-
- if (y1_in <= 0 || y0_in >= h)
- return;
-
- y0 = y0_in < 0 ? 0 : y0_in;
- y1 = y1_in >= h ? h : y1_in;
-
- for (y = y0; y < y1; y++) {
- /*-b(x-x0) + a(y-y0) = 0 */
- int iXl, iXr, x;
- float x_l = s_stable != 0 ? (s0_s + (((s1_s - s0_s) * (y - t0_s)) / (t1_s - t0_s))) : s0_s;
- float x_r = l_stable != 0 ? (s0_l + (((s1_l - s0_l) * (y - t0_l)) / (t1_l - t0_l))) : s0_l;
-
- if (is_mid_right != 0)
- SWAP(float, x_l, x_r);
-
- iXl = (int)ceilf(x_l);
- iXr = (int)ceilf(x_r);
-
- if (iXr > 0 && iXl < w) {
- iXl = iXl < 0 ? 0 : iXl;
- iXr = iXr >= w ? w : iXr;
-
- for (x = iXl; x < iXr; x++)
- set_rast_triangle(bake_rast, x, y);
- }
- }
+ const int s_stable = fabsf(t1_s - t0_s) > FLT_EPSILON ? 1 : 0;
+ const int l_stable = fabsf(t1_l - t0_l) > FLT_EPSILON ? 1 : 0;
+ const int w = bake_rast->w;
+ const int h = bake_rast->h;
+ int y, y0, y1;
+
+ if (y1_in <= 0 || y0_in >= h)
+ return;
+
+ y0 = y0_in < 0 ? 0 : y0_in;
+ y1 = y1_in >= h ? h : y1_in;
+
+ for (y = y0; y < y1; y++) {
+ /*-b(x-x0) + a(y-y0) = 0 */
+ int iXl, iXr, x;
+ float x_l = s_stable != 0 ? (s0_s + (((s1_s - s0_s) * (y - t0_s)) / (t1_s - t0_s))) : s0_s;
+ float x_r = l_stable != 0 ? (s0_l + (((s1_l - s0_l) * (y - t0_l)) / (t1_l - t0_l))) : s0_l;
+
+ if (is_mid_right != 0)
+ SWAP(float, x_l, x_r);
+
+ iXl = (int)ceilf(x_l);
+ iXr = (int)ceilf(x_r);
+
+ if (iXr > 0 && iXl < w) {
+ iXl = iXl < 0 ? 0 : iXl;
+ iXr = iXr >= w ? w : iXr;
+
+ for (x = iXl; x < iXr; x++)
+ set_rast_triangle(bake_rast, x, y);
+ }
+ }
}
-static void bake_rasterize(const MBakeRast *bake_rast, const float st0_in[2], const float st1_in[2], const float st2_in[2])
+static void bake_rasterize(const MBakeRast *bake_rast,
+ const float st0_in[2],
+ const float st1_in[2],
+ const float st2_in[2])
{
- const int w = bake_rast->w;
- const int h = bake_rast->h;
- float slo = st0_in[0] * w - 0.5f;
- float tlo = st0_in[1] * h - 0.5f;
- float smi = st1_in[0] * w - 0.5f;
- float tmi = st1_in[1] * h - 0.5f;
- float shi = st2_in[0] * w - 0.5f;
- float thi = st2_in[1] * h - 0.5f;
- int is_mid_right = 0, ylo, yhi, yhi_beg;
-
- /* skip degenerates */
- if ((slo == smi && tlo == tmi) || (slo == shi && tlo == thi) || (smi == shi && tmi == thi))
- return;
-
- /* sort by T */
- if (tlo > tmi && tlo > thi) {
- SWAP(float, shi, slo);
- SWAP(float, thi, tlo);
- }
- else if (tmi > thi) {
- SWAP(float, shi, smi);
- SWAP(float, thi, tmi);
- }
-
- if (tlo > tmi) {
- SWAP(float, slo, smi);
- SWAP(float, tlo, tmi);
- }
-
- /* check if mid point is to the left or to the right of the lo-hi edge */
- is_mid_right = (-(shi - slo) * (tmi - thi) + (thi - tlo) * (smi - shi)) > 0 ? 1 : 0;
- ylo = (int)ceilf(tlo);
- yhi_beg = (int)ceilf(tmi);
- yhi = (int)ceilf(thi);
-
- /*if (fTmi>ceilf(fTlo))*/
- rasterize_half(bake_rast, slo, tlo, smi, tmi, slo, tlo, shi, thi, ylo, yhi_beg, is_mid_right);
- rasterize_half(bake_rast, smi, tmi, shi, thi, slo, tlo, shi, thi, yhi_beg, yhi, is_mid_right);
+ const int w = bake_rast->w;
+ const int h = bake_rast->h;
+ float slo = st0_in[0] * w - 0.5f;
+ float tlo = st0_in[1] * h - 0.5f;
+ float smi = st1_in[0] * w - 0.5f;
+ float tmi = st1_in[1] * h - 0.5f;
+ float shi = st2_in[0] * w - 0.5f;
+ float thi = st2_in[1] * h - 0.5f;
+ int is_mid_right = 0, ylo, yhi, yhi_beg;
+
+ /* skip degenerates */
+ if ((slo == smi && tlo == tmi) || (slo == shi && tlo == thi) || (smi == shi && tmi == thi))
+ return;
+
+ /* sort by T */
+ if (tlo > tmi && tlo > thi) {
+ SWAP(float, shi, slo);
+ SWAP(float, thi, tlo);
+ }
+ else if (tmi > thi) {
+ SWAP(float, shi, smi);
+ SWAP(float, thi, tmi);
+ }
+
+ if (tlo > tmi) {
+ SWAP(float, slo, smi);
+ SWAP(float, tlo, tmi);
+ }
+
+ /* check if mid point is to the left or to the right of the lo-hi edge */
+ is_mid_right = (-(shi - slo) * (tmi - thi) + (thi - tlo) * (smi - shi)) > 0 ? 1 : 0;
+ ylo = (int)ceilf(tlo);
+ yhi_beg = (int)ceilf(tmi);
+ yhi = (int)ceilf(thi);
+
+ /*if (fTmi>ceilf(fTlo))*/
+ rasterize_half(bake_rast, slo, tlo, smi, tmi, slo, tlo, shi, thi, ylo, yhi_beg, is_mid_right);
+ rasterize_half(bake_rast, smi, tmi, shi, thi, slo, tlo, shi, thi, yhi_beg, yhi, is_mid_right);
}
static int multiresbake_test_break(MultiresBakeRender *bkr)
{
- if (!bkr->stop) {
- /* this means baker is executed outside from job system */
- return 0;
- }
+ if (!bkr->stop) {
+ /* this means baker is executed outside from job system */
+ return 0;
+ }
- return *bkr->stop || G.is_break;
+ return *bkr->stop || G.is_break;
}
/* **** Threading routines **** */
typedef struct MultiresBakeQueue {
- int cur_tri;
- int tot_tri;
- SpinLock spin;
+ int cur_tri;
+ int tot_tri;
+ SpinLock spin;
} MultiresBakeQueue;
typedef struct MultiresBakeThread {
- /* this data is actually shared between all the threads */
- MultiresBakeQueue *queue;
- MultiresBakeRender *bkr;
- Image *image;
- void *bake_data;
-
- /* thread-specific data */
- MBakeRast bake_rast;
- MResolvePixelData data;
-
- /* displacement-specific data */
- float height_min, height_max;
+ /* this data is actually shared between all the threads */
+ MultiresBakeQueue *queue;
+ MultiresBakeRender *bkr;
+ Image *image;
+ void *bake_data;
+
+ /* thread-specific data */
+ MBakeRast bake_rast;
+ MResolvePixelData data;
+
+ /* displacement-specific data */
+ float height_min, height_max;
} MultiresBakeThread;
static int multires_bake_queue_next_tri(MultiresBakeQueue *queue)
{
- int face = -1;
+ int face = -1;
- /* TODO: it could worth making it so thread will handle neighbor faces
- * for better memory cache utilization
- */
+ /* TODO: it could worth making it so thread will handle neighbor faces
+ * for better memory cache utilization
+ */
- BLI_spin_lock(&queue->spin);
- if (queue->cur_tri < queue->tot_tri) {
- face = queue->cur_tri;
- queue->cur_tri++;
- }
- BLI_spin_unlock(&queue->spin);
+ BLI_spin_lock(&queue->spin);
+ if (queue->cur_tri < queue->tot_tri) {
+ face = queue->cur_tri;
+ queue->cur_tri++;
+ }
+ BLI_spin_unlock(&queue->spin);
- return face;
+ return face;
}
static void *do_multires_bake_thread(void *data_v)
{
- MultiresBakeThread *handle = (MultiresBakeThread *)data_v;
- MResolvePixelData *data = &handle->data;
- MBakeRast *bake_rast = &handle->bake_rast;
- MultiresBakeRender *bkr = handle->bkr;
- int tri_index;
+ MultiresBakeThread *handle = (MultiresBakeThread *)data_v;
+ MResolvePixelData *data = &handle->data;
+ MBakeRast *bake_rast = &handle->bake_rast;
+ MultiresBakeRender *bkr = handle->bkr;
+ int tri_index;
- while ((tri_index = multires_bake_queue_next_tri(handle->queue)) >= 0) {
- const MLoopTri *lt = &data->mlooptri[tri_index];
- const MPoly *mp = &data->mpoly[lt->poly];
- const short mat_nr = mp->mat_nr;
- const MLoopUV *mloopuv = data->mloopuv;
+ while ((tri_index = multires_bake_queue_next_tri(handle->queue)) >= 0) {
+ const MLoopTri *lt = &data->mlooptri[tri_index];
+ const MPoly *mp = &data->mpoly[lt->poly];
+ const short mat_nr = mp->mat_nr;
+ const MLoopUV *mloopuv = data->mloopuv;
- if (multiresbake_test_break(bkr))
- break;
+ if (multiresbake_test_break(bkr))
+ break;
- Image *tri_image = mat_nr < bkr->ob_image.len ? bkr->ob_image.array[mat_nr] : NULL;
- if (tri_image != handle->image)
- continue;
+ Image *tri_image = mat_nr < bkr->ob_image.len ? bkr->ob_image.array[mat_nr] : NULL;
+ if (tri_image != handle->image)
+ continue;
- data->tri_index = tri_index;
+ data->tri_index = tri_index;
- bake_rasterize(bake_rast, mloopuv[lt->tri[0]].uv, mloopuv[lt->tri[1]].uv, mloopuv[lt->tri[2]].uv);
+ bake_rasterize(
+ bake_rast, mloopuv[lt->tri[0]].uv, mloopuv[lt->tri[1]].uv, mloopuv[lt->tri[2]].uv);
- /* tag image buffer for refresh */
- if (data->ibuf->rect_float)
- data->ibuf->userflags |= IB_RECT_INVALID;
+ /* tag image buffer for refresh */
+ if (data->ibuf->rect_float)
+ data->ibuf->userflags |= IB_RECT_INVALID;
- data->ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ data->ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
- /* update progress */
- BLI_spin_lock(&handle->queue->spin);
- bkr->baked_faces++;
+ /* update progress */
+ BLI_spin_lock(&handle->queue->spin);
+ bkr->baked_faces++;
- if (bkr->do_update)
- *bkr->do_update = true;
+ if (bkr->do_update)
+ *bkr->do_update = true;
- if (bkr->progress)
- *bkr->progress = ((float)bkr->baked_objects + (float)bkr->baked_faces / handle->queue->tot_tri) / bkr->tot_obj;
- BLI_spin_unlock(&handle->queue->spin);
- }
+ if (bkr->progress)
+ *bkr->progress = ((float)bkr->baked_objects +
+ (float)bkr->baked_faces / handle->queue->tot_tri) /
+ bkr->tot_obj;
+ BLI_spin_unlock(&handle->queue->spin);
+ }
- return NULL;
+ return NULL;
}
/* some of arrays inside ccgdm are lazy-initialized, which will generally
@@ -393,313 +430,347 @@ static void *do_multires_bake_thread(void *data_v)
*/
static void init_ccgdm_arrays(DerivedMesh *dm)
{
- CCGElem **grid_data;
- CCGKey key;
- int grid_size;
- const 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;
+ CCGElem **grid_data;
+ CCGKey key;
+ int grid_size;
+ const 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, bool require_tangent, MPassKnownData passKnownData,
- MInitBakeData initBakeData, MFreeBakeData freeBakeData, MultiresBakeResult *result)
+static void do_multires_bake(MultiresBakeRender *bkr,
+ Image *ima,
+ bool require_tangent,
+ MPassKnownData passKnownData,
+ MInitBakeData initBakeData,
+ MFreeBakeData freeBakeData,
+ MultiresBakeResult *result)
{
- DerivedMesh *dm = bkr->lores_dm;
- const MLoopTri *mlooptri = dm->getLoopTriArray(dm);
- const int lvl = bkr->lvl;
- int tot_tri = dm->getNumLoopTri(dm);
-
- if (tot_tri > 0) {
- MultiresBakeThread *handles;
- MultiresBakeQueue queue;
-
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- MVert *mvert = dm->getVertArray(dm);
- MPoly *mpoly = dm->getPolyArray(dm);
- MLoop *mloop = dm->getLoopArray(dm);
- MLoopUV *mloopuv = dm->getLoopDataArray(dm, CD_MLOOPUV);
- const float *precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL);
- float *pvtangent = NULL;
-
- ListBase threads;
- int i, tot_thread = bkr->threads > 0 ? bkr->threads : BLI_system_thread_count();
-
- void *bake_data = NULL;
-
- if (require_tangent) {
- if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1)
- DM_calc_loop_tangents(dm, true, NULL, 0);
-
- pvtangent = DM_get_loop_data_layer(dm, CD_TANGENT);
- }
-
- /* all threads shares the same custom bake data */
- if (initBakeData)
- bake_data = initBakeData(bkr, ima);
-
- if (tot_thread > 1)
- BLI_threadpool_init(&threads, do_multires_bake_thread, tot_thread);
-
- handles = MEM_callocN(tot_thread * sizeof(MultiresBakeThread), "do_multires_bake handles");
-
- init_ccgdm_arrays(bkr->hires_dm);
-
- /* faces queue */
- queue.cur_tri = 0;
- queue.tot_tri = tot_tri;
- BLI_spin_init(&queue.spin);
-
- /* fill in threads handles */
- for (i = 0; i < tot_thread; i++) {
- MultiresBakeThread *handle = &handles[i];
-
- handle->bkr = bkr;
- handle->image = ima;
- handle->queue = &queue;
-
- handle->data.mpoly = mpoly;
- handle->data.mvert = mvert;
- handle->data.mloopuv = mloopuv;
- handle->data.mlooptri = mlooptri;
- handle->data.mloop = mloop;
- handle->data.pvtangent = pvtangent;
- handle->data.precomputed_normals = precomputed_normals; /* don't strictly need this */
- handle->data.w = ibuf->x;
- handle->data.h = ibuf->y;
- handle->data.lores_dm = dm;
- 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, bkr->do_update);
-
- if (tot_thread > 1)
- BLI_threadpool_insert(&threads, handle);
- }
-
- /* run threads */
- if (tot_thread > 1)
- BLI_threadpool_end(&threads);
- 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 (freeBakeData)
- freeBakeData(bake_data);
-
- MEM_freeN(handles);
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
+ DerivedMesh *dm = bkr->lores_dm;
+ const MLoopTri *mlooptri = dm->getLoopTriArray(dm);
+ const int lvl = bkr->lvl;
+ int tot_tri = dm->getNumLoopTri(dm);
+
+ if (tot_tri > 0) {
+ MultiresBakeThread *handles;
+ MultiresBakeQueue queue;
+
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ MVert *mvert = dm->getVertArray(dm);
+ MPoly *mpoly = dm->getPolyArray(dm);
+ MLoop *mloop = dm->getLoopArray(dm);
+ MLoopUV *mloopuv = dm->getLoopDataArray(dm, CD_MLOOPUV);
+ const float *precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL);
+ float *pvtangent = NULL;
+
+ ListBase threads;
+ int i, tot_thread = bkr->threads > 0 ? bkr->threads : BLI_system_thread_count();
+
+ void *bake_data = NULL;
+
+ if (require_tangent) {
+ if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1)
+ DM_calc_loop_tangents(dm, true, NULL, 0);
+
+ pvtangent = DM_get_loop_data_layer(dm, CD_TANGENT);
+ }
+
+ /* all threads shares the same custom bake data */
+ if (initBakeData)
+ bake_data = initBakeData(bkr, ima);
+
+ if (tot_thread > 1)
+ BLI_threadpool_init(&threads, do_multires_bake_thread, tot_thread);
+
+ handles = MEM_callocN(tot_thread * sizeof(MultiresBakeThread), "do_multires_bake handles");
+
+ init_ccgdm_arrays(bkr->hires_dm);
+
+ /* faces queue */
+ queue.cur_tri = 0;
+ queue.tot_tri = tot_tri;
+ BLI_spin_init(&queue.spin);
+
+ /* fill in threads handles */
+ for (i = 0; i < tot_thread; i++) {
+ MultiresBakeThread *handle = &handles[i];
+
+ handle->bkr = bkr;
+ handle->image = ima;
+ handle->queue = &queue;
+
+ handle->data.mpoly = mpoly;
+ handle->data.mvert = mvert;
+ handle->data.mloopuv = mloopuv;
+ handle->data.mlooptri = mlooptri;
+ handle->data.mloop = mloop;
+ handle->data.pvtangent = pvtangent;
+ handle->data.precomputed_normals = precomputed_normals; /* don't strictly need this */
+ handle->data.w = ibuf->x;
+ handle->data.h = ibuf->y;
+ handle->data.lores_dm = dm;
+ 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, bkr->do_update);
+
+ if (tot_thread > 1)
+ BLI_threadpool_insert(&threads, handle);
+ }
+
+ /* run threads */
+ if (tot_thread > 1)
+ BLI_threadpool_end(&threads);
+ 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 (freeBakeData)
+ freeBakeData(bake_data);
+
+ MEM_freeN(handles);
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
}
/* mode = 0: interpolate normals,
* mode = 1: interpolate coord */
-static void interp_bilinear_grid(CCGKey *key, CCGElem *grid, float crn_x, float crn_y, int mode, float res[3])
+static void interp_bilinear_grid(
+ CCGKey *key, CCGElem *grid, float crn_x, float crn_y, int mode, float res[3])
{
- int x0, x1, y0, y1;
- float u, v;
- float data[4][3];
-
- x0 = (int)crn_x;
- x1 = x0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (x0 + 1);
-
- y0 = (int)crn_y;
- y1 = y0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (y0 + 1);
-
- u = crn_x - x0;
- v = crn_y - y0;
-
- if (mode == 0) {
- copy_v3_v3(data[0], CCG_grid_elem_no(key, grid, x0, y0));
- copy_v3_v3(data[1], CCG_grid_elem_no(key, grid, x1, y0));
- copy_v3_v3(data[2], CCG_grid_elem_no(key, grid, x1, y1));
- copy_v3_v3(data[3], CCG_grid_elem_no(key, grid, x0, y1));
- }
- else {
- copy_v3_v3(data[0], CCG_grid_elem_co(key, grid, x0, y0));
- copy_v3_v3(data[1], CCG_grid_elem_co(key, grid, x1, y0));
- copy_v3_v3(data[2], CCG_grid_elem_co(key, grid, x1, y1));
- copy_v3_v3(data[3], CCG_grid_elem_co(key, grid, x0, y1));
- }
-
- interp_bilinear_quad_v3(data, u, v, res);
+ int x0, x1, y0, y1;
+ float u, v;
+ float data[4][3];
+
+ x0 = (int)crn_x;
+ x1 = x0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (x0 + 1);
+
+ y0 = (int)crn_y;
+ y1 = y0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (y0 + 1);
+
+ u = crn_x - x0;
+ v = crn_y - y0;
+
+ if (mode == 0) {
+ copy_v3_v3(data[0], CCG_grid_elem_no(key, grid, x0, y0));
+ copy_v3_v3(data[1], CCG_grid_elem_no(key, grid, x1, y0));
+ copy_v3_v3(data[2], CCG_grid_elem_no(key, grid, x1, y1));
+ copy_v3_v3(data[3], CCG_grid_elem_no(key, grid, x0, y1));
+ }
+ else {
+ copy_v3_v3(data[0], CCG_grid_elem_co(key, grid, x0, y0));
+ copy_v3_v3(data[1], CCG_grid_elem_co(key, grid, x1, y0));
+ copy_v3_v3(data[2], CCG_grid_elem_co(key, grid, x1, y1));
+ copy_v3_v3(data[3], CCG_grid_elem_co(key, grid, x0, y1));
+ }
+
+ interp_bilinear_quad_v3(data, u, v, res);
}
-static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm,
+static void get_ccgdm_data(DerivedMesh *lodm,
+ DerivedMesh *hidm,
const int *index_mp_to_orig,
- const int lvl, const MLoopTri *lt, const float u, const float v, float co[3], float n[3])
+ const int lvl,
+ const MLoopTri *lt,
+ const float u,
+ const float v,
+ float co[3],
+ float n[3])
{
- CCGElem **grid_data;
- CCGKey key;
- float crn_x, crn_y;
- int grid_size, S, face_side;
- int *grid_offset, g_index;
- int poly_index = lt->poly;
-
- grid_size = hidm->getGridSize(hidm);
- grid_data = hidm->getGridData(hidm);
- grid_offset = hidm->getGridOffset(hidm);
- hidm->getGridKey(hidm, &key);
-
- if (lvl == 0) {
- MPoly *mpoly;
- face_side = (grid_size << 1) - 1;
-
- mpoly = lodm->getPolyArray(lodm) + poly_index;
- g_index = grid_offset[poly_index];
- S = mdisp_rot_face_to_crn(lodm->getVertArray(lodm), mpoly, lodm->getLoopArray(lodm), lt, face_side, u * (face_side - 1), v * (face_side - 1), &crn_x, &crn_y);
- }
- else {
- /* number of faces per grid side */
- int polys_per_grid_side = (1 << (lvl - 1));
- /* get the original cage face index */
- int cage_face_index = index_mp_to_orig ? index_mp_to_orig[poly_index] : poly_index;
- /* local offset in total cage face grids
- * (1 << (2 * lvl)) is number of all polys for one cage face */
- int loc_cage_poly_offs = poly_index % (1 << (2 * lvl));
- /* local offset in the vertex grid itself */
- int cell_index = loc_cage_poly_offs % (polys_per_grid_side * polys_per_grid_side);
- int cell_side = (grid_size - 1) / polys_per_grid_side;
- /* row and column based on grid side */
- int row = cell_index / polys_per_grid_side;
- int col = cell_index % polys_per_grid_side;
-
- /* S is the vertex whose grid we are examining */
- S = poly_index / (1 << (2 * (lvl - 1))) - grid_offset[cage_face_index];
- /* get offset of grid data for original cage face */
- g_index = grid_offset[cage_face_index];
-
- crn_y = (row * cell_side) + u * cell_side;
- crn_x = (col * cell_side) + v * cell_side;
- }
-
- CLAMP(crn_x, 0.0f, grid_size);
- CLAMP(crn_y, 0.0f, grid_size);
-
- if (n != NULL)
- interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 0, n);
-
- if (co != NULL)
- interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 1, co);
+ CCGElem **grid_data;
+ CCGKey key;
+ float crn_x, crn_y;
+ int grid_size, S, face_side;
+ int *grid_offset, g_index;
+ int poly_index = lt->poly;
+
+ grid_size = hidm->getGridSize(hidm);
+ grid_data = hidm->getGridData(hidm);
+ grid_offset = hidm->getGridOffset(hidm);
+ hidm->getGridKey(hidm, &key);
+
+ if (lvl == 0) {
+ MPoly *mpoly;
+ face_side = (grid_size << 1) - 1;
+
+ mpoly = lodm->getPolyArray(lodm) + poly_index;
+ g_index = grid_offset[poly_index];
+ S = mdisp_rot_face_to_crn(lodm->getVertArray(lodm),
+ mpoly,
+ lodm->getLoopArray(lodm),
+ lt,
+ face_side,
+ u * (face_side - 1),
+ v * (face_side - 1),
+ &crn_x,
+ &crn_y);
+ }
+ else {
+ /* number of faces per grid side */
+ int polys_per_grid_side = (1 << (lvl - 1));
+ /* get the original cage face index */
+ int cage_face_index = index_mp_to_orig ? index_mp_to_orig[poly_index] : poly_index;
+ /* local offset in total cage face grids
+ * (1 << (2 * lvl)) is number of all polys for one cage face */
+ int loc_cage_poly_offs = poly_index % (1 << (2 * lvl));
+ /* local offset in the vertex grid itself */
+ int cell_index = loc_cage_poly_offs % (polys_per_grid_side * polys_per_grid_side);
+ int cell_side = (grid_size - 1) / polys_per_grid_side;
+ /* row and column based on grid side */
+ int row = cell_index / polys_per_grid_side;
+ int col = cell_index % polys_per_grid_side;
+
+ /* S is the vertex whose grid we are examining */
+ S = poly_index / (1 << (2 * (lvl - 1))) - grid_offset[cage_face_index];
+ /* get offset of grid data for original cage face */
+ g_index = grid_offset[cage_face_index];
+
+ crn_y = (row * cell_side) + u * cell_side;
+ crn_x = (col * cell_side) + v * cell_side;
+ }
+
+ CLAMP(crn_x, 0.0f, grid_size);
+ CLAMP(crn_y, 0.0f, grid_size);
+
+ if (n != NULL)
+ interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 0, n);
+
+ if (co != NULL)
+ interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 1, co);
}
/* mode = 0: interpolate normals,
* mode = 1: interpolate coord */
-static void interp_bilinear_mpoly(DerivedMesh *dm, MLoop *mloop, MPoly *mpoly, const float u, const float v, const int mode, float res[3])
+static void interp_bilinear_mpoly(DerivedMesh *dm,
+ MLoop *mloop,
+ MPoly *mpoly,
+ const float u,
+ const float v,
+ const int mode,
+ float res[3])
{
- float data[4][3];
-
- if (mode == 0) {
- dm->getVertNo(dm, mloop[mpoly->loopstart].v, data[0]);
- dm->getVertNo(dm, mloop[mpoly->loopstart + 1].v, data[1]);
- dm->getVertNo(dm, mloop[mpoly->loopstart + 2].v, data[2]);
- dm->getVertNo(dm, mloop[mpoly->loopstart + 3].v, data[3]);
- }
- else {
- dm->getVertCo(dm, mloop[mpoly->loopstart].v, data[0]);
- dm->getVertCo(dm, mloop[mpoly->loopstart + 1].v, data[1]);
- dm->getVertCo(dm, mloop[mpoly->loopstart + 2].v, data[2]);
- dm->getVertCo(dm, mloop[mpoly->loopstart + 3].v, data[3]);
- }
-
- interp_bilinear_quad_v3(data, u, v, res);
+ float data[4][3];
+
+ if (mode == 0) {
+ dm->getVertNo(dm, mloop[mpoly->loopstart].v, data[0]);
+ dm->getVertNo(dm, mloop[mpoly->loopstart + 1].v, data[1]);
+ dm->getVertNo(dm, mloop[mpoly->loopstart + 2].v, data[2]);
+ dm->getVertNo(dm, mloop[mpoly->loopstart + 3].v, data[3]);
+ }
+ else {
+ dm->getVertCo(dm, mloop[mpoly->loopstart].v, data[0]);
+ dm->getVertCo(dm, mloop[mpoly->loopstart + 1].v, data[1]);
+ dm->getVertCo(dm, mloop[mpoly->loopstart + 2].v, data[2]);
+ dm->getVertCo(dm, mloop[mpoly->loopstart + 3].v, data[3]);
+ }
+
+ interp_bilinear_quad_v3(data, u, v, res);
}
-static void interp_barycentric_mlooptri(DerivedMesh *dm, MLoop *mloop, const MLoopTri *lt, const float u, const float v, const int mode, float res[3])
+static void interp_barycentric_mlooptri(DerivedMesh *dm,
+ MLoop *mloop,
+ const MLoopTri *lt,
+ const float u,
+ const float v,
+ const int mode,
+ float res[3])
{
- float data[3][3];
-
- if (mode == 0) {
- dm->getVertNo(dm, mloop[lt->tri[0]].v, data[0]);
- dm->getVertNo(dm, mloop[lt->tri[1]].v, data[1]);
- dm->getVertNo(dm, mloop[lt->tri[2]].v, data[2]);
- }
- else {
- dm->getVertCo(dm, mloop[lt->tri[0]].v, data[0]);
- dm->getVertCo(dm, mloop[lt->tri[1]].v, data[1]);
- dm->getVertCo(dm, mloop[lt->tri[2]].v, data[2]);
- }
-
- interp_barycentric_tri_v3(data, u, v, res);
+ float data[3][3];
+
+ if (mode == 0) {
+ dm->getVertNo(dm, mloop[lt->tri[0]].v, data[0]);
+ dm->getVertNo(dm, mloop[lt->tri[1]].v, data[1]);
+ dm->getVertNo(dm, mloop[lt->tri[2]].v, data[2]);
+ }
+ else {
+ dm->getVertCo(dm, mloop[lt->tri[0]].v, data[0]);
+ dm->getVertCo(dm, mloop[lt->tri[1]].v, data[1]);
+ dm->getVertCo(dm, mloop[lt->tri[2]].v, data[2]);
+ }
+
+ interp_barycentric_tri_v3(data, u, v, res);
}
/* **************** Displacement Baker **************** */
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;
+ 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");
+ 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 = MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData");
- height_data->ima = ima;
- height_data->heights = userdata->displacement_buffer;
+ height_data->ima = ima;
+ height_data->heights = userdata->displacement_buffer;
- if (!bkr->use_lores_mesh) {
- SubsurfModifierData smd = {{NULL}};
- int ss_lvl = bkr->tot_lvl - bkr->lvl;
+ if (!bkr->use_lores_mesh) {
+ SubsurfModifierData smd = {{NULL}};
+ int ss_lvl = bkr->tot_lvl - bkr->lvl;
- CLAMP(ss_lvl, 0, 6);
+ CLAMP(ss_lvl, 0, 6);
- if (ss_lvl > 0) {
- smd.levels = smd.renderLevels = ss_lvl;
- smd.uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS;
- smd.quality = 3;
+ if (ss_lvl > 0) {
+ smd.levels = smd.renderLevels = ss_lvl;
+ smd.uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS;
+ smd.quality = 3;
- if (bkr->simple)
- smd.subdivType = ME_SIMPLE_SUBSURF;
+ if (bkr->simple)
+ smd.subdivType = ME_SIMPLE_SUBSURF;
- height_data->ssdm = subsurf_make_derived_from_derived(bkr->lores_dm, &smd, bkr->scene, NULL, 0);
- init_ccgdm_arrays(height_data->ssdm);
- }
- }
+ height_data->ssdm = subsurf_make_derived_from_derived(
+ bkr->lores_dm, &smd, bkr->scene, NULL, 0);
+ init_ccgdm_arrays(height_data->ssdm);
+ }
+ }
- height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
+ height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_release_ibuf(ima, ibuf, NULL);
- return (void *)height_data;
+ return (void *)height_data;
}
static void free_heights_data(void *bake_data)
{
- MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
+ MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
- if (height_data->ssdm)
- height_data->ssdm->release(height_data->ssdm);
+ if (height_data->ssdm)
+ height_data->ssdm->release(height_data->ssdm);
- MEM_freeN(height_data);
+ MEM_freeN(height_data);
}
/* MultiresBake callback for heights baking
@@ -708,98 +779,111 @@ 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, void *thread_data_v, void *bake_data,
- ImBuf *ibuf, const int tri_index, const int lvl, const float st[2],
- float UNUSED(tangmat[3][3]), const int x, const int y)
+static void apply_heights_callback(DerivedMesh *lores_dm,
+ DerivedMesh *hires_dm,
+ void *thread_data_v,
+ void *bake_data,
+ ImBuf *ibuf,
+ const int tri_index,
+ const int lvl,
+ const float st[2],
+ float UNUSED(tangmat[3][3]),
+ const int x,
+ const int y)
{
- const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index;
- MLoop *mloop = lores_dm->getLoopArray(lores_dm);
- MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly;
- MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV);
- 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;
-
- /* ideally we would work on triangles only, however, we rely on quads to get orthogonal
- * coordinates for use in grid space (triangle barycentric is not orthogonal) */
- if (mpoly->totloop == 4) {
- st0 = mloopuv[mpoly->loopstart].uv;
- st1 = mloopuv[mpoly->loopstart + 1].uv;
- st2 = mloopuv[mpoly->loopstart + 2].uv;
- st3 = mloopuv[mpoly->loopstart + 3].uv;
- resolve_quad_uv_v2(uv, st, st0, st1, st2, st3);
- }
- else {
- st0 = mloopuv[lt->tri[0]].uv;
- st1 = mloopuv[lt->tri[1]].uv;
- st2 = mloopuv[lt->tri[2]].uv;
- resolve_tri_uv_v2(uv, st, st0, st1, st2);
- }
-
- CLAMP(uv[0], 0.0f, 1.0f);
- CLAMP(uv[1], 0.0f, 1.0f);
-
- get_ccgdm_data(lores_dm, hires_dm,
- height_data->orig_index_mp_to_orig,
- lvl, lt, uv[0], uv[1], p1, NULL);
-
- if (height_data->ssdm) {
- get_ccgdm_data(lores_dm, height_data->ssdm,
- height_data->orig_index_mp_to_orig,
- 0, lt, uv[0], uv[1], p0, n);
- }
- else {
- if (mpoly->totloop == 4) {
- interp_bilinear_mpoly(lores_dm, mloop, mpoly, uv[0], uv[1], 1, p0);
- interp_bilinear_mpoly(lores_dm, mloop, mpoly, uv[0], uv[1], 0, n);
- }
- else {
- interp_barycentric_mlooptri(lores_dm, mloop, lt, uv[0], uv[1], 1, p0);
- interp_barycentric_mlooptri(lores_dm, mloop, lt, uv[0], uv[1], 0, n);
- }
- }
-
- sub_v3_v3v3(vec, p1, p0);
- len = dot_v3v3(n, vec);
-
- height_data->heights[pixel] = 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] = unit_float_to_uchar_clamp(len);
- rrgb[3] = 255;
- }
+ const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index;
+ MLoop *mloop = lores_dm->getLoopArray(lores_dm);
+ MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly;
+ MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV);
+ 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;
+
+ /* ideally we would work on triangles only, however, we rely on quads to get orthogonal
+ * coordinates for use in grid space (triangle barycentric is not orthogonal) */
+ if (mpoly->totloop == 4) {
+ st0 = mloopuv[mpoly->loopstart].uv;
+ st1 = mloopuv[mpoly->loopstart + 1].uv;
+ st2 = mloopuv[mpoly->loopstart + 2].uv;
+ st3 = mloopuv[mpoly->loopstart + 3].uv;
+ resolve_quad_uv_v2(uv, st, st0, st1, st2, st3);
+ }
+ else {
+ st0 = mloopuv[lt->tri[0]].uv;
+ st1 = mloopuv[lt->tri[1]].uv;
+ st2 = mloopuv[lt->tri[2]].uv;
+ resolve_tri_uv_v2(uv, st, st0, st1, st2);
+ }
+
+ CLAMP(uv[0], 0.0f, 1.0f);
+ CLAMP(uv[1], 0.0f, 1.0f);
+
+ get_ccgdm_data(
+ lores_dm, hires_dm, height_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], p1, NULL);
+
+ if (height_data->ssdm) {
+ get_ccgdm_data(lores_dm,
+ height_data->ssdm,
+ height_data->orig_index_mp_to_orig,
+ 0,
+ lt,
+ uv[0],
+ uv[1],
+ p0,
+ n);
+ }
+ else {
+ if (mpoly->totloop == 4) {
+ interp_bilinear_mpoly(lores_dm, mloop, mpoly, uv[0], uv[1], 1, p0);
+ interp_bilinear_mpoly(lores_dm, mloop, mpoly, uv[0], uv[1], 0, n);
+ }
+ else {
+ interp_barycentric_mlooptri(lores_dm, mloop, lt, uv[0], uv[1], 1, p0);
+ interp_barycentric_mlooptri(lores_dm, mloop, lt, uv[0], uv[1], 0, n);
+ }
+ }
+
+ sub_v3_v3v3(vec, p1, p0);
+ len = dot_v3v3(n, vec);
+
+ height_data->heights[pixel] = 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] = unit_float_to_uchar_clamp(len);
+ rrgb[3] = 255;
+ }
}
/* **************** Normal Maps Baker **************** */
static void *init_normal_data(MultiresBakeRender *bkr, Image *UNUSED(ima))
{
- MNormalBakeData *normal_data;
- DerivedMesh *lodm = bkr->lores_dm;
+ MNormalBakeData *normal_data;
+ DerivedMesh *lodm = bkr->lores_dm;
- normal_data = MEM_callocN(sizeof(MNormalBakeData), "MultiresBake normalData");
+ normal_data = MEM_callocN(sizeof(MNormalBakeData), "MultiresBake normalData");
- normal_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
+ normal_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
- return (void *)normal_data;
+ return (void *)normal_data;
}
static void free_normal_data(void *bake_data)
{
- MNormalBakeData *normal_data = (MNormalBakeData *)bake_data;
+ MNormalBakeData *normal_data = (MNormalBakeData *)bake_data;
- MEM_freeN(normal_data);
+ MEM_freeN(normal_data);
}
/**
@@ -810,57 +894,64 @@ static void free_normal_data(void *bake_data)
* - 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, void *UNUSED(thread_data),
- void *bake_data, ImBuf *ibuf, const int tri_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 tri_index,
+ const int lvl,
+ const float st[2],
+ float tangmat[3][3],
+ const int x,
+ const int y)
{
- const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index;
- MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly;
- MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV);
- MNormalBakeData *normal_data = (MNormalBakeData *)bake_data;
- float uv[2], *st0, *st1, *st2, *st3;
- int pixel = ibuf->x * y + x;
- float n[3], vec[3], tmp[3] = {0.5, 0.5, 0.5};
-
- /* ideally we would work on triangles only, however, we rely on quads to get orthogonal
- * coordinates for use in grid space (triangle barycentric is not orthogonal) */
- if (mpoly->totloop == 4) {
- st0 = mloopuv[mpoly->loopstart].uv;
- st1 = mloopuv[mpoly->loopstart + 1].uv;
- st2 = mloopuv[mpoly->loopstart + 2].uv;
- st3 = mloopuv[mpoly->loopstart + 3].uv;
- resolve_quad_uv_v2(uv, st, st0, st1, st2, st3);
- }
- else {
- st0 = mloopuv[lt->tri[0]].uv;
- st1 = mloopuv[lt->tri[1]].uv;
- st2 = mloopuv[lt->tri[2]].uv;
- resolve_tri_uv_v2(uv, st, st0, st1, st2);
- }
-
- CLAMP(uv[0], 0.0f, 1.0f);
- CLAMP(uv[1], 0.0f, 1.0f);
-
- get_ccgdm_data(lores_dm, hires_dm,
- normal_data->orig_index_mp_to_orig,
- lvl, lt, uv[0], uv[1], NULL, n);
-
- mul_v3_m3v3(vec, tangmat, n);
- normalize_v3_length(vec, 0.5);
- add_v3_v3(vec, tmp);
-
- if (ibuf->rect_float) {
- float *rrgbf = ibuf->rect_float + pixel * 4;
- rrgbf[0] = vec[0];
- rrgbf[1] = vec[1];
- rrgbf[2] = vec[2];
- rrgbf[3] = 1.0f;
- }
- else {
- unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4;
- rgb_float_to_uchar(rrgb, vec);
- rrgb[3] = 255;
- }
+ const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index;
+ MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly;
+ MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV);
+ MNormalBakeData *normal_data = (MNormalBakeData *)bake_data;
+ float uv[2], *st0, *st1, *st2, *st3;
+ int pixel = ibuf->x * y + x;
+ float n[3], vec[3], tmp[3] = {0.5, 0.5, 0.5};
+
+ /* ideally we would work on triangles only, however, we rely on quads to get orthogonal
+ * coordinates for use in grid space (triangle barycentric is not orthogonal) */
+ if (mpoly->totloop == 4) {
+ st0 = mloopuv[mpoly->loopstart].uv;
+ st1 = mloopuv[mpoly->loopstart + 1].uv;
+ st2 = mloopuv[mpoly->loopstart + 2].uv;
+ st3 = mloopuv[mpoly->loopstart + 3].uv;
+ resolve_quad_uv_v2(uv, st, st0, st1, st2, st3);
+ }
+ else {
+ st0 = mloopuv[lt->tri[0]].uv;
+ st1 = mloopuv[lt->tri[1]].uv;
+ st2 = mloopuv[lt->tri[2]].uv;
+ resolve_tri_uv_v2(uv, st, st0, st1, st2);
+ }
+
+ CLAMP(uv[0], 0.0f, 1.0f);
+ CLAMP(uv[1], 0.0f, 1.0f);
+
+ get_ccgdm_data(
+ lores_dm, hires_dm, normal_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], NULL, n);
+
+ mul_v3_m3v3(vec, tangmat, n);
+ normalize_v3_length(vec, 0.5);
+ add_v3_v3(vec, tmp);
+
+ if (ibuf->rect_float) {
+ float *rrgbf = ibuf->rect_float + pixel * 4;
+ rrgbf[0] = vec[0];
+ rrgbf[1] = vec[1];
+ rrgbf[2] = vec[2];
+ rrgbf[3] = 1.0f;
+ }
+ else {
+ unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4;
+ rgb_float_to_uchar(rrgb, vec);
+ rrgb[3] = 255;
+ }
}
/* TODO: restore ambient occlusion baking support, using BLI BVH? */
@@ -868,294 +959,294 @@ static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm,
/* **************** Ambient Occlusion Baker **************** */
// must be a power of two
-#define MAX_NUMBER_OF_AO_RAYS 1024
+# define MAX_NUMBER_OF_AO_RAYS 1024
static unsigned short ao_random_table_1[MAX_NUMBER_OF_AO_RAYS];
static unsigned short ao_random_table_2[MAX_NUMBER_OF_AO_RAYS];
static void init_ao_random(void)
{
- int i;
+ int i;
- for (i = 0; i < MAX_NUMBER_OF_AO_RAYS; i++) {
- ao_random_table_1[i] = rand() & 0xffff;
- ao_random_table_2[i] = rand() & 0xffff;
- }
+ for (i = 0; i < MAX_NUMBER_OF_AO_RAYS; i++) {
+ ao_random_table_1[i] = rand() & 0xffff;
+ ao_random_table_2[i] = rand() & 0xffff;
+ }
}
static unsigned short get_ao_random1(const int i)
{
- return ao_random_table_1[i & (MAX_NUMBER_OF_AO_RAYS - 1)];
+ return ao_random_table_1[i & (MAX_NUMBER_OF_AO_RAYS - 1)];
}
static unsigned short get_ao_random2(const int i)
{
- return ao_random_table_2[i & (MAX_NUMBER_OF_AO_RAYS - 1)];
+ return ao_random_table_2[i & (MAX_NUMBER_OF_AO_RAYS - 1)];
}
static void build_permutation_table(unsigned short permutation[], unsigned short temp_permutation[],
const int number_of_rays, const int is_first_perm_table)
{
- int i, k;
-
- for (i = 0; i < number_of_rays; i++)
- temp_permutation[i] = i;
-
- for (i = 0; i < number_of_rays; i++) {
- const unsigned int nr_entries_left = number_of_rays - i;
- unsigned short rnd = is_first_perm_table != false ? get_ao_random1(i) : get_ao_random2(i);
- const unsigned short entry = rnd % nr_entries_left;
-
- /* pull entry */
- permutation[i] = temp_permutation[entry];
-
- /* delete entry */
- for (k = entry; k < nr_entries_left - 1; k++) {
- temp_permutation[k] = temp_permutation[k + 1];
- }
- }
-
- /* verify permutation table
- * every entry must appear exactly once
- */
-#if 0
- for (i = 0; i < number_of_rays; i++) temp_permutation[i] = 0;
- for (i = 0; i < number_of_rays; i++) ++temp_permutation[permutation[i]];
- for (i = 0; i < number_of_rays; i++) BLI_assert(temp_permutation[i] == 1);
-#endif
+ int i, k;
+
+ for (i = 0; i < number_of_rays; i++)
+ temp_permutation[i] = i;
+
+ for (i = 0; i < number_of_rays; i++) {
+ const unsigned int nr_entries_left = number_of_rays - i;
+ unsigned short rnd = is_first_perm_table != false ? get_ao_random1(i) : get_ao_random2(i);
+ const unsigned short entry = rnd % nr_entries_left;
+
+ /* pull entry */
+ permutation[i] = temp_permutation[entry];
+
+ /* delete entry */
+ for (k = entry; k < nr_entries_left - 1; k++) {
+ temp_permutation[k] = temp_permutation[k + 1];
+ }
+ }
+
+ /* verify permutation table
+ * every entry must appear exactly once
+ */
+# if 0
+ for (i = 0; i < number_of_rays; i++) temp_permutation[i] = 0;
+ for (i = 0; i < number_of_rays; i++) ++temp_permutation[permutation[i]];
+ for (i = 0; i < number_of_rays; i++) BLI_assert(temp_permutation[i] == 1);
+# endif
}
static void create_ao_raytree(MultiresBakeRender *bkr, MAOBakeData *ao_data)
{
- DerivedMesh *hidm = bkr->hires_dm;
- RayObject *raytree;
- RayFace *face;
- CCGElem **grid_data;
- CCGKey key;
- int num_grids, grid_size /*, face_side */, num_faces;
- int i;
-
- num_grids = hidm->getNumGrids(hidm);
- grid_size = hidm->getGridSize(hidm);
- grid_data = hidm->getGridData(hidm);
- hidm->getGridKey(hidm, &key);
-
- /* face_side = (grid_size << 1) - 1; */ /* UNUSED */
- num_faces = num_grids * (grid_size - 1) * (grid_size - 1);
-
- raytree = ao_data->raytree = RE_rayobject_create(bkr->raytrace_structure, num_faces, bkr->octree_resolution);
- face = ao_data->rayfaces = (RayFace *)MEM_callocN(num_faces * sizeof(RayFace), "ObjectRen faces");
-
- for (i = 0; i < num_grids; i++) {
- int x, y;
- for (x = 0; x < grid_size - 1; x++) {
- for (y = 0; y < grid_size - 1; y++) {
- float co[4][3];
-
- copy_v3_v3(co[0], CCG_grid_elem_co(&key, grid_data[i], x, y));
- copy_v3_v3(co[1], CCG_grid_elem_co(&key, grid_data[i], x, y + 1));
- copy_v3_v3(co[2], CCG_grid_elem_co(&key, grid_data[i], x + 1, y + 1));
- copy_v3_v3(co[3], CCG_grid_elem_co(&key, grid_data[i], x + 1, y));
-
- RE_rayface_from_coords(face, ao_data, face, co[0], co[1], co[2], co[3]);
- RE_rayobject_add(raytree, RE_rayobject_unalignRayFace(face));
-
- face++;
- }
- }
- }
-
- RE_rayobject_done(raytree);
+ DerivedMesh *hidm = bkr->hires_dm;
+ RayObject *raytree;
+ RayFace *face;
+ CCGElem **grid_data;
+ CCGKey key;
+ int num_grids, grid_size /*, face_side */, num_faces;
+ int i;
+
+ num_grids = hidm->getNumGrids(hidm);
+ grid_size = hidm->getGridSize(hidm);
+ grid_data = hidm->getGridData(hidm);
+ hidm->getGridKey(hidm, &key);
+
+ /* face_side = (grid_size << 1) - 1; */ /* UNUSED */
+ num_faces = num_grids * (grid_size - 1) * (grid_size - 1);
+
+ raytree = ao_data->raytree = RE_rayobject_create(bkr->raytrace_structure, num_faces, bkr->octree_resolution);
+ face = ao_data->rayfaces = (RayFace *)MEM_callocN(num_faces * sizeof(RayFace), "ObjectRen faces");
+
+ for (i = 0; i < num_grids; i++) {
+ int x, y;
+ for (x = 0; x < grid_size - 1; x++) {
+ for (y = 0; y < grid_size - 1; y++) {
+ float co[4][3];
+
+ copy_v3_v3(co[0], CCG_grid_elem_co(&key, grid_data[i], x, y));
+ copy_v3_v3(co[1], CCG_grid_elem_co(&key, grid_data[i], x, y + 1));
+ copy_v3_v3(co[2], CCG_grid_elem_co(&key, grid_data[i], x + 1, y + 1));
+ copy_v3_v3(co[3], CCG_grid_elem_co(&key, grid_data[i], x + 1, y));
+
+ RE_rayface_from_coords(face, ao_data, face, co[0], co[1], co[2], co[3]);
+ RE_rayobject_add(raytree, RE_rayobject_unalignRayFace(face));
+
+ face++;
+ }
+ }
+ }
+
+ RE_rayobject_done(raytree);
}
static void *init_ao_data(MultiresBakeRender *bkr, Image *UNUSED(ima))
{
- MAOBakeData *ao_data;
- DerivedMesh *lodm = bkr->lores_dm;
- unsigned short *temp_permutation_table;
- size_t permutation_size;
+ MAOBakeData *ao_data;
+ DerivedMesh *lodm = bkr->lores_dm;
+ unsigned short *temp_permutation_table;
+ size_t permutation_size;
- init_ao_random();
+ init_ao_random();
- ao_data = MEM_callocN(sizeof(MAOBakeData), "MultiresBake aoData");
+ ao_data = MEM_callocN(sizeof(MAOBakeData), "MultiresBake aoData");
- ao_data->number_of_rays = bkr->number_of_rays;
- ao_data->bias = bkr->bias;
+ ao_data->number_of_rays = bkr->number_of_rays;
+ ao_data->bias = bkr->bias;
- ao_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
+ ao_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
- create_ao_raytree(bkr, ao_data);
+ create_ao_raytree(bkr, ao_data);
- /* initialize permutation tables */
- permutation_size = sizeof(unsigned short) * bkr->number_of_rays;
- ao_data->permutation_table_1 = MEM_callocN(permutation_size, "multires AO baker perm1");
- ao_data->permutation_table_2 = MEM_callocN(permutation_size, "multires AO baker perm2");
- temp_permutation_table = MEM_callocN(permutation_size, "multires AO baker temp perm");
+ /* initialize permutation tables */
+ permutation_size = sizeof(unsigned short) * bkr->number_of_rays;
+ ao_data->permutation_table_1 = MEM_callocN(permutation_size, "multires AO baker perm1");
+ ao_data->permutation_table_2 = MEM_callocN(permutation_size, "multires AO baker perm2");
+ temp_permutation_table = MEM_callocN(permutation_size, "multires AO baker temp perm");
- build_permutation_table(ao_data->permutation_table_1, temp_permutation_table, bkr->number_of_rays, 1);
- build_permutation_table(ao_data->permutation_table_2, temp_permutation_table, bkr->number_of_rays, 0);
+ build_permutation_table(ao_data->permutation_table_1, temp_permutation_table, bkr->number_of_rays, 1);
+ build_permutation_table(ao_data->permutation_table_2, temp_permutation_table, bkr->number_of_rays, 0);
- MEM_freeN(temp_permutation_table);
+ MEM_freeN(temp_permutation_table);
- return (void *)ao_data;
+ return (void *)ao_data;
}
static void free_ao_data(void *bake_data)
{
- MAOBakeData *ao_data = (MAOBakeData *)bake_data;
+ MAOBakeData *ao_data = (MAOBakeData *)bake_data;
- RE_rayobject_free(ao_data->raytree);
- MEM_freeN(ao_data->rayfaces);
+ RE_rayobject_free(ao_data->raytree);
+ MEM_freeN(ao_data->rayfaces);
- MEM_freeN(ao_data->permutation_table_1);
- MEM_freeN(ao_data->permutation_table_2);
+ MEM_freeN(ao_data->permutation_table_1);
+ MEM_freeN(ao_data->permutation_table_2);
- MEM_freeN(ao_data);
+ MEM_freeN(ao_data);
}
/* builds an X and a Y axis from the given Z axis */
static void build_coordinate_frame(float axisX[3], float axisY[3], const float axisZ[3])
{
- const float faX = fabsf(axisZ[0]);
- const float faY = fabsf(axisZ[1]);
- const float faZ = fabsf(axisZ[2]);
-
- if (faX <= faY && faX <= faZ) {
- const float len = sqrtf(axisZ[1] * axisZ[1] + axisZ[2] * axisZ[2]);
- axisY[0] = 0; axisY[1] = axisZ[2] / len; axisY[2] = -axisZ[1] / len;
- cross_v3_v3v3(axisX, axisY, axisZ);
- }
- else if (faY <= faZ) {
- const float len = sqrtf(axisZ[0] * axisZ[0] + axisZ[2] * axisZ[2]);
- axisX[0] = axisZ[2] / len; axisX[1] = 0; axisX[2] = -axisZ[0] / len;
- cross_v3_v3v3(axisY, axisZ, axisX);
- }
- else {
- const float len = sqrtf(axisZ[0] * axisZ[0] + axisZ[1] * axisZ[1]);
- axisX[0] = axisZ[1] / len; axisX[1] = -axisZ[0] / len; axisX[2] = 0;
- cross_v3_v3v3(axisY, axisZ, axisX);
- }
+ const float faX = fabsf(axisZ[0]);
+ const float faY = fabsf(axisZ[1]);
+ const float faZ = fabsf(axisZ[2]);
+
+ if (faX <= faY && faX <= faZ) {
+ const float len = sqrtf(axisZ[1] * axisZ[1] + axisZ[2] * axisZ[2]);
+ axisY[0] = 0; axisY[1] = axisZ[2] / len; axisY[2] = -axisZ[1] / len;
+ cross_v3_v3v3(axisX, axisY, axisZ);
+ }
+ else if (faY <= faZ) {
+ const float len = sqrtf(axisZ[0] * axisZ[0] + axisZ[2] * axisZ[2]);
+ axisX[0] = axisZ[2] / len; axisX[1] = 0; axisX[2] = -axisZ[0] / len;
+ cross_v3_v3v3(axisY, axisZ, axisX);
+ }
+ else {
+ const float len = sqrtf(axisZ[0] * axisZ[0] + axisZ[1] * axisZ[1]);
+ axisX[0] = axisZ[1] / len; axisX[1] = -axisZ[0] / len; axisX[2] = 0;
+ cross_v3_v3v3(axisY, axisZ, axisX);
+ }
}
/* return false if nothing was hit and true otherwise */
static int trace_ao_ray(MAOBakeData *ao_data, float ray_start[3], float ray_direction[3])
{
- Isect isect = {{0}};
+ Isect isect = {{0}};
- isect.dist = RE_RAYTRACE_MAXDIST;
- copy_v3_v3(isect.start, ray_start);
- copy_v3_v3(isect.dir, ray_direction);
- isect.lay = -1;
+ isect.dist = RE_RAYTRACE_MAXDIST;
+ copy_v3_v3(isect.start, ray_start);
+ copy_v3_v3(isect.dir, ray_direction);
+ isect.lay = -1;
- normalize_v3(isect.dir);
+ normalize_v3(isect.dir);
- return RE_rayobject_raycast(ao_data->raytree, &isect);
+ return RE_rayobject_raycast(ao_data->raytree, &isect);
}
static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *UNUSED(thread_data),
void *bake_data, ImBuf *ibuf, const int tri_index, const int lvl,
const float st[2], float UNUSED(tangmat[3][3]), const int x, const int y)
{
- const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index;
- MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly;
- MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV);
- MAOBakeData *ao_data = (MAOBakeData *)bake_data;
-
- int i, k, perm_offs;
- float pos[3], nrm[3];
- float cen[3];
- float axisX[3], axisY[3], axisZ[3];
- float shadow = 0;
- float value;
- int pixel = ibuf->x * y + x;
- float uv[2], *st0, *st1, *st2, *st3;
-
- /* ideally we would work on triangles only, however, we rely on quads to get orthogonal
- * coordinates for use in grid space (triangle barycentric is not orthogonal) */
- if (mpoly->totloop == 4) {
- st0 = mloopuv[mpoly->loopstart].uv;
- st1 = mloopuv[mpoly->loopstart + 1].uv;
- st2 = mloopuv[mpoly->loopstart + 2].uv;
- st3 = mloopuv[mpoly->loopstart + 3].uv;
- resolve_quad_uv_v2(uv, st, st0, st1, st2, st3);
- }
- else {
- st0 = mloopuv[lt->tri[0]].uv;
- st1 = mloopuv[lt->tri[1]].uv;
- st2 = mloopuv[lt->tri[2]].uv;
- resolve_tri_uv_v2(uv, st, st0, st1, st2);
- }
-
- CLAMP(uv[0], 0.0f, 1.0f);
- CLAMP(uv[1], 0.0f, 1.0f);
-
- get_ccgdm_data(lores_dm, hires_dm,
- ao_data->orig_index_mp_to_orig,
- lvl, lt, uv[0], uv[1], pos, nrm);
-
- /* offset ray origin by user bias along normal */
- for (i = 0; i < 3; i++)
- cen[i] = pos[i] + ao_data->bias * nrm[i];
-
- /* build tangent frame */
- for (i = 0; i < 3; i++)
- axisZ[i] = nrm[i];
-
- build_coordinate_frame(axisX, axisY, axisZ);
-
- /* static noise */
- perm_offs = (get_ao_random2(get_ao_random1(x) + y)) & (MAX_NUMBER_OF_AO_RAYS - 1);
-
- /* importance sample shadow rays (cosine weighted) */
- for (i = 0; i < ao_data->number_of_rays; i++) {
- int hit_something;
-
- /* use N-Rooks to distribute our N ray samples across
- * a multi-dimensional domain (2D)
- */
- const unsigned short I = ao_data->permutation_table_1[(i + perm_offs) % ao_data->number_of_rays];
- const unsigned short J = ao_data->permutation_table_2[i];
-
- const float JitPh = (get_ao_random2(I + perm_offs) & (MAX_NUMBER_OF_AO_RAYS - 1)) / ((float)MAX_NUMBER_OF_AO_RAYS);
- const float JitTh = (get_ao_random1(J + perm_offs) & (MAX_NUMBER_OF_AO_RAYS - 1)) / ((float)MAX_NUMBER_OF_AO_RAYS);
- const float SiSqPhi = (I + JitPh) / ao_data->number_of_rays;
- const float Theta = (float)(2 * M_PI) * ((J + JitTh) / ao_data->number_of_rays);
-
- /* this gives results identical to the so-called cosine
- * weighted distribution relative to the north pole.
- */
- float SiPhi = sqrtf(SiSqPhi);
- float CoPhi = SiSqPhi < 1.0f ? sqrtf(1.0f - SiSqPhi) : 0;
- float CoThe = cosf(Theta);
- float SiThe = sinf(Theta);
-
- const float dx = CoThe * CoPhi;
- const float dy = SiThe * CoPhi;
- const float dz = SiPhi;
-
- /* transform ray direction out of tangent frame */
- float dv[3];
- for (k = 0; k < 3; k++)
- dv[k] = axisX[k] * dx + axisY[k] * dy + axisZ[k] * dz;
-
- hit_something = trace_ao_ray(ao_data, cen, dv);
-
- if (hit_something != 0)
- shadow += 1;
- }
-
- value = 1.0f - (shadow / ao_data->number_of_rays);
-
- if (ibuf->rect_float) {
- float *rrgbf = ibuf->rect_float + pixel * 4;
- rrgbf[0] = rrgbf[1] = rrgbf[2] = value;
- rrgbf[3] = 1.0f;
- }
- else {
- unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4;
- rrgb[0] = rrgb[1] = rrgb[2] = unit_float_to_uchar_clamp(value);
- rrgb[3] = 255;
- }
+ const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index;
+ MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly;
+ MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV);
+ MAOBakeData *ao_data = (MAOBakeData *)bake_data;
+
+ int i, k, perm_offs;
+ float pos[3], nrm[3];
+ float cen[3];
+ float axisX[3], axisY[3], axisZ[3];
+ float shadow = 0;
+ float value;
+ int pixel = ibuf->x * y + x;
+ float uv[2], *st0, *st1, *st2, *st3;
+
+ /* ideally we would work on triangles only, however, we rely on quads to get orthogonal
+ * coordinates for use in grid space (triangle barycentric is not orthogonal) */
+ if (mpoly->totloop == 4) {
+ st0 = mloopuv[mpoly->loopstart].uv;
+ st1 = mloopuv[mpoly->loopstart + 1].uv;
+ st2 = mloopuv[mpoly->loopstart + 2].uv;
+ st3 = mloopuv[mpoly->loopstart + 3].uv;
+ resolve_quad_uv_v2(uv, st, st0, st1, st2, st3);
+ }
+ else {
+ st0 = mloopuv[lt->tri[0]].uv;
+ st1 = mloopuv[lt->tri[1]].uv;
+ st2 = mloopuv[lt->tri[2]].uv;
+ resolve_tri_uv_v2(uv, st, st0, st1, st2);
+ }
+
+ CLAMP(uv[0], 0.0f, 1.0f);
+ CLAMP(uv[1], 0.0f, 1.0f);
+
+ get_ccgdm_data(lores_dm, hires_dm,
+ ao_data->orig_index_mp_to_orig,
+ lvl, lt, uv[0], uv[1], pos, nrm);
+
+ /* offset ray origin by user bias along normal */
+ for (i = 0; i < 3; i++)
+ cen[i] = pos[i] + ao_data->bias * nrm[i];
+
+ /* build tangent frame */
+ for (i = 0; i < 3; i++)
+ axisZ[i] = nrm[i];
+
+ build_coordinate_frame(axisX, axisY, axisZ);
+
+ /* static noise */
+ perm_offs = (get_ao_random2(get_ao_random1(x) + y)) & (MAX_NUMBER_OF_AO_RAYS - 1);
+
+ /* importance sample shadow rays (cosine weighted) */
+ for (i = 0; i < ao_data->number_of_rays; i++) {
+ int hit_something;
+
+ /* use N-Rooks to distribute our N ray samples across
+ * a multi-dimensional domain (2D)
+ */
+ const unsigned short I = ao_data->permutation_table_1[(i + perm_offs) % ao_data->number_of_rays];
+ const unsigned short J = ao_data->permutation_table_2[i];
+
+ const float JitPh = (get_ao_random2(I + perm_offs) & (MAX_NUMBER_OF_AO_RAYS - 1)) / ((float)MAX_NUMBER_OF_AO_RAYS);
+ const float JitTh = (get_ao_random1(J + perm_offs) & (MAX_NUMBER_OF_AO_RAYS - 1)) / ((float)MAX_NUMBER_OF_AO_RAYS);
+ const float SiSqPhi = (I + JitPh) / ao_data->number_of_rays;
+ const float Theta = (float)(2 * M_PI) * ((J + JitTh) / ao_data->number_of_rays);
+
+ /* this gives results identical to the so-called cosine
+ * weighted distribution relative to the north pole.
+ */
+ float SiPhi = sqrtf(SiSqPhi);
+ float CoPhi = SiSqPhi < 1.0f ? sqrtf(1.0f - SiSqPhi) : 0;
+ float CoThe = cosf(Theta);
+ float SiThe = sinf(Theta);
+
+ const float dx = CoThe * CoPhi;
+ const float dy = SiThe * CoPhi;
+ const float dz = SiPhi;
+
+ /* transform ray direction out of tangent frame */
+ float dv[3];
+ for (k = 0; k < 3; k++)
+ dv[k] = axisX[k] * dx + axisY[k] * dy + axisZ[k] * dz;
+
+ hit_something = trace_ao_ray(ao_data, cen, dv);
+
+ if (hit_something != 0)
+ shadow += 1;
+ }
+
+ value = 1.0f - (shadow / ao_data->number_of_rays);
+
+ if (ibuf->rect_float) {
+ float *rrgbf = ibuf->rect_float + pixel * 4;
+ rrgbf[0] = rrgbf[1] = rrgbf[2] = value;
+ rrgbf[3] = 1.0f;
+ }
+ else {
+ unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4;
+ rrgb[0] = rrgb[1] = rrgb[2] = unit_float_to_uchar_clamp(value);
+ rrgb[3] = 255;
+ }
}
#endif
@@ -1163,181 +1254,193 @@ static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void
static void bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter)
{
- /* must check before filtering */
- const bool 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);
- }
- }
+ /* must check before filtering */
+ const bool 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);
+ }
+ }
}
-static void bake_ibuf_normalize_displacement(ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max)
+static void bake_ibuf_normalize_displacement(
+ ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max)
{
- int i;
- const float *current_displacement = displacement;
- const 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] = unit_float_to_uchar_clamp(normalized_displacement);
- cp[3] = 255;
- }
- }
-
- current_displacement++;
- current_mask++;
- }
+ int i;
+ const float *current_displacement = displacement;
+ const 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] = unit_float_to_uchar_clamp(normalized_displacement);
+ cp[3] = 255;
+ }
+ }
+
+ current_displacement++;
+ current_mask++;
+ }
}
/* **************** Common functions public API relates on **************** */
static void count_images(MultiresBakeRender *bkr)
{
- BLI_listbase_clear(&bkr->image);
- bkr->tot_image = 0;
-
- for (int i = 0; i < bkr->ob_image.len; i++) {
- Image *ima = bkr->ob_image.array[i];
- if (ima) {
- ima->id.tag &= ~LIB_TAG_DOIT;
- }
- }
-
- for (int i = 0; i < bkr->ob_image.len; i++) {
- Image *ima = bkr->ob_image.array[i];
- if (ima) {
- if ((ima->id.tag & LIB_TAG_DOIT) == 0) {
- LinkData *data = BLI_genericNodeN(ima);
- BLI_addtail(&bkr->image, data);
- bkr->tot_image++;
- ima->id.tag |= LIB_TAG_DOIT;
- }
- }
- }
-
- for (int i = 0; i < bkr->ob_image.len; i++) {
- Image *ima = bkr->ob_image.array[i];
- if (ima) {
- ima->id.tag &= ~LIB_TAG_DOIT;
- }
- }
+ BLI_listbase_clear(&bkr->image);
+ bkr->tot_image = 0;
+
+ for (int i = 0; i < bkr->ob_image.len; i++) {
+ Image *ima = bkr->ob_image.array[i];
+ if (ima) {
+ ima->id.tag &= ~LIB_TAG_DOIT;
+ }
+ }
+
+ for (int i = 0; i < bkr->ob_image.len; i++) {
+ Image *ima = bkr->ob_image.array[i];
+ if (ima) {
+ if ((ima->id.tag & LIB_TAG_DOIT) == 0) {
+ LinkData *data = BLI_genericNodeN(ima);
+ BLI_addtail(&bkr->image, data);
+ bkr->tot_image++;
+ ima->id.tag |= LIB_TAG_DOIT;
+ }
+ }
+ }
+
+ for (int i = 0; i < bkr->ob_image.len; i++) {
+ Image *ima = bkr->ob_image.array[i];
+ if (ima) {
+ ima->id.tag &= ~LIB_TAG_DOIT;
+ }
+ }
}
static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
{
- LinkData *link;
-
- for (link = bkr->image.first; link; link = link->next) {
- Image *ima = (Image *)link->data;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
-
- if (ibuf->x > 0 && ibuf->y > 0) {
- 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, free_normal_data, result);
- break;
- case RE_BAKE_DISPLACEMENT:
- do_multires_bake(bkr, ima, false, apply_heights_callback, init_heights_data, free_heights_data, result);
- break;
+ LinkData *link;
+
+ for (link = bkr->image.first; link; link = link->next) {
+ Image *ima = (Image *)link->data;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+
+ if (ibuf->x > 0 && ibuf->y > 0) {
+ 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, free_normal_data, result);
+ break;
+ case RE_BAKE_DISPLACEMENT:
+ do_multires_bake(bkr,
+ ima,
+ false,
+ apply_heights_callback,
+ init_heights_data,
+ free_heights_data,
+ result);
+ break;
/* TODO: restore ambient occlusion baking support. */
#if 0
- case RE_BAKE_AO:
- do_multires_bake(bkr, ima, false, apply_ao_callback, init_ao_data, free_ao_data, result);
- break;
+ case RE_BAKE_AO:
+ do_multires_bake(bkr, ima, false, apply_ao_callback, init_ao_data, free_ao_data, result);
+ break;
#endif
- }
- }
+ }
+ }
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_release_ibuf(ima, ibuf, NULL);
- ima->id.tag |= LIB_TAG_DOIT;
- }
+ ima->id.tag |= LIB_TAG_DOIT;
+ }
}
static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
{
- LinkData *link;
- bool use_displacement_buffer = bkr->mode == RE_BAKE_DISPLACEMENT;
+ LinkData *link;
+ bool 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;
+ 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;
+ if (ibuf->x <= 0 || ibuf->y <= 0)
+ continue;
- if (use_displacement_buffer) {
- bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
- result->height_min, result->height_max);
- }
+ if (use_displacement_buffer) {
+ bake_ibuf_normalize_displacement(ibuf,
+ userdata->displacement_buffer,
+ userdata->mask_buffer,
+ result->height_min,
+ result->height_max);
+ }
- bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter);
+ bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter);
- ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;
+ ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;
- if (ibuf->rect_float)
- ibuf->userflags |= IB_RECT_INVALID;
+ if (ibuf->rect_float)
+ ibuf->userflags |= IB_RECT_INVALID;
- if (ibuf->mipmap[0]) {
- ibuf->userflags |= IB_MIPMAP_INVALID;
- imb_freemipmapImBuf(ibuf);
- }
+ if (ibuf->mipmap[0]) {
+ ibuf->userflags |= IB_MIPMAP_INVALID;
+ imb_freemipmapImBuf(ibuf);
+ }
- if (ibuf->userdata) {
- if (userdata->displacement_buffer)
- MEM_freeN(userdata->displacement_buffer);
+ if (ibuf->userdata) {
+ if (userdata->displacement_buffer)
+ MEM_freeN(userdata->displacement_buffer);
- MEM_freeN(userdata->mask_buffer);
- MEM_freeN(userdata);
- ibuf->userdata = NULL;
- }
+ MEM_freeN(userdata->mask_buffer);
+ MEM_freeN(userdata);
+ ibuf->userdata = NULL;
+ }
- BKE_image_release_ibuf(ima, ibuf, NULL);
- DEG_id_tag_update(&ima->id, 0);
- }
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ DEG_id_tag_update(&ima->id, 0);
+ }
}
void RE_multires_bake_images(MultiresBakeRender *bkr)
{
- MultiresBakeResult result;
+ MultiresBakeResult result;
- count_images(bkr);
- bake_images(bkr, &result);
- finish_images(bkr, &result);
+ count_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 021abe89105..b6aa9904747 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -52,7 +52,7 @@
#include "BLT_translation.h"
-#include "BKE_animsys.h" /* <------ should this be here?, needed for sequencer update */
+#include "BKE_animsys.h" /* <------ should this be here?, needed for sequencer update */
#include "BKE_camera.h"
#include "BKE_colortools.h"
#include "BKE_context.h" /* XXX needed by wm_window.h */
@@ -70,7 +70,7 @@
#include "BKE_scene.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
-#include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */
+#include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -86,7 +86,7 @@
#include "RE_pipeline.h"
#include "RE_render_ext.h"
-#include "../../../windowmanager/WM_api.h" /* XXX */
+#include "../../../windowmanager/WM_api.h" /* XXX */
#include "../../../windowmanager/wm_window.h" /* XXX */
#include "GPU_context.h"
@@ -126,239 +126,273 @@
* - save file or append in movie
*/
-
/* ********* globals ******** */
/* here we store all renders */
static struct {
- ListBase renderlist;
+ ListBase renderlist;
} RenderGlobal = {{NULL, NULL}};
/* ********* alloc and free ******** */
-static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const int totvideos, const char *name_override);
+static int do_write_image_or_movie(Render *re,
+ Main *bmain,
+ Scene *scene,
+ bMovieHandle *mh,
+ const int totvideos,
+ const char *name_override);
/* default callbacks, set in each new render */
-static void result_nothing(void *UNUSED(arg), RenderResult *UNUSED(rr)) {}
-static void result_rcti_nothing(void *UNUSED(arg), RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect)) {}
-static void current_scene_nothing(void *UNUSED(arg), Scene *UNUSED(scene)) {}
-static void stats_nothing(void *UNUSED(arg), RenderStats *UNUSED(rs)) {}
-static void float_nothing(void *UNUSED(arg), float UNUSED(val)) {}
-static int default_break(void *UNUSED(arg)) { return G.is_break == true; }
-
-static void stats_background(void *UNUSED(arg), RenderStats *rs)
+static void result_nothing(void *UNUSED(arg), RenderResult *UNUSED(rr))
{
- uintptr_t mem_in_use, mmap_in_use, peak_memory;
- float megs_used_memory, mmap_used_memory, megs_peak_memory;
- char info_time_str[32];
-
- mem_in_use = MEM_get_memory_in_use();
- mmap_in_use = MEM_get_mapped_memory_in_use();
- peak_memory = MEM_get_peak_memory();
-
- megs_used_memory = (mem_in_use - mmap_in_use) / (1024.0 * 1024.0);
- mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0);
- megs_peak_memory = (peak_memory) / (1024.0 * 1024.0);
-
- fprintf(stdout, IFACE_("Fra:%d Mem:%.2fM (%.2fM, Peak %.2fM) "), rs->cfra,
- megs_used_memory, mmap_used_memory, megs_peak_memory);
-
- if (rs->curfield)
- fprintf(stdout, IFACE_("Field %d "), rs->curfield);
- if (rs->curblur)
- fprintf(stdout, IFACE_("Blur %d "), rs->curblur);
-
- BLI_timecode_string_from_time_simple(info_time_str, sizeof(info_time_str), PIL_check_seconds_timer() - rs->starttime);
- fprintf(stdout, IFACE_("| Time:%s | "), info_time_str);
-
- if (rs->infostr) {
- fprintf(stdout, "%s", rs->infostr);
- }
- else {
- if (rs->tothalo)
- fprintf(stdout, IFACE_("Sce: %s Ve:%d Fa:%d Ha:%d La:%d"),
- rs->scene_name, rs->totvert, rs->totface, rs->tothalo, rs->totlamp);
- else
- fprintf(stdout, IFACE_("Sce: %s Ve:%d Fa:%d La:%d"), rs->scene_name, rs->totvert, rs->totface, rs->totlamp);
- }
-
- /* Flush stdout to be sure python callbacks are printing stuff after blender. */
- fflush(stdout);
-
- /* NOTE: using G_MAIN seems valid here??? Not sure it's actually even used anyway, we could as well pass NULL? */
- BLI_callback_exec(G_MAIN, NULL, BLI_CB_EVT_RENDER_STATS);
-
- fputc('\n', stdout);
- fflush(stdout);
}
-
-static void render_print_save_message(
- ReportList *reports, const char *name, int ok, int err)
+static void result_rcti_nothing(void *UNUSED(arg),
+ RenderResult *UNUSED(rr),
+ volatile struct rcti *UNUSED(rect))
{
- if (ok) {
- /* no need to report, just some helpful console info */
- printf("Saved: '%s'\n", name);
- }
- else {
- /* report on error since users will want to know what failed */
- BKE_reportf(reports, RPT_ERROR, "Render error (%s) cannot save: '%s'", strerror(err), name);
- }
}
-
-static int render_imbuf_write_stamp_test(
- ReportList *reports,
- Scene *scene, struct RenderResult *rr, ImBuf *ibuf, const char *name,
- const ImageFormatData *imf, bool stamp)
+static void current_scene_nothing(void *UNUSED(arg), Scene *UNUSED(scene))
{
- int ok;
-
- if (stamp) {
- /* writes the name of the individual cameras */
- ok = BKE_imbuf_write_stamp(scene, rr, ibuf, name, imf);
- }
- else {
- ok = BKE_imbuf_write(ibuf, name, imf);
- }
-
- render_print_save_message(reports, name, ok, errno);
+}
+static void stats_nothing(void *UNUSED(arg), RenderStats *UNUSED(rs))
+{
+}
+static void float_nothing(void *UNUSED(arg), float UNUSED(val))
+{
+}
+static int default_break(void *UNUSED(arg))
+{
+ return G.is_break == true;
+}
- return ok;
+static void stats_background(void *UNUSED(arg), RenderStats *rs)
+{
+ uintptr_t mem_in_use, mmap_in_use, peak_memory;
+ float megs_used_memory, mmap_used_memory, megs_peak_memory;
+ char info_time_str[32];
+
+ mem_in_use = MEM_get_memory_in_use();
+ mmap_in_use = MEM_get_mapped_memory_in_use();
+ peak_memory = MEM_get_peak_memory();
+
+ megs_used_memory = (mem_in_use - mmap_in_use) / (1024.0 * 1024.0);
+ mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0);
+ megs_peak_memory = (peak_memory) / (1024.0 * 1024.0);
+
+ fprintf(stdout,
+ IFACE_("Fra:%d Mem:%.2fM (%.2fM, Peak %.2fM) "),
+ rs->cfra,
+ megs_used_memory,
+ mmap_used_memory,
+ megs_peak_memory);
+
+ if (rs->curfield)
+ fprintf(stdout, IFACE_("Field %d "), rs->curfield);
+ if (rs->curblur)
+ fprintf(stdout, IFACE_("Blur %d "), rs->curblur);
+
+ BLI_timecode_string_from_time_simple(
+ info_time_str, sizeof(info_time_str), PIL_check_seconds_timer() - rs->starttime);
+ fprintf(stdout, IFACE_("| Time:%s | "), info_time_str);
+
+ if (rs->infostr) {
+ fprintf(stdout, "%s", rs->infostr);
+ }
+ else {
+ if (rs->tothalo)
+ fprintf(stdout,
+ IFACE_("Sce: %s Ve:%d Fa:%d Ha:%d La:%d"),
+ rs->scene_name,
+ rs->totvert,
+ rs->totface,
+ rs->tothalo,
+ rs->totlamp);
+ else
+ fprintf(stdout,
+ IFACE_("Sce: %s Ve:%d Fa:%d La:%d"),
+ rs->scene_name,
+ rs->totvert,
+ rs->totface,
+ rs->totlamp);
+ }
+
+ /* Flush stdout to be sure python callbacks are printing stuff after blender. */
+ fflush(stdout);
+
+ /* NOTE: using G_MAIN seems valid here??? Not sure it's actually even used anyway, we could as well pass NULL? */
+ BLI_callback_exec(G_MAIN, NULL, BLI_CB_EVT_RENDER_STATS);
+
+ fputc('\n', stdout);
+ fflush(stdout);
+}
+
+static void render_print_save_message(ReportList *reports, const char *name, int ok, int err)
+{
+ if (ok) {
+ /* no need to report, just some helpful console info */
+ printf("Saved: '%s'\n", name);
+ }
+ else {
+ /* report on error since users will want to know what failed */
+ BKE_reportf(reports, RPT_ERROR, "Render error (%s) cannot save: '%s'", strerror(err), name);
+ }
+}
+
+static int render_imbuf_write_stamp_test(ReportList *reports,
+ Scene *scene,
+ struct RenderResult *rr,
+ ImBuf *ibuf,
+ const char *name,
+ const ImageFormatData *imf,
+ bool stamp)
+{
+ int ok;
+
+ if (stamp) {
+ /* writes the name of the individual cameras */
+ ok = BKE_imbuf_write_stamp(scene, rr, ibuf, name, imf);
+ }
+ else {
+ ok = BKE_imbuf_write(ibuf, name, imf);
+ }
+
+ render_print_save_message(reports, name, ok, errno);
+
+ return ok;
}
void RE_FreeRenderResult(RenderResult *res)
{
- render_result_free(res);
+ render_result_free(res);
}
float *RE_RenderLayerGetPass(volatile RenderLayer *rl, const char *name, const char *viewname)
{
- RenderPass *rpass = RE_pass_find_by_name(rl, name, viewname);
- return rpass ? rpass->rect : NULL;
+ RenderPass *rpass = RE_pass_find_by_name(rl, name, viewname);
+ return rpass ? rpass->rect : NULL;
}
RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name)
{
- if (rr == NULL) {
- return NULL;
- }
- else {
- return BLI_findstring(&rr->layers, name, offsetof(RenderLayer, name));
- }
+ if (rr == NULL) {
+ return NULL;
+ }
+ else {
+ return BLI_findstring(&rr->layers, name, offsetof(RenderLayer, name));
+ }
}
bool RE_HasSingleLayer(Render *re)
{
- return (re->r.scemode & R_SINGLE_LAYER);
+ return (re->r.scemode & R_SINGLE_LAYER);
}
-RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty)
+RenderResult *RE_MultilayerConvert(
+ void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty)
{
- return render_result_new_from_exr(exrhandle, colorspace, predivide, rectx, recty);
+ return render_result_new_from_exr(exrhandle, colorspace, predivide, rectx, recty);
}
RenderLayer *render_get_active_layer(Render *re, RenderResult *rr)
{
- ViewLayer *view_layer = BLI_findlink(&re->view_layers, re->active_view_layer);
+ ViewLayer *view_layer = BLI_findlink(&re->view_layers, re->active_view_layer);
- if (view_layer) {
- RenderLayer *rl = BLI_findstring(&rr->layers,
- view_layer->name,
- offsetof(RenderLayer, name));
+ if (view_layer) {
+ RenderLayer *rl = BLI_findstring(&rr->layers, view_layer->name, offsetof(RenderLayer, name));
- if (rl) {
- return rl;
- }
- }
+ if (rl) {
+ return rl;
+ }
+ }
- return rr->layers.first;
+ return rr->layers.first;
}
static bool render_scene_has_layers_to_render(Scene *scene, ViewLayer *single_layer)
{
- if (single_layer) {
- return true;
- }
+ if (single_layer) {
+ return true;
+ }
- ViewLayer *view_layer;
- for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
- if (view_layer->flag & VIEW_LAYER_RENDER) {
- return true;
- }
- }
- return false;
+ ViewLayer *view_layer;
+ for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ if (view_layer->flag & VIEW_LAYER_RENDER) {
+ return true;
+ }
+ }
+ return false;
}
/* *************************************************** */
Render *RE_GetRender(const char *name)
{
- Render *re;
+ Render *re;
- /* search for existing renders */
- for (re = RenderGlobal.renderlist.first; re; re = re->next)
- if (STREQLEN(re->name, name, RE_MAXNAME))
- break;
+ /* search for existing renders */
+ for (re = RenderGlobal.renderlist.first; re; re = re->next)
+ if (STREQLEN(re->name, name, RE_MAXNAME))
+ break;
- return re;
+ return re;
}
/* if you want to know exactly what has been done */
RenderResult *RE_AcquireResultRead(Render *re)
{
- if (re) {
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ);
- return re->result;
- }
+ if (re) {
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ);
+ return re->result;
+ }
- return NULL;
+ return NULL;
}
RenderResult *RE_AcquireResultWrite(Render *re)
{
- if (re) {
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- return re->result;
- }
+ if (re) {
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ return re->result;
+ }
- return NULL;
+ return NULL;
}
void RE_ClearResult(Render *re)
{
- if (re) {
- render_result_free(re->result);
- re->result = NULL;
- }
+ if (re) {
+ render_result_free(re->result);
+ re->result = NULL;
+ }
}
void RE_SwapResult(Render *re, RenderResult **rr)
{
- /* for keeping render buffers */
- if (re) {
- SWAP(RenderResult *, re->result, *rr);
- }
+ /* for keeping render buffers */
+ if (re) {
+ SWAP(RenderResult *, re->result, *rr);
+ }
}
-
void RE_ReleaseResult(Render *re)
{
- if (re)
- BLI_rw_mutex_unlock(&re->resultmutex);
+ if (re)
+ BLI_rw_mutex_unlock(&re->resultmutex);
}
/* displist.c util.... */
Scene *RE_GetScene(Render *re)
{
- if (re)
- return re->scene;
- return NULL;
+ if (re)
+ return re->scene;
+ return NULL;
}
void RE_SetScene(Render *re, Scene *sce)
{
- if (re) {
- re->scene = sce;
- }
+ if (re) {
+ re->scene = sce;
+ }
}
/**
@@ -368,58 +402,58 @@ void RE_SetScene(Render *re, Scene *sce)
*/
void RE_AcquireResultImageViews(Render *re, RenderResult *rr)
{
- memset(rr, 0, sizeof(RenderResult));
+ memset(rr, 0, sizeof(RenderResult));
- if (re) {
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ);
+ if (re) {
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ);
- if (re->result) {
- RenderLayer *rl;
- RenderView *rv, *rview;
+ if (re->result) {
+ RenderLayer *rl;
+ RenderView *rv, *rview;
- rr->rectx = re->result->rectx;
- rr->recty = re->result->recty;
+ rr->rectx = re->result->rectx;
+ rr->recty = re->result->recty;
- /* creates a temporary duplication of views */
- render_result_views_shallowcopy(rr, re->result);
+ /* creates a temporary duplication of views */
+ render_result_views_shallowcopy(rr, re->result);
- rv = rr->views.first;
- rr->have_combined = (rv->rectf != NULL);
+ rv = rr->views.first;
+ rr->have_combined = (rv->rectf != NULL);
- /* active layer */
- rl = render_get_active_layer(re, re->result);
+ /* active layer */
+ rl = render_get_active_layer(re, re->result);
- if (rl) {
- if (rv->rectf == NULL) {
- for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) {
- rview->rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, rview->name);
- }
- }
+ if (rl) {
+ if (rv->rectf == NULL) {
+ for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) {
+ rview->rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, rview->name);
+ }
+ }
- if (rv->rectz == NULL) {
- for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) {
- rview->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rview->name);
- }
- }
- }
+ if (rv->rectz == NULL) {
+ for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) {
+ rview->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rview->name);
+ }
+ }
+ }
- rr->layers = re->result->layers;
- rr->xof = re->disprect.xmin;
- rr->yof = re->disprect.ymin;
- rr->stamp_data = re->result->stamp_data;
- }
- }
+ rr->layers = re->result->layers;
+ rr->xof = re->disprect.xmin;
+ rr->yof = re->disprect.ymin;
+ rr->stamp_data = re->result->stamp_data;
+ }
+ }
}
/* clear temporary renderresult struct */
void RE_ReleaseResultImageViews(Render *re, RenderResult *rr)
{
- if (re) {
- if (rr) {
- render_result_views_shallowdelete(rr);
- }
- BLI_rw_mutex_unlock(&re->resultmutex);
- }
+ if (re) {
+ if (rr) {
+ render_result_views_shallowdelete(rr);
+ }
+ BLI_rw_mutex_unlock(&re->resultmutex);
+ }
}
/* fill provided result struct with what's currently active or done */
@@ -427,224 +461,236 @@ void RE_ReleaseResultImageViews(Render *re, RenderResult *rr)
/* always having at least one RenderView */
void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id)
{
- memset(rr, 0, sizeof(RenderResult));
+ memset(rr, 0, sizeof(RenderResult));
- if (re) {
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ);
+ if (re) {
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ);
- if (re->result) {
- RenderLayer *rl;
- RenderView *rv;
+ if (re->result) {
+ RenderLayer *rl;
+ RenderView *rv;
- rr->rectx = re->result->rectx;
- rr->recty = re->result->recty;
+ rr->rectx = re->result->rectx;
+ rr->recty = re->result->recty;
- /* actview view */
- rv = RE_RenderViewGetById(re->result, view_id);
- rr->have_combined = (rv->rectf != NULL);
+ /* actview view */
+ rv = RE_RenderViewGetById(re->result, view_id);
+ rr->have_combined = (rv->rectf != NULL);
- rr->rectf = rv->rectf;
- rr->rectz = rv->rectz;
- rr->rect32 = rv->rect32;
+ rr->rectf = rv->rectf;
+ rr->rectz = rv->rectz;
+ rr->rect32 = rv->rect32;
- /* active layer */
- rl = render_get_active_layer(re, re->result);
+ /* active layer */
+ rl = render_get_active_layer(re, re->result);
- if (rl) {
- if (rv->rectf == NULL)
- rr->rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, rv->name);
+ if (rl) {
+ if (rv->rectf == NULL)
+ rr->rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, rv->name);
- if (rv->rectz == NULL)
- rr->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rv->name);
- }
+ if (rv->rectz == NULL)
+ rr->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rv->name);
+ }
- rr->layers = re->result->layers;
- rr->views = re->result->views;
+ rr->layers = re->result->layers;
+ rr->views = re->result->views;
- rr->xof = re->disprect.xmin;
- rr->yof = re->disprect.ymin;
+ rr->xof = re->disprect.xmin;
+ rr->yof = re->disprect.ymin;
- rr->stamp_data = re->result->stamp_data;
- }
- }
+ rr->stamp_data = re->result->stamp_data;
+ }
+ }
}
void RE_ReleaseResultImage(Render *re)
{
- if (re)
- BLI_rw_mutex_unlock(&re->resultmutex);
+ if (re)
+ BLI_rw_mutex_unlock(&re->resultmutex);
}
/* caller is responsible for allocating rect in correct size! */
void RE_ResultGet32(Render *re, unsigned int *rect)
{
- RenderResult rres;
- const int view_id = BKE_scene_multiview_view_id_get(&re->r, re->viewname);
+ RenderResult rres;
+ const int view_id = BKE_scene_multiview_view_id_get(&re->r, re->viewname);
- RE_AcquireResultImageViews(re, &rres);
- render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings, view_id);
- RE_ReleaseResultImageViews(re, &rres);
+ RE_AcquireResultImageViews(re, &rres);
+ render_result_rect_get_pixels(&rres,
+ rect,
+ re->rectx,
+ re->recty,
+ &re->scene->view_settings,
+ &re->scene->display_settings,
+ view_id);
+ RE_ReleaseResultImageViews(re, &rres);
}
/* caller is responsible for allocating rect in correct size! */
/* Only for acquired results, for lock */
-void RE_AcquiredResultGet32(Render *re, RenderResult *result, unsigned int *rect, const int view_id)
+void RE_AcquiredResultGet32(Render *re,
+ RenderResult *result,
+ unsigned int *rect,
+ const int view_id)
{
- render_result_rect_get_pixels(result, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings, view_id);
+ render_result_rect_get_pixels(result,
+ rect,
+ re->rectx,
+ re->recty,
+ &re->scene->view_settings,
+ &re->scene->display_settings,
+ view_id);
}
RenderStats *RE_GetStats(Render *re)
{
- return &re->i;
+ return &re->i;
}
Render *RE_NewRender(const char *name)
{
- Render *re;
+ Render *re;
- /* only one render per name exists */
- re = RE_GetRender(name);
- if (re == NULL) {
+ /* only one render per name exists */
+ re = RE_GetRender(name);
+ if (re == NULL) {
- /* new render data struct */
- re = MEM_callocN(sizeof(Render), "new render");
- BLI_addtail(&RenderGlobal.renderlist, re);
- BLI_strncpy(re->name, name, RE_MAXNAME);
- BLI_rw_mutex_init(&re->resultmutex);
- BLI_rw_mutex_init(&re->partsmutex);
- }
+ /* new render data struct */
+ re = MEM_callocN(sizeof(Render), "new render");
+ BLI_addtail(&RenderGlobal.renderlist, re);
+ BLI_strncpy(re->name, name, RE_MAXNAME);
+ BLI_rw_mutex_init(&re->resultmutex);
+ BLI_rw_mutex_init(&re->partsmutex);
+ }
- RE_InitRenderCB(re);
+ RE_InitRenderCB(re);
- return re;
+ return re;
}
/* MAX_ID_NAME + sizeof(Library->name) + space + null-terminator. */
#define MAX_SCENE_RENDER_NAME (MAX_ID_NAME + 1024 + 2)
-static void scene_render_name_get(const Scene *scene,
- const size_t max_size,
- char *render_name)
+static void scene_render_name_get(const Scene *scene, const size_t max_size, char *render_name)
{
- if (ID_IS_LINKED(scene)) {
- BLI_snprintf(render_name, max_size, "%s %s",
- scene->id.lib->id.name, scene->id.name);
- }
- else {
- BLI_snprintf(render_name, max_size, "%s", scene->id.name);
- }
+ if (ID_IS_LINKED(scene)) {
+ BLI_snprintf(render_name, max_size, "%s %s", scene->id.lib->id.name, scene->id.name);
+ }
+ else {
+ BLI_snprintf(render_name, max_size, "%s", scene->id.name);
+ }
}
Render *RE_GetSceneRender(const Scene *scene)
{
- char render_name[MAX_SCENE_RENDER_NAME];
- scene_render_name_get(scene, sizeof(render_name), render_name);
- return RE_GetRender(render_name);
+ char render_name[MAX_SCENE_RENDER_NAME];
+ scene_render_name_get(scene, sizeof(render_name), render_name);
+ return RE_GetRender(render_name);
}
Render *RE_NewSceneRender(const Scene *scene)
{
- char render_name[MAX_SCENE_RENDER_NAME];
- scene_render_name_get(scene, sizeof(render_name), render_name);
- return RE_NewRender(render_name);
+ char render_name[MAX_SCENE_RENDER_NAME];
+ scene_render_name_get(scene, sizeof(render_name), render_name);
+ return RE_NewRender(render_name);
}
/* called for new renders and when finishing rendering so
* we always have valid callbacks on a render */
void RE_InitRenderCB(Render *re)
{
- /* set default empty callbacks */
- re->display_init = result_nothing;
- re->display_clear = result_nothing;
- re->display_update = result_rcti_nothing;
- re->current_scene_update = current_scene_nothing;
- re->progress = float_nothing;
- re->test_break = default_break;
- if (G.background)
- re->stats_draw = stats_background;
- else
- re->stats_draw = stats_nothing;
- /* clear callback handles */
- re->dih = re->dch = re->duh = re->sdh = re->prh = re->tbh = NULL;
+ /* set default empty callbacks */
+ re->display_init = result_nothing;
+ re->display_clear = result_nothing;
+ re->display_update = result_rcti_nothing;
+ re->current_scene_update = current_scene_nothing;
+ re->progress = float_nothing;
+ re->test_break = default_break;
+ if (G.background)
+ re->stats_draw = stats_background;
+ else
+ re->stats_draw = stats_nothing;
+ /* clear callback handles */
+ re->dih = re->dch = re->duh = re->sdh = re->prh = re->tbh = NULL;
}
/* only call this while you know it will remove the link too */
void RE_FreeRender(Render *re)
{
- if (re->engine)
- RE_engine_free(re->engine);
+ if (re->engine)
+ RE_engine_free(re->engine);
- BLI_rw_mutex_end(&re->resultmutex);
- BLI_rw_mutex_end(&re->partsmutex);
+ BLI_rw_mutex_end(&re->resultmutex);
+ BLI_rw_mutex_end(&re->partsmutex);
- BLI_freelistN(&re->view_layers);
- BLI_freelistN(&re->r.views);
+ BLI_freelistN(&re->view_layers);
+ BLI_freelistN(&re->r.views);
- curvemapping_free_data(&re->r.mblur_shutter_curve);
+ curvemapping_free_data(&re->r.mblur_shutter_curve);
- /* main dbase can already be invalid now, some database-free code checks it */
- re->main = NULL;
- re->scene = NULL;
+ /* main dbase can already be invalid now, some database-free code checks it */
+ re->main = NULL;
+ re->scene = NULL;
- render_result_free(re->result);
- render_result_free(re->pushedresult);
+ render_result_free(re->result);
+ render_result_free(re->pushedresult);
- BLI_remlink(&RenderGlobal.renderlist, re);
- MEM_freeN(re);
+ BLI_remlink(&RenderGlobal.renderlist, re);
+ MEM_freeN(re);
}
/* exit blender */
void RE_FreeAllRender(void)
{
- while (RenderGlobal.renderlist.first) {
- RE_FreeRender(RenderGlobal.renderlist.first);
- }
+ while (RenderGlobal.renderlist.first) {
+ RE_FreeRender(RenderGlobal.renderlist.first);
+ }
#ifdef WITH_FREESTYLE
- /* finalize Freestyle */
- FRS_exit();
+ /* finalize Freestyle */
+ FRS_exit();
#endif
}
void RE_FreeAllPersistentData(void)
{
- Render *re;
- for (re = RenderGlobal.renderlist.first; re != NULL; re = re->next) {
- if ((re->r.mode & R_PERSISTENT_DATA) != 0 && re->engine != NULL) {
- RE_engine_free(re->engine);
- re->engine = NULL;
- }
- }
+ Render *re;
+ for (re = RenderGlobal.renderlist.first; re != NULL; re = re->next) {
+ if ((re->r.mode & R_PERSISTENT_DATA) != 0 && re->engine != NULL) {
+ RE_engine_free(re->engine);
+ re->engine = NULL;
+ }
+ }
}
/* on file load, free all re */
void RE_FreeAllRenderResults(void)
{
- Render *re;
+ Render *re;
- for (re = RenderGlobal.renderlist.first; re; re = re->next) {
- render_result_free(re->result);
- render_result_free(re->pushedresult);
+ for (re = RenderGlobal.renderlist.first; re; re = re->next) {
+ render_result_free(re->result);
+ render_result_free(re->pushedresult);
- re->result = NULL;
- re->pushedresult = NULL;
- }
+ re->result = NULL;
+ re->pushedresult = NULL;
+ }
}
void RE_FreePersistentData(void)
{
- Render *re;
+ Render *re;
- /* render engines can be kept around for quick re-render, this clears all */
- for (re = RenderGlobal.renderlist.first; re; re = re->next) {
- if (re->engine) {
- /* if engine is currently rendering, just tag it to be freed when render is finished */
- if (!(re->engine->flag & RE_ENGINE_RENDERING))
- RE_engine_free(re->engine);
+ /* render engines can be kept around for quick re-render, this clears all */
+ for (re = RenderGlobal.renderlist.first; re; re = re->next) {
+ if (re->engine) {
+ /* if engine is currently rendering, just tag it to be freed when render is finished */
+ if (!(re->engine->flag & RE_ENGINE_RENDERING))
+ RE_engine_free(re->engine);
- re->engine = NULL;
- }
- }
+ re->engine = NULL;
+ }
+ }
}
/* ********* initialize state ******** */
@@ -652,244 +698,238 @@ void RE_FreePersistentData(void)
/* clear full sample and tile flags if needed */
static int check_mode_full_sample(RenderData *rd)
{
- int scemode = rd->scemode;
+ int scemode = rd->scemode;
- /* not supported by any current renderer */
- scemode &= ~R_FULL_SAMPLE;
+ /* not supported by any current renderer */
+ scemode &= ~R_FULL_SAMPLE;
#ifdef WITH_OPENEXR
- if (scemode & R_FULL_SAMPLE)
- scemode |= R_EXR_TILE_FILE; /* enable automatic */
+ if (scemode & R_FULL_SAMPLE)
+ scemode |= R_EXR_TILE_FILE; /* enable automatic */
#else
- /* can't do this without openexr support */
- scemode &= ~(R_EXR_TILE_FILE | R_FULL_SAMPLE);
+ /* can't do this without openexr support */
+ scemode &= ~(R_EXR_TILE_FILE | R_FULL_SAMPLE);
#endif
- return scemode;
+ return scemode;
}
-static void re_init_resolution(Render *re, Render *source,
- int winx, int winy, rcti *disprect)
+static void re_init_resolution(Render *re, Render *source, int winx, int winy, rcti *disprect)
{
- re->winx = winx;
- re->winy = winy;
- if (source && (source->r.mode & R_BORDER)) {
- /* eeh, doesn't seem original bordered disprect is storing anywhere
- * after insertion on black happening in do_render(),
- * so for now simply re-calculate disprect using border from source
- * renderer (sergey)
- */
+ re->winx = winx;
+ re->winy = winy;
+ if (source && (source->r.mode & R_BORDER)) {
+ /* eeh, doesn't seem original bordered disprect is storing anywhere
+ * after insertion on black happening in do_render(),
+ * so for now simply re-calculate disprect using border from source
+ * renderer (sergey)
+ */
- re->disprect.xmin = source->r.border.xmin * winx;
- re->disprect.xmax = source->r.border.xmax * winx;
+ re->disprect.xmin = source->r.border.xmin * winx;
+ re->disprect.xmax = source->r.border.xmax * winx;
- re->disprect.ymin = source->r.border.ymin * winy;
- re->disprect.ymax = source->r.border.ymax * winy;
+ re->disprect.ymin = source->r.border.ymin * winy;
+ re->disprect.ymax = source->r.border.ymax * winy;
- re->rectx = BLI_rcti_size_x(&re->disprect);
- re->recty = BLI_rcti_size_y(&re->disprect);
+ re->rectx = BLI_rcti_size_x(&re->disprect);
+ re->recty = BLI_rcti_size_y(&re->disprect);
- /* copy border itself, since it could be used by external engines */
- re->r.border = source->r.border;
- }
- else if (disprect) {
- re->disprect = *disprect;
- re->rectx = BLI_rcti_size_x(&re->disprect);
- re->recty = BLI_rcti_size_y(&re->disprect);
- }
- else {
- re->disprect.xmin = re->disprect.ymin = 0;
- re->disprect.xmax = winx;
- re->disprect.ymax = winy;
- re->rectx = winx;
- re->recty = winy;
- }
+ /* copy border itself, since it could be used by external engines */
+ re->r.border = source->r.border;
+ }
+ else if (disprect) {
+ re->disprect = *disprect;
+ re->rectx = BLI_rcti_size_x(&re->disprect);
+ re->recty = BLI_rcti_size_y(&re->disprect);
+ }
+ else {
+ re->disprect.xmin = re->disprect.ymin = 0;
+ re->disprect.xmax = winx;
+ re->disprect.ymax = winy;
+ re->rectx = winx;
+ re->recty = winy;
+ }
}
void render_copy_renderdata(RenderData *to, RenderData *from)
{
- BLI_freelistN(&to->views);
- curvemapping_free_data(&to->mblur_shutter_curve);
+ BLI_freelistN(&to->views);
+ curvemapping_free_data(&to->mblur_shutter_curve);
- *to = *from;
+ *to = *from;
- BLI_duplicatelist(&to->views, &from->views);
- curvemapping_copy_data(&to->mblur_shutter_curve, &from->mblur_shutter_curve);
+ BLI_duplicatelist(&to->views, &from->views);
+ curvemapping_copy_data(&to->mblur_shutter_curve, &from->mblur_shutter_curve);
}
/* what doesn't change during entire render sequence */
/* disprect is optional, if NULL it assumes full window render */
-void RE_InitState(Render *re, Render *source, RenderData *rd,
- ListBase *render_layers, ViewLayer *single_layer,
- int winx, int winy, rcti *disprect)
-{
- bool had_freestyle = (re->r.mode & R_EDGE_FRS) != 0;
-
- re->ok = true; /* maybe flag */
-
- re->i.starttime = PIL_check_seconds_timer();
-
- /* copy render data and render layers for thread safety */
- render_copy_renderdata(&re->r, rd);
- BLI_freelistN(&re->view_layers);
- BLI_duplicatelist(&re->view_layers, render_layers);
- re->active_view_layer = 0;
-
- if (source) {
- /* reuse border flags from source renderer */
- re->r.mode &= ~(R_BORDER | R_CROP);
- re->r.mode |= source->r.mode & (R_BORDER | R_CROP);
-
- /* dimensions shall be shared between all renderers */
- re->r.xsch = source->r.xsch;
- re->r.ysch = source->r.ysch;
- re->r.size = source->r.size;
- }
-
- re_init_resolution(re, source, winx, winy, disprect);
-
- /* disable border if it's a full render anyway */
- if (re->r.border.xmin == 0.0f && re->r.border.xmax == 1.0f &&
- re->r.border.ymin == 0.0f && re->r.border.ymax == 1.0f)
- {
- re->r.mode &= ~R_BORDER;
- }
-
- 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");
- re->ok = 0;
- return;
- }
-
- re->r.scemode = check_mode_full_sample(&re->r);
-
- if (single_layer) {
- int index = BLI_findindex(render_layers, single_layer);
- if (index != -1) {
- re->active_view_layer = index;
- re->r.scemode |= R_SINGLE_LAYER;
- }
- }
-
- /* if preview render, we try to keep old result */
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
-
- if (re->r.scemode & R_BUTS_PREVIEW) {
- if (had_freestyle || (re->r.mode & R_EDGE_FRS)) {
- /* freestyle manipulates render layers so always have to free */
- render_result_free(re->result);
- re->result = NULL;
- }
- else if (re->result) {
- ViewLayer *active_render_layer = BLI_findlink(&re->view_layers, re->active_view_layer);
- RenderLayer *rl;
- bool have_layer = false;
-
- for (rl = re->result->layers.first; rl; rl = rl->next)
- if (STREQ(rl->name, active_render_layer->name))
- have_layer = true;
-
- if (re->result->rectx == re->rectx && re->result->recty == re->recty &&
- have_layer)
- {
- /* keep render result, this avoids flickering black tiles
- * when the preview changes */
- }
- else {
- /* free because resolution changed */
- render_result_free(re->result);
- re->result = NULL;
- }
- }
- }
- else {
-
- /* make empty render result, so display callbacks can initialize */
- render_result_free(re->result);
- re->result = MEM_callocN(sizeof(RenderResult), "new render result");
- re->result->rectx = re->rectx;
- re->result->recty = re->recty;
- render_result_view_new(re->result, "");
- }
-
- /* ensure renderdatabase can use part settings correct */
- RE_parts_clamp(re);
-
- BLI_rw_mutex_unlock(&re->resultmutex);
-
- RE_init_threadcount(re);
-
- RE_point_density_fix_linking();
+void RE_InitState(Render *re,
+ Render *source,
+ RenderData *rd,
+ ListBase *render_layers,
+ ViewLayer *single_layer,
+ int winx,
+ int winy,
+ rcti *disprect)
+{
+ bool had_freestyle = (re->r.mode & R_EDGE_FRS) != 0;
+
+ re->ok = true; /* maybe flag */
+
+ re->i.starttime = PIL_check_seconds_timer();
+
+ /* copy render data and render layers for thread safety */
+ render_copy_renderdata(&re->r, rd);
+ BLI_freelistN(&re->view_layers);
+ BLI_duplicatelist(&re->view_layers, render_layers);
+ re->active_view_layer = 0;
+
+ if (source) {
+ /* reuse border flags from source renderer */
+ re->r.mode &= ~(R_BORDER | R_CROP);
+ re->r.mode |= source->r.mode & (R_BORDER | R_CROP);
+
+ /* dimensions shall be shared between all renderers */
+ re->r.xsch = source->r.xsch;
+ re->r.ysch = source->r.ysch;
+ re->r.size = source->r.size;
+ }
+
+ re_init_resolution(re, source, winx, winy, disprect);
+
+ /* disable border if it's a full render anyway */
+ if (re->r.border.xmin == 0.0f && re->r.border.xmax == 1.0f && re->r.border.ymin == 0.0f &&
+ re->r.border.ymax == 1.0f) {
+ re->r.mode &= ~R_BORDER;
+ }
+
+ 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");
+ re->ok = 0;
+ return;
+ }
+
+ re->r.scemode = check_mode_full_sample(&re->r);
+
+ if (single_layer) {
+ int index = BLI_findindex(render_layers, single_layer);
+ if (index != -1) {
+ re->active_view_layer = index;
+ re->r.scemode |= R_SINGLE_LAYER;
+ }
+ }
+
+ /* if preview render, we try to keep old result */
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+
+ if (re->r.scemode & R_BUTS_PREVIEW) {
+ if (had_freestyle || (re->r.mode & R_EDGE_FRS)) {
+ /* freestyle manipulates render layers so always have to free */
+ render_result_free(re->result);
+ re->result = NULL;
+ }
+ else if (re->result) {
+ ViewLayer *active_render_layer = BLI_findlink(&re->view_layers, re->active_view_layer);
+ RenderLayer *rl;
+ bool have_layer = false;
+
+ for (rl = re->result->layers.first; rl; rl = rl->next)
+ if (STREQ(rl->name, active_render_layer->name))
+ have_layer = true;
+
+ if (re->result->rectx == re->rectx && re->result->recty == re->recty && have_layer) {
+ /* keep render result, this avoids flickering black tiles
+ * when the preview changes */
+ }
+ else {
+ /* free because resolution changed */
+ render_result_free(re->result);
+ re->result = NULL;
+ }
+ }
+ }
+ else {
+
+ /* make empty render result, so display callbacks can initialize */
+ render_result_free(re->result);
+ re->result = MEM_callocN(sizeof(RenderResult), "new render result");
+ re->result->rectx = re->rectx;
+ re->result->recty = re->recty;
+ render_result_view_new(re->result, "");
+ }
+
+ /* ensure renderdatabase can use part settings correct */
+ RE_parts_clamp(re);
+
+ BLI_rw_mutex_unlock(&re->resultmutex);
+
+ RE_init_threadcount(re);
+
+ RE_point_density_fix_linking();
}
/* This function is only called by view3d rendering, which doesn't support
* multiview at the moment. so handle only one view here */
static void render_result_rescale(Render *re)
{
- RenderResult *result = re->result;
- RenderView *rv;
- int x, y;
- float scale_x, scale_y;
- float *src_rectf;
-
- rv = RE_RenderViewGetById(result, 0);
- src_rectf = rv->rectf;
-
- if (src_rectf == NULL) {
- RenderLayer *rl = render_get_active_layer(re, re->result);
- if (rl != NULL) {
- src_rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, NULL);
- }
- }
-
- if (src_rectf != NULL) {
- float *dst_rectf = NULL;
- re->result = render_result_new(re,
- &re->disprect,
- 0,
- RR_USE_MEM,
- RR_ALL_LAYERS,
- "");
-
- if (re->result != NULL) {
- dst_rectf = RE_RenderViewGetById(re->result, 0)->rectf;
- if (dst_rectf == NULL) {
- RenderLayer *rl;
- rl = render_get_active_layer(re, re->result);
- if (rl != NULL) {
- dst_rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, NULL);
- }
- }
-
- scale_x = (float)result->rectx / re->result->rectx;
- scale_y = (float)result->recty / re->result->recty;
- for (x = 0; x < re->result->rectx; ++x) {
- for (y = 0; y < re->result->recty; ++y) {
- int src_x = x * scale_x;
- int src_y = y * scale_y;
- int dst_index = y * re->result->rectx + x;
- int src_index = src_y * result->rectx + src_x;
- copy_v4_v4(dst_rectf + dst_index * 4,
- src_rectf + src_index * 4);
- }
- }
- }
- render_result_free(result);
- }
+ RenderResult *result = re->result;
+ RenderView *rv;
+ int x, y;
+ float scale_x, scale_y;
+ float *src_rectf;
+
+ rv = RE_RenderViewGetById(result, 0);
+ src_rectf = rv->rectf;
+
+ if (src_rectf == NULL) {
+ RenderLayer *rl = render_get_active_layer(re, re->result);
+ if (rl != NULL) {
+ src_rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, NULL);
+ }
+ }
+
+ if (src_rectf != NULL) {
+ float *dst_rectf = NULL;
+ re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, "");
+
+ if (re->result != NULL) {
+ dst_rectf = RE_RenderViewGetById(re->result, 0)->rectf;
+ if (dst_rectf == NULL) {
+ RenderLayer *rl;
+ rl = render_get_active_layer(re, re->result);
+ if (rl != NULL) {
+ dst_rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, NULL);
+ }
+ }
+
+ scale_x = (float)result->rectx / re->result->rectx;
+ scale_y = (float)result->recty / re->result->recty;
+ for (x = 0; x < re->result->rectx; ++x) {
+ for (y = 0; y < re->result->recty; ++y) {
+ int src_x = x * scale_x;
+ int src_y = y * scale_y;
+ int dst_index = y * re->result->rectx + x;
+ int src_index = src_y * result->rectx + src_x;
+ copy_v4_v4(dst_rectf + dst_index * 4, src_rectf + src_index * 4);
+ }
+ }
+ }
+ render_result_free(result);
+ }
}
void RE_ChangeResolution(Render *re, int winx, int winy, rcti *disprect)
{
- re_init_resolution(re, NULL, winx, winy, disprect);
- RE_parts_clamp(re);
+ re_init_resolution(re, NULL, winx, winy, disprect);
+ RE_parts_clamp(re);
- if (re->result) {
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- render_result_rescale(re);
- BLI_rw_mutex_unlock(&re->resultmutex);
- }
+ if (re->result) {
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ render_result_rescale(re);
+ BLI_rw_mutex_unlock(&re->resultmutex);
+ }
}
/* TODO(sergey): This is a bit hackish, used to temporary disable freestyle when
@@ -898,158 +938,167 @@ void RE_ChangeResolution(Render *re, int winx, int winy, rcti *disprect)
*/
void RE_ChangeModeFlag(Render *re, int flag, bool clear)
{
- if (clear) {
- re->r.mode &= ~flag;
- }
- else {
- re->r.mode |= flag;
- }
+ if (clear) {
+ re->r.mode &= ~flag;
+ }
+ else {
+ re->r.mode |= flag;
+ }
}
/* update some variables that can be animated, and otherwise wouldn't be due to
* RenderData getting copied once at the start of animation render */
void render_update_anim_renderdata(Render *re, RenderData *rd, ListBase *render_layers)
{
- /* filter */
- re->r.gauss = rd->gauss;
+ /* filter */
+ re->r.gauss = rd->gauss;
- /* motion blur */
- re->r.blurfac = rd->blurfac;
+ /* motion blur */
+ re->r.blurfac = rd->blurfac;
- /* freestyle */
- re->r.line_thickness_mode = rd->line_thickness_mode;
- re->r.unit_line_thickness = rd->unit_line_thickness;
+ /* freestyle */
+ re->r.line_thickness_mode = rd->line_thickness_mode;
+ re->r.unit_line_thickness = rd->unit_line_thickness;
- /* render layers */
- BLI_freelistN(&re->view_layers);
- BLI_duplicatelist(&re->view_layers, render_layers);
+ /* render layers */
+ BLI_freelistN(&re->view_layers);
+ BLI_duplicatelist(&re->view_layers, render_layers);
- /* render views */
- BLI_freelistN(&re->r.views);
- BLI_duplicatelist(&re->r.views, &rd->views);
+ /* render views */
+ BLI_freelistN(&re->r.views);
+ BLI_duplicatelist(&re->r.views, &rd->views);
}
void RE_SetWindow(Render *re, const rctf *viewplane, float clip_start, float clip_end)
{
- /* re->ok flag? */
-
- re->viewplane = *viewplane;
- re->clip_start = clip_start;
- re->clip_end = clip_end;
+ /* re->ok flag? */
- perspective_m4(re->winmat,
- re->viewplane.xmin, re->viewplane.xmax,
- re->viewplane.ymin, re->viewplane.ymax, re->clip_start, re->clip_end);
+ re->viewplane = *viewplane;
+ re->clip_start = clip_start;
+ re->clip_end = clip_end;
+ perspective_m4(re->winmat,
+ re->viewplane.xmin,
+ re->viewplane.xmax,
+ re->viewplane.ymin,
+ re->viewplane.ymax,
+ re->clip_start,
+ re->clip_end);
}
void RE_SetOrtho(Render *re, const rctf *viewplane, float clip_start, float clip_end)
{
- /* re->ok flag? */
+ /* re->ok flag? */
- re->viewplane = *viewplane;
- re->clip_start = clip_start;
- re->clip_end = clip_end;
+ re->viewplane = *viewplane;
+ re->clip_start = clip_start;
+ re->clip_end = clip_end;
- orthographic_m4(re->winmat,
- re->viewplane.xmin, re->viewplane.xmax,
- re->viewplane.ymin, re->viewplane.ymax, re->clip_start, re->clip_end);
+ orthographic_m4(re->winmat,
+ re->viewplane.xmin,
+ re->viewplane.xmax,
+ re->viewplane.ymin,
+ re->viewplane.ymax,
+ re->clip_start,
+ re->clip_end);
}
void RE_GetViewPlane(Render *re, rctf *r_viewplane, rcti *r_disprect)
{
- *r_viewplane = re->viewplane;
+ *r_viewplane = re->viewplane;
- /* make disprect zero when no border render, is needed to detect changes in 3d view render */
- if (re->r.mode & R_BORDER) {
- *r_disprect = re->disprect;
- }
- else {
- BLI_rcti_init(r_disprect, 0, 0, 0, 0);
- }
+ /* make disprect zero when no border render, is needed to detect changes in 3d view render */
+ if (re->r.mode & R_BORDER) {
+ *r_disprect = re->disprect;
+ }
+ else {
+ BLI_rcti_init(r_disprect, 0, 0, 0, 0);
+ }
}
/* image and movie output has to move to either imbuf or kernel */
void RE_display_init_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr))
{
- re->display_init = f;
- re->dih = handle;
+ re->display_init = f;
+ re->dih = handle;
}
void RE_display_clear_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr))
{
- re->display_clear = f;
- re->dch = handle;
+ re->display_clear = f;
+ re->dch = handle;
}
-void RE_display_update_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr, volatile rcti *rect))
+void RE_display_update_cb(Render *re,
+ void *handle,
+ void (*f)(void *handle, RenderResult *rr, volatile rcti *rect))
{
- re->display_update = f;
- re->duh = handle;
+ re->display_update = f;
+ re->duh = handle;
}
void RE_current_scene_update_cb(Render *re, void *handle, void (*f)(void *handle, Scene *scene))
{
- re->current_scene_update = f;
- re->suh = handle;
+ re->current_scene_update = f;
+ re->suh = handle;
}
void RE_stats_draw_cb(Render *re, void *handle, void (*f)(void *handle, RenderStats *rs))
{
- re->stats_draw = f;
- re->sdh = handle;
+ re->stats_draw = f;
+ re->sdh = handle;
}
void RE_progress_cb(Render *re, void *handle, void (*f)(void *handle, float))
{
- re->progress = f;
- re->prh = handle;
+ re->progress = f;
+ re->prh = handle;
}
void RE_draw_lock_cb(Render *re, void *handle, void (*f)(void *handle, int i))
{
- re->draw_lock = f;
- re->dlh = handle;
+ re->draw_lock = f;
+ re->dlh = handle;
}
void RE_test_break_cb(Render *re, void *handle, int (*f)(void *handle))
{
- re->test_break = f;
- re->tbh = handle;
+ re->test_break = f;
+ re->tbh = handle;
}
/* ********* GL Context ******** */
void RE_gl_context_create(Render *re)
{
- /* Needs to be created in the main ogl thread. */
- re->gl_context = WM_opengl_context_create();
- /* So we activate the window's one afterwards. */
- wm_window_reset_drawable();
+ /* Needs to be created in the main ogl thread. */
+ re->gl_context = WM_opengl_context_create();
+ /* So we activate the window's one afterwards. */
+ wm_window_reset_drawable();
}
void RE_gl_context_destroy(Render *re)
{
- /* Needs to be called from the thread which used the ogl context for rendering. */
- if (re->gl_context) {
- if (re->gpu_context) {
- WM_opengl_context_activate(re->gl_context);
- GPU_context_active_set(re->gpu_context);
- GPU_context_discard(re->gpu_context);
- re->gpu_context = NULL;
- }
+ /* Needs to be called from the thread which used the ogl context for rendering. */
+ if (re->gl_context) {
+ if (re->gpu_context) {
+ WM_opengl_context_activate(re->gl_context);
+ GPU_context_active_set(re->gpu_context);
+ GPU_context_discard(re->gpu_context);
+ re->gpu_context = NULL;
+ }
- WM_opengl_context_dispose(re->gl_context);
- re->gl_context = NULL;
- }
+ WM_opengl_context_dispose(re->gl_context);
+ re->gl_context = NULL;
+ }
}
void *RE_gl_context_get(Render *re)
{
- return re->gl_context;
+ return re->gl_context;
}
void *RE_gpu_context_get(Render *re)
{
- if (re->gpu_context == NULL) {
- re->gpu_context = GPU_context_create();
- }
- return re->gpu_context;
+ if (re->gpu_context == NULL) {
+ re->gpu_context = GPU_context_create();
+ }
+ return re->gpu_context;
}
/* ********* add object data (later) ******** */
@@ -1071,520 +1120,529 @@ static void add_freestyle(Render *re, int render);
static void free_all_freestyle_renders(void);
#endif
-
/* ************ This part uses API, for rendering Blender scenes ********** */
static void do_render_3d(Render *re)
{
- re->current_scene_update(re->suh, re->scene);
- RE_engine_render(re, 0);
+ re->current_scene_update(re->suh, re->scene);
+ RE_engine_render(re, 0);
}
/* make sure disprect is not affected by the render border */
static void render_result_disprect_to_full_resolution(Render *re)
{
- re->disprect.xmin = re->disprect.ymin = 0;
- re->disprect.xmax = re->winx;
- re->disprect.ymax = re->winy;
- re->rectx = re->winx;
- re->recty = re->winy;
+ re->disprect.xmin = re->disprect.ymin = 0;
+ re->disprect.xmax = re->winx;
+ re->disprect.ymax = re->winy;
+ re->rectx = re->winx;
+ re->recty = re->winy;
}
static void render_result_uncrop(Render *re)
{
- /* when using border render with crop disabled, insert render result into
- * full size with black pixels outside */
- if (re->result && (re->r.mode & R_BORDER)) {
- if ((re->r.mode & R_CROP) == 0) {
- RenderResult *rres;
+ /* when using border render with crop disabled, insert render result into
+ * full size with black pixels outside */
+ if (re->result && (re->r.mode & R_BORDER)) {
+ if ((re->r.mode & R_CROP) == 0) {
+ RenderResult *rres;
- /* backup */
- const rcti orig_disprect = re->disprect;
- const int orig_rectx = re->rectx, orig_recty = re->recty;
+ /* backup */
+ const rcti orig_disprect = re->disprect;
+ const int orig_rectx = re->rectx, orig_recty = re->recty;
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- /* sub-rect for merge call later on */
- re->result->tilerect = re->disprect;
+ /* sub-rect for merge call later on */
+ re->result->tilerect = re->disprect;
- /* weak is: it chances disprect from border */
- render_result_disprect_to_full_resolution(re);
+ /* weak is: it chances disprect from border */
+ render_result_disprect_to_full_resolution(re);
- rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
- rres->stamp_data = BKE_stamp_data_copy(re->result->stamp_data);
+ rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
+ rres->stamp_data = BKE_stamp_data_copy(re->result->stamp_data);
- render_result_clone_passes(re, rres, NULL);
+ render_result_clone_passes(re, rres, NULL);
- render_result_merge(rres, re->result);
- render_result_free(re->result);
- re->result = rres;
+ render_result_merge(rres, re->result);
+ render_result_free(re->result);
+ re->result = rres;
- /* weak... the display callback wants an active renderlayer pointer... */
- re->result->renlay = render_get_active_layer(re, re->result);
+ /* weak... the display callback wants an active renderlayer pointer... */
+ re->result->renlay = render_get_active_layer(re, re->result);
- BLI_rw_mutex_unlock(&re->resultmutex);
+ BLI_rw_mutex_unlock(&re->resultmutex);
- re->display_init(re->dih, re->result);
- re->display_update(re->duh, re->result, NULL);
+ re->display_init(re->dih, re->result);
+ re->display_update(re->duh, re->result, NULL);
- /* restore the disprect from border */
- re->disprect = orig_disprect;
- re->rectx = orig_rectx;
- re->recty = orig_recty;
- }
- else {
- /* set offset (again) for use in compositor, disprect was manipulated. */
- re->result->xof = 0;
- re->result->yof = 0;
- }
- }
+ /* restore the disprect from border */
+ re->disprect = orig_disprect;
+ re->rectx = orig_rectx;
+ re->recty = orig_recty;
+ }
+ else {
+ /* set offset (again) for use in compositor, disprect was manipulated. */
+ re->result->xof = 0;
+ re->result->yof = 0;
+ }
+ }
}
/* main render routine, no compositing */
static void do_render(Render *re)
{
- Object *camera = RE_GetCamera(re);
- /* also check for camera here */
- if (camera == NULL) {
- BKE_report(re->reports, RPT_ERROR, "Cannot render, no camera");
- G.is_break = true;
- return;
- }
+ Object *camera = RE_GetCamera(re);
+ /* also check for camera here */
+ if (camera == NULL) {
+ BKE_report(re->reports, RPT_ERROR, "Cannot render, no camera");
+ G.is_break = true;
+ return;
+ }
- /* now use renderdata and camera to set viewplane */
- RE_SetCamera(re, camera);
+ /* now use renderdata and camera to set viewplane */
+ RE_SetCamera(re, camera);
- do_render_3d(re);
+ do_render_3d(re);
- /* when border render, check if we have to insert it in black */
- render_result_uncrop(re);
+ /* when border render, check if we have to insert it in black */
+ render_result_uncrop(re);
}
-
/* within context of current Render *re, render another scene.
* it uses current render image size and disprect, but doesn't execute composite
*/
static void render_scene(Render *re, Scene *sce, int cfra)
{
- Render *resc = RE_NewSceneRender(sce);
- int winx = re->winx, winy = re->winy;
+ Render *resc = RE_NewSceneRender(sce);
+ int winx = re->winx, winy = re->winy;
- sce->r.cfra = cfra;
+ sce->r.cfra = cfra;
- BKE_scene_camera_switch_update(sce);
+ BKE_scene_camera_switch_update(sce);
- /* exception: scene uses own size (unfinished code) */
- if (0) {
- winx = (sce->r.size * sce->r.xsch) / 100;
- winy = (sce->r.size * sce->r.ysch) / 100;
- }
+ /* exception: scene uses own size (unfinished code) */
+ if (0) {
+ winx = (sce->r.size * sce->r.xsch) / 100;
+ winy = (sce->r.size * sce->r.ysch) / 100;
+ }
- /* initial setup */
- RE_InitState(resc, re, &sce->r, &sce->view_layers, NULL, winx, winy, &re->disprect);
+ /* initial setup */
+ RE_InitState(resc, re, &sce->r, &sce->view_layers, NULL, winx, winy, &re->disprect);
- /* We still want to use 'rendercache' setting from org (main) scene... */
- resc->r.scemode = (resc->r.scemode & ~R_EXR_CACHE_FILE) | (re->r.scemode & R_EXR_CACHE_FILE);
+ /* We still want to use 'rendercache' setting from org (main) scene... */
+ resc->r.scemode = (resc->r.scemode & ~R_EXR_CACHE_FILE) | (re->r.scemode & R_EXR_CACHE_FILE);
- /* still unsure entity this... */
- resc->main = re->main;
- resc->scene = sce;
+ /* still unsure entity this... */
+ resc->main = re->main;
+ resc->scene = sce;
- /* copy callbacks */
- resc->display_update = re->display_update;
- resc->duh = re->duh;
- resc->test_break = re->test_break;
- resc->tbh = re->tbh;
- resc->stats_draw = re->stats_draw;
- resc->sdh = re->sdh;
- resc->current_scene_update = re->current_scene_update;
- resc->suh = re->suh;
+ /* copy callbacks */
+ resc->display_update = re->display_update;
+ resc->duh = re->duh;
+ resc->test_break = re->test_break;
+ resc->tbh = re->tbh;
+ resc->stats_draw = re->stats_draw;
+ resc->sdh = re->sdh;
+ resc->current_scene_update = re->current_scene_update;
+ resc->suh = re->suh;
- do_render(resc);
+ do_render(resc);
}
/* helper call to detect if this scene needs a render, or if there's a any render layer to render */
static int composite_needs_render(Scene *sce, int this_scene)
{
- bNodeTree *ntree = sce->nodetree;
- bNode *node;
+ bNodeTree *ntree = sce->nodetree;
+ bNode *node;
- if (ntree == NULL) return 1;
- if (sce->use_nodes == false) return 1;
- if ((sce->r.scemode & R_DOCOMP) == 0) return 1;
+ if (ntree == NULL)
+ return 1;
+ if (sce->use_nodes == false)
+ return 1;
+ if ((sce->r.scemode & R_DOCOMP) == 0)
+ return 1;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0)
- if (this_scene == 0 || node->id == NULL || node->id == &sce->id)
- return 1;
- }
- return 0;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0)
+ if (this_scene == 0 || node->id == NULL || node->id == &sce->id)
+ return 1;
+ }
+ return 0;
}
bool RE_allow_render_generic_object(Object *ob)
{
- /* override not showing object when duplis are used with particles */
- if (ob->transflag & OB_DUPLIPARTS) {
- /* pass */ /* let particle system(s) handle showing vs. not showing */
- }
- else if (ob->transflag & OB_DUPLI) {
- return false;
- }
- return true;
+ /* override not showing object when duplis are used with particles */
+ if (ob->transflag & OB_DUPLIPARTS) {
+ /* pass */ /* let particle system(s) handle showing vs. not showing */
+ }
+ else if (ob->transflag & OB_DUPLI) {
+ return false;
+ }
+ return true;
}
static void ntree_render_scenes(Render *re)
{
- bNode *node;
- int cfra = re->scene->r.cfra;
- Scene *restore_scene = re->scene;
-
- if (re->scene->nodetree == NULL) return;
-
- /* now foreach render-result node we do a full render */
- /* results are stored in a way compositor will find it */
- GSet *scenes_rendered = BLI_gset_ptr_new(__func__);
- for (node = re->scene->nodetree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0) {
- if (node->id && node->id != (ID *)re->scene) {
- Scene *scene = (Scene *)node->id;
- if (!BLI_gset_haskey(scenes_rendered, scene) && render_scene_has_layers_to_render(scene, false)) {
- render_scene(re, scene, cfra);
- BLI_gset_add(scenes_rendered, scene);
- nodeUpdate(restore_scene->nodetree, node);
- }
- }
- }
- }
- BLI_gset_free(scenes_rendered, NULL);
+ bNode *node;
+ int cfra = re->scene->r.cfra;
+ Scene *restore_scene = re->scene;
+
+ if (re->scene->nodetree == NULL)
+ return;
+
+ /* now foreach render-result node we do a full render */
+ /* results are stored in a way compositor will find it */
+ GSet *scenes_rendered = BLI_gset_ptr_new(__func__);
+ for (node = re->scene->nodetree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0) {
+ if (node->id && node->id != (ID *)re->scene) {
+ Scene *scene = (Scene *)node->id;
+ if (!BLI_gset_haskey(scenes_rendered, scene) &&
+ render_scene_has_layers_to_render(scene, false)) {
+ render_scene(re, scene, cfra);
+ BLI_gset_add(scenes_rendered, scene);
+ nodeUpdate(restore_scene->nodetree, node);
+ }
+ }
+ }
+ }
+ BLI_gset_free(scenes_rendered, NULL);
}
/* bad call... need to think over proper method still */
static void render_composit_stats(void *arg, const char *str)
{
- Render *re = (Render *)arg;
+ Render *re = (Render *)arg;
- RenderStats i;
- memcpy(&i, &re->i, sizeof(i));
- i.infostr = str;
- re->stats_draw(re->sdh, &i);
+ RenderStats i;
+ memcpy(&i, &re->i, sizeof(i));
+ i.infostr = str;
+ re->stats_draw(re->sdh, &i);
}
#ifdef WITH_FREESTYLE
/* init Freestyle renderer */
static void init_freestyle(Render *re)
{
- re->freestyle_bmain = BKE_main_new();
+ re->freestyle_bmain = BKE_main_new();
- /* We use the same window manager for freestyle bmain as
- * real bmain uses. This is needed because freestyle's
- * bmain could be used to tag scenes for update, which
- * implies call of ED_render_scene_update in some cases
- * and that function requires proper window manager
- * to present (sergey)
- */
- re->freestyle_bmain->wm = re->main->wm;
+ /* We use the same window manager for freestyle bmain as
+ * real bmain uses. This is needed because freestyle's
+ * bmain could be used to tag scenes for update, which
+ * implies call of ED_render_scene_update in some cases
+ * and that function requires proper window manager
+ * to present (sergey)
+ */
+ re->freestyle_bmain->wm = re->main->wm;
- FRS_init_stroke_renderer(re);
+ FRS_init_stroke_renderer(re);
}
/* invokes Freestyle stroke rendering */
static void add_freestyle(Render *re, int render)
{
- ViewLayer *view_layer, *active_view_layer;
- LinkData *link;
- Render *r;
+ ViewLayer *view_layer, *active_view_layer;
+ LinkData *link;
+ Render *r;
- active_view_layer = BLI_findlink(&re->view_layers, re->active_view_layer);
+ active_view_layer = BLI_findlink(&re->view_layers, re->active_view_layer);
- FRS_begin_stroke_rendering(re);
+ FRS_begin_stroke_rendering(re);
- for (view_layer = (ViewLayer *)re->view_layers.first; view_layer; view_layer = view_layer->next) {
- link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render");
- BLI_addtail(&re->freestyle_renders, link);
+ for (view_layer = (ViewLayer *)re->view_layers.first; view_layer;
+ view_layer = view_layer->next) {
+ link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render");
+ BLI_addtail(&re->freestyle_renders, link);
- if ((re->r.scemode & R_SINGLE_LAYER) && view_layer != active_view_layer)
- continue;
- if (FRS_is_freestyle_enabled(view_layer)) {
- r = FRS_do_stroke_rendering(re, view_layer, render);
- link->data = (void *)r;
- }
- }
+ if ((re->r.scemode & R_SINGLE_LAYER) && view_layer != active_view_layer)
+ continue;
+ if (FRS_is_freestyle_enabled(view_layer)) {
+ r = FRS_do_stroke_rendering(re, view_layer, render);
+ link->data = (void *)r;
+ }
+ }
- FRS_end_stroke_rendering(re);
+ FRS_end_stroke_rendering(re);
}
/* releases temporary scenes and renders for Freestyle stroke rendering */
static void free_all_freestyle_renders(void)
{
- Render *re1;
- LinkData *link;
+ Render *re1;
+ LinkData *link;
- for (re1 = RenderGlobal.renderlist.first; re1; re1 = re1->next) {
- for (link = (LinkData *)re1->freestyle_renders.first; link; link = link->next) {
- Render *freestyle_render = (Render *)link->data;
+ for (re1 = RenderGlobal.renderlist.first; re1; re1 = re1->next) {
+ for (link = (LinkData *)re1->freestyle_renders.first; link; link = link->next) {
+ Render *freestyle_render = (Render *)link->data;
- if (freestyle_render) {
- Scene *freestyle_scene = freestyle_render->scene;
- RE_FreeRender(freestyle_render);
+ if (freestyle_render) {
+ Scene *freestyle_scene = freestyle_render->scene;
+ RE_FreeRender(freestyle_render);
- if (freestyle_scene) {
- BKE_libblock_unlink(re1->freestyle_bmain, freestyle_scene, false, false);
- BKE_id_free(re1->freestyle_bmain, freestyle_scene);
- }
- }
- }
- BLI_freelistN(&re1->freestyle_renders);
+ if (freestyle_scene) {
+ BKE_libblock_unlink(re1->freestyle_bmain, freestyle_scene, false, false);
+ BKE_id_free(re1->freestyle_bmain, freestyle_scene);
+ }
+ }
+ }
+ BLI_freelistN(&re1->freestyle_renders);
- if (re1->freestyle_bmain) {
- /* detach the window manager from freestyle bmain (see comments
- * in add_freestyle() for more detail)
- */
- BLI_listbase_clear(&re1->freestyle_bmain->wm);
+ if (re1->freestyle_bmain) {
+ /* detach the window manager from freestyle bmain (see comments
+ * in add_freestyle() for more detail)
+ */
+ BLI_listbase_clear(&re1->freestyle_bmain->wm);
- BKE_main_free(re1->freestyle_bmain);
- re1->freestyle_bmain = NULL;
- }
- }
+ BKE_main_free(re1->freestyle_bmain);
+ re1->freestyle_bmain = NULL;
+ }
+ }
}
#endif
/* returns fully composited render-result on given time step (in RenderData) */
static void do_render_composite(Render *re)
{
- bNodeTree *ntree = re->scene->nodetree;
- int update_newframe = 0;
-
- if (composite_needs_render(re->scene, 1)) {
- /* save memory... free all cached images */
- ntreeFreeCache(ntree);
-
- /* render the frames
- * it could be optimized to render only the needed view
- * but what if a scene has a different number of views
- * than the main scene? */
- do_render(re);
- }
- else {
- re->i.cfra = re->r.cfra;
-
- /* ensure new result gets added, like for regular renders */
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
-
- render_result_free(re->result);
- if ((re->r.mode & R_CROP) == 0) {
- render_result_disprect_to_full_resolution(re);
- }
- re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
-
- BLI_rw_mutex_unlock(&re->resultmutex);
-
- /* scene render process already updates animsys */
- update_newframe = 1;
- }
-
- /* swap render result */
- if (re->r.scemode & R_SINGLE_LAYER) {
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- render_result_single_layer_end(re);
- BLI_rw_mutex_unlock(&re->resultmutex);
- }
-
- if (!re->test_break(re->tbh)) {
-
- if (ntree) {
- ntreeCompositTagRender(re->scene);
- ntreeCompositTagAnimated(ntree);
- }
-
- if (ntree && re->scene->use_nodes && re->r.scemode & R_DOCOMP) {
- /* checks if there are render-result nodes that need scene */
- if ((re->r.scemode & R_SINGLE_LAYER) == 0)
- ntree_render_scenes(re);
-
- if (!re->test_break(re->tbh)) {
- ntree->stats_draw = render_composit_stats;
- ntree->test_break = re->test_break;
- ntree->progress = re->progress;
- ntree->sdh = re;
- ntree->tbh = re->tbh;
- ntree->prh = re->prh;
-
- if (update_newframe) {
- /* If we have consistent depsgraph now would be a time to update them. */
- }
-
- RenderView *rv;
- for (rv = re->result->views.first; rv; rv = rv->next) {
- ntreeCompositExecTree(re->scene, ntree, &re->r, true, G.background == 0, &re->scene->view_settings, &re->scene->display_settings, rv->name);
- }
-
- ntree->stats_draw = NULL;
- ntree->test_break = NULL;
- ntree->progress = NULL;
- ntree->tbh = ntree->sdh = ntree->prh = NULL;
- }
- }
- }
+ bNodeTree *ntree = re->scene->nodetree;
+ int update_newframe = 0;
+
+ if (composite_needs_render(re->scene, 1)) {
+ /* save memory... free all cached images */
+ ntreeFreeCache(ntree);
+
+ /* render the frames
+ * it could be optimized to render only the needed view
+ * but what if a scene has a different number of views
+ * than the main scene? */
+ do_render(re);
+ }
+ else {
+ re->i.cfra = re->r.cfra;
+
+ /* ensure new result gets added, like for regular renders */
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+
+ render_result_free(re->result);
+ if ((re->r.mode & R_CROP) == 0) {
+ render_result_disprect_to_full_resolution(re);
+ }
+ re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
+
+ BLI_rw_mutex_unlock(&re->resultmutex);
+
+ /* scene render process already updates animsys */
+ update_newframe = 1;
+ }
+
+ /* swap render result */
+ if (re->r.scemode & R_SINGLE_LAYER) {
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ render_result_single_layer_end(re);
+ BLI_rw_mutex_unlock(&re->resultmutex);
+ }
+
+ if (!re->test_break(re->tbh)) {
+
+ if (ntree) {
+ ntreeCompositTagRender(re->scene);
+ ntreeCompositTagAnimated(ntree);
+ }
+
+ if (ntree && re->scene->use_nodes && re->r.scemode & R_DOCOMP) {
+ /* checks if there are render-result nodes that need scene */
+ if ((re->r.scemode & R_SINGLE_LAYER) == 0)
+ ntree_render_scenes(re);
+
+ if (!re->test_break(re->tbh)) {
+ ntree->stats_draw = render_composit_stats;
+ ntree->test_break = re->test_break;
+ ntree->progress = re->progress;
+ ntree->sdh = re;
+ ntree->tbh = re->tbh;
+ ntree->prh = re->prh;
+
+ if (update_newframe) {
+ /* If we have consistent depsgraph now would be a time to update them. */
+ }
+
+ RenderView *rv;
+ for (rv = re->result->views.first; rv; rv = rv->next) {
+ ntreeCompositExecTree(re->scene,
+ ntree,
+ &re->r,
+ true,
+ G.background == 0,
+ &re->scene->view_settings,
+ &re->scene->display_settings,
+ rv->name);
+ }
+
+ ntree->stats_draw = NULL;
+ ntree->test_break = NULL;
+ ntree->progress = NULL;
+ ntree->tbh = ntree->sdh = ntree->prh = NULL;
+ }
+ }
+ }
#ifdef WITH_FREESTYLE
- free_all_freestyle_renders();
+ free_all_freestyle_renders();
#endif
- /* weak... the display callback wants an active renderlayer pointer... */
- if (re->result != NULL) {
- re->result->renlay = render_get_active_layer(re, re->result);
- re->display_update(re->duh, re->result, NULL);
- }
+ /* weak... the display callback wants an active renderlayer pointer... */
+ if (re->result != NULL) {
+ re->result->renlay = render_get_active_layer(re, re->result);
+ re->display_update(re->duh, re->result, NULL);
+ }
}
static void renderresult_stampinfo(Render *re)
{
- RenderResult rres;
- RenderView *rv;
- int nr;
-
- /* this is the basic trick to get the displayed float or char rect from render result */
- nr = 0;
- for (rv = re->result->views.first; rv; rv = rv->next, nr++) {
- RE_SetActiveRenderView(re, rv->name);
- RE_AcquireResultImage(re, &rres, nr);
- BKE_image_stamp_buf(re->scene,
- RE_GetCamera(re),
- (re->r.stamp & R_STAMP_STRIPMETA) ? rres.stamp_data : NULL,
- (unsigned char *)rres.rect32,
- rres.rectf,
- rres.rectx, rres.recty,
- 4);
- RE_ReleaseResultImage(re);
- }
+ RenderResult rres;
+ RenderView *rv;
+ int nr;
+
+ /* this is the basic trick to get the displayed float or char rect from render result */
+ nr = 0;
+ for (rv = re->result->views.first; rv; rv = rv->next, nr++) {
+ RE_SetActiveRenderView(re, rv->name);
+ RE_AcquireResultImage(re, &rres, nr);
+ BKE_image_stamp_buf(re->scene,
+ RE_GetCamera(re),
+ (re->r.stamp & R_STAMP_STRIPMETA) ? rres.stamp_data : NULL,
+ (unsigned char *)rres.rect32,
+ rres.rectf,
+ rres.rectx,
+ rres.recty,
+ 4);
+ RE_ReleaseResultImage(re);
+ }
}
int RE_seq_render_active(Scene *scene, RenderData *rd)
{
- Editing *ed;
- Sequence *seq;
+ Editing *ed;
+ Sequence *seq;
- ed = scene->ed;
+ ed = scene->ed;
- if (!(rd->scemode & R_DOSEQ) || !ed || !ed->seqbase.first)
- return 0;
+ if (!(rd->scemode & R_DOSEQ) || !ed || !ed->seqbase.first)
+ return 0;
- for (seq = ed->seqbase.first; seq; seq = seq->next) {
- if (seq->type != SEQ_TYPE_SOUND_RAM)
- return 1;
- }
+ for (seq = ed->seqbase.first; seq; seq = seq->next) {
+ if (seq->type != SEQ_TYPE_SOUND_RAM)
+ return 1;
+ }
- return 0;
+ return 0;
}
static void do_render_seq(Render *re)
{
- static int recurs_depth = 0;
- struct ImBuf *out;
- RenderResult *rr; /* don't assign re->result here as it might change during give_ibuf_seq */
- int cfra = re->r.cfra;
- SeqRenderData context;
- int view_id, tot_views;
- struct ImBuf **ibuf_arr;
- int re_x, re_y;
-
- re->i.cfra = cfra;
-
- recurs_depth++;
-
- if ((re->r.mode & R_BORDER) && (re->r.mode & R_CROP) == 0) {
- /* if border rendering is used and cropping is disabled, final buffer should
- * be as large as the whole frame */
- re_x = re->winx;
- re_y = re->winy;
- }
- else {
- re_x = re->result->rectx;
- re_y = re->result->recty;
- }
-
- tot_views = BKE_scene_multiview_num_views_get(&re->r);
- ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * tot_views, "Sequencer Views ImBufs");
-
- /* TODO(sergey): Currently depsgraph is only used to check whether it is an active
- * edit window or not to deal with unkeyed changes. We don't have depsgraph here yet,
- * but we also dont' deal with unkeyed changes. But still nice to get proper depsgraph
- * within tjhe render pipeline, somehow.
- */
- BKE_sequencer_new_render_data(
- re->main, NULL, re->scene,
- re_x, re_y, 100, true,
- &context);
-
- /* the renderresult gets destroyed during the rendering, so we first collect all ibufs
- * and then we populate the final renderesult */
-
- for (view_id = 0; view_id < tot_views; view_id++) {
- context.view_id = view_id;
- out = BKE_sequencer_give_ibuf(&context, cfra, 0);
-
- if (out) {
- ibuf_arr[view_id] = IMB_dupImBuf(out);
- IMB_metadata_copy(ibuf_arr[view_id], out);
- IMB_freeImBuf(out);
- BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf_arr[view_id]);
- }
- else {
- ibuf_arr[view_id] = NULL;
- }
- }
-
- rr = re->result;
-
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- render_result_views_new(rr, &re->r);
- BLI_rw_mutex_unlock(&re->resultmutex);
-
- for (view_id = 0; view_id < tot_views; view_id++) {
- RenderView *rv = RE_RenderViewGetById(rr, view_id);
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
-
- if (ibuf_arr[view_id]) {
- /* copy ibuf into combined pixel rect */
- RE_render_result_rect_from_ibuf(rr, &re->r, ibuf_arr[view_id], view_id);
-
- if (ibuf_arr[view_id]->metadata && (re->r.stamp & R_STAMP_STRIPMETA)) {
- /* ensure render stamp info first */
- BKE_render_result_stamp_info(NULL, NULL, rr, true);
- BKE_stamp_info_from_imbuf(rr, ibuf_arr[view_id]);
- }
-
- if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */
- Editing *ed = re->scene->ed;
- if (ed)
- BKE_sequencer_free_imbuf(re->scene, &ed->seqbase, true);
- }
- IMB_freeImBuf(ibuf_arr[view_id]);
- }
- else {
- /* render result is delivered empty in most cases, nevertheless we handle all cases */
- render_result_rect_fill_zero(rr, view_id);
- }
-
- BLI_rw_mutex_unlock(&re->resultmutex);
-
- /* would mark display buffers as invalid */
- RE_SetActiveRenderView(re, rv->name);
- re->display_update(re->duh, re->result, NULL);
- }
-
- MEM_freeN(ibuf_arr);
-
- recurs_depth--;
-
- /* just in case this flag went missing at some point */
- re->r.scemode |= R_DOSEQ;
-
- /* set overall progress of sequence rendering */
- if (re->r.efra != re->r.sfra)
- re->progress(re->prh, (float)(cfra - re->r.sfra) / (re->r.efra - re->r.sfra));
- else
- re->progress(re->prh, 1.0f);
+ static int recurs_depth = 0;
+ struct ImBuf *out;
+ RenderResult *rr; /* don't assign re->result here as it might change during give_ibuf_seq */
+ int cfra = re->r.cfra;
+ SeqRenderData context;
+ int view_id, tot_views;
+ struct ImBuf **ibuf_arr;
+ int re_x, re_y;
+
+ re->i.cfra = cfra;
+
+ recurs_depth++;
+
+ if ((re->r.mode & R_BORDER) && (re->r.mode & R_CROP) == 0) {
+ /* if border rendering is used and cropping is disabled, final buffer should
+ * be as large as the whole frame */
+ re_x = re->winx;
+ re_y = re->winy;
+ }
+ else {
+ re_x = re->result->rectx;
+ re_y = re->result->recty;
+ }
+
+ tot_views = BKE_scene_multiview_num_views_get(&re->r);
+ ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * tot_views, "Sequencer Views ImBufs");
+
+ /* TODO(sergey): Currently depsgraph is only used to check whether it is an active
+ * edit window or not to deal with unkeyed changes. We don't have depsgraph here yet,
+ * but we also dont' deal with unkeyed changes. But still nice to get proper depsgraph
+ * within tjhe render pipeline, somehow.
+ */
+ BKE_sequencer_new_render_data(re->main, NULL, re->scene, re_x, re_y, 100, true, &context);
+
+ /* the renderresult gets destroyed during the rendering, so we first collect all ibufs
+ * and then we populate the final renderesult */
+
+ for (view_id = 0; view_id < tot_views; view_id++) {
+ context.view_id = view_id;
+ out = BKE_sequencer_give_ibuf(&context, cfra, 0);
+
+ if (out) {
+ ibuf_arr[view_id] = IMB_dupImBuf(out);
+ IMB_metadata_copy(ibuf_arr[view_id], out);
+ IMB_freeImBuf(out);
+ BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf_arr[view_id]);
+ }
+ else {
+ ibuf_arr[view_id] = NULL;
+ }
+ }
+
+ rr = re->result;
+
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ render_result_views_new(rr, &re->r);
+ BLI_rw_mutex_unlock(&re->resultmutex);
+
+ for (view_id = 0; view_id < tot_views; view_id++) {
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+
+ if (ibuf_arr[view_id]) {
+ /* copy ibuf into combined pixel rect */
+ RE_render_result_rect_from_ibuf(rr, &re->r, ibuf_arr[view_id], view_id);
+
+ if (ibuf_arr[view_id]->metadata && (re->r.stamp & R_STAMP_STRIPMETA)) {
+ /* ensure render stamp info first */
+ BKE_render_result_stamp_info(NULL, NULL, rr, true);
+ BKE_stamp_info_from_imbuf(rr, ibuf_arr[view_id]);
+ }
+
+ if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */
+ Editing *ed = re->scene->ed;
+ if (ed)
+ BKE_sequencer_free_imbuf(re->scene, &ed->seqbase, true);
+ }
+ IMB_freeImBuf(ibuf_arr[view_id]);
+ }
+ else {
+ /* render result is delivered empty in most cases, nevertheless we handle all cases */
+ render_result_rect_fill_zero(rr, view_id);
+ }
+
+ BLI_rw_mutex_unlock(&re->resultmutex);
+
+ /* would mark display buffers as invalid */
+ RE_SetActiveRenderView(re, rv->name);
+ re->display_update(re->duh, re->result, NULL);
+ }
+
+ MEM_freeN(ibuf_arr);
+
+ recurs_depth--;
+
+ /* just in case this flag went missing at some point */
+ re->r.scemode |= R_DOSEQ;
+
+ /* set overall progress of sequence rendering */
+ if (re->r.efra != re->r.sfra)
+ re->progress(re->prh, (float)(cfra - re->r.sfra) / (re->r.efra - re->r.sfra));
+ else
+ re->progress(re->prh, 1.0f);
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
@@ -1592,986 +1650,1052 @@ static void do_render_seq(Render *re)
/* main loop: doing sequence + 3d render + compositing */
static void do_render_all_options(Render *re)
{
- Object *camera;
- bool render_seq = false;
- int cfra = re->r.cfra;
+ Object *camera;
+ bool render_seq = false;
+ int cfra = re->r.cfra;
- re->current_scene_update(re->suh, re->scene);
+ re->current_scene_update(re->suh, re->scene);
- BKE_scene_camera_switch_update(re->scene);
+ BKE_scene_camera_switch_update(re->scene);
- re->i.starttime = PIL_check_seconds_timer();
+ re->i.starttime = PIL_check_seconds_timer();
- /* ensure no images are in memory from previous animated sequences */
- BKE_image_all_free_anim_ibufs(re->main, re->r.cfra);
- BKE_sequencer_all_free_anim_ibufs(re->main, re->r.cfra);
+ /* ensure no images are in memory from previous animated sequences */
+ BKE_image_all_free_anim_ibufs(re->main, re->r.cfra);
+ BKE_sequencer_all_free_anim_ibufs(re->main, re->r.cfra);
- /* Update for sequencer and compositing animation.
- * TODO: ideally we would create a depsgraph with a copy of the scene
- * like the render engine, but sequencer and compositing do not (yet?)
- * work with copy-on-write. */
- BKE_animsys_evaluate_all_animation(re->main, NULL, re->scene, (float)cfra);
+ /* Update for sequencer and compositing animation.
+ * TODO: ideally we would create a depsgraph with a copy of the scene
+ * like the render engine, but sequencer and compositing do not (yet?)
+ * work with copy-on-write. */
+ BKE_animsys_evaluate_all_animation(re->main, NULL, re->scene, (float)cfra);
- /* Update for masks (these do not use animsys but own lighter weight structure to define animation). */
- BKE_mask_evaluate_all_masks(re->main, (float)cfra, true);
+ /* Update for masks (these do not use animsys but own lighter weight structure to define animation). */
+ BKE_mask_evaluate_all_masks(re->main, (float)cfra, true);
- if (RE_engine_render(re, 1)) {
- /* in this case external render overrides all */
- }
- else if (RE_seq_render_active(re->scene, &re->r)) {
- /* note: do_render_seq() frees rect32 when sequencer returns float images */
- if (!re->test_break(re->tbh)) {
- do_render_seq(re);
- render_seq = true;
- }
+ if (RE_engine_render(re, 1)) {
+ /* in this case external render overrides all */
+ }
+ else if (RE_seq_render_active(re->scene, &re->r)) {
+ /* note: do_render_seq() frees rect32 when sequencer returns float images */
+ if (!re->test_break(re->tbh)) {
+ do_render_seq(re);
+ render_seq = true;
+ }
- re->stats_draw(re->sdh, &re->i);
- re->display_update(re->duh, re->result, NULL);
- }
- else {
- do_render_composite(re);
- }
+ re->stats_draw(re->sdh, &re->i);
+ re->display_update(re->duh, re->result, NULL);
+ }
+ else {
+ do_render_composite(re);
+ }
- re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
+ re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
- re->stats_draw(re->sdh, &re->i);
+ re->stats_draw(re->sdh, &re->i);
- /* save render result stamp if needed */
- if (re->result != NULL) {
- camera = RE_GetCamera(re);
- /* sequence rendering should have taken care of that already */
- if (!(render_seq && (re->r.stamp & R_STAMP_STRIPMETA)))
- BKE_render_result_stamp_info(re->scene, camera, re->result, false);
+ /* save render result stamp if needed */
+ if (re->result != NULL) {
+ camera = RE_GetCamera(re);
+ /* sequence rendering should have taken care of that already */
+ if (!(render_seq && (re->r.stamp & R_STAMP_STRIPMETA)))
+ BKE_render_result_stamp_info(re->scene, camera, re->result, false);
- /* stamp image info here */
- if ((re->r.stamp & R_STAMP_ALL) && (re->r.stamp & R_STAMP_DRAW)) {
- renderresult_stampinfo(re);
- re->display_update(re->duh, re->result, NULL);
- }
- }
+ /* stamp image info here */
+ if ((re->r.stamp & R_STAMP_ALL) && (re->r.stamp & R_STAMP_DRAW)) {
+ renderresult_stampinfo(re);
+ re->display_update(re->duh, re->result, NULL);
+ }
+ }
}
static bool check_valid_compositing_camera(Scene *scene, Object *camera_override)
{
- if (scene->r.scemode & R_DOCOMP && scene->use_nodes) {
- bNode *node = scene->nodetree->nodes.first;
-
- while (node) {
- if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0) {
- Scene *sce = node->id ? (Scene *)node->id : scene;
- if (sce->camera == NULL) {
- sce->camera = BKE_view_layer_camera_find(BKE_view_layer_default_render(sce));
- }
- if (sce->camera == NULL) {
- /* all render layers nodes need camera */
- return false;
- }
- }
- node = node->next;
- }
-
- return true;
- }
- else {
- return (camera_override != NULL || scene->camera != NULL);
- }
+ if (scene->r.scemode & R_DOCOMP && scene->use_nodes) {
+ bNode *node = scene->nodetree->nodes.first;
+
+ while (node) {
+ if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0) {
+ Scene *sce = node->id ? (Scene *)node->id : scene;
+ if (sce->camera == NULL) {
+ sce->camera = BKE_view_layer_camera_find(BKE_view_layer_default_render(sce));
+ }
+ if (sce->camera == NULL) {
+ /* all render layers nodes need camera */
+ return false;
+ }
+ }
+ node = node->next;
+ }
+
+ return true;
+ }
+ else {
+ return (camera_override != NULL || scene->camera != NULL);
+ }
}
static bool check_valid_camera_multiview(Scene *scene, Object *camera, ReportList *reports)
{
- SceneRenderView *srv;
- bool active_view = false;
+ SceneRenderView *srv;
+ bool active_view = false;
- if (camera == NULL || (scene->r.scemode & R_MULTIVIEW) == 0)
- return true;
+ if (camera == NULL || (scene->r.scemode & R_MULTIVIEW) == 0)
+ return true;
- for (srv = scene->r.views.first; srv; srv = srv->next) {
- if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) {
- active_view = true;
+ for (srv = scene->r.views.first; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) {
+ active_view = true;
- if (scene->r.views_format == SCE_VIEWS_FORMAT_MULTIVIEW) {
- Object *view_camera;
- view_camera = BKE_camera_multiview_render(scene, camera, srv->name);
+ if (scene->r.views_format == SCE_VIEWS_FORMAT_MULTIVIEW) {
+ Object *view_camera;
+ view_camera = BKE_camera_multiview_render(scene, camera, srv->name);
- if (view_camera == camera) {
- /* if the suffix is not in the camera, means we are using the fallback camera */
- if (!BLI_str_endswith(view_camera->id.name + 2, srv->suffix)) {
- BKE_reportf(reports, RPT_ERROR, "Camera \"%s\" is not a multi-view camera",
- camera->id.name + 2);
- return false;
- }
- }
- }
- }
- }
+ if (view_camera == camera) {
+ /* if the suffix is not in the camera, means we are using the fallback camera */
+ if (!BLI_str_endswith(view_camera->id.name + 2, srv->suffix)) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Camera \"%s\" is not a multi-view camera",
+ camera->id.name + 2);
+ return false;
+ }
+ }
+ }
+ }
+ }
- if (!active_view) {
- BKE_reportf(reports, RPT_ERROR, "No active view found in scene \"%s\"", scene->id.name + 2);
- return false;
- }
+ if (!active_view) {
+ BKE_reportf(reports, RPT_ERROR, "No active view found in scene \"%s\"", scene->id.name + 2);
+ return false;
+ }
- return true;
+ return true;
}
static int check_valid_camera(Scene *scene, Object *camera_override, ReportList *reports)
{
- const char *err_msg = "No camera found in scene \"%s\"";
-
- if (camera_override == NULL && scene->camera == NULL)
- scene->camera = BKE_view_layer_camera_find(BKE_view_layer_default_render(scene));
-
- if (!check_valid_camera_multiview(scene, scene->camera, reports))
- return false;
-
- if (RE_seq_render_active(scene, &scene->r)) {
- if (scene->ed) {
- Sequence *seq = scene->ed->seqbase.first;
-
- while (seq) {
- if ((seq->type == SEQ_TYPE_SCENE) &&
- ((seq->flag & SEQ_SCENE_STRIPS) == 0) &&
- (seq->scene != NULL))
- {
- if (!seq->scene_camera) {
- if (!seq->scene->camera &&
- !BKE_view_layer_camera_find(BKE_view_layer_default_render(seq->scene)))
- {
- /* camera could be unneeded due to composite nodes */
- Object *override = (seq->scene == scene) ? camera_override : NULL;
-
- if (!check_valid_compositing_camera(seq->scene, override)) {
- BKE_reportf(reports, RPT_ERROR, err_msg, seq->scene->id.name + 2);
- return false;
- }
- }
- }
- else if (!check_valid_camera_multiview(seq->scene, seq->scene_camera, reports))
- return false;
- }
-
- seq = seq->next;
- }
- }
- }
- else if (!check_valid_compositing_camera(scene, camera_override)) {
- BKE_reportf(reports, RPT_ERROR, err_msg, scene->id.name + 2);
- return false;
- }
-
- return true;
+ const char *err_msg = "No camera found in scene \"%s\"";
+
+ if (camera_override == NULL && scene->camera == NULL)
+ scene->camera = BKE_view_layer_camera_find(BKE_view_layer_default_render(scene));
+
+ if (!check_valid_camera_multiview(scene, scene->camera, reports))
+ return false;
+
+ if (RE_seq_render_active(scene, &scene->r)) {
+ if (scene->ed) {
+ Sequence *seq = scene->ed->seqbase.first;
+
+ while (seq) {
+ if ((seq->type == SEQ_TYPE_SCENE) && ((seq->flag & SEQ_SCENE_STRIPS) == 0) &&
+ (seq->scene != NULL)) {
+ if (!seq->scene_camera) {
+ if (!seq->scene->camera &&
+ !BKE_view_layer_camera_find(BKE_view_layer_default_render(seq->scene))) {
+ /* camera could be unneeded due to composite nodes */
+ Object *override = (seq->scene == scene) ? camera_override : NULL;
+
+ if (!check_valid_compositing_camera(seq->scene, override)) {
+ BKE_reportf(reports, RPT_ERROR, err_msg, seq->scene->id.name + 2);
+ return false;
+ }
+ }
+ }
+ else if (!check_valid_camera_multiview(seq->scene, seq->scene_camera, reports))
+ return false;
+ }
+
+ seq = seq->next;
+ }
+ }
+ }
+ else if (!check_valid_compositing_camera(scene, camera_override)) {
+ BKE_reportf(reports, RPT_ERROR, err_msg, scene->id.name + 2);
+ return false;
+ }
+
+ return true;
}
static bool node_tree_has_composite_output(bNodeTree *ntree)
{
- bNode *node;
+ bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM(node->type, CMP_NODE_COMPOSITE, CMP_NODE_OUTPUT_FILE)) {
- return true;
- }
- else if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
- if (node->id) {
- if (node_tree_has_composite_output((bNodeTree *)node->id)) {
- return true;
- }
- }
- }
- }
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (ELEM(node->type, CMP_NODE_COMPOSITE, CMP_NODE_OUTPUT_FILE)) {
+ return true;
+ }
+ else if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
+ if (node->id) {
+ if (node_tree_has_composite_output((bNodeTree *)node->id)) {
+ return true;
+ }
+ }
+ }
+ }
- return false;
+ return false;
}
static int check_composite_output(Scene *scene)
{
- return node_tree_has_composite_output(scene->nodetree);
-}
-
-bool RE_is_rendering_allowed(Scene *scene, ViewLayer *single_layer, Object *camera_override, ReportList *reports)
-{
- int scemode = check_mode_full_sample(&scene->r);
-
- if (scene->r.mode & R_BORDER) {
- if (scene->r.border.xmax <= scene->r.border.xmin ||
- scene->r.border.ymax <= scene->r.border.ymin)
- {
- BKE_report(reports, RPT_ERROR, "No border area selected");
- return 0;
- }
- }
-
- if (scemode & (R_EXR_TILE_FILE | R_FULL_SAMPLE)) {
- char str[FILE_MAX];
-
- render_result_exr_file_path(scene, "", 0, str);
-
- if (!BLI_file_is_writable(str)) {
- BKE_report(reports, RPT_ERROR, "Cannot save render buffers, check the temp default path");
- return 0;
- }
- }
-
- if (scemode & R_DOCOMP) {
- if (scene->use_nodes) {
- if (!scene->nodetree) {
- BKE_report(reports, RPT_ERROR, "No node tree in scene");
- return 0;
- }
-
- if (!check_composite_output(scene)) {
- BKE_report(reports, RPT_ERROR, "No render output node in scene");
- return 0;
- }
-
- if (scemode & R_FULL_SAMPLE) {
- if (composite_needs_render(scene, 0) == 0) {
- BKE_report(reports, RPT_ERROR, "Full sample AA not supported without 3D rendering");
- return 0;
- }
- }
- }
- }
-
- /* check valid camera, without camera render is OK (compo, seq) */
- if (!check_valid_camera(scene, camera_override, reports)) {
- return 0;
- }
-
- if (RE_seq_render_active(scene, &scene->r)) {
- if (scene->r.mode & R_BORDER) {
- BKE_report(reports, RPT_ERROR, "Border rendering is not supported by sequencer");
- return false;
- }
- }
-
- /* layer flag tests */
- if (!render_scene_has_layers_to_render(scene, single_layer)) {
- BKE_report(reports, RPT_ERROR, "All render layers are disabled");
- return 0;
- }
-
- return 1;
+ return node_tree_has_composite_output(scene->nodetree);
+}
+
+bool RE_is_rendering_allowed(Scene *scene,
+ ViewLayer *single_layer,
+ Object *camera_override,
+ ReportList *reports)
+{
+ int scemode = check_mode_full_sample(&scene->r);
+
+ if (scene->r.mode & R_BORDER) {
+ if (scene->r.border.xmax <= scene->r.border.xmin ||
+ scene->r.border.ymax <= scene->r.border.ymin) {
+ BKE_report(reports, RPT_ERROR, "No border area selected");
+ return 0;
+ }
+ }
+
+ if (scemode & (R_EXR_TILE_FILE | R_FULL_SAMPLE)) {
+ char str[FILE_MAX];
+
+ render_result_exr_file_path(scene, "", 0, str);
+
+ if (!BLI_file_is_writable(str)) {
+ BKE_report(reports, RPT_ERROR, "Cannot save render buffers, check the temp default path");
+ return 0;
+ }
+ }
+
+ if (scemode & R_DOCOMP) {
+ if (scene->use_nodes) {
+ if (!scene->nodetree) {
+ BKE_report(reports, RPT_ERROR, "No node tree in scene");
+ return 0;
+ }
+
+ if (!check_composite_output(scene)) {
+ BKE_report(reports, RPT_ERROR, "No render output node in scene");
+ return 0;
+ }
+
+ if (scemode & R_FULL_SAMPLE) {
+ if (composite_needs_render(scene, 0) == 0) {
+ BKE_report(reports, RPT_ERROR, "Full sample AA not supported without 3D rendering");
+ return 0;
+ }
+ }
+ }
+ }
+
+ /* check valid camera, without camera render is OK (compo, seq) */
+ if (!check_valid_camera(scene, camera_override, reports)) {
+ return 0;
+ }
+
+ if (RE_seq_render_active(scene, &scene->r)) {
+ if (scene->r.mode & R_BORDER) {
+ BKE_report(reports, RPT_ERROR, "Border rendering is not supported by sequencer");
+ return false;
+ }
+ }
+
+ /* layer flag tests */
+ if (!render_scene_has_layers_to_render(scene, single_layer)) {
+ BKE_report(reports, RPT_ERROR, "All render layers are disabled");
+ return 0;
+ }
+
+ return 1;
}
static void validate_render_settings(Render *re)
{
- if (RE_engine_is_external(re)) {
- /* not supported yet */
- re->r.scemode &= ~(R_FULL_SAMPLE);
- }
+ if (RE_engine_is_external(re)) {
+ /* not supported yet */
+ re->r.scemode &= ~(R_FULL_SAMPLE);
+ }
}
-static void update_physics_cache(Render *re, Scene *scene, ViewLayer *view_layer, int UNUSED(anim_init))
+static void update_physics_cache(Render *re,
+ Scene *scene,
+ ViewLayer *view_layer,
+ int UNUSED(anim_init))
{
- PTCacheBaker baker;
+ PTCacheBaker baker;
- memset(&baker, 0, sizeof(baker));
- baker.bmain = re->main;
- baker.scene = scene;
- baker.view_layer = view_layer;
- baker.depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
- baker.bake = 0;
- baker.render = 1;
- baker.anim_init = 1;
- baker.quick_step = 1;
+ memset(&baker, 0, sizeof(baker));
+ baker.bmain = re->main;
+ baker.scene = scene;
+ baker.view_layer = view_layer;
+ baker.depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ baker.bake = 0;
+ baker.render = 1;
+ baker.anim_init = 1;
+ baker.quick_step = 1;
- BKE_ptcache_bake(&baker);
+ BKE_ptcache_bake(&baker);
}
void RE_SetActiveRenderView(Render *re, const char *viewname)
{
- BLI_strncpy(re->viewname, viewname, sizeof(re->viewname));
+ BLI_strncpy(re->viewname, viewname, sizeof(re->viewname));
}
const char *RE_GetActiveRenderView(Render *re)
{
- return re->viewname;
+ return re->viewname;
}
/* evaluating scene options for general Blender render */
-static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, Scene *scene,
- ViewLayer *single_layer, Object *camera_override,
- int anim, int anim_init)
-{
- int winx, winy;
- rcti disprect;
-
- /* r.xsch and r.ysch has the actual view window size
- * r.border is the clipping rect */
-
- /* calculate actual render result and display size */
- winx = (rd->size * rd->xsch) / 100;
- winy = (rd->size * rd->ysch) / 100;
-
- /* we always render smaller part, inserting it in larger image is compositor bizz, it uses disprect for it */
- if (scene->r.mode & R_BORDER) {
- disprect.xmin = rd->border.xmin * winx;
- disprect.xmax = rd->border.xmax * winx;
-
- disprect.ymin = rd->border.ymin * winy;
- disprect.ymax = rd->border.ymax * winy;
- }
- else {
- disprect.xmin = disprect.ymin = 0;
- disprect.xmax = winx;
- disprect.ymax = winy;
- }
-
- re->main = bmain;
- re->scene = scene;
- re->camera_override = camera_override;
- re->viewname[0] = '\0';
-
- /* not too nice, but it survives anim-border render */
- if (anim) {
- render_update_anim_renderdata(re, &scene->r, &scene->view_layers);
- re->disprect = disprect;
- return 1;
- }
-
- /*
- * Disabled completely for now,
- * can be later set as render profile option
- * and default for background render.
- */
- if (0) {
- /* make sure dynamics are up to date */
- ViewLayer *view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene);
- update_physics_cache(re, scene, view_layer, anim_init);
- }
-
- if (single_layer || scene->r.scemode & R_SINGLE_LAYER) {
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- render_result_single_layer_begin(re);
- BLI_rw_mutex_unlock(&re->resultmutex);
- }
-
- RE_InitState(re, NULL, &scene->r, &scene->view_layers, single_layer, winx, winy, &disprect);
- if (!re->ok) /* if an error was printed, abort */
- return 0;
-
- /* initstate makes new result, have to send changed tags around */
- ntreeCompositTagRender(re->scene);
-
- validate_render_settings(re);
-
- re->display_init(re->dih, re->result);
- re->display_clear(re->dch, re->result);
-
- return 1;
+static int render_initialize_from_main(Render *re,
+ RenderData *rd,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *single_layer,
+ Object *camera_override,
+ int anim,
+ int anim_init)
+{
+ int winx, winy;
+ rcti disprect;
+
+ /* r.xsch and r.ysch has the actual view window size
+ * r.border is the clipping rect */
+
+ /* calculate actual render result and display size */
+ winx = (rd->size * rd->xsch) / 100;
+ winy = (rd->size * rd->ysch) / 100;
+
+ /* we always render smaller part, inserting it in larger image is compositor bizz, it uses disprect for it */
+ if (scene->r.mode & R_BORDER) {
+ disprect.xmin = rd->border.xmin * winx;
+ disprect.xmax = rd->border.xmax * winx;
+
+ disprect.ymin = rd->border.ymin * winy;
+ disprect.ymax = rd->border.ymax * winy;
+ }
+ else {
+ disprect.xmin = disprect.ymin = 0;
+ disprect.xmax = winx;
+ disprect.ymax = winy;
+ }
+
+ re->main = bmain;
+ re->scene = scene;
+ re->camera_override = camera_override;
+ re->viewname[0] = '\0';
+
+ /* not too nice, but it survives anim-border render */
+ if (anim) {
+ render_update_anim_renderdata(re, &scene->r, &scene->view_layers);
+ re->disprect = disprect;
+ return 1;
+ }
+
+ /*
+ * Disabled completely for now,
+ * can be later set as render profile option
+ * and default for background render.
+ */
+ if (0) {
+ /* make sure dynamics are up to date */
+ ViewLayer *view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene);
+ update_physics_cache(re, scene, view_layer, anim_init);
+ }
+
+ if (single_layer || scene->r.scemode & R_SINGLE_LAYER) {
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ render_result_single_layer_begin(re);
+ BLI_rw_mutex_unlock(&re->resultmutex);
+ }
+
+ RE_InitState(re, NULL, &scene->r, &scene->view_layers, single_layer, winx, winy, &disprect);
+ if (!re->ok) /* if an error was printed, abort */
+ return 0;
+
+ /* initstate makes new result, have to send changed tags around */
+ ntreeCompositTagRender(re->scene);
+
+ validate_render_settings(re);
+
+ re->display_init(re->dih, re->result);
+ re->display_clear(re->dch, re->result);
+
+ return 1;
}
void RE_SetReports(Render *re, ReportList *reports)
{
- re->reports = reports;
+ re->reports = reports;
}
/* general Blender frame render call */
-void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, ViewLayer *single_layer, Object *camera_override,
- int frame, const bool write_still)
-{
- BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT);
-
- /* ugly global still... is to prevent preview events and signal subsurfs etc to make full resol */
- G.is_rendering = true;
-
- scene->r.cfra = frame;
-
- if (render_initialize_from_main(re, &scene->r, bmain, scene, single_layer,
- camera_override, 0, 0))
- {
- MEM_reset_peak_memory();
-
- BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
-
- do_render_all_options(re);
-
- if (write_still && !G.is_break) {
- if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
- /* operator checks this but in case its called from elsewhere */
- printf("Error: cant write single images with a movie format!\n");
- }
- else {
- char name[FILE_MAX];
- BKE_image_path_from_imformat(
- name, scene->r.pic, BKE_main_blendfile_path(bmain), scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false, NULL);
-
- /* reports only used for Movie */
- do_write_image_or_movie(re, bmain, scene, NULL, 0, name);
- }
- }
-
- BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
- if (write_still) {
- BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_WRITE);
- }
- }
-
- BLI_callback_exec(re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE);
-
- /* Destroy the opengl context in the correct thread. */
- RE_gl_context_destroy(re);
-
- /* UGLY WARNING */
- G.is_rendering = false;
+void RE_BlenderFrame(Render *re,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *single_layer,
+ Object *camera_override,
+ int frame,
+ const bool write_still)
+{
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT);
+
+ /* ugly global still... is to prevent preview events and signal subsurfs etc to make full resol */
+ G.is_rendering = true;
+
+ scene->r.cfra = frame;
+
+ if (render_initialize_from_main(
+ re, &scene->r, bmain, scene, single_layer, camera_override, 0, 0)) {
+ MEM_reset_peak_memory();
+
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
+
+ do_render_all_options(re);
+
+ if (write_still && !G.is_break) {
+ if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
+ /* operator checks this but in case its called from elsewhere */
+ printf("Error: cant write single images with a movie format!\n");
+ }
+ else {
+ char name[FILE_MAX];
+ BKE_image_path_from_imformat(name,
+ scene->r.pic,
+ BKE_main_blendfile_path(bmain),
+ scene->r.cfra,
+ &scene->r.im_format,
+ (scene->r.scemode & R_EXTENSION) != 0,
+ false,
+ NULL);
+
+ /* reports only used for Movie */
+ do_write_image_or_movie(re, bmain, scene, NULL, 0, name);
+ }
+ }
+
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
+ if (write_still) {
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_WRITE);
+ }
+ }
+
+ BLI_callback_exec(
+ re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE);
+
+ /* Destroy the opengl context in the correct thread. */
+ RE_gl_context_destroy(re);
+
+ /* UGLY WARNING */
+ G.is_rendering = false;
}
#ifdef WITH_FREESTYLE
void RE_RenderFreestyleStrokes(Render *re, Main *bmain, Scene *scene, int render)
{
- re->result_ok = 0;
- if (render_initialize_from_main(re, &scene->r, bmain, scene, NULL, NULL, 0, 0)) {
- if (render)
- do_render_3d(re);
- }
- re->result_ok = 1;
+ re->result_ok = 0;
+ if (render_initialize_from_main(re, &scene->r, bmain, scene, NULL, NULL, 0, 0)) {
+ if (render)
+ do_render_3d(re);
+ }
+ re->result_ok = 1;
}
void RE_RenderFreestyleExternal(Render *re)
{
- if (!re->test_break(re->tbh)) {
- RenderView *rv;
+ if (!re->test_break(re->tbh)) {
+ RenderView *rv;
- init_freestyle(re);
+ init_freestyle(re);
- for (rv = re->result->views.first; rv; rv = rv->next) {
- RE_SetActiveRenderView(re, rv->name);
- add_freestyle(re, 1);
- }
- }
+ for (rv = re->result->views.first; rv; rv = rv->next) {
+ RE_SetActiveRenderView(re, rv->name);
+ add_freestyle(re, 1);
+ }
+ }
}
#endif
-bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scene, const bool stamp, char *name)
-{
- bool ok = true;
- RenderData *rd = &scene->r;
-
- if (!rr)
- return false;
-
- bool is_mono = BLI_listbase_count_at_most(&rr->views, 2) < 2;
- bool is_exr_rr = ELEM(rd->im_format.imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) &&
- RE_HasFloatPixels(rr);
-
- if (rd->im_format.views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr)
- {
- ok = RE_WriteRenderResult(reports, rr, name, &rd->im_format, NULL, -1);
- render_print_save_message(reports, name, ok, errno);
- }
-
- /* mono, legacy code */
- else if (is_mono || (rd->im_format.views_format == R_IMF_VIEWS_INDIVIDUAL))
- {
- RenderView *rv;
- int view_id;
- char filepath[FILE_MAX];
-
- BLI_strncpy(filepath, name, sizeof(filepath));
-
- for (view_id = 0, rv = rr->views.first; rv; rv = rv->next, view_id++) {
- if (!is_mono) {
- BKE_scene_multiview_view_filepath_get(&scene->r, filepath, rv->name, name);
- }
-
- if (is_exr_rr) {
- ok = RE_WriteRenderResult(reports, rr, name, &rd->im_format, rv->name, -1);
- render_print_save_message(reports, name, ok, errno);
-
- /* optional preview images for exr */
- if (ok && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
- ImageFormatData imf = rd->im_format;
- imf.imtype = R_IMF_IMTYPE_JPEG90;
-
- if (BLI_path_extension_check(name, ".exr"))
- name[strlen(name) - 4] = 0;
- BKE_image_path_ensure_ext_from_imformat(name, &imf);
-
- ImBuf *ibuf = render_result_rect_to_ibuf(rr, rd, view_id);
- ibuf->planes = 24;
- IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
- &scene->display_settings, &imf);
-
- ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf, name, &imf, stamp);
-
- IMB_freeImBuf(ibuf);
- }
- }
- else {
- ImBuf *ibuf = render_result_rect_to_ibuf(rr, rd, view_id);
-
- IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
- &scene->display_settings, &rd->im_format);
-
- ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf, name, &rd->im_format, stamp);
-
- /* imbuf knows which rects are not part of ibuf */
- IMB_freeImBuf(ibuf);
- }
- }
- }
- else { /* R_IMF_VIEWS_STEREO_3D */
- BLI_assert(scene->r.im_format.views_format == R_IMF_VIEWS_STEREO_3D);
-
- if (rd->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
- printf("Stereo 3D not supported for MultiLayer image: %s\n", name);
- }
- else {
- ImBuf *ibuf_arr[3] = {NULL};
- const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
- int i;
-
- for (i = 0; i < 2; i++) {
- int view_id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
- ibuf_arr[i] = render_result_rect_to_ibuf(rr, rd, view_id);
- IMB_colormanagement_imbuf_for_write(ibuf_arr[i], true, false, &scene->view_settings,
- &scene->display_settings, &scene->r.im_format);
- IMB_prepare_write_ImBuf(IMB_isfloat(ibuf_arr[i]), ibuf_arr[i]);
- }
-
- ibuf_arr[2] = IMB_stereo3d_ImBuf(&scene->r.im_format, ibuf_arr[0], ibuf_arr[1]);
-
- ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf_arr[2], name, &rd->im_format, stamp);
-
- /* optional preview images for exr */
- if (ok && is_exr_rr &&
- (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG))
- {
- ImageFormatData imf = rd->im_format;
- imf.imtype = R_IMF_IMTYPE_JPEG90;
-
- if (BLI_path_extension_check(name, ".exr"))
- name[strlen(name) - 4] = 0;
-
- BKE_image_path_ensure_ext_from_imformat(name, &imf);
- ibuf_arr[2]->planes = 24;
-
- ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf_arr[2], name, &rd->im_format, stamp);
- }
-
- /* imbuf knows which rects are not part of ibuf */
- for (i = 0; i < 3; i++) {
- IMB_freeImBuf(ibuf_arr[i]);
- }
- }
- }
-
- return ok;
-}
-
-bool RE_WriteRenderViewsMovie(
- ReportList *reports, RenderResult *rr, Scene *scene, RenderData *rd, bMovieHandle *mh,
- void **movie_ctx_arr, const int totvideos, bool preview)
-{
- bool is_mono;
- bool ok = true;
-
- if (!rr)
- return false;
-
- is_mono = BLI_listbase_count_at_most(&rr->views, 2) < 2;
-
- if (is_mono || (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) {
- int view_id;
- for (view_id = 0; view_id < totvideos; view_id++) {
- const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id);
- ImBuf *ibuf = render_result_rect_to_ibuf(rr, &scene->r, view_id);
-
- IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
- &scene->display_settings, &scene->r.im_format);
-
- ok &= mh->append_movie(movie_ctx_arr[view_id], rd, preview ? scene->r.psfra : scene->r.sfra, scene->r.cfra,
- (int *)ibuf->rect, ibuf->x, ibuf->y, suffix, reports);
-
- /* imbuf knows which rects are not part of ibuf */
- IMB_freeImBuf(ibuf);
- }
- printf("Append frame %d\n", scene->r.cfra);
- }
- else { /* R_IMF_VIEWS_STEREO_3D */
- const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
- ImBuf *ibuf_arr[3] = {NULL};
- int i;
-
- BLI_assert((totvideos == 1) && (scene->r.im_format.views_format == R_IMF_VIEWS_STEREO_3D));
-
- for (i = 0; i < 2; i++) {
- int view_id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
- ibuf_arr[i] = render_result_rect_to_ibuf(rr, &scene->r, view_id);
-
- IMB_colormanagement_imbuf_for_write(ibuf_arr[i], true, false, &scene->view_settings,
- &scene->display_settings, &scene->r.im_format);
- }
-
- ibuf_arr[2] = IMB_stereo3d_ImBuf(&scene->r.im_format, ibuf_arr[0], ibuf_arr[1]);
-
- ok = mh->append_movie(movie_ctx_arr[0], rd, preview ? scene->r.psfra : scene->r.sfra, scene->r.cfra, (int *)ibuf_arr[2]->rect,
- ibuf_arr[2]->x, ibuf_arr[2]->y, "", reports);
-
- for (i = 0; i < 3; i++) {
- /* imbuf knows which rects are not part of ibuf */
- IMB_freeImBuf(ibuf_arr[i]);
- }
- }
-
- return ok;
-}
-
-static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const int totvideos, const char *name_override)
-{
- char name[FILE_MAX];
- RenderResult rres;
- double render_time;
- bool ok = true;
-
- RE_AcquireResultImageViews(re, &rres);
-
- /* write movie or image */
- if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
- RE_WriteRenderViewsMovie(re->reports, &rres, scene, &re->r, mh, re->movie_ctx_arr, totvideos, false);
- }
- else {
- if (name_override)
- BLI_strncpy(name, name_override, sizeof(name));
- else
- BKE_image_path_from_imformat(
- name, scene->r.pic, BKE_main_blendfile_path(bmain), scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL);
-
- /* write images as individual images or stereo */
- ok = RE_WriteRenderViewsImage(re->reports, &rres, scene, true, name);
- }
-
- RE_ReleaseResultImageViews(re, &rres);
-
- render_time = re->i.lastframetime;
- re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
-
- BLI_timecode_string_from_time_simple(name, sizeof(name), re->i.lastframetime);
- printf(" Time: %s", name);
-
- /* Flush stdout to be sure python callbacks are printing stuff after blender. */
- fflush(stdout);
-
- /* NOTE: using G_MAIN seems valid here??? Not sure it's actually even used anyway, we could as well pass NULL? */
- BLI_callback_exec(G_MAIN, NULL, BLI_CB_EVT_RENDER_STATS);
-
- BLI_timecode_string_from_time_simple(name, sizeof(name), re->i.lastframetime - render_time);
- printf(" (Saving: %s)\n", name);
-
- fputc('\n', stdout);
- fflush(stdout); /* needed for renderd !! (not anymore... (ton)) */
-
- return ok;
-}
-
-static void get_videos_dimensions(
- Render *re, RenderData *rd,
- size_t *r_width, size_t *r_height)
-{
- size_t width, height;
- if (re->r.mode & R_BORDER) {
- if ((re->r.mode & R_CROP) == 0) {
- width = re->winx;
- height = re->winy;
- }
- else {
- width = re->rectx;
- height = re->recty;
- }
- }
- else {
- width = re->rectx;
- height = re->recty;
- }
-
- BKE_scene_multiview_videos_dimensions_get(rd, width, height, r_width, r_height);
+bool RE_WriteRenderViewsImage(
+ ReportList *reports, RenderResult *rr, Scene *scene, const bool stamp, char *name)
+{
+ bool ok = true;
+ RenderData *rd = &scene->r;
+
+ if (!rr)
+ return false;
+
+ bool is_mono = BLI_listbase_count_at_most(&rr->views, 2) < 2;
+ bool is_exr_rr = ELEM(rd->im_format.imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) &&
+ RE_HasFloatPixels(rr);
+
+ if (rd->im_format.views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr) {
+ ok = RE_WriteRenderResult(reports, rr, name, &rd->im_format, NULL, -1);
+ render_print_save_message(reports, name, ok, errno);
+ }
+
+ /* mono, legacy code */
+ else if (is_mono || (rd->im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) {
+ RenderView *rv;
+ int view_id;
+ char filepath[FILE_MAX];
+
+ BLI_strncpy(filepath, name, sizeof(filepath));
+
+ for (view_id = 0, rv = rr->views.first; rv; rv = rv->next, view_id++) {
+ if (!is_mono) {
+ BKE_scene_multiview_view_filepath_get(&scene->r, filepath, rv->name, name);
+ }
+
+ if (is_exr_rr) {
+ ok = RE_WriteRenderResult(reports, rr, name, &rd->im_format, rv->name, -1);
+ render_print_save_message(reports, name, ok, errno);
+
+ /* optional preview images for exr */
+ if (ok && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
+ ImageFormatData imf = rd->im_format;
+ imf.imtype = R_IMF_IMTYPE_JPEG90;
+
+ if (BLI_path_extension_check(name, ".exr"))
+ name[strlen(name) - 4] = 0;
+ BKE_image_path_ensure_ext_from_imformat(name, &imf);
+
+ ImBuf *ibuf = render_result_rect_to_ibuf(rr, rd, view_id);
+ ibuf->planes = 24;
+ IMB_colormanagement_imbuf_for_write(
+ ibuf, true, false, &scene->view_settings, &scene->display_settings, &imf);
+
+ ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf, name, &imf, stamp);
+
+ IMB_freeImBuf(ibuf);
+ }
+ }
+ else {
+ ImBuf *ibuf = render_result_rect_to_ibuf(rr, rd, view_id);
+
+ IMB_colormanagement_imbuf_for_write(
+ ibuf, true, false, &scene->view_settings, &scene->display_settings, &rd->im_format);
+
+ ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf, name, &rd->im_format, stamp);
+
+ /* imbuf knows which rects are not part of ibuf */
+ IMB_freeImBuf(ibuf);
+ }
+ }
+ }
+ else { /* R_IMF_VIEWS_STEREO_3D */
+ BLI_assert(scene->r.im_format.views_format == R_IMF_VIEWS_STEREO_3D);
+
+ if (rd->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
+ printf("Stereo 3D not supported for MultiLayer image: %s\n", name);
+ }
+ else {
+ ImBuf *ibuf_arr[3] = {NULL};
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ int view_id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
+ ibuf_arr[i] = render_result_rect_to_ibuf(rr, rd, view_id);
+ IMB_colormanagement_imbuf_for_write(ibuf_arr[i],
+ true,
+ false,
+ &scene->view_settings,
+ &scene->display_settings,
+ &scene->r.im_format);
+ IMB_prepare_write_ImBuf(IMB_isfloat(ibuf_arr[i]), ibuf_arr[i]);
+ }
+
+ ibuf_arr[2] = IMB_stereo3d_ImBuf(&scene->r.im_format, ibuf_arr[0], ibuf_arr[1]);
+
+ ok = render_imbuf_write_stamp_test(
+ reports, scene, rr, ibuf_arr[2], name, &rd->im_format, stamp);
+
+ /* optional preview images for exr */
+ if (ok && is_exr_rr && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
+ ImageFormatData imf = rd->im_format;
+ imf.imtype = R_IMF_IMTYPE_JPEG90;
+
+ if (BLI_path_extension_check(name, ".exr"))
+ name[strlen(name) - 4] = 0;
+
+ BKE_image_path_ensure_ext_from_imformat(name, &imf);
+ ibuf_arr[2]->planes = 24;
+
+ ok = render_imbuf_write_stamp_test(
+ reports, scene, rr, ibuf_arr[2], name, &rd->im_format, stamp);
+ }
+
+ /* imbuf knows which rects are not part of ibuf */
+ for (i = 0; i < 3; i++) {
+ IMB_freeImBuf(ibuf_arr[i]);
+ }
+ }
+ }
+
+ return ok;
+}
+
+bool RE_WriteRenderViewsMovie(ReportList *reports,
+ RenderResult *rr,
+ Scene *scene,
+ RenderData *rd,
+ bMovieHandle *mh,
+ void **movie_ctx_arr,
+ const int totvideos,
+ bool preview)
+{
+ bool is_mono;
+ bool ok = true;
+
+ if (!rr)
+ return false;
+
+ is_mono = BLI_listbase_count_at_most(&rr->views, 2) < 2;
+
+ if (is_mono || (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) {
+ int view_id;
+ for (view_id = 0; view_id < totvideos; view_id++) {
+ const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id);
+ ImBuf *ibuf = render_result_rect_to_ibuf(rr, &scene->r, view_id);
+
+ IMB_colormanagement_imbuf_for_write(
+ ibuf, true, false, &scene->view_settings, &scene->display_settings, &scene->r.im_format);
+
+ ok &= mh->append_movie(movie_ctx_arr[view_id],
+ rd,
+ preview ? scene->r.psfra : scene->r.sfra,
+ scene->r.cfra,
+ (int *)ibuf->rect,
+ ibuf->x,
+ ibuf->y,
+ suffix,
+ reports);
+
+ /* imbuf knows which rects are not part of ibuf */
+ IMB_freeImBuf(ibuf);
+ }
+ printf("Append frame %d\n", scene->r.cfra);
+ }
+ else { /* R_IMF_VIEWS_STEREO_3D */
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+ ImBuf *ibuf_arr[3] = {NULL};
+ int i;
+
+ BLI_assert((totvideos == 1) && (scene->r.im_format.views_format == R_IMF_VIEWS_STEREO_3D));
+
+ for (i = 0; i < 2; i++) {
+ int view_id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
+ ibuf_arr[i] = render_result_rect_to_ibuf(rr, &scene->r, view_id);
+
+ IMB_colormanagement_imbuf_for_write(ibuf_arr[i],
+ true,
+ false,
+ &scene->view_settings,
+ &scene->display_settings,
+ &scene->r.im_format);
+ }
+
+ ibuf_arr[2] = IMB_stereo3d_ImBuf(&scene->r.im_format, ibuf_arr[0], ibuf_arr[1]);
+
+ ok = mh->append_movie(movie_ctx_arr[0],
+ rd,
+ preview ? scene->r.psfra : scene->r.sfra,
+ scene->r.cfra,
+ (int *)ibuf_arr[2]->rect,
+ ibuf_arr[2]->x,
+ ibuf_arr[2]->y,
+ "",
+ reports);
+
+ for (i = 0; i < 3; i++) {
+ /* imbuf knows which rects are not part of ibuf */
+ IMB_freeImBuf(ibuf_arr[i]);
+ }
+ }
+
+ return ok;
+}
+
+static int do_write_image_or_movie(Render *re,
+ Main *bmain,
+ Scene *scene,
+ bMovieHandle *mh,
+ const int totvideos,
+ const char *name_override)
+{
+ char name[FILE_MAX];
+ RenderResult rres;
+ double render_time;
+ bool ok = true;
+
+ RE_AcquireResultImageViews(re, &rres);
+
+ /* write movie or image */
+ if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
+ RE_WriteRenderViewsMovie(
+ re->reports, &rres, scene, &re->r, mh, re->movie_ctx_arr, totvideos, false);
+ }
+ else {
+ if (name_override)
+ BLI_strncpy(name, name_override, sizeof(name));
+ else
+ BKE_image_path_from_imformat(name,
+ scene->r.pic,
+ BKE_main_blendfile_path(bmain),
+ scene->r.cfra,
+ &scene->r.im_format,
+ (scene->r.scemode & R_EXTENSION) != 0,
+ true,
+ NULL);
+
+ /* write images as individual images or stereo */
+ ok = RE_WriteRenderViewsImage(re->reports, &rres, scene, true, name);
+ }
+
+ RE_ReleaseResultImageViews(re, &rres);
+
+ render_time = re->i.lastframetime;
+ re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
+
+ BLI_timecode_string_from_time_simple(name, sizeof(name), re->i.lastframetime);
+ printf(" Time: %s", name);
+
+ /* Flush stdout to be sure python callbacks are printing stuff after blender. */
+ fflush(stdout);
+
+ /* NOTE: using G_MAIN seems valid here??? Not sure it's actually even used anyway, we could as well pass NULL? */
+ BLI_callback_exec(G_MAIN, NULL, BLI_CB_EVT_RENDER_STATS);
+
+ BLI_timecode_string_from_time_simple(name, sizeof(name), re->i.lastframetime - render_time);
+ printf(" (Saving: %s)\n", name);
+
+ fputc('\n', stdout);
+ fflush(stdout); /* needed for renderd !! (not anymore... (ton)) */
+
+ return ok;
+}
+
+static void get_videos_dimensions(Render *re, RenderData *rd, size_t *r_width, size_t *r_height)
+{
+ size_t width, height;
+ if (re->r.mode & R_BORDER) {
+ if ((re->r.mode & R_CROP) == 0) {
+ width = re->winx;
+ height = re->winy;
+ }
+ else {
+ width = re->rectx;
+ height = re->recty;
+ }
+ }
+ else {
+ width = re->rectx;
+ height = re->recty;
+ }
+
+ BKE_scene_multiview_videos_dimensions_get(rd, width, height, r_width, r_height);
}
static void re_movie_free_all(Render *re, bMovieHandle *mh, int totvideos)
{
- int i;
+ int i;
- for (i = 0; i < totvideos; i++) {
- mh->end_movie(re->movie_ctx_arr[i]);
- mh->context_free(re->movie_ctx_arr[i]);
- }
+ for (i = 0; i < totvideos; i++) {
+ mh->end_movie(re->movie_ctx_arr[i]);
+ mh->context_free(re->movie_ctx_arr[i]);
+ }
- MEM_SAFE_FREE(re->movie_ctx_arr);
+ MEM_SAFE_FREE(re->movie_ctx_arr);
}
/* saves images to disk */
-void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, ViewLayer *single_layer, Object *camera_override,
- int sfra, int efra, int tfra)
-{
- RenderData rd = scene->r;
- bMovieHandle *mh = NULL;
- int cfrao = scene->r.cfra;
- int nfra, totrendered = 0, totskipped = 0;
- const int totvideos = BKE_scene_multiview_num_videos_get(&rd);
- const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);
- const bool is_multiview_name = ((scene->r.scemode & R_MULTIVIEW) != 0 &&
- (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL));
-
- BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT);
-
- /* do not fully call for each frame, it initializes & pops output window */
- if (!render_initialize_from_main(re, &rd, bmain, scene, single_layer, camera_override, 0, 1))
- return;
-
- if (is_movie) {
- size_t width, height;
- int i;
- bool is_error = false;
-
- get_videos_dimensions(re, &rd, &width, &height);
-
- mh = BKE_movie_handle_get(scene->r.im_format.imtype);
- if (mh == NULL) {
- BKE_report(re->reports, RPT_ERROR, "Movie format unsupported");
- return;
- }
-
- re->movie_ctx_arr = MEM_mallocN(sizeof(void *) * totvideos, "Movies' Context");
-
- for (i = 0; i < totvideos; i++) {
- const char *suffix = BKE_scene_multiview_view_id_suffix_get(&re->r, i);
-
- re->movie_ctx_arr[i] = mh->context_create();
-
- if (!mh->start_movie(re->movie_ctx_arr[i], scene, &re->r, width, height, re->reports, false, suffix)) {
- is_error = true;
- break;
- }
- }
-
- if (is_error) {
- /* report is handled above */
- re_movie_free_all(re, mh, i + 1);
- return;
- }
- }
-
- /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */
- /* is also set by caller renderwin.c */
- G.is_rendering = true;
-
- re->flag |= R_ANIMATION;
-
- {
- for (nfra = sfra, scene->r.cfra = sfra; scene->r.cfra <= efra; scene->r.cfra++) {
- char name[FILE_MAX];
-
- /* Special case for 'mh->get_next_frame'
- * this overrides regular frame stepping logic */
- if (mh && mh->get_next_frame) {
- while (G.is_break == false) {
- int nfra_test = mh->get_next_frame(re->movie_ctx_arr[0], &re->r, re->reports);
- if (nfra_test >= 0 && nfra_test >= sfra && nfra_test <= efra) {
- nfra = nfra_test;
- break;
- }
- else {
- if (re->test_break(re->tbh)) {
- G.is_break = true;
- }
- }
- }
- }
-
- /* Here is a feedback loop exists -- render initialization requires updated
- * render layers settings which could be animated, but scene evaluation for
- * the frame happens later because it depends on what layers are visible to
- * render engine.
- *
- * The idea here is to only evaluate animation data associated with the scene,
- * which will make sure render layer settings are up-to-date, initialize the
- * render database itself and then perform full scene update with only needed
- * layers.
- * -sergey-
- */
- {
- float ctime = BKE_scene_frame_get(scene);
- AnimData *adt = BKE_animdata_from_id(&scene->id);
- /* TODO(sergey): Currently depsgraph is only used to check whether it is an active
- * edit window or not to deal with unkeyed changes. We don't have depsgraph here yet,
- * but we also dont' deal with unkeyed changes. But still nice to get proper depsgraph
- * within tjhe render pipeline, somehow.
- */
- BKE_animsys_evaluate_animdata(NULL, scene, &scene->id, adt, ctime, ADT_RECALC_ALL);
- }
-
- /* only border now, todo: camera lens. (ton) */
- render_initialize_from_main(re, &rd, bmain, scene,
- single_layer, camera_override, 1, 0);
-
- if (nfra != scene->r.cfra) {
- /* Skip this frame, but could update for physics and particles system. */
- continue;
- }
- else
- nfra += tfra;
-
- /* Touch/NoOverwrite options are only valid for image's */
- if (is_movie == false) {
- if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH))
- BKE_image_path_from_imformat(
- name, scene->r.pic, BKE_main_blendfile_path(bmain), scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL);
-
- if (scene->r.mode & R_NO_OVERWRITE) {
- if (!is_multiview_name) {
- if (BLI_exists(name)) {
- printf("skipping existing frame \"%s\"\n", name);
- totskipped++;
- continue;
- }
- }
- else {
- SceneRenderView *srv;
- bool is_skip = false;
- char filepath[FILE_MAX];
-
- for (srv = scene->r.views.first; srv; srv = srv->next) {
- if (!BKE_scene_multiview_is_render_view_active(&scene->r, srv))
- continue;
-
- BKE_scene_multiview_filepath_get(srv, name, filepath);
-
- if (BLI_exists(filepath)) {
- is_skip = true;
- printf("skipping existing frame \"%s\" for view \"%s\"\n", filepath, srv->name);
- }
- }
-
- if (is_skip) {
- totskipped++;
- continue;
- }
- }
- }
-
- if (scene->r.mode & R_TOUCH) {
- if (!is_multiview_name) {
- if (!BLI_exists(name)) {
- BLI_make_existing_file(name); /* makes the dir if its not there */
- BLI_file_touch(name);
- }
- }
- else {
- SceneRenderView *srv;
- char filepath[FILE_MAX];
-
- for (srv = scene->r.views.first; srv; srv = srv->next) {
- if (!BKE_scene_multiview_is_render_view_active(&scene->r, srv))
- continue;
-
- BKE_scene_multiview_filepath_get(srv, name, filepath);
-
- if (!BLI_exists(filepath)) {
- BLI_make_existing_file(filepath); /* makes the dir if its not there */
- BLI_file_touch(filepath);
- }
- }
- }
- }
- }
-
- re->r.cfra = scene->r.cfra; /* weak.... */
-
- /* run callbacs before rendering, before the scene is updated */
- BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
-
-
- do_render_all_options(re);
- totrendered++;
-
- if (re->test_break(re->tbh) == 0) {
- if (!G.is_break)
- if (!do_write_image_or_movie(re, bmain, scene, mh, totvideos, NULL))
- G.is_break = true;
- }
- else
- G.is_break = true;
-
- if (G.is_break == true) {
- /* remove touched file */
- if (is_movie == false) {
- if ((scene->r.mode & R_TOUCH)) {
- if (!is_multiview_name) {
- if ((BLI_file_size(name) == 0)) {
- /* BLI_exists(name) is implicit */
- BLI_delete(name, false, false);
- }
- }
- else {
- SceneRenderView *srv;
- char filepath[FILE_MAX];
-
- for (srv = scene->r.views.first; srv; srv = srv->next) {
- if (!BKE_scene_multiview_is_render_view_active(&scene->r, srv))
- continue;
-
- BKE_scene_multiview_filepath_get(srv, name, filepath);
-
- if ((BLI_file_size(filepath) == 0)) {
- /* BLI_exists(filepath) is implicit */
- BLI_delete(filepath, false, false);
- }
- }
- }
- }
- }
-
- break;
- }
-
- if (G.is_break == false) {
- BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
- BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_WRITE);
- }
- }
- }
-
- /* end movie */
- if (is_movie) {
- re_movie_free_all(re, mh, totvideos);
- }
-
- if (totskipped && totrendered == 0)
- BKE_report(re->reports, RPT_INFO, "No frames rendered, skipped to not overwrite");
-
- scene->r.cfra = cfrao;
-
- re->flag &= ~R_ANIMATION;
-
- BLI_callback_exec(re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE);
- BKE_sound_reset_scene_specs(scene);
-
- /* Destroy the opengl context in the correct thread. */
- RE_gl_context_destroy(re);
-
- /* UGLY WARNING */
- G.is_rendering = false;
+void RE_BlenderAnim(Render *re,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *single_layer,
+ Object *camera_override,
+ int sfra,
+ int efra,
+ int tfra)
+{
+ RenderData rd = scene->r;
+ bMovieHandle *mh = NULL;
+ int cfrao = scene->r.cfra;
+ int nfra, totrendered = 0, totskipped = 0;
+ const int totvideos = BKE_scene_multiview_num_videos_get(&rd);
+ const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);
+ const bool is_multiview_name = ((scene->r.scemode & R_MULTIVIEW) != 0 &&
+ (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL));
+
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT);
+
+ /* do not fully call for each frame, it initializes & pops output window */
+ if (!render_initialize_from_main(re, &rd, bmain, scene, single_layer, camera_override, 0, 1))
+ return;
+
+ if (is_movie) {
+ size_t width, height;
+ int i;
+ bool is_error = false;
+
+ get_videos_dimensions(re, &rd, &width, &height);
+
+ mh = BKE_movie_handle_get(scene->r.im_format.imtype);
+ if (mh == NULL) {
+ BKE_report(re->reports, RPT_ERROR, "Movie format unsupported");
+ return;
+ }
+
+ re->movie_ctx_arr = MEM_mallocN(sizeof(void *) * totvideos, "Movies' Context");
+
+ for (i = 0; i < totvideos; i++) {
+ const char *suffix = BKE_scene_multiview_view_id_suffix_get(&re->r, i);
+
+ re->movie_ctx_arr[i] = mh->context_create();
+
+ if (!mh->start_movie(
+ re->movie_ctx_arr[i], scene, &re->r, width, height, re->reports, false, suffix)) {
+ is_error = true;
+ break;
+ }
+ }
+
+ if (is_error) {
+ /* report is handled above */
+ re_movie_free_all(re, mh, i + 1);
+ return;
+ }
+ }
+
+ /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */
+ /* is also set by caller renderwin.c */
+ G.is_rendering = true;
+
+ re->flag |= R_ANIMATION;
+
+ {
+ for (nfra = sfra, scene->r.cfra = sfra; scene->r.cfra <= efra; scene->r.cfra++) {
+ char name[FILE_MAX];
+
+ /* Special case for 'mh->get_next_frame'
+ * this overrides regular frame stepping logic */
+ if (mh && mh->get_next_frame) {
+ while (G.is_break == false) {
+ int nfra_test = mh->get_next_frame(re->movie_ctx_arr[0], &re->r, re->reports);
+ if (nfra_test >= 0 && nfra_test >= sfra && nfra_test <= efra) {
+ nfra = nfra_test;
+ break;
+ }
+ else {
+ if (re->test_break(re->tbh)) {
+ G.is_break = true;
+ }
+ }
+ }
+ }
+
+ /* Here is a feedback loop exists -- render initialization requires updated
+ * render layers settings which could be animated, but scene evaluation for
+ * the frame happens later because it depends on what layers are visible to
+ * render engine.
+ *
+ * The idea here is to only evaluate animation data associated with the scene,
+ * which will make sure render layer settings are up-to-date, initialize the
+ * render database itself and then perform full scene update with only needed
+ * layers.
+ * -sergey-
+ */
+ {
+ float ctime = BKE_scene_frame_get(scene);
+ AnimData *adt = BKE_animdata_from_id(&scene->id);
+ /* TODO(sergey): Currently depsgraph is only used to check whether it is an active
+ * edit window or not to deal with unkeyed changes. We don't have depsgraph here yet,
+ * but we also dont' deal with unkeyed changes. But still nice to get proper depsgraph
+ * within tjhe render pipeline, somehow.
+ */
+ BKE_animsys_evaluate_animdata(NULL, scene, &scene->id, adt, ctime, ADT_RECALC_ALL);
+ }
+
+ /* only border now, todo: camera lens. (ton) */
+ render_initialize_from_main(re, &rd, bmain, scene, single_layer, camera_override, 1, 0);
+
+ if (nfra != scene->r.cfra) {
+ /* Skip this frame, but could update for physics and particles system. */
+ continue;
+ }
+ else
+ nfra += tfra;
+
+ /* Touch/NoOverwrite options are only valid for image's */
+ if (is_movie == false) {
+ if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH))
+ BKE_image_path_from_imformat(name,
+ scene->r.pic,
+ BKE_main_blendfile_path(bmain),
+ scene->r.cfra,
+ &scene->r.im_format,
+ (scene->r.scemode & R_EXTENSION) != 0,
+ true,
+ NULL);
+
+ if (scene->r.mode & R_NO_OVERWRITE) {
+ if (!is_multiview_name) {
+ if (BLI_exists(name)) {
+ printf("skipping existing frame \"%s\"\n", name);
+ totskipped++;
+ continue;
+ }
+ }
+ else {
+ SceneRenderView *srv;
+ bool is_skip = false;
+ char filepath[FILE_MAX];
+
+ for (srv = scene->r.views.first; srv; srv = srv->next) {
+ if (!BKE_scene_multiview_is_render_view_active(&scene->r, srv))
+ continue;
+
+ BKE_scene_multiview_filepath_get(srv, name, filepath);
+
+ if (BLI_exists(filepath)) {
+ is_skip = true;
+ printf("skipping existing frame \"%s\" for view \"%s\"\n", filepath, srv->name);
+ }
+ }
+
+ if (is_skip) {
+ totskipped++;
+ continue;
+ }
+ }
+ }
+
+ if (scene->r.mode & R_TOUCH) {
+ if (!is_multiview_name) {
+ if (!BLI_exists(name)) {
+ BLI_make_existing_file(name); /* makes the dir if its not there */
+ BLI_file_touch(name);
+ }
+ }
+ else {
+ SceneRenderView *srv;
+ char filepath[FILE_MAX];
+
+ for (srv = scene->r.views.first; srv; srv = srv->next) {
+ if (!BKE_scene_multiview_is_render_view_active(&scene->r, srv))
+ continue;
+
+ BKE_scene_multiview_filepath_get(srv, name, filepath);
+
+ if (!BLI_exists(filepath)) {
+ BLI_make_existing_file(filepath); /* makes the dir if its not there */
+ BLI_file_touch(filepath);
+ }
+ }
+ }
+ }
+ }
+
+ re->r.cfra = scene->r.cfra; /* weak.... */
+
+ /* run callbacs before rendering, before the scene is updated */
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
+
+ do_render_all_options(re);
+ totrendered++;
+
+ if (re->test_break(re->tbh) == 0) {
+ if (!G.is_break)
+ if (!do_write_image_or_movie(re, bmain, scene, mh, totvideos, NULL))
+ G.is_break = true;
+ }
+ else
+ G.is_break = true;
+
+ if (G.is_break == true) {
+ /* remove touched file */
+ if (is_movie == false) {
+ if ((scene->r.mode & R_TOUCH)) {
+ if (!is_multiview_name) {
+ if ((BLI_file_size(name) == 0)) {
+ /* BLI_exists(name) is implicit */
+ BLI_delete(name, false, false);
+ }
+ }
+ else {
+ SceneRenderView *srv;
+ char filepath[FILE_MAX];
+
+ for (srv = scene->r.views.first; srv; srv = srv->next) {
+ if (!BKE_scene_multiview_is_render_view_active(&scene->r, srv))
+ continue;
+
+ BKE_scene_multiview_filepath_get(srv, name, filepath);
+
+ if ((BLI_file_size(filepath) == 0)) {
+ /* BLI_exists(filepath) is implicit */
+ BLI_delete(filepath, false, false);
+ }
+ }
+ }
+ }
+ }
+
+ break;
+ }
+
+ if (G.is_break == false) {
+ BLI_callback_exec(
+ re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_WRITE);
+ }
+ }
+ }
+
+ /* end movie */
+ if (is_movie) {
+ re_movie_free_all(re, mh, totvideos);
+ }
+
+ if (totskipped && totrendered == 0)
+ BKE_report(re->reports, RPT_INFO, "No frames rendered, skipped to not overwrite");
+
+ scene->r.cfra = cfrao;
+
+ re->flag &= ~R_ANIMATION;
+
+ BLI_callback_exec(
+ re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE);
+ BKE_sound_reset_scene_specs(scene);
+
+ /* Destroy the opengl context in the correct thread. */
+ RE_gl_context_destroy(re);
+
+ /* UGLY WARNING */
+ G.is_rendering = false;
}
void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
{
- Object *camera;
- int winx, winy;
+ Object *camera;
+ int winx, winy;
- winx = (sce->r.size * sce->r.xsch) / 100;
- winy = (sce->r.size * sce->r.ysch) / 100;
+ winx = (sce->r.size * sce->r.xsch) / 100;
+ winy = (sce->r.size * sce->r.ysch) / 100;
- RE_InitState(re, NULL, &sce->r, &sce->view_layers, NULL, winx, winy, NULL);
+ RE_InitState(re, NULL, &sce->r, &sce->view_layers, NULL, winx, winy, NULL);
- re->main = bmain;
- re->scene = sce;
+ re->main = bmain;
+ re->scene = sce;
- camera = RE_GetCamera(re);
- RE_SetCamera(re, camera);
+ camera = RE_GetCamera(re);
+ RE_SetCamera(re, camera);
- do_render_3d(re);
+ do_render_3d(re);
}
/* note; repeated win/disprect calc... solve that nicer, also in compo */
@@ -2579,215 +2703,226 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
/* only the temp file! */
bool RE_ReadRenderResult(Scene *scene, Scene *scenode)
{
- Render *re;
- int winx, winy;
- bool success;
- rcti disprect;
+ Render *re;
+ int winx, winy;
+ bool success;
+ rcti disprect;
- /* calculate actual render result and display size */
- winx = (scene->r.size * scene->r.xsch) / 100;
- winy = (scene->r.size * scene->r.ysch) / 100;
+ /* calculate actual render result and display size */
+ winx = (scene->r.size * scene->r.xsch) / 100;
+ winy = (scene->r.size * scene->r.ysch) / 100;
- /* only in movie case we render smaller part */
- if (scene->r.mode & R_BORDER) {
- disprect.xmin = scene->r.border.xmin * winx;
- disprect.xmax = scene->r.border.xmax * winx;
+ /* only in movie case we render smaller part */
+ if (scene->r.mode & R_BORDER) {
+ disprect.xmin = scene->r.border.xmin * winx;
+ disprect.xmax = scene->r.border.xmax * winx;
- disprect.ymin = scene->r.border.ymin * winy;
- disprect.ymax = scene->r.border.ymax * winy;
- }
- else {
- disprect.xmin = disprect.ymin = 0;
- disprect.xmax = winx;
- disprect.ymax = winy;
- }
+ disprect.ymin = scene->r.border.ymin * winy;
+ disprect.ymax = scene->r.border.ymax * winy;
+ }
+ else {
+ disprect.xmin = disprect.ymin = 0;
+ disprect.xmax = winx;
+ disprect.ymax = winy;
+ }
- if (scenode)
- scene = scenode;
+ if (scenode)
+ scene = scenode;
- /* get render: it can be called from UI with draw callbacks */
- re = RE_GetSceneRender(scene);
- if (re == NULL)
- re = RE_NewSceneRender(scene);
- RE_InitState(re, NULL, &scene->r, &scene->view_layers, NULL, winx, winy, &disprect);
- re->scene = scene;
+ /* get render: it can be called from UI with draw callbacks */
+ re = RE_GetSceneRender(scene);
+ if (re == NULL)
+ re = RE_NewSceneRender(scene);
+ RE_InitState(re, NULL, &scene->r, &scene->view_layers, NULL, winx, winy, &disprect);
+ re->scene = scene;
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- success = render_result_exr_file_cache_read(re);
- BLI_rw_mutex_unlock(&re->resultmutex);
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ success = render_result_exr_file_cache_read(re);
+ BLI_rw_mutex_unlock(&re->resultmutex);
- render_result_uncrop(re);
+ render_result_uncrop(re);
- return success;
+ return success;
}
void RE_init_threadcount(Render *re)
{
- re->r.threads = BKE_render_num_threads(&re->r);
+ re->r.threads = BKE_render_num_threads(&re->r);
}
/* loads in image into a result, size must match
* x/y offsets are only used on a partial copy when dimensions don't match */
-void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char *filename, int x, int y)
-{
- /* OCIO_TODO: assume layer was saved in defaule color space */
- ImBuf *ibuf = IMB_loadiffname(filename, IB_rect, NULL);
- RenderPass *rpass = NULL;
-
- /* multiview: since the API takes no 'view', we use the first combined pass found */
- for (rpass = layer->passes.first; rpass; rpass = rpass->next)
- if (STREQ(rpass->name, RE_PASSNAME_COMBINED))
- break;
-
- if (rpass == NULL)
- BKE_reportf(reports, RPT_ERROR, "%s: no Combined pass found in the render layer '%s'", __func__, filename);
-
- if (ibuf && (ibuf->rect || ibuf->rect_float)) {
- if (ibuf->x == layer->rectx && ibuf->y == layer->recty) {
- if (ibuf->rect_float == NULL)
- IMB_float_from_rect(ibuf);
-
- memcpy(rpass->rect, ibuf->rect_float, sizeof(float) * 4 * layer->rectx * layer->recty);
- }
- else {
- if ((ibuf->x - x >= layer->rectx) && (ibuf->y - y >= layer->recty)) {
- ImBuf *ibuf_clip;
-
- if (ibuf->rect_float == NULL)
- IMB_float_from_rect(ibuf);
-
- ibuf_clip = IMB_allocImBuf(layer->rectx, layer->recty, 32, IB_rectfloat);
- if (ibuf_clip) {
- IMB_rectcpy(ibuf_clip, ibuf, 0, 0, x, y, layer->rectx, layer->recty);
-
- memcpy(rpass->rect, ibuf_clip->rect_float, sizeof(float) * 4 * layer->rectx * layer->recty);
- IMB_freeImBuf(ibuf_clip);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "%s: failed to allocate clip buffer '%s'", __func__, filename);
- }
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "%s: incorrect dimensions for partial copy '%s'", __func__, filename);
- }
- }
-
- IMB_freeImBuf(ibuf);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "%s: failed to load '%s'", __func__, filename);
- }
+void RE_layer_load_from_file(
+ RenderLayer *layer, ReportList *reports, const char *filename, int x, int y)
+{
+ /* OCIO_TODO: assume layer was saved in defaule color space */
+ ImBuf *ibuf = IMB_loadiffname(filename, IB_rect, NULL);
+ RenderPass *rpass = NULL;
+
+ /* multiview: since the API takes no 'view', we use the first combined pass found */
+ for (rpass = layer->passes.first; rpass; rpass = rpass->next)
+ if (STREQ(rpass->name, RE_PASSNAME_COMBINED))
+ break;
+
+ if (rpass == NULL)
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "%s: no Combined pass found in the render layer '%s'",
+ __func__,
+ filename);
+
+ if (ibuf && (ibuf->rect || ibuf->rect_float)) {
+ if (ibuf->x == layer->rectx && ibuf->y == layer->recty) {
+ if (ibuf->rect_float == NULL)
+ IMB_float_from_rect(ibuf);
+
+ memcpy(rpass->rect, ibuf->rect_float, sizeof(float) * 4 * layer->rectx * layer->recty);
+ }
+ else {
+ if ((ibuf->x - x >= layer->rectx) && (ibuf->y - y >= layer->recty)) {
+ ImBuf *ibuf_clip;
+
+ if (ibuf->rect_float == NULL)
+ IMB_float_from_rect(ibuf);
+
+ ibuf_clip = IMB_allocImBuf(layer->rectx, layer->recty, 32, IB_rectfloat);
+ if (ibuf_clip) {
+ IMB_rectcpy(ibuf_clip, ibuf, 0, 0, x, y, layer->rectx, layer->recty);
+
+ memcpy(
+ rpass->rect, ibuf_clip->rect_float, sizeof(float) * 4 * layer->rectx * layer->recty);
+ IMB_freeImBuf(ibuf_clip);
+ }
+ else {
+ BKE_reportf(
+ reports, RPT_ERROR, "%s: failed to allocate clip buffer '%s'", __func__, filename);
+ }
+ }
+ else {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "%s: incorrect dimensions for partial copy '%s'",
+ __func__,
+ filename);
+ }
+ }
+
+ IMB_freeImBuf(ibuf);
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR, "%s: failed to load '%s'", __func__, filename);
+ }
}
void RE_result_load_from_file(RenderResult *result, ReportList *reports, const char *filename)
{
- if (!render_result_exr_file_read_path(result, NULL, filename)) {
- BKE_reportf(reports, RPT_ERROR, "%s: failed to load '%s'", __func__, filename);
- return;
- }
+ if (!render_result_exr_file_read_path(result, NULL, filename)) {
+ BKE_reportf(reports, RPT_ERROR, "%s: failed to load '%s'", __func__, filename);
+ return;
+ }
}
/* Used in the interface to decide whether to show layers or passes. */
bool RE_layers_have_name(struct RenderResult *rr)
{
- switch (BLI_listbase_count_at_most(&rr->layers, 2)) {
- case 0:
- return false;
- case 1:
- return (((RenderLayer *)rr->layers.first)->name[0] != '\0');
- default:
- return true;
- }
- return false;
+ switch (BLI_listbase_count_at_most(&rr->layers, 2)) {
+ case 0:
+ return false;
+ case 1:
+ return (((RenderLayer *)rr->layers.first)->name[0] != '\0');
+ default:
+ return true;
+ }
+ return false;
}
bool RE_passes_have_name(struct RenderLayer *rl)
{
- for (RenderPass *rp = rl->passes.first; rp; rp = rp->next) {
- if (!STREQ(rp->name, "Combined")) {
- return true;
- }
- }
+ for (RenderPass *rp = rl->passes.first; rp; rp = rp->next) {
+ if (!STREQ(rp->name, "Combined")) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
RenderPass *RE_pass_find_by_name(volatile RenderLayer *rl, const char *name, const char *viewname)
{
- RenderPass *rp = NULL;
+ RenderPass *rp = NULL;
- for (rp = rl->passes.last; rp; rp = rp->prev) {
- if (STREQ(rp->name, name)) {
- if (viewname == NULL || viewname[0] == '\0')
- break;
- else if (STREQ(rp->view, viewname))
- break;
- }
- }
- return rp;
+ for (rp = rl->passes.last; rp; rp = rp->prev) {
+ if (STREQ(rp->name, name)) {
+ if (viewname == NULL || viewname[0] == '\0')
+ break;
+ else if (STREQ(rp->view, viewname))
+ break;
+ }
+ }
+ return rp;
}
/* Only provided for API compatibility, don't use this in new code! */
RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const char *viewname)
{
#define CHECK_PASS(NAME) \
- if (passtype == SCE_PASS_ ## NAME) \
- return RE_pass_find_by_name(rl, RE_PASSNAME_ ## NAME, viewname);
-
- CHECK_PASS(COMBINED);
- CHECK_PASS(Z);
- CHECK_PASS(VECTOR);
- CHECK_PASS(NORMAL);
- CHECK_PASS(UV);
- CHECK_PASS(EMIT);
- CHECK_PASS(SHADOW);
- CHECK_PASS(AO);
- CHECK_PASS(ENVIRONMENT);
- CHECK_PASS(INDEXOB);
- CHECK_PASS(INDEXMA);
- CHECK_PASS(MIST);
- CHECK_PASS(RAYHITS);
- CHECK_PASS(DIFFUSE_DIRECT);
- CHECK_PASS(DIFFUSE_INDIRECT);
- CHECK_PASS(DIFFUSE_COLOR);
- CHECK_PASS(GLOSSY_DIRECT);
- CHECK_PASS(GLOSSY_INDIRECT);
- CHECK_PASS(GLOSSY_COLOR);
- CHECK_PASS(TRANSM_DIRECT);
- CHECK_PASS(TRANSM_INDIRECT);
- CHECK_PASS(TRANSM_COLOR);
- CHECK_PASS(SUBSURFACE_DIRECT);
- CHECK_PASS(SUBSURFACE_INDIRECT);
- CHECK_PASS(SUBSURFACE_COLOR);
+ if (passtype == SCE_PASS_##NAME) \
+ return RE_pass_find_by_name(rl, RE_PASSNAME_##NAME, viewname);
+
+ CHECK_PASS(COMBINED);
+ CHECK_PASS(Z);
+ CHECK_PASS(VECTOR);
+ CHECK_PASS(NORMAL);
+ CHECK_PASS(UV);
+ CHECK_PASS(EMIT);
+ CHECK_PASS(SHADOW);
+ CHECK_PASS(AO);
+ CHECK_PASS(ENVIRONMENT);
+ CHECK_PASS(INDEXOB);
+ CHECK_PASS(INDEXMA);
+ CHECK_PASS(MIST);
+ CHECK_PASS(RAYHITS);
+ CHECK_PASS(DIFFUSE_DIRECT);
+ CHECK_PASS(DIFFUSE_INDIRECT);
+ CHECK_PASS(DIFFUSE_COLOR);
+ CHECK_PASS(GLOSSY_DIRECT);
+ CHECK_PASS(GLOSSY_INDIRECT);
+ CHECK_PASS(GLOSSY_COLOR);
+ CHECK_PASS(TRANSM_DIRECT);
+ CHECK_PASS(TRANSM_INDIRECT);
+ CHECK_PASS(TRANSM_COLOR);
+ CHECK_PASS(SUBSURFACE_DIRECT);
+ CHECK_PASS(SUBSURFACE_INDIRECT);
+ CHECK_PASS(SUBSURFACE_COLOR);
#undef CHECK_PASS
- return NULL;
+ return NULL;
}
/* create a renderlayer and renderpass for grease pencil layer */
RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const char *viewname)
{
- RenderLayer *rl = BLI_findstring(&rr->layers, layername, offsetof(RenderLayer, name));
- /* only create render layer if not exist */
- if (!rl) {
- rl = MEM_callocN(sizeof(RenderLayer), layername);
- BLI_addtail(&rr->layers, rl);
- BLI_strncpy(rl->name, layername, sizeof(rl->name));
- rl->layflag = SCE_LAY_SOLID;
- rl->passflag = SCE_PASS_COMBINED;
- rl->rectx = rr->rectx;
- rl->recty = rr->recty;
- }
-
- /* clear previous pass if exist or the new image will be over previous one*/
- RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname);
- if (rp) {
- if (rp->rect) {
- MEM_freeN(rp->rect);
- }
- BLI_freelinkN(&rl->passes, rp);
- }
- /* create a totally new pass */
- return gp_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, viewname);
+ RenderLayer *rl = BLI_findstring(&rr->layers, layername, offsetof(RenderLayer, name));
+ /* only create render layer if not exist */
+ if (!rl) {
+ rl = MEM_callocN(sizeof(RenderLayer), layername);
+ BLI_addtail(&rr->layers, rl);
+ BLI_strncpy(rl->name, layername, sizeof(rl->name));
+ rl->layflag = SCE_LAY_SOLID;
+ rl->passflag = SCE_PASS_COMBINED;
+ rl->rectx = rr->rectx;
+ rl->recty = rr->recty;
+ }
+
+ /* clear previous pass if exist or the new image will be over previous one*/
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname);
+ if (rp) {
+ if (rp->rect) {
+ MEM_freeN(rp->rect);
+ }
+ BLI_freelinkN(&rl->passes, rp);
+ }
+ /* create a totally new pass */
+ return gp_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, viewname);
}
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index d3e6b6c6c51..a38c0d71a79 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -21,7 +21,6 @@
* \ingroup render
*/
-
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
@@ -64,67 +63,70 @@ static ThreadMutex sample_mutex = PTHREAD_MUTEX_INITIALIZER;
static int point_data_used(PointDensity *pd)
{
- int pd_bitflag = 0;
-
- if (pd->source == TEX_PD_PSYS) {
- if ((pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) ||
- (pd->color_source == TEX_PD_COLOR_PARTVEL) ||
- (pd->color_source == TEX_PD_COLOR_PARTSPEED))
- {
- pd_bitflag |= POINT_DATA_VEL;
- }
- if ((pd->color_source == TEX_PD_COLOR_PARTAGE) ||
- (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE))
- {
- pd_bitflag |= POINT_DATA_LIFE;
- }
- }
- else if (pd->source == TEX_PD_OBJECT) {
- if (ELEM(pd->ob_color_source, TEX_PD_COLOR_VERTCOL, TEX_PD_COLOR_VERTWEIGHT, TEX_PD_COLOR_VERTNOR)) {
- pd_bitflag |= POINT_DATA_COLOR;
- }
- }
-
- return pd_bitflag;
+ int pd_bitflag = 0;
+
+ if (pd->source == TEX_PD_PSYS) {
+ if ((pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) ||
+ (pd->color_source == TEX_PD_COLOR_PARTVEL) ||
+ (pd->color_source == TEX_PD_COLOR_PARTSPEED)) {
+ pd_bitflag |= POINT_DATA_VEL;
+ }
+ if ((pd->color_source == TEX_PD_COLOR_PARTAGE) ||
+ (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE)) {
+ pd_bitflag |= POINT_DATA_LIFE;
+ }
+ }
+ else if (pd->source == TEX_PD_OBJECT) {
+ if (ELEM(pd->ob_color_source,
+ TEX_PD_COLOR_VERTCOL,
+ TEX_PD_COLOR_VERTWEIGHT,
+ TEX_PD_COLOR_VERTNOR)) {
+ pd_bitflag |= POINT_DATA_COLOR;
+ }
+ }
+
+ return pd_bitflag;
}
static void point_data_pointers(PointDensity *pd,
- float **r_data_velocity, float **r_data_life, float **r_data_color)
+ float **r_data_velocity,
+ float **r_data_life,
+ float **r_data_color)
{
- const int data_used = point_data_used(pd);
- const int totpoint = pd->totpoints;
- float *data = pd->point_data;
- int offset = 0;
-
- if (data_used & POINT_DATA_VEL) {
- if (r_data_velocity)
- *r_data_velocity = data + offset;
- offset += 3 * totpoint;
- }
- else {
- if (r_data_velocity)
- *r_data_velocity = NULL;
- }
-
- if (data_used & POINT_DATA_LIFE) {
- if (r_data_life)
- *r_data_life = data + offset;
- offset += totpoint;
- }
- else {
- if (r_data_life)
- *r_data_life = NULL;
- }
-
- if (data_used & POINT_DATA_COLOR) {
- if (r_data_color)
- *r_data_color = data + offset;
- offset += 3 * totpoint;
- }
- else {
- if (r_data_color)
- *r_data_color = NULL;
- }
+ const int data_used = point_data_used(pd);
+ const int totpoint = pd->totpoints;
+ float *data = pd->point_data;
+ int offset = 0;
+
+ if (data_used & POINT_DATA_VEL) {
+ if (r_data_velocity)
+ *r_data_velocity = data + offset;
+ offset += 3 * totpoint;
+ }
+ else {
+ if (r_data_velocity)
+ *r_data_velocity = NULL;
+ }
+
+ if (data_used & POINT_DATA_LIFE) {
+ if (r_data_life)
+ *r_data_life = data + offset;
+ offset += totpoint;
+ }
+ else {
+ if (r_data_life)
+ *r_data_life = NULL;
+ }
+
+ if (data_used & POINT_DATA_COLOR) {
+ if (r_data_color)
+ *r_data_color = data + offset;
+ offset += 3 * totpoint;
+ }
+ else {
+ if (r_data_color)
+ *r_data_color = NULL;
+ }
}
/* additional data stored alongside the point density BVH,
@@ -132,458 +134,460 @@ static void point_data_pointers(PointDensity *pd,
* such as particle velocity or lifetime */
static void alloc_point_data(PointDensity *pd)
{
- const int totpoints = pd->totpoints;
- int data_used = point_data_used(pd);
- int data_size = 0;
-
- if (data_used & POINT_DATA_VEL) {
- /* store 3 channels of velocity data */
- data_size += 3;
- }
- if (data_used & POINT_DATA_LIFE) {
- /* store 1 channel of lifetime data */
- data_size += 1;
- }
- if (data_used & POINT_DATA_COLOR) {
- /* store 3 channels of RGB data */
- data_size += 3;
- }
-
- if (data_size) {
- pd->point_data = MEM_callocN(sizeof(float) * data_size * totpoints,
- "particle point data");
- }
+ const int totpoints = pd->totpoints;
+ int data_used = point_data_used(pd);
+ int data_size = 0;
+
+ if (data_used & POINT_DATA_VEL) {
+ /* store 3 channels of velocity data */
+ data_size += 3;
+ }
+ if (data_used & POINT_DATA_LIFE) {
+ /* store 1 channel of lifetime data */
+ data_size += 1;
+ }
+ if (data_used & POINT_DATA_COLOR) {
+ /* store 3 channels of RGB data */
+ data_size += 3;
+ }
+
+ if (data_size) {
+ pd->point_data = MEM_callocN(sizeof(float) * data_size * totpoints, "particle point data");
+ }
}
-static void pointdensity_cache_psys(Depsgraph *depsgraph, Scene *scene,
- PointDensity *pd,
- Object *ob,
- ParticleSystem *psys)
+static void pointdensity_cache_psys(
+ Depsgraph *depsgraph, Scene *scene, PointDensity *pd, Object *ob, ParticleSystem *psys)
{
- ParticleKey state;
- ParticleCacheKey *cache;
- ParticleSimulationData sim = {NULL};
- ParticleData *pa = NULL;
- float cfra = BKE_scene_frame_get(scene);
- int i /*, childexists*/ /* UNUSED */;
- int total_particles;
- int data_used;
- float *data_vel, *data_life;
- float partco[3];
- const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
-
- data_used = point_data_used(pd);
-
- if (!psys_check_enabled(ob, psys, use_render_params)) {
- return;
- }
-
- sim.depsgraph = depsgraph;
- sim.scene = scene;
- sim.ob = ob;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(ob, psys);
-
- /* in case ob->imat isn't up-to-date */
- invert_m4_m4(ob->imat, ob->obmat);
-
- total_particles = psys->totpart + psys->totchild;
- psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6);
- pd->totpoints = total_particles;
- alloc_point_data(pd);
- point_data_pointers(pd, &data_vel, &data_life, NULL);
+ ParticleKey state;
+ ParticleCacheKey *cache;
+ ParticleSimulationData sim = {NULL};
+ ParticleData *pa = NULL;
+ float cfra = BKE_scene_frame_get(scene);
+ int i /*, childexists*/ /* UNUSED */;
+ int total_particles;
+ int data_used;
+ float *data_vel, *data_life;
+ float partco[3];
+ const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
+
+ data_used = point_data_used(pd);
+
+ if (!psys_check_enabled(ob, psys, use_render_params)) {
+ return;
+ }
+
+ sim.depsgraph = depsgraph;
+ sim.scene = scene;
+ sim.ob = ob;
+ sim.psys = psys;
+ sim.psmd = psys_get_modifier(ob, psys);
+
+ /* in case ob->imat isn't up-to-date */
+ invert_m4_m4(ob->imat, ob->obmat);
+
+ total_particles = psys->totpart + psys->totchild;
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
+
+ pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6);
+ pd->totpoints = total_particles;
+ alloc_point_data(pd);
+ point_data_pointers(pd, &data_vel, &data_life, NULL);
#if 0 /* UNUSED */
- if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
- childexists = 1;
+ if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
+ childexists = 1;
#endif
- for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
-
- if (psys->part->type == PART_HAIR) {
- /* hair particles */
- if (i < psys->totpart && psys->pathcache)
- cache = psys->pathcache[i];
- else if (i >= psys->totpart && psys->childcache)
- cache = psys->childcache[i - psys->totpart];
- else
- continue;
-
- cache += cache->segments; /* use endpoint */
-
- copy_v3_v3(state.co, cache->co);
- zero_v3(state.vel);
- state.time = 0.0f;
- }
- else {
- /* emitter particles */
- state.time = cfra;
-
- if (!psys_get_particle_state(&sim, i, &state, 0))
- continue;
-
- if (data_used & POINT_DATA_LIFE) {
- if (i < psys->totpart) {
- state.time = (cfra - pa->time) / pa->lifetime;
- }
- else {
- ChildParticle *cpa = (psys->child + i) - psys->totpart;
- float pa_birthtime, pa_dietime;
-
- state.time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
- }
- }
- }
-
- copy_v3_v3(partco, state.co);
-
- if (pd->psys_cache_space == TEX_PD_OBJECTSPACE)
- mul_m4_v3(ob->imat, partco);
- else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) {
- sub_v3_v3(partco, ob->loc);
- }
- else {
- /* TEX_PD_WORLDSPACE */
- }
-
- BLI_bvhtree_insert(pd->point_tree, i, partco, 1);
-
- if (data_vel) {
- data_vel[i * 3 + 0] = state.vel[0];
- data_vel[i * 3 + 1] = state.vel[1];
- data_vel[i * 3 + 2] = state.vel[2];
- }
- if (data_life) {
- data_life[i] = state.time;
- }
- }
-
- BLI_bvhtree_balance(pd->point_tree);
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
+ for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
+
+ if (psys->part->type == PART_HAIR) {
+ /* hair particles */
+ if (i < psys->totpart && psys->pathcache)
+ cache = psys->pathcache[i];
+ else if (i >= psys->totpart && psys->childcache)
+ cache = psys->childcache[i - psys->totpart];
+ else
+ continue;
+
+ cache += cache->segments; /* use endpoint */
+
+ copy_v3_v3(state.co, cache->co);
+ zero_v3(state.vel);
+ state.time = 0.0f;
+ }
+ else {
+ /* emitter particles */
+ state.time = cfra;
+
+ if (!psys_get_particle_state(&sim, i, &state, 0))
+ continue;
+
+ if (data_used & POINT_DATA_LIFE) {
+ if (i < psys->totpart) {
+ state.time = (cfra - pa->time) / pa->lifetime;
+ }
+ else {
+ ChildParticle *cpa = (psys->child + i) - psys->totpart;
+ float pa_birthtime, pa_dietime;
+
+ state.time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
+ }
+ }
+ }
+
+ copy_v3_v3(partco, state.co);
+
+ if (pd->psys_cache_space == TEX_PD_OBJECTSPACE)
+ mul_m4_v3(ob->imat, partco);
+ else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) {
+ sub_v3_v3(partco, ob->loc);
+ }
+ else {
+ /* TEX_PD_WORLDSPACE */
+ }
+
+ BLI_bvhtree_insert(pd->point_tree, i, partco, 1);
+
+ if (data_vel) {
+ data_vel[i * 3 + 0] = state.vel[0];
+ data_vel[i * 3 + 1] = state.vel[1];
+ data_vel[i * 3 + 2] = state.vel[2];
+ }
+ if (data_life) {
+ data_life[i] = state.time;
+ }
+ }
+
+ BLI_bvhtree_balance(pd->point_tree);
+
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
+ }
}
-
-static void pointdensity_cache_vertex_color(PointDensity *pd, Object *UNUSED(ob), Mesh *mesh, float *data_color)
+static void pointdensity_cache_vertex_color(PointDensity *pd,
+ Object *UNUSED(ob),
+ Mesh *mesh,
+ float *data_color)
{
- const MLoop *mloop = mesh->mloop;
- const int totloop = mesh->totloop;
- const MLoopCol *mcol;
- char layername[MAX_CUSTOMDATA_LAYER_NAME];
- int i;
-
- BLI_assert(data_color);
-
- if (!CustomData_has_layer(&mesh->ldata, CD_MLOOPCOL))
- return;
- CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPCOL, pd->vertex_attribute_name, layername);
- mcol = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPCOL, layername);
- if (!mcol)
- return;
-
- /* Stores the number of MLoops using the same vertex, so we can normalize colors. */
- int *mcorners = MEM_callocN(sizeof(int) * pd->totpoints, "point density corner count");
-
- for (i = 0; i < totloop; i++) {
- int v = mloop[i].v;
-
- if (mcorners[v] == 0) {
- rgb_uchar_to_float(&data_color[v * 3], &mcol[i].r);
- }
- else {
- float col[3];
- rgb_uchar_to_float(col, &mcol[i].r);
- add_v3_v3(&data_color[v * 3], col);
- }
-
- ++mcorners[v];
- }
-
- /* Normalize colors by averaging over mcorners.
- * All the corners share the same vertex, ie. occupy the same point in space.
- */
- for (i = 0; i < pd->totpoints; i++) {
- if (mcorners[i] > 0)
- mul_v3_fl(&data_color[i * 3], 1.0f / mcorners[i]);
- }
-
- MEM_freeN(mcorners);
+ const MLoop *mloop = mesh->mloop;
+ const int totloop = mesh->totloop;
+ const MLoopCol *mcol;
+ char layername[MAX_CUSTOMDATA_LAYER_NAME];
+ int i;
+
+ BLI_assert(data_color);
+
+ if (!CustomData_has_layer(&mesh->ldata, CD_MLOOPCOL))
+ return;
+ CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPCOL, pd->vertex_attribute_name, layername);
+ mcol = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPCOL, layername);
+ if (!mcol)
+ return;
+
+ /* Stores the number of MLoops using the same vertex, so we can normalize colors. */
+ int *mcorners = MEM_callocN(sizeof(int) * pd->totpoints, "point density corner count");
+
+ for (i = 0; i < totloop; i++) {
+ int v = mloop[i].v;
+
+ if (mcorners[v] == 0) {
+ rgb_uchar_to_float(&data_color[v * 3], &mcol[i].r);
+ }
+ else {
+ float col[3];
+ rgb_uchar_to_float(col, &mcol[i].r);
+ add_v3_v3(&data_color[v * 3], col);
+ }
+
+ ++mcorners[v];
+ }
+
+ /* Normalize colors by averaging over mcorners.
+ * All the corners share the same vertex, ie. occupy the same point in space.
+ */
+ for (i = 0; i < pd->totpoints; i++) {
+ if (mcorners[i] > 0)
+ mul_v3_fl(&data_color[i * 3], 1.0f / mcorners[i]);
+ }
+
+ MEM_freeN(mcorners);
}
-static void pointdensity_cache_vertex_weight(PointDensity *pd, Object *ob, Mesh *mesh, float *data_color)
+static void pointdensity_cache_vertex_weight(PointDensity *pd,
+ Object *ob,
+ Mesh *mesh,
+ float *data_color)
{
- const int totvert = mesh->totvert;
- const MDeformVert *mdef, *dv;
- int mdef_index;
- int i;
-
- BLI_assert(data_color);
-
- mdef = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT);
- if (!mdef)
- return;
- mdef_index = defgroup_name_index(ob, pd->vertex_attribute_name);
- if (mdef_index < 0)
- mdef_index = ob->actdef - 1;
- if (mdef_index < 0)
- return;
-
- for (i = 0, dv = mdef; i < totvert; ++i, ++dv, data_color += 3) {
- MDeformWeight *dw;
- int j;
-
- for (j = 0, dw = dv->dw; j < dv->totweight; ++j, ++dw) {
- if (dw->def_nr == mdef_index) {
- copy_v3_fl(data_color, dw->weight);
- break;
- }
- }
- }
+ const int totvert = mesh->totvert;
+ const MDeformVert *mdef, *dv;
+ int mdef_index;
+ int i;
+
+ BLI_assert(data_color);
+
+ mdef = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT);
+ if (!mdef)
+ return;
+ mdef_index = defgroup_name_index(ob, pd->vertex_attribute_name);
+ if (mdef_index < 0)
+ mdef_index = ob->actdef - 1;
+ if (mdef_index < 0)
+ return;
+
+ for (i = 0, dv = mdef; i < totvert; ++i, ++dv, data_color += 3) {
+ MDeformWeight *dw;
+ int j;
+
+ for (j = 0, dw = dv->dw; j < dv->totweight; ++j, ++dw) {
+ if (dw->def_nr == mdef_index) {
+ copy_v3_fl(data_color, dw->weight);
+ break;
+ }
+ }
+ }
}
-static void pointdensity_cache_vertex_normal(PointDensity *pd, Object *UNUSED(ob), Mesh *mesh, float *data_color)
+static void pointdensity_cache_vertex_normal(PointDensity *pd,
+ Object *UNUSED(ob),
+ Mesh *mesh,
+ float *data_color)
{
- MVert *mvert = mesh->mvert, *mv;
- int i;
+ MVert *mvert = mesh->mvert, *mv;
+ int i;
- BLI_assert(data_color);
+ BLI_assert(data_color);
- for (i = 0, mv = mvert; i < pd->totpoints; i++, mv++, data_color += 3) {
- normal_short_to_float_v3(data_color, mv->no);
- }
+ for (i = 0, mv = mvert; i < pd->totpoints; i++, mv++, data_color += 3) {
+ normal_short_to_float_v3(data_color, mv->no);
+ }
}
-static void pointdensity_cache_object(PointDensity *pd,
- Object *ob)
+static void pointdensity_cache_object(PointDensity *pd, Object *ob)
{
- float *data_color;
- int i;
- MVert *mvert = NULL, *mv;
- Mesh *mesh = ob->data;
-
-#if 0 /* UNUSED */
- CustomData_MeshMasks mask = CD_MASK_BAREMESH;
- mask.fmask |= CD_MASK_MTFACE | CD_MASK_MCOL;
- switch (pd->ob_color_source) {
- case TEX_PD_COLOR_VERTCOL:
- mask.lmask |= CD_MASK_MLOOPCOL;
- break;
- case TEX_PD_COLOR_VERTWEIGHT:
- mask.vmask |= CD_MASK_MDEFORMVERT;
- break;
- }
+ float *data_color;
+ int i;
+ MVert *mvert = NULL, *mv;
+ Mesh *mesh = ob->data;
+
+#if 0 /* UNUSED */
+ CustomData_MeshMasks mask = CD_MASK_BAREMESH;
+ mask.fmask |= CD_MASK_MTFACE | CD_MASK_MCOL;
+ switch (pd->ob_color_source) {
+ case TEX_PD_COLOR_VERTCOL:
+ mask.lmask |= CD_MASK_MLOOPCOL;
+ break;
+ case TEX_PD_COLOR_VERTWEIGHT:
+ mask.vmask |= CD_MASK_MDEFORMVERT;
+ break;
+ }
#endif
- mvert = mesh->mvert; /* local object space */
- pd->totpoints = mesh->totvert;
- if (pd->totpoints == 0) {
- return;
- }
-
- pd->point_tree = BLI_bvhtree_new(pd->totpoints, 0.0, 4, 6);
- alloc_point_data(pd);
- point_data_pointers(pd, NULL, NULL, &data_color);
-
- for (i = 0, mv = mvert; i < pd->totpoints; i++, mv++) {
- float co[3];
-
- copy_v3_v3(co, mv->co);
-
- switch (pd->ob_cache_space) {
- case TEX_PD_OBJECTSPACE:
- break;
- case TEX_PD_OBJECTLOC:
- mul_m4_v3(ob->obmat, co);
- sub_v3_v3(co, ob->loc);
- break;
- case TEX_PD_WORLDSPACE:
- default:
- mul_m4_v3(ob->obmat, co);
- break;
- }
-
- BLI_bvhtree_insert(pd->point_tree, i, co, 1);
- }
-
- switch (pd->ob_color_source) {
- case TEX_PD_COLOR_VERTCOL:
- pointdensity_cache_vertex_color(pd, ob, mesh, data_color);
- break;
- case TEX_PD_COLOR_VERTWEIGHT:
- pointdensity_cache_vertex_weight(pd, ob, mesh, data_color);
- break;
- case TEX_PD_COLOR_VERTNOR:
- pointdensity_cache_vertex_normal(pd, ob, mesh, data_color);
- break;
- }
-
- BLI_bvhtree_balance(pd->point_tree);
+ mvert = mesh->mvert; /* local object space */
+ pd->totpoints = mesh->totvert;
+ if (pd->totpoints == 0) {
+ return;
+ }
+
+ pd->point_tree = BLI_bvhtree_new(pd->totpoints, 0.0, 4, 6);
+ alloc_point_data(pd);
+ point_data_pointers(pd, NULL, NULL, &data_color);
+
+ for (i = 0, mv = mvert; i < pd->totpoints; i++, mv++) {
+ float co[3];
+
+ copy_v3_v3(co, mv->co);
+
+ switch (pd->ob_cache_space) {
+ case TEX_PD_OBJECTSPACE:
+ break;
+ case TEX_PD_OBJECTLOC:
+ mul_m4_v3(ob->obmat, co);
+ sub_v3_v3(co, ob->loc);
+ break;
+ case TEX_PD_WORLDSPACE:
+ default:
+ mul_m4_v3(ob->obmat, co);
+ break;
+ }
+
+ BLI_bvhtree_insert(pd->point_tree, i, co, 1);
+ }
+
+ switch (pd->ob_color_source) {
+ case TEX_PD_COLOR_VERTCOL:
+ pointdensity_cache_vertex_color(pd, ob, mesh, data_color);
+ break;
+ case TEX_PD_COLOR_VERTWEIGHT:
+ pointdensity_cache_vertex_weight(pd, ob, mesh, data_color);
+ break;
+ case TEX_PD_COLOR_VERTNOR:
+ pointdensity_cache_vertex_normal(pd, ob, mesh, data_color);
+ break;
+ }
+
+ BLI_bvhtree_balance(pd->point_tree);
}
-static void cache_pointdensity(Depsgraph *depsgraph,
- Scene *scene,
- PointDensity *pd)
+static void cache_pointdensity(Depsgraph *depsgraph, Scene *scene, PointDensity *pd)
{
- if (pd == NULL) {
- return;
- }
-
- if (pd->point_tree) {
- BLI_bvhtree_free(pd->point_tree);
- pd->point_tree = NULL;
- }
-
- if (pd->source == TEX_PD_PSYS) {
- Object *ob = pd->object;
- ParticleSystem *psys;
-
- if (!ob || !pd->psys) {
- return;
- }
-
- psys = BLI_findlink(&ob->particlesystem, pd->psys - 1);
- if (!psys) {
- return;
- }
-
- pointdensity_cache_psys(depsgraph,
- scene,
- pd,
- ob,
- psys);
- }
- else if (pd->source == TEX_PD_OBJECT) {
- Object *ob = pd->object;
- if (ob && ob->type == OB_MESH)
- pointdensity_cache_object(pd, ob);
- }
+ if (pd == NULL) {
+ return;
+ }
+
+ if (pd->point_tree) {
+ BLI_bvhtree_free(pd->point_tree);
+ pd->point_tree = NULL;
+ }
+
+ if (pd->source == TEX_PD_PSYS) {
+ Object *ob = pd->object;
+ ParticleSystem *psys;
+
+ if (!ob || !pd->psys) {
+ return;
+ }
+
+ psys = BLI_findlink(&ob->particlesystem, pd->psys - 1);
+ if (!psys) {
+ return;
+ }
+
+ pointdensity_cache_psys(depsgraph, scene, pd, ob, psys);
+ }
+ else if (pd->source == TEX_PD_OBJECT) {
+ Object *ob = pd->object;
+ if (ob && ob->type == OB_MESH)
+ pointdensity_cache_object(pd, ob);
+ }
}
static void free_pointdensity(PointDensity *pd)
{
- if (pd == NULL) {
- return;
- }
-
- if (pd->point_tree) {
- BLI_bvhtree_free(pd->point_tree);
- pd->point_tree = NULL;
- }
-
- if (pd->point_data) {
- MEM_freeN(pd->point_data);
- pd->point_data = NULL;
- }
- pd->totpoints = 0;
+ if (pd == NULL) {
+ return;
+ }
+
+ if (pd->point_tree) {
+ BLI_bvhtree_free(pd->point_tree);
+ pd->point_tree = NULL;
+ }
+
+ if (pd->point_data) {
+ MEM_freeN(pd->point_data);
+ pd->point_data = NULL;
+ }
+ pd->totpoints = 0;
}
typedef struct PointDensityRangeData {
- float *density;
- float squared_radius;
- float *point_data_life;
- float *point_data_velocity;
- float *point_data_color;
- float *vec;
- float *col;
- float softness;
- short falloff_type;
- short noise_influence;
- float *age;
- struct CurveMapping *density_curve;
- float velscale;
+ float *density;
+ float squared_radius;
+ float *point_data_life;
+ float *point_data_velocity;
+ float *point_data_color;
+ float *vec;
+ float *col;
+ float softness;
+ short falloff_type;
+ short noise_influence;
+ float *age;
+ struct CurveMapping *density_curve;
+ float velscale;
} PointDensityRangeData;
static float density_falloff(PointDensityRangeData *pdr, int index, float squared_dist)
{
- const float dist = (pdr->squared_radius - squared_dist) / pdr->squared_radius * 0.5f;
- float density = 0.0f;
-
- switch (pdr->falloff_type) {
- case TEX_PD_FALLOFF_STD:
- density = dist;
- break;
- case TEX_PD_FALLOFF_SMOOTH:
- density = 3.0f * dist * dist - 2.0f * dist * dist * dist;
- break;
- case TEX_PD_FALLOFF_SOFT:
- density = pow(dist, pdr->softness);
- break;
- case TEX_PD_FALLOFF_CONSTANT:
- density = pdr->squared_radius;
- break;
- case TEX_PD_FALLOFF_ROOT:
- density = sqrtf(dist);
- break;
- case TEX_PD_FALLOFF_PARTICLE_AGE:
- if (pdr->point_data_life)
- density = dist * MIN2(pdr->point_data_life[index], 1.0f);
- else
- density = dist;
- break;
- case TEX_PD_FALLOFF_PARTICLE_VEL:
- if (pdr->point_data_velocity)
- density = dist * len_v3(&pdr->point_data_velocity[index * 3]) * pdr->velscale;
- else
- density = dist;
- break;
- }
-
- if (pdr->density_curve && dist != 0.0f) {
- curvemapping_initialize(pdr->density_curve);
- density = curvemapping_evaluateF(pdr->density_curve, 0, density / dist) * dist;
- }
-
- return density;
+ const float dist = (pdr->squared_radius - squared_dist) / pdr->squared_radius * 0.5f;
+ float density = 0.0f;
+
+ switch (pdr->falloff_type) {
+ case TEX_PD_FALLOFF_STD:
+ density = dist;
+ break;
+ case TEX_PD_FALLOFF_SMOOTH:
+ density = 3.0f * dist * dist - 2.0f * dist * dist * dist;
+ break;
+ case TEX_PD_FALLOFF_SOFT:
+ density = pow(dist, pdr->softness);
+ break;
+ case TEX_PD_FALLOFF_CONSTANT:
+ density = pdr->squared_radius;
+ break;
+ case TEX_PD_FALLOFF_ROOT:
+ density = sqrtf(dist);
+ break;
+ case TEX_PD_FALLOFF_PARTICLE_AGE:
+ if (pdr->point_data_life)
+ density = dist * MIN2(pdr->point_data_life[index], 1.0f);
+ else
+ density = dist;
+ break;
+ case TEX_PD_FALLOFF_PARTICLE_VEL:
+ if (pdr->point_data_velocity)
+ density = dist * len_v3(&pdr->point_data_velocity[index * 3]) * pdr->velscale;
+ else
+ density = dist;
+ break;
+ }
+
+ if (pdr->density_curve && dist != 0.0f) {
+ curvemapping_initialize(pdr->density_curve);
+ density = curvemapping_evaluateF(pdr->density_curve, 0, density / dist) * dist;
+ }
+
+ return density;
}
static void accum_density(void *userdata, int index, const float co[3], float squared_dist)
{
- PointDensityRangeData *pdr = (PointDensityRangeData *)userdata;
- float density = 0.0f;
-
- UNUSED_VARS(co);
-
- if (pdr->point_data_velocity) {
- pdr->vec[0] += pdr->point_data_velocity[index * 3 + 0]; // * density;
- pdr->vec[1] += pdr->point_data_velocity[index * 3 + 1]; // * density;
- pdr->vec[2] += pdr->point_data_velocity[index * 3 + 2]; // * density;
- }
- if (pdr->point_data_life) {
- *pdr->age += pdr->point_data_life[index]; // * density;
- }
- if (pdr->point_data_color) {
- add_v3_v3(pdr->col, &pdr->point_data_color[index * 3]); // * density;
- }
-
- density = density_falloff(pdr, index, squared_dist);
-
- *pdr->density += density;
+ PointDensityRangeData *pdr = (PointDensityRangeData *)userdata;
+ float density = 0.0f;
+
+ UNUSED_VARS(co);
+
+ if (pdr->point_data_velocity) {
+ pdr->vec[0] += pdr->point_data_velocity[index * 3 + 0]; // * density;
+ pdr->vec[1] += pdr->point_data_velocity[index * 3 + 1]; // * density;
+ pdr->vec[2] += pdr->point_data_velocity[index * 3 + 2]; // * density;
+ }
+ if (pdr->point_data_life) {
+ *pdr->age += pdr->point_data_life[index]; // * density;
+ }
+ if (pdr->point_data_color) {
+ add_v3_v3(pdr->col, &pdr->point_data_color[index * 3]); // * density;
+ }
+
+ density = density_falloff(pdr, index, squared_dist);
+
+ *pdr->density += density;
}
-
-static void init_pointdensityrangedata(
- PointDensity *pd, PointDensityRangeData *pdr,
- float *density, float *vec, float *age, float *col, struct CurveMapping *density_curve, float velscale)
+static void init_pointdensityrangedata(PointDensity *pd,
+ PointDensityRangeData *pdr,
+ float *density,
+ float *vec,
+ float *age,
+ float *col,
+ struct CurveMapping *density_curve,
+ float velscale)
{
- pdr->squared_radius = pd->radius * pd->radius;
- pdr->density = density;
- pdr->falloff_type = pd->falloff_type;
- pdr->vec = vec;
- pdr->age = age;
- pdr->col = col;
- pdr->softness = pd->falloff_softness;
- pdr->noise_influence = pd->noise_influence;
- point_data_pointers(pd, &pdr->point_data_velocity, &pdr->point_data_life, &pdr->point_data_color);
- pdr->density_curve = density_curve;
- pdr->velscale = velscale;
+ pdr->squared_radius = pd->radius * pd->radius;
+ pdr->density = density;
+ pdr->falloff_type = pd->falloff_type;
+ pdr->vec = vec;
+ pdr->age = age;
+ pdr->col = col;
+ pdr->softness = pd->falloff_softness;
+ pdr->noise_influence = pd->noise_influence;
+ point_data_pointers(
+ pd, &pdr->point_data_velocity, &pdr->point_data_life, &pdr->point_data_color);
+ pdr->density_curve = density_curve;
+ pdr->velscale = velscale;
}
-
static int pointdensity(PointDensity *pd,
const float texvec[3],
TexResult *texres,
@@ -591,149 +595,159 @@ static int pointdensity(PointDensity *pd,
float *r_age,
float r_col[3])
{
- int retval = TEX_INT;
- PointDensityRangeData pdr;
- float density = 0.0f, age = 0.0f;
- float vec[3] = {0.0f, 0.0f, 0.0f}, col[3] = {0.0f, 0.0f, 0.0f}, co[3];
- float turb, noise_fac;
- int num = 0;
-
- texres->tin = 0.0f;
-
- init_pointdensityrangedata(pd, &pdr, &density, vec, &age, col,
- (pd->flag & TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : NULL),
- pd->falloff_speed_scale * 0.001f);
- noise_fac = pd->noise_fac * 0.5f; /* better default */
-
- copy_v3_v3(co, texvec);
-
- if (point_data_used(pd)) {
- /* does a BVH lookup to find accumulated density and additional point data *
- * stores particle velocity vector in 'vec', and particle lifetime in 'time' */
- num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr);
- if (num > 0) {
- age /= num;
- mul_v3_fl(vec, 1.0f / num);
- mul_v3_fl(col, 1.0f / num);
- }
-
- /* reset */
- density = 0.0f;
- zero_v3(vec);
- zero_v3(col);
- }
-
- if (pd->flag & TEX_PD_TURBULENCE) {
- turb = BLI_gTurbulence(pd->noise_size, texvec[0] + vec[0], texvec[1] + vec[1], texvec[2] + vec[2],
- pd->noise_depth, 0, pd->noise_basis);
-
- turb -= 0.5f; /* re-center 0.0-1.0 range around 0 to prevent offsetting result */
-
- /* now we have an offset coordinate to use for the density lookup */
- co[0] = texvec[0] + noise_fac * turb;
- co[1] = texvec[1] + noise_fac * turb;
- co[2] = texvec[2] + noise_fac * turb;
- }
-
- /* BVH query with the potentially perturbed coordinates */
- num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr);
- if (num > 0) {
- age /= num;
- mul_v3_fl(vec, 1.0f / num);
- mul_v3_fl(col, 1.0f / num);
- }
-
- texres->tin = density;
- if (r_age != NULL) {
- *r_age = age;
- }
- if (r_vec != NULL) {
- copy_v3_v3(r_vec, vec);
- }
- if (r_col != NULL) {
- copy_v3_v3(r_col, col);
- }
-
- return retval;
+ int retval = TEX_INT;
+ PointDensityRangeData pdr;
+ float density = 0.0f, age = 0.0f;
+ float vec[3] = {0.0f, 0.0f, 0.0f}, col[3] = {0.0f, 0.0f, 0.0f}, co[3];
+ float turb, noise_fac;
+ int num = 0;
+
+ texres->tin = 0.0f;
+
+ init_pointdensityrangedata(pd,
+ &pdr,
+ &density,
+ vec,
+ &age,
+ col,
+ (pd->flag & TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : NULL),
+ pd->falloff_speed_scale * 0.001f);
+ noise_fac = pd->noise_fac * 0.5f; /* better default */
+
+ copy_v3_v3(co, texvec);
+
+ if (point_data_used(pd)) {
+ /* does a BVH lookup to find accumulated density and additional point data *
+ * stores particle velocity vector in 'vec', and particle lifetime in 'time' */
+ num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr);
+ if (num > 0) {
+ age /= num;
+ mul_v3_fl(vec, 1.0f / num);
+ mul_v3_fl(col, 1.0f / num);
+ }
+
+ /* reset */
+ density = 0.0f;
+ zero_v3(vec);
+ zero_v3(col);
+ }
+
+ if (pd->flag & TEX_PD_TURBULENCE) {
+ turb = BLI_gTurbulence(pd->noise_size,
+ texvec[0] + vec[0],
+ texvec[1] + vec[1],
+ texvec[2] + vec[2],
+ pd->noise_depth,
+ 0,
+ pd->noise_basis);
+
+ turb -= 0.5f; /* re-center 0.0-1.0 range around 0 to prevent offsetting result */
+
+ /* now we have an offset coordinate to use for the density lookup */
+ co[0] = texvec[0] + noise_fac * turb;
+ co[1] = texvec[1] + noise_fac * turb;
+ co[2] = texvec[2] + noise_fac * turb;
+ }
+
+ /* BVH query with the potentially perturbed coordinates */
+ num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr);
+ if (num > 0) {
+ age /= num;
+ mul_v3_fl(vec, 1.0f / num);
+ mul_v3_fl(col, 1.0f / num);
+ }
+
+ texres->tin = density;
+ if (r_age != NULL) {
+ *r_age = age;
+ }
+ if (r_vec != NULL) {
+ copy_v3_v3(r_vec, vec);
+ }
+ if (r_col != NULL) {
+ copy_v3_v3(r_col, col);
+ }
+
+ return retval;
}
-static void pointdensity_color(PointDensity *pd, TexResult *texres, float age, const float vec[3], const float col[3])
+static void pointdensity_color(
+ PointDensity *pd, TexResult *texres, float age, const float vec[3], const float col[3])
{
- texres->tr = texres->tg = texres->tb = texres->ta = 1.0f;
-
- if (pd->source == TEX_PD_PSYS) {
- float rgba[4];
-
- switch (pd->color_source) {
- case TEX_PD_COLOR_PARTAGE:
- if (pd->coba) {
- if (BKE_colorband_evaluate(pd->coba, age, rgba)) {
- texres->talpha = true;
- copy_v3_v3(&texres->tr, rgba);
- texres->tin *= rgba[3];
- texres->ta = texres->tin;
- }
- }
- break;
- case TEX_PD_COLOR_PARTSPEED:
- {
- float speed = len_v3(vec) * pd->speed_scale;
-
- if (pd->coba) {
- if (BKE_colorband_evaluate(pd->coba, speed, rgba)) {
- texres->talpha = true;
- copy_v3_v3(&texres->tr, rgba);
- texres->tin *= rgba[3];
- texres->ta = texres->tin;
- }
- }
- break;
- }
- case TEX_PD_COLOR_PARTVEL:
- texres->talpha = true;
- mul_v3_v3fl(&texres->tr, vec, pd->speed_scale);
- texres->ta = texres->tin;
- break;
- case TEX_PD_COLOR_CONSTANT:
- default:
- break;
- }
- }
- else {
- float rgba[4];
-
- switch (pd->ob_color_source) {
- case TEX_PD_COLOR_VERTCOL:
- texres->talpha = true;
- copy_v3_v3(&texres->tr, col);
- texres->ta = texres->tin;
- break;
- case TEX_PD_COLOR_VERTWEIGHT:
- texres->talpha = true;
- if (pd->coba && BKE_colorband_evaluate(pd->coba, col[0], rgba)) {
- copy_v3_v3(&texres->tr, rgba);
- texres->tin *= rgba[3];
- }
- else {
- copy_v3_v3(&texres->tr, col);
- }
- texres->ta = texres->tin;
- break;
- case TEX_PD_COLOR_VERTNOR:
- texres->talpha = true;
- copy_v3_v3(&texres->tr, col);
- texres->ta = texres->tin;
- break;
- case TEX_PD_COLOR_CONSTANT:
- default:
- break;
- }
- }
+ texres->tr = texres->tg = texres->tb = texres->ta = 1.0f;
+
+ if (pd->source == TEX_PD_PSYS) {
+ float rgba[4];
+
+ switch (pd->color_source) {
+ case TEX_PD_COLOR_PARTAGE:
+ if (pd->coba) {
+ if (BKE_colorband_evaluate(pd->coba, age, rgba)) {
+ texres->talpha = true;
+ copy_v3_v3(&texres->tr, rgba);
+ texres->tin *= rgba[3];
+ texres->ta = texres->tin;
+ }
+ }
+ break;
+ case TEX_PD_COLOR_PARTSPEED: {
+ float speed = len_v3(vec) * pd->speed_scale;
+
+ if (pd->coba) {
+ if (BKE_colorband_evaluate(pd->coba, speed, rgba)) {
+ texres->talpha = true;
+ copy_v3_v3(&texres->tr, rgba);
+ texres->tin *= rgba[3];
+ texres->ta = texres->tin;
+ }
+ }
+ break;
+ }
+ case TEX_PD_COLOR_PARTVEL:
+ texres->talpha = true;
+ mul_v3_v3fl(&texres->tr, vec, pd->speed_scale);
+ texres->ta = texres->tin;
+ break;
+ case TEX_PD_COLOR_CONSTANT:
+ default:
+ break;
+ }
+ }
+ else {
+ float rgba[4];
+
+ switch (pd->ob_color_source) {
+ case TEX_PD_COLOR_VERTCOL:
+ texres->talpha = true;
+ copy_v3_v3(&texres->tr, col);
+ texres->ta = texres->tin;
+ break;
+ case TEX_PD_COLOR_VERTWEIGHT:
+ texres->talpha = true;
+ if (pd->coba && BKE_colorband_evaluate(pd->coba, col[0], rgba)) {
+ copy_v3_v3(&texres->tr, rgba);
+ texres->tin *= rgba[3];
+ }
+ else {
+ copy_v3_v3(&texres->tr, col);
+ }
+ texres->ta = texres->tin;
+ break;
+ case TEX_PD_COLOR_VERTNOR:
+ texres->talpha = true;
+ copy_v3_v3(&texres->tr, col);
+ texres->ta = texres->tin;
+ break;
+ case TEX_PD_COLOR_CONSTANT:
+ default:
+ break;
+ }
+ }
}
static void sample_dummy_point_density(int resolution, float *values)
{
- memset(values, 0, sizeof(float) * 4 * resolution * resolution * resolution);
+ memset(values, 0, sizeof(float) * 4 * resolution * resolution * resolution);
}
static void particle_system_minmax(Depsgraph *depsgraph,
@@ -741,220 +755,205 @@ static void particle_system_minmax(Depsgraph *depsgraph,
Object *object,
ParticleSystem *psys,
float radius,
- float min[3], float max[3])
+ float min[3],
+ float max[3])
{
- const float size[3] = {radius, radius, radius};
- const float cfra = BKE_scene_frame_get(scene);
- ParticleSettings *part = psys->part;
- ParticleSimulationData sim = {NULL};
- ParticleData *pa = NULL;
- int i;
- int total_particles;
- float mat[4][4], imat[4][4];
-
- INIT_MINMAX(min, max);
- if (part->type == PART_HAIR) {
- /* TOOD(sergey): Not supported currently. */
- return;
- }
-
- unit_m4(mat);
-
- sim.depsgraph = depsgraph;
- sim.scene = scene;
- sim.ob = object;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(object, psys);
-
- invert_m4_m4(imat, object->obmat);
- total_particles = psys->totpart + psys->totchild;
- psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
- float co_object[3], co_min[3], co_max[3];
- ParticleKey state;
- state.time = cfra;
- if (!psys_get_particle_state(&sim, i, &state, 0)) {
- continue;
- }
- mul_v3_m4v3(co_object, imat, state.co);
- sub_v3_v3v3(co_min, co_object, size);
- add_v3_v3v3(co_max, co_object, size);
- minmax_v3v3_v3(min, max, co_min);
- minmax_v3v3_v3(min, max, co_max);
- }
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
+ const float size[3] = {radius, radius, radius};
+ const float cfra = BKE_scene_frame_get(scene);
+ ParticleSettings *part = psys->part;
+ ParticleSimulationData sim = {NULL};
+ ParticleData *pa = NULL;
+ int i;
+ int total_particles;
+ float mat[4][4], imat[4][4];
+
+ INIT_MINMAX(min, max);
+ if (part->type == PART_HAIR) {
+ /* TOOD(sergey): Not supported currently. */
+ return;
+ }
+
+ unit_m4(mat);
+
+ sim.depsgraph = depsgraph;
+ sim.scene = scene;
+ sim.ob = object;
+ sim.psys = psys;
+ sim.psmd = psys_get_modifier(object, psys);
+
+ invert_m4_m4(imat, object->obmat);
+ total_particles = psys->totpart + psys->totchild;
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
+
+ for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
+ float co_object[3], co_min[3], co_max[3];
+ ParticleKey state;
+ state.time = cfra;
+ if (!psys_get_particle_state(&sim, i, &state, 0)) {
+ continue;
+ }
+ mul_v3_m4v3(co_object, imat, state.co);
+ sub_v3_v3v3(co_min, co_object, size);
+ add_v3_v3v3(co_max, co_object, size);
+ minmax_v3v3_v3(min, max, co_min);
+ minmax_v3v3_v3(min, max, co_max);
+ }
+
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
+ }
}
-void RE_point_density_cache(
- struct Depsgraph *depsgraph,
- PointDensity *pd)
+void RE_point_density_cache(struct Depsgraph *depsgraph, PointDensity *pd)
{
- Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
- /* Same matricies/resolution as dupli_render_particle_set(). */
- BLI_mutex_lock(&sample_mutex);
- cache_pointdensity(depsgraph, scene, pd);
- BLI_mutex_unlock(&sample_mutex);
+ /* Same matricies/resolution as dupli_render_particle_set(). */
+ BLI_mutex_lock(&sample_mutex);
+ cache_pointdensity(depsgraph, scene, pd);
+ BLI_mutex_unlock(&sample_mutex);
}
-void RE_point_density_minmax(
- struct Depsgraph *depsgraph,
- struct PointDensity *pd,
- float r_min[3], float r_max[3])
+void RE_point_density_minmax(struct Depsgraph *depsgraph,
+ struct PointDensity *pd,
+ float r_min[3],
+ float r_max[3])
{
- Scene *scene = DEG_get_evaluated_scene(depsgraph);
- Object *object = pd->object;
- if (object == NULL) {
- zero_v3(r_min);
- zero_v3(r_max);
- return;
- }
- if (pd->source == TEX_PD_PSYS) {
- ParticleSystem *psys;
-
- if (pd->psys == 0) {
- zero_v3(r_min);
- zero_v3(r_max);
- return;
- }
- psys = BLI_findlink(&object->particlesystem, pd->psys - 1);
- if (psys == NULL) {
- zero_v3(r_min);
- zero_v3(r_max);
- return;
- }
-
- particle_system_minmax(depsgraph,
- scene,
- object,
- psys,
- pd->radius,
- r_min, r_max);
- }
- else {
- float radius[3] = {pd->radius, pd->radius, pd->radius};
- BoundBox *bb = BKE_object_boundbox_get(object);
-
- if (bb != NULL) {
- BLI_assert((bb->flag & BOUNDBOX_DIRTY) == 0);
- copy_v3_v3(r_min, bb->vec[0]);
- copy_v3_v3(r_max, bb->vec[6]);
- /* Adjust texture space to include density points on the boundaries. */
- sub_v3_v3(r_min, radius);
- add_v3_v3(r_max, radius);
- }
- else {
- zero_v3(r_min);
- zero_v3(r_max);
- }
- }
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ Object *object = pd->object;
+ if (object == NULL) {
+ zero_v3(r_min);
+ zero_v3(r_max);
+ return;
+ }
+ if (pd->source == TEX_PD_PSYS) {
+ ParticleSystem *psys;
+
+ if (pd->psys == 0) {
+ zero_v3(r_min);
+ zero_v3(r_max);
+ return;
+ }
+ psys = BLI_findlink(&object->particlesystem, pd->psys - 1);
+ if (psys == NULL) {
+ zero_v3(r_min);
+ zero_v3(r_max);
+ return;
+ }
+
+ particle_system_minmax(depsgraph, scene, object, psys, pd->radius, r_min, r_max);
+ }
+ else {
+ float radius[3] = {pd->radius, pd->radius, pd->radius};
+ BoundBox *bb = BKE_object_boundbox_get(object);
+
+ if (bb != NULL) {
+ BLI_assert((bb->flag & BOUNDBOX_DIRTY) == 0);
+ copy_v3_v3(r_min, bb->vec[0]);
+ copy_v3_v3(r_max, bb->vec[6]);
+ /* Adjust texture space to include density points on the boundaries. */
+ sub_v3_v3(r_min, radius);
+ add_v3_v3(r_max, radius);
+ }
+ else {
+ zero_v3(r_min);
+ zero_v3(r_max);
+ }
+ }
}
typedef struct SampleCallbackData {
- PointDensity *pd;
- int resolution;
- float *min, *dim;
- float *values;
+ PointDensity *pd;
+ int resolution;
+ float *min, *dim;
+ float *values;
} SampleCallbackData;
-static void point_density_sample_func(
- void *__restrict data_v,
- const int iter,
- const ParallelRangeTLS *__restrict UNUSED(tls))
+static void point_density_sample_func(void *__restrict data_v,
+ const int iter,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
- SampleCallbackData *data = (SampleCallbackData *)data_v;
-
- const int resolution = data->resolution;
- const int resolution2 = resolution * resolution;
- const float *min = data->min, *dim = data->dim;
- PointDensity *pd = data->pd;
- float *values = data->values;
-
- if (!pd || !pd->point_tree) {
- return;
- }
-
- size_t z = (size_t)iter;
- for (size_t y = 0; y < resolution; ++y) {
- for (size_t x = 0; x < resolution; ++x) {
- size_t index = z * resolution2 + y * resolution + x;
- float texvec[3];
- float age, vec[3], col[3];
- TexResult texres;
-
- copy_v3_v3(texvec, min);
- texvec[0] += dim[0] * (float)x / (float)resolution;
- texvec[1] += dim[1] * (float)y / (float)resolution;
- texvec[2] += dim[2] * (float)z / (float)resolution;
-
- pointdensity(pd, texvec, &texres, vec, &age, col);
- pointdensity_color(pd, &texres, age, vec, col);
-
- copy_v3_v3(&values[index * 4 + 0], &texres.tr);
- values[index * 4 + 3] = texres.tin;
- }
- }
+ SampleCallbackData *data = (SampleCallbackData *)data_v;
+
+ const int resolution = data->resolution;
+ const int resolution2 = resolution * resolution;
+ const float *min = data->min, *dim = data->dim;
+ PointDensity *pd = data->pd;
+ float *values = data->values;
+
+ if (!pd || !pd->point_tree) {
+ return;
+ }
+
+ size_t z = (size_t)iter;
+ for (size_t y = 0; y < resolution; ++y) {
+ for (size_t x = 0; x < resolution; ++x) {
+ size_t index = z * resolution2 + y * resolution + x;
+ float texvec[3];
+ float age, vec[3], col[3];
+ TexResult texres;
+
+ copy_v3_v3(texvec, min);
+ texvec[0] += dim[0] * (float)x / (float)resolution;
+ texvec[1] += dim[1] * (float)y / (float)resolution;
+ texvec[2] += dim[2] * (float)z / (float)resolution;
+
+ pointdensity(pd, texvec, &texres, vec, &age, col);
+ pointdensity_color(pd, &texres, age, vec, col);
+
+ copy_v3_v3(&values[index * 4 + 0], &texres.tr);
+ values[index * 4 + 3] = texres.tin;
+ }
+ }
}
/* NOTE 1: Requires RE_point_density_cache() to be called first.
* NOTE 2: Frees point density structure after sampling.
*/
-void RE_point_density_sample(
- Depsgraph *depsgraph,
- PointDensity *pd,
- const int resolution,
- float *values)
+void RE_point_density_sample(Depsgraph *depsgraph,
+ PointDensity *pd,
+ const int resolution,
+ float *values)
{
- Object *object = pd->object;
- float min[3], max[3], dim[3];
-
- /* TODO(sergey): Implement some sort of assert() that point density
- * was cached already.
- */
-
- if (object == NULL) {
- sample_dummy_point_density(resolution, values);
- return;
- }
-
- BLI_mutex_lock(&sample_mutex);
- RE_point_density_minmax(depsgraph,
- pd,
- min,
- max);
- BLI_mutex_unlock(&sample_mutex);
- sub_v3_v3v3(dim, max, min);
- if (dim[0] <= 0.0f || dim[1] <= 0.0f || dim[2] <= 0.0f) {
- sample_dummy_point_density(resolution, values);
- return;
- }
-
- SampleCallbackData data;
- data.pd = pd;
- data.resolution = resolution;
- data.min = min;
- data.dim = dim;
- data.values = values;
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = (resolution > 32);
- BLI_task_parallel_range(0,
- resolution,
- &data,
- point_density_sample_func,
- &settings);
-
- free_pointdensity(pd);
+ Object *object = pd->object;
+ float min[3], max[3], dim[3];
+
+ /* TODO(sergey): Implement some sort of assert() that point density
+ * was cached already.
+ */
+
+ if (object == NULL) {
+ sample_dummy_point_density(resolution, values);
+ return;
+ }
+
+ BLI_mutex_lock(&sample_mutex);
+ RE_point_density_minmax(depsgraph, pd, min, max);
+ BLI_mutex_unlock(&sample_mutex);
+ sub_v3_v3v3(dim, max, min);
+ if (dim[0] <= 0.0f || dim[1] <= 0.0f || dim[2] <= 0.0f) {
+ sample_dummy_point_density(resolution, values);
+ return;
+ }
+
+ SampleCallbackData data;
+ data.pd = pd;
+ data.resolution = resolution;
+ data.min = min;
+ data.dim = dim;
+ data.values = values;
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = (resolution > 32);
+ BLI_task_parallel_range(0, resolution, &data, point_density_sample_func, &settings);
+
+ free_pointdensity(pd);
}
void RE_point_density_free(struct PointDensity *pd)
{
- free_pointdensity(pd);
+ free_pointdensity(pd);
}
void RE_point_density_fix_linking(void)
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index c00fc48bcd0..0140aa44645 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -58,78 +58,83 @@
static void render_result_views_free(RenderResult *res)
{
- while (res->views.first) {
- RenderView *rv = res->views.first;
- BLI_remlink(&res->views, rv);
+ while (res->views.first) {
+ RenderView *rv = res->views.first;
+ BLI_remlink(&res->views, rv);
- if (rv->rect32)
- MEM_freeN(rv->rect32);
+ if (rv->rect32)
+ MEM_freeN(rv->rect32);
- if (rv->rectz)
- MEM_freeN(rv->rectz);
+ if (rv->rectz)
+ MEM_freeN(rv->rectz);
- if (rv->rectf)
- MEM_freeN(rv->rectf);
+ if (rv->rectf)
+ MEM_freeN(rv->rectf);
- MEM_freeN(rv);
- }
+ MEM_freeN(rv);
+ }
- res->have_combined = false;
+ res->have_combined = false;
}
void render_result_free(RenderResult *res)
{
- if (res == NULL) return;
-
- while (res->layers.first) {
- RenderLayer *rl = res->layers.first;
-
- /* acolrect and scolrect are optionally allocated in shade_tile, only free here since it can be used for drawing */
- if (rl->acolrect) MEM_freeN(rl->acolrect);
- if (rl->scolrect) MEM_freeN(rl->scolrect);
- if (rl->display_buffer) MEM_freeN(rl->display_buffer);
-
- while (rl->passes.first) {
- RenderPass *rpass = rl->passes.first;
- if (rpass->rect) MEM_freeN(rpass->rect);
- BLI_remlink(&rl->passes, rpass);
- MEM_freeN(rpass);
- }
- BLI_remlink(&res->layers, rl);
- MEM_freeN(rl);
- }
-
- render_result_views_free(res);
-
- if (res->rect32)
- MEM_freeN(res->rect32);
- if (res->rectz)
- MEM_freeN(res->rectz);
- if (res->rectf)
- MEM_freeN(res->rectf);
- if (res->text)
- MEM_freeN(res->text);
- if (res->error)
- MEM_freeN(res->error);
-
- BKE_stamp_data_free(res->stamp_data);
-
- MEM_freeN(res);
+ if (res == NULL)
+ return;
+
+ while (res->layers.first) {
+ RenderLayer *rl = res->layers.first;
+
+ /* acolrect and scolrect are optionally allocated in shade_tile, only free here since it can be used for drawing */
+ if (rl->acolrect)
+ MEM_freeN(rl->acolrect);
+ if (rl->scolrect)
+ MEM_freeN(rl->scolrect);
+ if (rl->display_buffer)
+ MEM_freeN(rl->display_buffer);
+
+ while (rl->passes.first) {
+ RenderPass *rpass = rl->passes.first;
+ if (rpass->rect)
+ MEM_freeN(rpass->rect);
+ BLI_remlink(&rl->passes, rpass);
+ MEM_freeN(rpass);
+ }
+ BLI_remlink(&res->layers, rl);
+ MEM_freeN(rl);
+ }
+
+ render_result_views_free(res);
+
+ if (res->rect32)
+ MEM_freeN(res->rect32);
+ if (res->rectz)
+ MEM_freeN(res->rectz);
+ if (res->rectf)
+ MEM_freeN(res->rectf);
+ if (res->text)
+ MEM_freeN(res->text);
+ if (res->error)
+ MEM_freeN(res->error);
+
+ BKE_stamp_data_free(res->stamp_data);
+
+ MEM_freeN(res);
}
/* version that's compatible with fullsample buffers */
void render_result_free_list(ListBase *lb, RenderResult *rr)
{
- RenderResult *rrnext;
+ RenderResult *rrnext;
- for (; rr; rr = rrnext) {
- rrnext = rr->next;
+ for (; rr; rr = rrnext) {
+ rrnext = rr->next;
- if (lb && lb->first)
- BLI_remlink(lb, rr);
+ if (lb && lb->first)
+ BLI_remlink(lb, rr);
- render_result_free(rr);
- }
+ render_result_free(rr);
+ }
}
/********************************* multiview *************************************/
@@ -137,611 +142,658 @@ void render_result_free_list(ListBase *lb, RenderResult *rr)
/* create a new views Listbase in rr without duplicating the memory pointers */
void render_result_views_shallowcopy(RenderResult *dst, RenderResult *src)
{
- RenderView *rview;
+ RenderView *rview;
- if (dst == NULL || src == NULL)
- return;
+ if (dst == NULL || src == NULL)
+ return;
- for (rview = src->views.first; rview; rview = rview->next) {
- RenderView *rv;
+ for (rview = src->views.first; rview; rview = rview->next) {
+ RenderView *rv;
- rv = MEM_mallocN(sizeof(RenderView), "new render view");
- BLI_addtail(&dst->views, rv);
+ rv = MEM_mallocN(sizeof(RenderView), "new render view");
+ BLI_addtail(&dst->views, rv);
- BLI_strncpy(rv->name, rview->name, sizeof(rv->name));
- rv->rectf = rview->rectf;
- rv->rectz = rview->rectz;
- rv->rect32 = rview->rect32;
- }
+ BLI_strncpy(rv->name, rview->name, sizeof(rv->name));
+ rv->rectf = rview->rectf;
+ rv->rectz = rview->rectz;
+ rv->rect32 = rview->rect32;
+ }
}
/* free the views created temporarily */
void render_result_views_shallowdelete(RenderResult *rr)
{
- if (rr == NULL)
- return;
-
- while (rr->views.first) {
- RenderView *rv = rr->views.first;
- BLI_remlink(&rr->views, rv);
- MEM_freeN(rv);
- }
+ if (rr == NULL)
+ return;
+
+ while (rr->views.first) {
+ RenderView *rv = rr->views.first;
+ BLI_remlink(&rr->views, rv);
+ MEM_freeN(rv);
+ }
}
-
static char *set_pass_name(char *outname, const char *name, int channel, const char *chan_id)
{
- BLI_strncpy(outname, name, EXR_PASS_MAXNAME);
- if (channel >= 0) {
- char token[3] = {'.', chan_id[channel], '\0'};
- strncat(outname, token, EXR_PASS_MAXNAME);
- }
- return outname;
+ BLI_strncpy(outname, name, EXR_PASS_MAXNAME);
+ if (channel >= 0) {
+ char token[3] = {'.', chan_id[channel], '\0'};
+ strncat(outname, token, EXR_PASS_MAXNAME);
+ }
+ return outname;
}
-static void set_pass_full_name(char *fullname, const char *name, int channel, const char *view, const char *chan_id)
+static void set_pass_full_name(
+ char *fullname, const char *name, int channel, const char *view, const char *chan_id)
{
- BLI_strncpy(fullname, name, EXR_PASS_MAXNAME);
- if (view && view[0]) {
- strncat(fullname, ".", EXR_PASS_MAXNAME);
- strncat(fullname, view, EXR_PASS_MAXNAME);
- }
- if (channel >= 0) {
- char token[3] = {'.', chan_id[channel], '\0'};
- strncat(fullname, token, EXR_PASS_MAXNAME);
- }
+ BLI_strncpy(fullname, name, EXR_PASS_MAXNAME);
+ if (view && view[0]) {
+ strncat(fullname, ".", EXR_PASS_MAXNAME);
+ strncat(fullname, view, EXR_PASS_MAXNAME);
+ }
+ if (channel >= 0) {
+ char token[3] = {'.', chan_id[channel], '\0'};
+ strncat(fullname, token, EXR_PASS_MAXNAME);
+ }
}
/********************************** New **************************************/
-static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname, const char *chan_id)
+static RenderPass *render_layer_add_pass(RenderResult *rr,
+ RenderLayer *rl,
+ int channels,
+ const char *name,
+ const char *viewname,
+ const char *chan_id)
{
- const int view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name));
- RenderPass *rpass = MEM_callocN(sizeof(RenderPass), name);
- size_t rectsize = ((size_t)rr->rectx) * rr->recty * channels;
-
- rpass->channels = channels;
- rpass->rectx = rl->rectx;
- rpass->recty = rl->recty;
- rpass->view_id = view_id;
-
- BLI_strncpy(rpass->name, name, sizeof(rpass->name));
- BLI_strncpy(rpass->chan_id, chan_id, sizeof(rpass->chan_id));
- BLI_strncpy(rpass->view, viewname, sizeof(rpass->view));
- set_pass_full_name(rpass->fullname, rpass->name, -1, rpass->view, rpass->chan_id);
-
- if (rl->exrhandle) {
- int a;
- for (a = 0; a < channels; a++) {
- char passname[EXR_PASS_MAXNAME];
- IMB_exr_add_channel(rl->exrhandle, rl->name, set_pass_name(passname, rpass->name, a, rpass->chan_id), viewname, 0, 0, NULL, false);
- }
- }
- else {
- float *rect;
- int x;
-
- rpass->rect = MEM_mapallocN(sizeof(float) * rectsize, name);
- if (rpass->rect == NULL) {
- MEM_freeN(rpass);
- return NULL;
- }
-
- if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
- /* initialize to max speed */
- rect = rpass->rect;
- for (x = rectsize - 1; x >= 0; x--)
- rect[x] = PASS_VECTOR_MAX;
- }
- else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
- rect = rpass->rect;
- for (x = rectsize - 1; x >= 0; x--)
- rect[x] = 10e10;
- }
- }
-
- BLI_addtail(&rl->passes, rpass);
-
- return rpass;
+ const int view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name));
+ RenderPass *rpass = MEM_callocN(sizeof(RenderPass), name);
+ size_t rectsize = ((size_t)rr->rectx) * rr->recty * channels;
+
+ rpass->channels = channels;
+ rpass->rectx = rl->rectx;
+ rpass->recty = rl->recty;
+ rpass->view_id = view_id;
+
+ BLI_strncpy(rpass->name, name, sizeof(rpass->name));
+ BLI_strncpy(rpass->chan_id, chan_id, sizeof(rpass->chan_id));
+ BLI_strncpy(rpass->view, viewname, sizeof(rpass->view));
+ set_pass_full_name(rpass->fullname, rpass->name, -1, rpass->view, rpass->chan_id);
+
+ if (rl->exrhandle) {
+ int a;
+ for (a = 0; a < channels; a++) {
+ char passname[EXR_PASS_MAXNAME];
+ IMB_exr_add_channel(rl->exrhandle,
+ rl->name,
+ set_pass_name(passname, rpass->name, a, rpass->chan_id),
+ viewname,
+ 0,
+ 0,
+ NULL,
+ false);
+ }
+ }
+ else {
+ float *rect;
+ int x;
+
+ rpass->rect = MEM_mapallocN(sizeof(float) * rectsize, name);
+ if (rpass->rect == NULL) {
+ MEM_freeN(rpass);
+ return NULL;
+ }
+
+ if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
+ /* initialize to max speed */
+ rect = rpass->rect;
+ for (x = rectsize - 1; x >= 0; x--)
+ rect[x] = PASS_VECTOR_MAX;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
+ rect = rpass->rect;
+ for (x = rectsize - 1; x >= 0; x--)
+ rect[x] = 10e10;
+ }
+ }
+
+ BLI_addtail(&rl->passes, rpass);
+
+ return rpass;
}
/* wrapper called from render_opengl */
-RenderPass *gp_add_pass(RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname)
+RenderPass *gp_add_pass(
+ RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname)
{
- return render_layer_add_pass(rr, rl, channels, name, viewname, "RGBA");
+ return render_layer_add_pass(rr, rl, channels, name, viewname, "RGBA");
}
/* called by main render as well for parts */
/* will read info from Render *re to define layers */
/* called in threads */
/* re->winx,winy is coordinate space of entire image, partrct the part within */
-RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers, const char *layername, const char *viewname)
+RenderResult *render_result_new(Render *re,
+ rcti *partrct,
+ int crop,
+ int savebuffers,
+ const char *layername,
+ const char *viewname)
{
- RenderResult *rr;
- RenderLayer *rl;
- RenderView *rv;
- int rectx, recty;
-
- rectx = BLI_rcti_size_x(partrct);
- recty = BLI_rcti_size_y(partrct);
-
- if (rectx <= 0 || recty <= 0)
- return NULL;
-
- rr = MEM_callocN(sizeof(RenderResult), "new render result");
- rr->rectx = rectx;
- rr->recty = recty;
- rr->renrect.xmin = 0; rr->renrect.xmax = rectx - 2 * crop;
- /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */
- rr->crop = crop;
-
- /* tilerect is relative coordinates within render disprect. do not subtract crop yet */
- rr->tilerect.xmin = partrct->xmin - re->disprect.xmin;
- rr->tilerect.xmax = partrct->xmax - re->disprect.xmin;
- rr->tilerect.ymin = partrct->ymin - re->disprect.ymin;
- rr->tilerect.ymax = partrct->ymax - re->disprect.ymin;
-
- if (savebuffers) {
- rr->do_exr_tile = true;
- }
-
- render_result_views_new(rr, &re->r);
-
- /* check renderdata for amount of layers */
- FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re, view_layer)
- {
- if (layername && layername[0]) {
- if (!STREQ(view_layer->name, layername)) {
- continue;
- }
- }
-
- rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
- BLI_addtail(&rr->layers, rl);
-
- BLI_strncpy(rl->name, view_layer->name, sizeof(rl->name));
- rl->layflag = view_layer->layflag;
- rl->passflag = view_layer->passflag; /* for debugging: view_layer->passflag | SCE_PASS_RAYHITS; */
- rl->rectx = rectx;
- rl->recty = recty;
-
- if (rr->do_exr_tile) {
- rl->display_buffer = MEM_mapallocN((size_t)rectx * recty * sizeof(unsigned int),
- "Combined display space rgba");
- if (rl->display_buffer == NULL) {
- render_result_free(rr);
- return NULL;
- }
- rl->exrhandle = IMB_exr_get_handle();
- }
-
- for (rv = rr->views.first; rv; rv = rv->next) {
- const char *view = rv->name;
-
- if (viewname && viewname[0])
- if (!STREQ(view, viewname))
- continue;
-
- if (rr->do_exr_tile)
- IMB_exr_add_view(rl->exrhandle, view);
+ RenderResult *rr;
+ RenderLayer *rl;
+ RenderView *rv;
+ int rectx, recty;
+
+ rectx = BLI_rcti_size_x(partrct);
+ recty = BLI_rcti_size_y(partrct);
+
+ if (rectx <= 0 || recty <= 0)
+ return NULL;
+
+ rr = MEM_callocN(sizeof(RenderResult), "new render result");
+ rr->rectx = rectx;
+ rr->recty = recty;
+ rr->renrect.xmin = 0;
+ rr->renrect.xmax = rectx - 2 * crop;
+ /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */
+ rr->crop = crop;
+
+ /* tilerect is relative coordinates within render disprect. do not subtract crop yet */
+ rr->tilerect.xmin = partrct->xmin - re->disprect.xmin;
+ rr->tilerect.xmax = partrct->xmax - re->disprect.xmin;
+ rr->tilerect.ymin = partrct->ymin - re->disprect.ymin;
+ rr->tilerect.ymax = partrct->ymax - re->disprect.ymin;
+
+ if (savebuffers) {
+ rr->do_exr_tile = true;
+ }
+
+ render_result_views_new(rr, &re->r);
+
+ /* check renderdata for amount of layers */
+ FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer) {
+ if (layername && layername[0]) {
+ if (!STREQ(view_layer->name, layername)) {
+ continue;
+ }
+ }
+
+ rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
+ BLI_addtail(&rr->layers, rl);
+
+ BLI_strncpy(rl->name, view_layer->name, sizeof(rl->name));
+ rl->layflag = view_layer->layflag;
+ rl->passflag =
+ view_layer->passflag; /* for debugging: view_layer->passflag | SCE_PASS_RAYHITS; */
+ rl->rectx = rectx;
+ rl->recty = recty;
+
+ if (rr->do_exr_tile) {
+ rl->display_buffer = MEM_mapallocN((size_t)rectx * recty * sizeof(unsigned int),
+ "Combined display space rgba");
+ if (rl->display_buffer == NULL) {
+ render_result_free(rr);
+ return NULL;
+ }
+ rl->exrhandle = IMB_exr_get_handle();
+ }
+
+ for (rv = rr->views.first; rv; rv = rv->next) {
+ const char *view = rv->name;
+
+ if (viewname && viewname[0])
+ if (!STREQ(view, viewname))
+ continue;
+
+ if (rr->do_exr_tile)
+ IMB_exr_add_view(rl->exrhandle, view);
#define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, name, viewname, chan_id) \
- do { \
- if (render_layer_add_pass(rr, rl, channels, name, viewname, chan_id) == NULL) { \
- render_result_free(rr); \
- return NULL; \
- } \
- } while (false)
-
- /* a renderlayer should always have a Combined pass*/
- render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA");
-
- if (view_layer->passflag & SCE_PASS_Z)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_Z, view, "Z");
- if (view_layer->passflag & SCE_PASS_VECTOR)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_VECTOR, view, "XYZW");
- if (view_layer->passflag & SCE_PASS_NORMAL)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_NORMAL, view, "XYZ");
- if (view_layer->passflag & SCE_PASS_UV)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA");
- if (view_layer->passflag & SCE_PASS_EMIT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_EMIT, view, "RGB");
- if (view_layer->passflag & SCE_PASS_AO)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_AO, view, "RGB");
- if (view_layer->passflag & SCE_PASS_ENVIRONMENT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_ENVIRONMENT, view, "RGB");
- if (view_layer->passflag & SCE_PASS_SHADOW)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SHADOW, view, "RGB");
- if (view_layer->passflag & SCE_PASS_INDEXOB)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXOB, view, "X");
- if (view_layer->passflag & SCE_PASS_INDEXMA)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXMA, view, "X");
- if (view_layer->passflag & SCE_PASS_MIST)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_MIST, view, "Z");
- if (rl->passflag & SCE_PASS_RAYHITS)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RAYHITS, view, "RGB");
- if (view_layer->passflag & SCE_PASS_DIFFUSE_DIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_DIRECT, view, "RGB");
- if (view_layer->passflag & SCE_PASS_DIFFUSE_INDIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_INDIRECT, view, "RGB");
- if (view_layer->passflag & SCE_PASS_DIFFUSE_COLOR)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_COLOR, view, "RGB");
- if (view_layer->passflag & SCE_PASS_GLOSSY_DIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_DIRECT, view, "RGB");
- if (view_layer->passflag & SCE_PASS_GLOSSY_INDIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_INDIRECT, view, "RGB");
- if (view_layer->passflag & SCE_PASS_GLOSSY_COLOR)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_COLOR, view, "RGB");
- if (view_layer->passflag & SCE_PASS_TRANSM_DIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_DIRECT, view, "RGB");
- if (view_layer->passflag & SCE_PASS_TRANSM_INDIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_INDIRECT, view, "RGB");
- if (view_layer->passflag & SCE_PASS_TRANSM_COLOR)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_COLOR, view, "RGB");
- if (view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_DIRECT, view, "RGB");
- if (view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_INDIRECT, view, "RGB");
- if (view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB");
+ do { \
+ if (render_layer_add_pass(rr, rl, channels, name, viewname, chan_id) == NULL) { \
+ render_result_free(rr); \
+ return NULL; \
+ } \
+ } while (false)
+
+ /* a renderlayer should always have a Combined pass*/
+ render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA");
+
+ if (view_layer->passflag & SCE_PASS_Z)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_Z, view, "Z");
+ if (view_layer->passflag & SCE_PASS_VECTOR)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_VECTOR, view, "XYZW");
+ if (view_layer->passflag & SCE_PASS_NORMAL)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_NORMAL, view, "XYZ");
+ if (view_layer->passflag & SCE_PASS_UV)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA");
+ if (view_layer->passflag & SCE_PASS_EMIT)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_EMIT, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_AO)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_AO, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_ENVIRONMENT)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_ENVIRONMENT, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_SHADOW)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SHADOW, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_INDEXOB)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXOB, view, "X");
+ if (view_layer->passflag & SCE_PASS_INDEXMA)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXMA, view, "X");
+ if (view_layer->passflag & SCE_PASS_MIST)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_MIST, view, "Z");
+ if (rl->passflag & SCE_PASS_RAYHITS)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RAYHITS, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_DIFFUSE_DIRECT)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_DIRECT, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_DIFFUSE_INDIRECT)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_INDIRECT, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_DIFFUSE_COLOR)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_COLOR, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_GLOSSY_DIRECT)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_DIRECT, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_GLOSSY_INDIRECT)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_INDIRECT, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_GLOSSY_COLOR)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_COLOR, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_TRANSM_DIRECT)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_DIRECT, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_TRANSM_INDIRECT)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_INDIRECT, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_TRANSM_COLOR)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_COLOR, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_DIRECT, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_INDIRECT, view, "RGB");
+ if (view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR)
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB");
#undef RENDER_LAYER_ADD_PASS_SAFE
- }
- }
- FOREACH_VIEW_LAYER_TO_RENDER_END;
+ }
+ }
+ FOREACH_VIEW_LAYER_TO_RENDER_END;
- /* previewrender doesn't do layers, so we make a default one */
- if (BLI_listbase_is_empty(&rr->layers) && !(layername && layername[0])) {
- rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
- BLI_addtail(&rr->layers, rl);
+ /* previewrender doesn't do layers, so we make a default one */
+ if (BLI_listbase_is_empty(&rr->layers) && !(layername && layername[0])) {
+ rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
+ BLI_addtail(&rr->layers, rl);
- rl->rectx = rectx;
- rl->recty = recty;
+ rl->rectx = rectx;
+ rl->recty = recty;
- /* duplicate code... */
- if (rr->do_exr_tile) {
- rl->display_buffer = MEM_mapallocN(rectx * recty * sizeof(unsigned int), "Combined display space rgba");
- rl->exrhandle = IMB_exr_get_handle();
- }
+ /* duplicate code... */
+ if (rr->do_exr_tile) {
+ rl->display_buffer = MEM_mapallocN(rectx * recty * sizeof(unsigned int),
+ "Combined display space rgba");
+ rl->exrhandle = IMB_exr_get_handle();
+ }
- for (rv = rr->views.first; rv; rv = rv->next) {
- const char *view = rv->name;
+ for (rv = rr->views.first; rv; rv = rv->next) {
+ const char *view = rv->name;
- if (viewname && viewname[0])
- if (strcmp(view, viewname) != 0)
- continue;
+ if (viewname && viewname[0])
+ if (strcmp(view, viewname) != 0)
+ continue;
- if (rr->do_exr_tile)
- IMB_exr_add_view(rl->exrhandle, view);
+ if (rr->do_exr_tile)
+ IMB_exr_add_view(rl->exrhandle, view);
- /* a renderlayer should always have a Combined pass */
- render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, view, "RGBA");
- }
+ /* a renderlayer should always have a Combined pass */
+ render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, view, "RGBA");
+ }
- /* note, this has to be in sync with scene.c */
- rl->layflag = 0x7FFF; /* solid ztra halo strand */
- rl->passflag = SCE_PASS_COMBINED;
+ /* note, this has to be in sync with scene.c */
+ rl->layflag = 0x7FFF; /* solid ztra halo strand */
+ rl->passflag = SCE_PASS_COMBINED;
- re->active_view_layer = 0;
- }
+ re->active_view_layer = 0;
+ }
- /* border render; calculate offset for use in compositor. compo is centralized coords */
- /* XXX obsolete? I now use it for drawing border render offset (ton) */
- rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2);
- rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2);
+ /* border render; calculate offset for use in compositor. compo is centralized coords */
+ /* XXX obsolete? I now use it for drawing border render offset (ton) */
+ rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2);
+ rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2);
- return rr;
+ return rr;
}
void render_result_clone_passes(Render *re, RenderResult *rr, const char *viewname)
{
- RenderLayer *rl;
- RenderPass *main_rp;
-
- for (rl = rr->layers.first; rl; rl = rl->next) {
- RenderLayer *main_rl = BLI_findstring(&re->result->layers, rl->name, offsetof(RenderLayer, name));
- if (!main_rl) {
- continue;
- }
-
- for (main_rp = main_rl->passes.first; main_rp; main_rp = main_rp->next) {
- if (viewname && viewname[0] && !STREQ(main_rp->view, viewname)) {
- continue;
- }
-
- /* Compare fullname to make sure that the view also is equal. */
- RenderPass *rp = BLI_findstring(&rl->passes, main_rp->fullname, offsetof(RenderPass, fullname));
- if (!rp) {
- render_layer_add_pass(rr, rl, main_rp->channels, main_rp->name, main_rp->view, main_rp->chan_id);
- }
- }
- }
+ RenderLayer *rl;
+ RenderPass *main_rp;
+
+ for (rl = rr->layers.first; rl; rl = rl->next) {
+ RenderLayer *main_rl = BLI_findstring(
+ &re->result->layers, rl->name, offsetof(RenderLayer, name));
+ if (!main_rl) {
+ continue;
+ }
+
+ for (main_rp = main_rl->passes.first; main_rp; main_rp = main_rp->next) {
+ if (viewname && viewname[0] && !STREQ(main_rp->view, viewname)) {
+ continue;
+ }
+
+ /* Compare fullname to make sure that the view also is equal. */
+ RenderPass *rp = BLI_findstring(
+ &rl->passes, main_rp->fullname, offsetof(RenderPass, fullname));
+ if (!rp) {
+ render_layer_add_pass(
+ rr, rl, main_rp->channels, main_rp->name, main_rp->view, main_rp->chan_id);
+ }
+ }
+ }
}
-void render_result_add_pass(RenderResult *rr, const char *name, int channels, const char *chan_id, const char *layername, const char *viewname)
+void render_result_add_pass(RenderResult *rr,
+ const char *name,
+ int channels,
+ const char *chan_id,
+ const char *layername,
+ const char *viewname)
{
- RenderLayer *rl;
- RenderPass *rp;
- RenderView *rv;
-
- for (rl = rr->layers.first; rl; rl = rl->next) {
- if (layername && layername[0] && !STREQ(rl->name, layername)) {
- continue;
- }
-
- for (rv = rr->views.first; rv; rv = rv->next) {
- const char *view = rv->name;
-
- if (viewname && viewname[0] && !STREQ(view, viewname)) continue;
-
- /* Ensure that the pass doesn't exist yet. */
- for (rp = rl->passes.first; rp; rp = rp->next) {
- if (!STREQ(rp->name, name)) continue;
- if (!STREQ(rp->view, view)) continue;
- break;
- }
-
- if (!rp) {
- render_layer_add_pass(rr, rl, channels, name, view, chan_id);
- }
- }
- }
+ RenderLayer *rl;
+ RenderPass *rp;
+ RenderView *rv;
+
+ for (rl = rr->layers.first; rl; rl = rl->next) {
+ if (layername && layername[0] && !STREQ(rl->name, layername)) {
+ continue;
+ }
+
+ for (rv = rr->views.first; rv; rv = rv->next) {
+ const char *view = rv->name;
+
+ if (viewname && viewname[0] && !STREQ(view, viewname))
+ continue;
+
+ /* Ensure that the pass doesn't exist yet. */
+ for (rp = rl->passes.first; rp; rp = rp->next) {
+ if (!STREQ(rp->name, name))
+ continue;
+ if (!STREQ(rp->view, view))
+ continue;
+ break;
+ }
+
+ if (!rp) {
+ render_layer_add_pass(rr, rl, channels, name, view, chan_id);
+ }
+ }
+ }
}
static int passtype_from_name(const char *name)
{
- const char delim[] = {'.', '\0'};
- const char *sep, *suf;
- int len = BLI_str_partition(name, delim, &sep, &suf);
-
-#define CHECK_PASS(NAME) if (STREQLEN(name, RE_PASSNAME_ ## NAME, len)) return SCE_PASS_ ## NAME
-
- CHECK_PASS(COMBINED);
- CHECK_PASS(Z);
- CHECK_PASS(VECTOR);
- CHECK_PASS(NORMAL);
- CHECK_PASS(UV);
- CHECK_PASS(EMIT);
- CHECK_PASS(SHADOW);
- CHECK_PASS(AO);
- CHECK_PASS(ENVIRONMENT);
- CHECK_PASS(INDEXOB);
- CHECK_PASS(INDEXMA);
- CHECK_PASS(MIST);
- CHECK_PASS(RAYHITS);
- CHECK_PASS(DIFFUSE_DIRECT);
- CHECK_PASS(DIFFUSE_INDIRECT);
- CHECK_PASS(DIFFUSE_COLOR);
- CHECK_PASS(GLOSSY_DIRECT);
- CHECK_PASS(GLOSSY_INDIRECT);
- CHECK_PASS(GLOSSY_COLOR);
- CHECK_PASS(TRANSM_DIRECT);
- CHECK_PASS(TRANSM_INDIRECT);
- CHECK_PASS(TRANSM_COLOR);
- CHECK_PASS(SUBSURFACE_DIRECT);
- CHECK_PASS(SUBSURFACE_INDIRECT);
- CHECK_PASS(SUBSURFACE_COLOR);
+ const char delim[] = {'.', '\0'};
+ const char *sep, *suf;
+ int len = BLI_str_partition(name, delim, &sep, &suf);
+
+#define CHECK_PASS(NAME) \
+ if (STREQLEN(name, RE_PASSNAME_##NAME, len)) \
+ return SCE_PASS_##NAME
+
+ CHECK_PASS(COMBINED);
+ CHECK_PASS(Z);
+ CHECK_PASS(VECTOR);
+ CHECK_PASS(NORMAL);
+ CHECK_PASS(UV);
+ CHECK_PASS(EMIT);
+ CHECK_PASS(SHADOW);
+ CHECK_PASS(AO);
+ CHECK_PASS(ENVIRONMENT);
+ CHECK_PASS(INDEXOB);
+ CHECK_PASS(INDEXMA);
+ CHECK_PASS(MIST);
+ CHECK_PASS(RAYHITS);
+ CHECK_PASS(DIFFUSE_DIRECT);
+ CHECK_PASS(DIFFUSE_INDIRECT);
+ CHECK_PASS(DIFFUSE_COLOR);
+ CHECK_PASS(GLOSSY_DIRECT);
+ CHECK_PASS(GLOSSY_INDIRECT);
+ CHECK_PASS(GLOSSY_COLOR);
+ CHECK_PASS(TRANSM_DIRECT);
+ CHECK_PASS(TRANSM_INDIRECT);
+ CHECK_PASS(TRANSM_COLOR);
+ CHECK_PASS(SUBSURFACE_DIRECT);
+ CHECK_PASS(SUBSURFACE_INDIRECT);
+ CHECK_PASS(SUBSURFACE_COLOR);
#undef CHECK_PASS
- return 0;
+ return 0;
}
/* callbacks for render_result_new_from_exr */
static void *ml_addlayer_cb(void *base, const char *str)
{
- RenderResult *rr = base;
- RenderLayer *rl;
+ RenderResult *rr = base;
+ RenderLayer *rl;
- rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
- BLI_addtail(&rr->layers, rl);
+ rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
+ BLI_addtail(&rr->layers, rl);
- BLI_strncpy(rl->name, str, EXR_LAY_MAXNAME);
- return rl;
+ BLI_strncpy(rl->name, str, EXR_LAY_MAXNAME);
+ return rl;
}
-static void ml_addpass_cb(void *base, void *lay, const char *name, float *rect, int totchan, const char *chan_id, const char *view)
+static void ml_addpass_cb(void *base,
+ void *lay,
+ const char *name,
+ float *rect,
+ int totchan,
+ const char *chan_id,
+ const char *view)
{
- RenderResult *rr = base;
- RenderLayer *rl = lay;
- RenderPass *rpass = MEM_callocN(sizeof(RenderPass), "loaded pass");
-
- BLI_addtail(&rl->passes, rpass);
- rpass->channels = totchan;
- rl->passflag |= passtype_from_name(name);
-
- /* channel id chars */
- BLI_strncpy(rpass->chan_id, chan_id, sizeof(rpass->chan_id));
-
- rpass->rect = rect;
- BLI_strncpy(rpass->name, name, EXR_PASS_MAXNAME);
- BLI_strncpy(rpass->view, view, sizeof(rpass->view));
- set_pass_full_name(rpass->fullname, name, -1, view, rpass->chan_id);
-
- if (view[0] != '\0') {
- rpass->view_id = BLI_findstringindex(&rr->views, view, offsetof(RenderView, name));
- }
- else {
- rpass->view_id = 0;
- }
+ RenderResult *rr = base;
+ RenderLayer *rl = lay;
+ RenderPass *rpass = MEM_callocN(sizeof(RenderPass), "loaded pass");
+
+ BLI_addtail(&rl->passes, rpass);
+ rpass->channels = totchan;
+ rl->passflag |= passtype_from_name(name);
+
+ /* channel id chars */
+ BLI_strncpy(rpass->chan_id, chan_id, sizeof(rpass->chan_id));
+
+ rpass->rect = rect;
+ BLI_strncpy(rpass->name, name, EXR_PASS_MAXNAME);
+ BLI_strncpy(rpass->view, view, sizeof(rpass->view));
+ set_pass_full_name(rpass->fullname, name, -1, view, rpass->chan_id);
+
+ if (view[0] != '\0') {
+ rpass->view_id = BLI_findstringindex(&rr->views, view, offsetof(RenderView, name));
+ }
+ else {
+ rpass->view_id = 0;
+ }
}
static void *ml_addview_cb(void *base, const char *str)
{
- RenderResult *rr = base;
- RenderView *rv;
-
- rv = MEM_callocN(sizeof(RenderView), "new render view");
- BLI_strncpy(rv->name, str, EXR_VIEW_MAXNAME);
-
- /* For stereo drawing we need to ensure:
- * STEREO_LEFT_NAME == STEREO_LEFT_ID and
- * STEREO_RIGHT_NAME == STEREO_RIGHT_ID */
-
- if (STREQ(str, STEREO_LEFT_NAME)) {
- BLI_addhead(&rr->views, rv);
- }
- else if (STREQ(str, STEREO_RIGHT_NAME)) {
- RenderView *left_rv = BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name));
-
- if (left_rv == NULL) {
- BLI_addhead(&rr->views, rv);
- }
- else {
- BLI_insertlinkafter(&rr->views, left_rv, rv);
- }
- }
- else {
- BLI_addtail(&rr->views, rv);
- }
-
- return rv;
+ RenderResult *rr = base;
+ RenderView *rv;
+
+ rv = MEM_callocN(sizeof(RenderView), "new render view");
+ BLI_strncpy(rv->name, str, EXR_VIEW_MAXNAME);
+
+ /* For stereo drawing we need to ensure:
+ * STEREO_LEFT_NAME == STEREO_LEFT_ID and
+ * STEREO_RIGHT_NAME == STEREO_RIGHT_ID */
+
+ if (STREQ(str, STEREO_LEFT_NAME)) {
+ BLI_addhead(&rr->views, rv);
+ }
+ else if (STREQ(str, STEREO_RIGHT_NAME)) {
+ RenderView *left_rv = BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name));
+
+ if (left_rv == NULL) {
+ BLI_addhead(&rr->views, rv);
+ }
+ else {
+ BLI_insertlinkafter(&rr->views, left_rv, rv);
+ }
+ }
+ else {
+ BLI_addtail(&rr->views, rv);
+ }
+
+ return rv;
}
static int order_render_passes(const void *a, const void *b)
{
- // 1 if a is after b
- RenderPass *rpa = (RenderPass *)a;
- RenderPass *rpb = (RenderPass *)b;
- unsigned int passtype_a = passtype_from_name(rpa->name);
- unsigned int passtype_b = passtype_from_name(rpb->name);
-
- /* Render passes with default type always go first. */
- if (passtype_b && !passtype_a)
- return 1;
- if (passtype_a && !passtype_b)
- return 0;
-
- if (passtype_a && passtype_b) {
- if (passtype_a > passtype_b)
- return 1;
- else if (passtype_a < passtype_b)
- return 0;
- }
- else {
- int cmp = strncmp(rpa->name, rpb->name, EXR_PASS_MAXNAME);
- if (cmp > 0)
- return 1;
- if (cmp < 0)
- return 0;
- }
-
-
- /* they have the same type */
- /* left first */
- if (STREQ(rpa->view, STEREO_LEFT_NAME))
- return 0;
- else if (STREQ(rpb->view, STEREO_LEFT_NAME))
- return 1;
-
- /* right second */
- if (STREQ(rpa->view, STEREO_RIGHT_NAME))
- return 0;
- else if (STREQ(rpb->view, STEREO_RIGHT_NAME))
- return 1;
-
- /* remaining in ascending id order */
- return (rpa->view_id < rpb->view_id);
+ // 1 if a is after b
+ RenderPass *rpa = (RenderPass *)a;
+ RenderPass *rpb = (RenderPass *)b;
+ unsigned int passtype_a = passtype_from_name(rpa->name);
+ unsigned int passtype_b = passtype_from_name(rpb->name);
+
+ /* Render passes with default type always go first. */
+ if (passtype_b && !passtype_a)
+ return 1;
+ if (passtype_a && !passtype_b)
+ return 0;
+
+ if (passtype_a && passtype_b) {
+ if (passtype_a > passtype_b)
+ return 1;
+ else if (passtype_a < passtype_b)
+ return 0;
+ }
+ else {
+ int cmp = strncmp(rpa->name, rpb->name, EXR_PASS_MAXNAME);
+ if (cmp > 0)
+ return 1;
+ if (cmp < 0)
+ return 0;
+ }
+
+ /* they have the same type */
+ /* left first */
+ if (STREQ(rpa->view, STEREO_LEFT_NAME))
+ return 0;
+ else if (STREQ(rpb->view, STEREO_LEFT_NAME))
+ return 1;
+
+ /* right second */
+ if (STREQ(rpa->view, STEREO_RIGHT_NAME))
+ return 0;
+ else if (STREQ(rpb->view, STEREO_RIGHT_NAME))
+ return 1;
+
+ /* remaining in ascending id order */
+ return (rpa->view_id < rpb->view_id);
}
/* from imbuf, if a handle was returned and it's not a singlelayer multiview we convert this to render result */
-RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty)
+RenderResult *render_result_new_from_exr(
+ void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty)
{
- RenderResult *rr = MEM_callocN(sizeof(RenderResult), __func__);
- RenderLayer *rl;
- RenderPass *rpass;
- const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
-
- rr->rectx = rectx;
- rr->recty = recty;
-
- IMB_exr_multilayer_convert(exrhandle, rr, ml_addview_cb, ml_addlayer_cb, ml_addpass_cb);
-
- for (rl = rr->layers.first; rl; rl = rl->next) {
- rl->rectx = rectx;
- rl->recty = recty;
-
- BLI_listbase_sort(&rl->passes, order_render_passes);
-
- for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
- rpass->rectx = rectx;
- rpass->recty = recty;
-
- if (rpass->channels >= 3) {
- IMB_colormanagement_transform(rpass->rect, rpass->rectx, rpass->recty, rpass->channels,
- colorspace, to_colorspace, predivide);
- }
- }
- }
-
- return rr;
+ RenderResult *rr = MEM_callocN(sizeof(RenderResult), __func__);
+ RenderLayer *rl;
+ RenderPass *rpass;
+ const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(
+ COLOR_ROLE_SCENE_LINEAR);
+
+ rr->rectx = rectx;
+ rr->recty = recty;
+
+ IMB_exr_multilayer_convert(exrhandle, rr, ml_addview_cb, ml_addlayer_cb, ml_addpass_cb);
+
+ for (rl = rr->layers.first; rl; rl = rl->next) {
+ rl->rectx = rectx;
+ rl->recty = recty;
+
+ BLI_listbase_sort(&rl->passes, order_render_passes);
+
+ for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
+ rpass->rectx = rectx;
+ rpass->recty = recty;
+
+ if (rpass->channels >= 3) {
+ IMB_colormanagement_transform(rpass->rect,
+ rpass->rectx,
+ rpass->recty,
+ rpass->channels,
+ colorspace,
+ to_colorspace,
+ predivide);
+ }
+ }
+ }
+
+ return rr;
}
void render_result_view_new(RenderResult *rr, const char *viewname)
{
- RenderView *rv = MEM_callocN(sizeof(RenderView), "new render view");
- BLI_addtail(&rr->views, rv);
- BLI_strncpy(rv->name, viewname, sizeof(rv->name));
+ RenderView *rv = MEM_callocN(sizeof(RenderView), "new render view");
+ BLI_addtail(&rr->views, rv);
+ BLI_strncpy(rv->name, viewname, sizeof(rv->name));
}
void render_result_views_new(RenderResult *rr, RenderData *rd)
{
- SceneRenderView *srv;
-
- /* clear previously existing views - for sequencer */
- render_result_views_free(rr);
-
- /* check renderdata for amount of views */
- if ((rd->scemode & R_MULTIVIEW)) {
- for (srv = rd->views.first; srv; srv = srv->next) {
- if (BKE_scene_multiview_is_render_view_active(rd, srv) == false)
- continue;
- render_result_view_new(rr, srv->name);
- }
- }
-
- /* we always need at least one view */
- if (BLI_listbase_count_at_most(&rr->views, 1) == 0) {
- render_result_view_new(rr, "");
- }
+ SceneRenderView *srv;
+
+ /* clear previously existing views - for sequencer */
+ render_result_views_free(rr);
+
+ /* check renderdata for amount of views */
+ if ((rd->scemode & R_MULTIVIEW)) {
+ for (srv = rd->views.first; srv; srv = srv->next) {
+ if (BKE_scene_multiview_is_render_view_active(rd, srv) == false)
+ continue;
+ render_result_view_new(rr, srv->name);
+ }
+ }
+
+ /* we always need at least one view */
+ if (BLI_listbase_count_at_most(&rr->views, 1) == 0) {
+ render_result_view_new(rr, "");
+ }
}
bool render_result_has_views(RenderResult *rr)
{
- RenderView *rv = rr->views.first;
- return (rv && (rv->next || rv->name[0]));
+ RenderView *rv = rr->views.first;
+ return (rv && (rv->next || rv->name[0]));
}
/*********************************** Merge ***********************************/
-static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize)
+static void do_merge_tile(
+ RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize)
{
- int y, tilex, tiley;
- size_t ofs, copylen;
-
- copylen = tilex = rrpart->rectx;
- tiley = rrpart->recty;
-
- if (rrpart->crop) { /* filters add pixel extra */
- tile += pixsize * (rrpart->crop + ((size_t)rrpart->crop) * tilex);
-
- copylen = tilex - 2 * rrpart->crop;
- tiley -= 2 * rrpart->crop;
-
- ofs = (((size_t)rrpart->tilerect.ymin) + rrpart->crop) * rr->rectx + (rrpart->tilerect.xmin + rrpart->crop);
- target += pixsize * ofs;
- }
- else {
- ofs = (((size_t)rrpart->tilerect.ymin) * rr->rectx + rrpart->tilerect.xmin);
- target += pixsize * ofs;
- }
-
- copylen *= sizeof(float) * pixsize;
- tilex *= pixsize;
- ofs = pixsize * rr->rectx;
-
- for (y = 0; y < tiley; y++) {
- memcpy(target, tile, copylen);
- target += ofs;
- tile += tilex;
- }
+ int y, tilex, tiley;
+ size_t ofs, copylen;
+
+ copylen = tilex = rrpart->rectx;
+ tiley = rrpart->recty;
+
+ if (rrpart->crop) { /* filters add pixel extra */
+ tile += pixsize * (rrpart->crop + ((size_t)rrpart->crop) * tilex);
+
+ copylen = tilex - 2 * rrpart->crop;
+ tiley -= 2 * rrpart->crop;
+
+ ofs = (((size_t)rrpart->tilerect.ymin) + rrpart->crop) * rr->rectx +
+ (rrpart->tilerect.xmin + rrpart->crop);
+ target += pixsize * ofs;
+ }
+ else {
+ ofs = (((size_t)rrpart->tilerect.ymin) * rr->rectx + rrpart->tilerect.xmin);
+ target += pixsize * ofs;
+ }
+
+ copylen *= sizeof(float) * pixsize;
+ tilex *= pixsize;
+ ofs = pixsize * rr->rectx;
+
+ for (y = 0; y < tiley; y++) {
+ memcpy(target, tile, copylen);
+ target += ofs;
+ tile += tilex;
+ }
}
/* used when rendering to a full buffer, or when reading the exr part-layer-pass file */
@@ -749,787 +801,831 @@ static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target,
/* is used within threads */
void render_result_merge(RenderResult *rr, RenderResult *rrpart)
{
- RenderLayer *rl, *rlp;
- RenderPass *rpass, *rpassp;
-
- for (rl = rr->layers.first; rl; rl = rl->next) {
- rlp = RE_GetRenderLayer(rrpart, rl->name);
- if (rlp) {
- /* passes are allocated in sync */
- for (rpass = rl->passes.first, rpassp = rlp->passes.first;
- rpass && rpassp;
- rpass = rpass->next)
- {
- /* renderresult have all passes, renderpart only the active view's passes */
- if (strcmp(rpassp->fullname, rpass->fullname) != 0)
- continue;
-
- do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels);
-
- /* manually get next render pass */
- rpassp = rpassp->next;
- }
- }
- }
+ RenderLayer *rl, *rlp;
+ RenderPass *rpass, *rpassp;
+
+ for (rl = rr->layers.first; rl; rl = rl->next) {
+ rlp = RE_GetRenderLayer(rrpart, rl->name);
+ if (rlp) {
+ /* passes are allocated in sync */
+ for (rpass = rl->passes.first, rpassp = rlp->passes.first; rpass && rpassp;
+ rpass = rpass->next) {
+ /* renderresult have all passes, renderpart only the active view's passes */
+ if (strcmp(rpassp->fullname, rpass->fullname) != 0)
+ continue;
+
+ do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels);
+
+ /* manually get next render pass */
+ rpassp = rpassp->next;
+ }
+ }
+ }
}
/* Called from the UI and render pipeline, to save multilayer and multiview
* images, optionally isolating a specific, view, layer or RGBA/Z pass. */
-bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, ImageFormatData *imf, const char *view, int layer)
+bool RE_WriteRenderResult(ReportList *reports,
+ RenderResult *rr,
+ const char *filename,
+ ImageFormatData *imf,
+ const char *view,
+ int layer)
{
- void *exrhandle = IMB_exr_get_handle();
- const bool half_float = (imf && imf->depth == R_IMF_CHAN_DEPTH_16);
- const bool multi_layer = !(imf && imf->imtype == R_IMF_IMTYPE_OPENEXR);
- const bool write_z = !multi_layer && (imf && (imf->flag & R_IMF_FLAG_ZBUF));
-
- /* Write first layer if not multilayer and no layer was specified. */
- if (!multi_layer && layer == -1) {
- layer = 0;
- }
-
- /* First add views since IMB_exr_add_channel checks number of views. */
- if (render_result_has_views(rr)) {
- for (RenderView *rview = rr->views.first; rview; rview = rview->next) {
- if (!view || STREQ(view, rview->name)) {
- IMB_exr_add_view(exrhandle, rview->name);
- }
- }
- }
-
- /* Compositing result. */
- if (rr->have_combined) {
- for (RenderView *rview = rr->views.first; rview; rview = rview->next) {
- if (!rview->rectf) {
- continue;
- }
-
- const char *viewname = rview->name;
- if (view) {
- if (!STREQ(view, viewname)) {
- continue;
- }
- else {
- viewname = "";
- }
- }
-
- /* Skip compositing if only a single other layer is requested. */
- if (!multi_layer && layer != 0) {
- continue;
- }
-
- for (int a = 0; a < 4; a++) {
- char passname[EXR_PASS_MAXNAME];
- char layname[EXR_PASS_MAXNAME];
- const char *chan_id = "RGBA";
-
- if (multi_layer) {
- set_pass_name(passname, "Combined", a, chan_id);
- BLI_strncpy(layname, "Composite", sizeof(layname));
- }
- else {
- passname[0] = chan_id[a];
- passname[1] = '\0';
- layname[0] = '\0';
- }
-
- IMB_exr_add_channel(exrhandle, layname, passname, viewname,
- 4, 4 * rr->rectx, rview->rectf + a, half_float);
- }
-
- if (write_z && rview->rectz) {
- const char *layname = (multi_layer) ? "Composite" : "";
- IMB_exr_add_channel(exrhandle, layname, "Z", viewname,
- 1, rr->rectx, rview->rectz, false);
- }
- }
- }
-
- /* Other render layers. */
- int nr = (rr->have_combined) ? 1 : 0;
- for (RenderLayer *rl = rr->layers.first; rl; rl = rl->next, nr++) {
- /* Skip other render layers if requested. */
- if (!multi_layer && nr != layer) {
- continue;
- }
-
- for (RenderPass *rp = rl->passes.first; rp; rp = rp->next) {
- /* Skip non-RGBA and Z passes if not using multi layer. */
- if (!multi_layer && !(STREQ(rp->name, RE_PASSNAME_COMBINED) ||
- STREQ(rp->name, "") ||
- (STREQ(rp->name, RE_PASSNAME_Z) && write_z)))
- {
- continue;
- }
-
- /* Skip pass if it does not match the requested view(s). */
- const char *viewname = rp->view;
- if (view) {
- if (!STREQ(view, viewname)) {
- continue;
- }
- else {
- viewname = "";
- }
- }
-
- /* We only store RGBA passes as half float, for
- * others precision loss can be problematic. */
- bool pass_half_float = half_float &&
- (STREQ(rp->chan_id, "RGB") ||
- STREQ(rp->chan_id, "RGBA") ||
- STREQ(rp->chan_id, "R") ||
- STREQ(rp->chan_id, "G") ||
- STREQ(rp->chan_id, "B") ||
- STREQ(rp->chan_id, "A"));
-
-
- for (int a = 0; a < rp->channels; a++) {
- /* Save Combined as RGBA if single layer save. */
- char passname[EXR_PASS_MAXNAME];
- char layname[EXR_PASS_MAXNAME];
-
- if (multi_layer) {
- set_pass_name(passname, rp->name, a, rp->chan_id);
- BLI_strncpy(layname, rl->name, sizeof(layname));
- }
- else {
- passname[0] = rp->chan_id[a];
- passname[1] = '\0';
- layname[0] = '\0';
- }
-
- IMB_exr_add_channel(exrhandle, layname, passname, viewname,
- rp->channels, rp->channels * rr->rectx, rp->rect + a,
- pass_half_float);
- }
- }
- }
-
- errno = 0;
-
- BLI_make_existing_file(filename);
-
- int compress = (imf ? imf->exr_codec : 0);
- bool success = IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress, rr->stamp_data);
- if (success) {
- IMB_exr_write_channels(exrhandle);
- }
- else {
- /* TODO, get the error from openexr's exception */
- BKE_reportf(reports, RPT_ERROR, "Error writing render result, %s (see console)", strerror(errno));
- }
-
- IMB_exr_close(exrhandle);
- return success;
+ void *exrhandle = IMB_exr_get_handle();
+ const bool half_float = (imf && imf->depth == R_IMF_CHAN_DEPTH_16);
+ const bool multi_layer = !(imf && imf->imtype == R_IMF_IMTYPE_OPENEXR);
+ const bool write_z = !multi_layer && (imf && (imf->flag & R_IMF_FLAG_ZBUF));
+
+ /* Write first layer if not multilayer and no layer was specified. */
+ if (!multi_layer && layer == -1) {
+ layer = 0;
+ }
+
+ /* First add views since IMB_exr_add_channel checks number of views. */
+ if (render_result_has_views(rr)) {
+ for (RenderView *rview = rr->views.first; rview; rview = rview->next) {
+ if (!view || STREQ(view, rview->name)) {
+ IMB_exr_add_view(exrhandle, rview->name);
+ }
+ }
+ }
+
+ /* Compositing result. */
+ if (rr->have_combined) {
+ for (RenderView *rview = rr->views.first; rview; rview = rview->next) {
+ if (!rview->rectf) {
+ continue;
+ }
+
+ const char *viewname = rview->name;
+ if (view) {
+ if (!STREQ(view, viewname)) {
+ continue;
+ }
+ else {
+ viewname = "";
+ }
+ }
+
+ /* Skip compositing if only a single other layer is requested. */
+ if (!multi_layer && layer != 0) {
+ continue;
+ }
+
+ for (int a = 0; a < 4; a++) {
+ char passname[EXR_PASS_MAXNAME];
+ char layname[EXR_PASS_MAXNAME];
+ const char *chan_id = "RGBA";
+
+ if (multi_layer) {
+ set_pass_name(passname, "Combined", a, chan_id);
+ BLI_strncpy(layname, "Composite", sizeof(layname));
+ }
+ else {
+ passname[0] = chan_id[a];
+ passname[1] = '\0';
+ layname[0] = '\0';
+ }
+
+ IMB_exr_add_channel(exrhandle,
+ layname,
+ passname,
+ viewname,
+ 4,
+ 4 * rr->rectx,
+ rview->rectf + a,
+ half_float);
+ }
+
+ if (write_z && rview->rectz) {
+ const char *layname = (multi_layer) ? "Composite" : "";
+ IMB_exr_add_channel(exrhandle, layname, "Z", viewname, 1, rr->rectx, rview->rectz, false);
+ }
+ }
+ }
+
+ /* Other render layers. */
+ int nr = (rr->have_combined) ? 1 : 0;
+ for (RenderLayer *rl = rr->layers.first; rl; rl = rl->next, nr++) {
+ /* Skip other render layers if requested. */
+ if (!multi_layer && nr != layer) {
+ continue;
+ }
+
+ for (RenderPass *rp = rl->passes.first; rp; rp = rp->next) {
+ /* Skip non-RGBA and Z passes if not using multi layer. */
+ if (!multi_layer && !(STREQ(rp->name, RE_PASSNAME_COMBINED) || STREQ(rp->name, "") ||
+ (STREQ(rp->name, RE_PASSNAME_Z) && write_z))) {
+ continue;
+ }
+
+ /* Skip pass if it does not match the requested view(s). */
+ const char *viewname = rp->view;
+ if (view) {
+ if (!STREQ(view, viewname)) {
+ continue;
+ }
+ else {
+ viewname = "";
+ }
+ }
+
+ /* We only store RGBA passes as half float, for
+ * others precision loss can be problematic. */
+ bool pass_half_float = half_float &&
+ (STREQ(rp->chan_id, "RGB") || STREQ(rp->chan_id, "RGBA") ||
+ STREQ(rp->chan_id, "R") || STREQ(rp->chan_id, "G") ||
+ STREQ(rp->chan_id, "B") || STREQ(rp->chan_id, "A"));
+
+ for (int a = 0; a < rp->channels; a++) {
+ /* Save Combined as RGBA if single layer save. */
+ char passname[EXR_PASS_MAXNAME];
+ char layname[EXR_PASS_MAXNAME];
+
+ if (multi_layer) {
+ set_pass_name(passname, rp->name, a, rp->chan_id);
+ BLI_strncpy(layname, rl->name, sizeof(layname));
+ }
+ else {
+ passname[0] = rp->chan_id[a];
+ passname[1] = '\0';
+ layname[0] = '\0';
+ }
+
+ IMB_exr_add_channel(exrhandle,
+ layname,
+ passname,
+ viewname,
+ rp->channels,
+ rp->channels * rr->rectx,
+ rp->rect + a,
+ pass_half_float);
+ }
+ }
+ }
+
+ errno = 0;
+
+ BLI_make_existing_file(filename);
+
+ int compress = (imf ? imf->exr_codec : 0);
+ bool success = IMB_exr_begin_write(
+ exrhandle, filename, rr->rectx, rr->recty, compress, rr->stamp_data);
+ if (success) {
+ IMB_exr_write_channels(exrhandle);
+ }
+ else {
+ /* TODO, get the error from openexr's exception */
+ BKE_reportf(
+ reports, RPT_ERROR, "Error writing render result, %s (see console)", strerror(errno));
+ }
+
+ IMB_exr_close(exrhandle);
+ return success;
}
/**************************** Single Layer Rendering *************************/
void render_result_single_layer_begin(Render *re)
{
- /* all layers except the active one get temporally pushed away */
+ /* all layers except the active one get temporally pushed away */
- /* officially pushed result should be NULL... error can happen with do_seq */
- RE_FreeRenderResult(re->pushedresult);
+ /* officially pushed result should be NULL... error can happen with do_seq */
+ RE_FreeRenderResult(re->pushedresult);
- re->pushedresult = re->result;
- re->result = NULL;
+ re->pushedresult = re->result;
+ re->result = NULL;
}
/* if scemode is R_SINGLE_LAYER, at end of rendering, merge the both render results */
void render_result_single_layer_end(Render *re)
{
- ViewLayer *view_layer;
- RenderLayer *rlpush;
- RenderLayer *rl;
- int nr;
-
- if (re->result == NULL) {
- printf("pop render result error; no current result!\n");
- return;
- }
-
- if (!re->pushedresult)
- return;
-
- if (re->pushedresult->rectx == re->result->rectx && re->pushedresult->recty == re->result->recty) {
- /* find which layer in re->pushedresult should be replaced */
- rl = re->result->layers.first;
-
- /* render result should be empty after this */
- BLI_remlink(&re->result->layers, rl);
-
- /* reconstruct render result layers */
- for (nr = 0, view_layer = re->view_layers.first; view_layer; view_layer = view_layer->next, nr++) {
- if (nr == re->active_view_layer) {
- BLI_addtail(&re->result->layers, rl);
- }
- else {
- rlpush = RE_GetRenderLayer(re->pushedresult, view_layer->name);
- if (rlpush) {
- BLI_remlink(&re->pushedresult->layers, rlpush);
- BLI_addtail(&re->result->layers, rlpush);
- }
- }
- }
- }
-
- RE_FreeRenderResult(re->pushedresult);
- re->pushedresult = NULL;
+ ViewLayer *view_layer;
+ RenderLayer *rlpush;
+ RenderLayer *rl;
+ int nr;
+
+ if (re->result == NULL) {
+ printf("pop render result error; no current result!\n");
+ return;
+ }
+
+ if (!re->pushedresult)
+ return;
+
+ if (re->pushedresult->rectx == re->result->rectx &&
+ re->pushedresult->recty == re->result->recty) {
+ /* find which layer in re->pushedresult should be replaced */
+ rl = re->result->layers.first;
+
+ /* render result should be empty after this */
+ BLI_remlink(&re->result->layers, rl);
+
+ /* reconstruct render result layers */
+ for (nr = 0, view_layer = re->view_layers.first; view_layer;
+ view_layer = view_layer->next, nr++) {
+ if (nr == re->active_view_layer) {
+ BLI_addtail(&re->result->layers, rl);
+ }
+ else {
+ rlpush = RE_GetRenderLayer(re->pushedresult, view_layer->name);
+ if (rlpush) {
+ BLI_remlink(&re->pushedresult->layers, rlpush);
+ BLI_addtail(&re->result->layers, rlpush);
+ }
+ }
+ }
+ }
+
+ RE_FreeRenderResult(re->pushedresult);
+ re->pushedresult = NULL;
}
/************************* EXR Tile File Rendering ***************************/
static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, const char *viewname)
{
- RenderLayer *rlp, *rl;
- RenderPass *rpassp;
- int offs, partx, party;
-
- BLI_thread_lock(LOCK_IMAGE);
-
- for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) {
- rl = RE_GetRenderLayer(rr, rlp->name);
-
- /* should never happen but prevents crash if it does */
- BLI_assert(rl);
- if (UNLIKELY(rl == NULL)) {
- continue;
- }
-
- if (rrpart->crop) { /* filters add pixel extra */
- offs = (rrpart->crop + rrpart->crop * rrpart->rectx);
- }
- else {
- offs = 0;
- }
-
- /* passes are allocated in sync */
- for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) {
- const int xstride = rpassp->channels;
- int a;
- char fullname[EXR_PASS_MAXNAME];
-
- for (a = 0; a < xstride; a++) {
- set_pass_full_name(fullname, rpassp->name, a, viewname, rpassp->chan_id);
-
- IMB_exr_set_channel(rl->exrhandle, rlp->name, fullname,
- xstride, xstride * rrpart->rectx, rpassp->rect + a + xstride * offs);
- }
- }
-
- }
-
- party = rrpart->tilerect.ymin + rrpart->crop;
- partx = rrpart->tilerect.xmin + rrpart->crop;
-
- for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) {
- rl = RE_GetRenderLayer(rr, rlp->name);
-
- /* should never happen but prevents crash if it does */
- BLI_assert(rl);
- if (UNLIKELY(rl == NULL)) {
- continue;
- }
-
- IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, viewname, false);
- }
-
- BLI_thread_unlock(LOCK_IMAGE);
+ RenderLayer *rlp, *rl;
+ RenderPass *rpassp;
+ int offs, partx, party;
+
+ BLI_thread_lock(LOCK_IMAGE);
+
+ for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) {
+ rl = RE_GetRenderLayer(rr, rlp->name);
+
+ /* should never happen but prevents crash if it does */
+ BLI_assert(rl);
+ if (UNLIKELY(rl == NULL)) {
+ continue;
+ }
+
+ if (rrpart->crop) { /* filters add pixel extra */
+ offs = (rrpart->crop + rrpart->crop * rrpart->rectx);
+ }
+ else {
+ offs = 0;
+ }
+
+ /* passes are allocated in sync */
+ for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) {
+ const int xstride = rpassp->channels;
+ int a;
+ char fullname[EXR_PASS_MAXNAME];
+
+ for (a = 0; a < xstride; a++) {
+ set_pass_full_name(fullname, rpassp->name, a, viewname, rpassp->chan_id);
+
+ IMB_exr_set_channel(rl->exrhandle,
+ rlp->name,
+ fullname,
+ xstride,
+ xstride * rrpart->rectx,
+ rpassp->rect + a + xstride * offs);
+ }
+ }
+ }
+
+ party = rrpart->tilerect.ymin + rrpart->crop;
+ partx = rrpart->tilerect.xmin + rrpart->crop;
+
+ for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) {
+ rl = RE_GetRenderLayer(rr, rlp->name);
+
+ /* should never happen but prevents crash if it does */
+ BLI_assert(rl);
+ if (UNLIKELY(rl == NULL)) {
+ continue;
+ }
+
+ IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, viewname, false);
+ }
+
+ BLI_thread_unlock(LOCK_IMAGE);
}
void render_result_save_empty_result_tiles(Render *re)
{
- RenderPart *pa;
- RenderResult *rr;
- RenderLayer *rl;
-
- for (rr = re->result; rr; rr = rr->next) {
- for (rl = rr->layers.first; rl; rl = rl->next) {
- for (pa = re->parts.first; pa; pa = pa->next) {
- if (pa->status != PART_STATUS_MERGED) {
- int party = pa->disprect.ymin - re->disprect.ymin;
- int partx = pa->disprect.xmin - re->disprect.xmin;
- IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, re->viewname, true);
- }
- }
- }
- }
+ RenderPart *pa;
+ RenderResult *rr;
+ RenderLayer *rl;
+
+ for (rr = re->result; rr; rr = rr->next) {
+ for (rl = rr->layers.first; rl; rl = rl->next) {
+ for (pa = re->parts.first; pa; pa = pa->next) {
+ if (pa->status != PART_STATUS_MERGED) {
+ int party = pa->disprect.ymin - re->disprect.ymin;
+ int partx = pa->disprect.xmin - re->disprect.xmin;
+ IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, re->viewname, true);
+ }
+ }
+ }
+ }
}
/* Compute list of passes needed by render engine. */
-static void templates_register_pass_cb(void *userdata, Scene *UNUSED(scene), ViewLayer *UNUSED(view_layer),
- const char *name, int channels, const char *chan_id, int UNUSED(type))
+static void templates_register_pass_cb(void *userdata,
+ Scene *UNUSED(scene),
+ ViewLayer *UNUSED(view_layer),
+ const char *name,
+ int channels,
+ const char *chan_id,
+ int UNUSED(type))
{
- ListBase *templates = userdata;
- RenderPass *pass = MEM_callocN(sizeof(RenderPass), "RenderPassTemplate");
+ ListBase *templates = userdata;
+ RenderPass *pass = MEM_callocN(sizeof(RenderPass), "RenderPassTemplate");
- pass->channels = channels;
- BLI_strncpy(pass->name, name, sizeof(pass->name));
- BLI_strncpy(pass->chan_id, chan_id, sizeof(pass->chan_id));
+ pass->channels = channels;
+ BLI_strncpy(pass->name, name, sizeof(pass->name));
+ BLI_strncpy(pass->chan_id, chan_id, sizeof(pass->chan_id));
- BLI_addtail(templates, pass);
+ BLI_addtail(templates, pass);
}
-static void render_result_get_pass_templates(RenderEngine *engine, Render *re, RenderLayer *rl, ListBase *templates)
+static void render_result_get_pass_templates(RenderEngine *engine,
+ Render *re,
+ RenderLayer *rl,
+ ListBase *templates)
{
- BLI_listbase_clear(templates);
-
- if (engine && engine->type->update_render_passes) {
- ViewLayer *view_layer = BLI_findstring(&re->view_layers, rl->name, offsetof(ViewLayer, name));
- if (view_layer) {
- RE_engine_update_render_passes(engine, re->scene, view_layer, templates_register_pass_cb, templates);
- }
- }
+ BLI_listbase_clear(templates);
+
+ if (engine && engine->type->update_render_passes) {
+ ViewLayer *view_layer = BLI_findstring(&re->view_layers, rl->name, offsetof(ViewLayer, name));
+ if (view_layer) {
+ RE_engine_update_render_passes(
+ engine, re->scene, view_layer, templates_register_pass_cb, templates);
+ }
+ }
}
/* begin write of exr tile file */
void render_result_exr_file_begin(Render *re, RenderEngine *engine)
{
- char str[FILE_MAX];
-
- for (RenderResult *rr = re->result; rr; rr = rr->next) {
- for (RenderLayer *rl = rr->layers.first; rl; rl = rl->next) {
- /* Get passes needed by engine. Normally we would wait for the
- * engine to create them, but for EXR file we need to know in
- * advance. */
- ListBase templates;
- render_result_get_pass_templates(engine, re, rl, &templates);
-
- /* Create render passes requested by engine. Only this part is
- * mutex locked to avoid deadlock with Python GIL. */
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- for (RenderPass *pass = templates.first; pass; pass = pass->next) {
- render_result_add_pass(re->result, pass->name, pass->channels, pass->chan_id, rl->name, NULL);
- }
- BLI_rw_mutex_unlock(&re->resultmutex);
-
- BLI_freelistN(&templates);
-
- /* Open EXR file for writing. */
- render_result_exr_file_path(re->scene, rl->name, rr->sample_nr, str);
- printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str);
- IMB_exrtile_begin_write(rl->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party);
- }
- }
+ char str[FILE_MAX];
+
+ for (RenderResult *rr = re->result; rr; rr = rr->next) {
+ for (RenderLayer *rl = rr->layers.first; rl; rl = rl->next) {
+ /* Get passes needed by engine. Normally we would wait for the
+ * engine to create them, but for EXR file we need to know in
+ * advance. */
+ ListBase templates;
+ render_result_get_pass_templates(engine, re, rl, &templates);
+
+ /* Create render passes requested by engine. Only this part is
+ * mutex locked to avoid deadlock with Python GIL. */
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ for (RenderPass *pass = templates.first; pass; pass = pass->next) {
+ render_result_add_pass(
+ re->result, pass->name, pass->channels, pass->chan_id, rl->name, NULL);
+ }
+ BLI_rw_mutex_unlock(&re->resultmutex);
+
+ BLI_freelistN(&templates);
+
+ /* Open EXR file for writing. */
+ render_result_exr_file_path(re->scene, rl->name, rr->sample_nr, str);
+ printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str);
+ IMB_exrtile_begin_write(rl->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party);
+ }
+ }
}
/* end write of exr tile file, read back first sample */
void render_result_exr_file_end(Render *re, RenderEngine *engine)
{
- /* Close EXR files. */
- for (RenderResult *rr = re->result; rr; rr = rr->next) {
- for (RenderLayer *rl = rr->layers.first; rl; rl = rl->next) {
- IMB_exr_close(rl->exrhandle);
- rl->exrhandle = NULL;
- }
-
- rr->do_exr_tile = false;
- }
-
- /* Create new render result in memory instead of on disk. */
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- render_result_free_list(&re->fullresult, re->result);
- re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
- BLI_rw_mutex_unlock(&re->resultmutex);
-
- for (RenderLayer *rl = re->result->layers.first; rl; rl = rl->next) {
- /* Get passes needed by engine. */
- ListBase templates;
- render_result_get_pass_templates(engine, re, rl, &templates);
-
- /* Create render passes requested by engine. Only this part is
- * mutex locked to avoid deadlock with Python GIL. */
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- for (RenderPass *pass = templates.first; pass; pass = pass->next) {
- render_result_add_pass(re->result, pass->name, pass->channels, pass->chan_id, rl->name, NULL);
- }
-
- BLI_freelistN(&templates);
-
- /* Render passes contents from file. */
- char str[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = "";
- render_result_exr_file_path(re->scene, rl->name, 0, str);
- printf("read exr tmp file: %s\n", str);
-
- if (!render_result_exr_file_read_path(re->result, rl, str)) {
- printf("cannot read: %s\n", str);
- }
- BLI_rw_mutex_unlock(&re->resultmutex);
- }
+ /* Close EXR files. */
+ for (RenderResult *rr = re->result; rr; rr = rr->next) {
+ for (RenderLayer *rl = rr->layers.first; rl; rl = rl->next) {
+ IMB_exr_close(rl->exrhandle);
+ rl->exrhandle = NULL;
+ }
+
+ rr->do_exr_tile = false;
+ }
+
+ /* Create new render result in memory instead of on disk. */
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ render_result_free_list(&re->fullresult, re->result);
+ re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
+ BLI_rw_mutex_unlock(&re->resultmutex);
+
+ for (RenderLayer *rl = re->result->layers.first; rl; rl = rl->next) {
+ /* Get passes needed by engine. */
+ ListBase templates;
+ render_result_get_pass_templates(engine, re, rl, &templates);
+
+ /* Create render passes requested by engine. Only this part is
+ * mutex locked to avoid deadlock with Python GIL. */
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ for (RenderPass *pass = templates.first; pass; pass = pass->next) {
+ render_result_add_pass(
+ re->result, pass->name, pass->channels, pass->chan_id, rl->name, NULL);
+ }
+
+ BLI_freelistN(&templates);
+
+ /* Render passes contents from file. */
+ char str[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = "";
+ render_result_exr_file_path(re->scene, rl->name, 0, str);
+ printf("read exr tmp file: %s\n", str);
+
+ if (!render_result_exr_file_read_path(re->result, rl, str)) {
+ printf("cannot read: %s\n", str);
+ }
+ BLI_rw_mutex_unlock(&re->resultmutex);
+ }
}
/* save part into exr file */
void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart, const char *viewname)
{
- for (; rr && rrpart; rr = rr->next, rrpart = rrpart->next)
- save_render_result_tile(rr, rrpart, viewname);
+ for (; rr && rrpart; rr = rr->next, rrpart = rrpart->next)
+ save_render_result_tile(rr, rrpart, viewname);
}
/* path to temporary exr file */
void render_result_exr_file_path(Scene *scene, const char *layname, int sample, char *filepath)
{
- char name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100];
- const char *fi = BLI_path_basename(BKE_main_blendfile_path_from_global());
+ char name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100];
+ const char *fi = BLI_path_basename(BKE_main_blendfile_path_from_global());
- if (sample == 0) {
- BLI_snprintf(name, sizeof(name), "%s_%s_%s.exr", fi, scene->id.name + 2, layname);
- }
- else {
- BLI_snprintf(name, sizeof(name), "%s_%s_%s%d.exr", fi, scene->id.name + 2, layname, sample);
- }
+ if (sample == 0) {
+ BLI_snprintf(name, sizeof(name), "%s_%s_%s.exr", fi, scene->id.name + 2, layname);
+ }
+ else {
+ BLI_snprintf(name, sizeof(name), "%s_%s_%s%d.exr", fi, scene->id.name + 2, layname, sample);
+ }
- /* Make name safe for paths, see T43275. */
- BLI_filename_make_safe(name);
+ /* Make name safe for paths, see T43275. */
+ BLI_filename_make_safe(name);
- BLI_make_file_string("/", filepath, BKE_tempdir_session(), name);
+ BLI_make_file_string("/", filepath, BKE_tempdir_session(), name);
}
/* called for reading temp files, and for external engines */
-int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, const char *filepath)
+int render_result_exr_file_read_path(RenderResult *rr,
+ RenderLayer *rl_single,
+ const char *filepath)
{
- RenderLayer *rl;
- RenderPass *rpass;
- void *exrhandle = IMB_exr_get_handle();
- int rectx, recty;
-
- if (IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty) == 0) {
- printf("failed being read %s\n", filepath);
- IMB_exr_close(exrhandle);
- return 0;
- }
-
- if (rr == NULL || rectx != rr->rectx || recty != rr->recty) {
- if (rr)
- printf("error in reading render result: dimensions don't match\n");
- else
- printf("error in reading render result: NULL result pointer\n");
- IMB_exr_close(exrhandle);
- return 0;
- }
-
- for (rl = rr->layers.first; rl; rl = rl->next) {
- if (rl_single && rl_single != rl)
- continue;
-
- /* passes are allocated in sync */
- for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
- const int xstride = rpass->channels;
- int a;
- char fullname[EXR_PASS_MAXNAME];
-
- for (a = 0; a < xstride; a++) {
- set_pass_full_name(fullname, rpass->name, a, rpass->view, rpass->chan_id);
- IMB_exr_set_channel(exrhandle, rl->name, fullname,
- xstride, xstride * rectx, rpass->rect + a);
- }
-
- set_pass_full_name(rpass->fullname, rpass->name, -1, rpass->view, rpass->chan_id);
- }
- }
-
- IMB_exr_read_channels(exrhandle);
- IMB_exr_close(exrhandle);
-
- return 1;
+ RenderLayer *rl;
+ RenderPass *rpass;
+ void *exrhandle = IMB_exr_get_handle();
+ int rectx, recty;
+
+ if (IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty) == 0) {
+ printf("failed being read %s\n", filepath);
+ IMB_exr_close(exrhandle);
+ return 0;
+ }
+
+ if (rr == NULL || rectx != rr->rectx || recty != rr->recty) {
+ if (rr)
+ printf("error in reading render result: dimensions don't match\n");
+ else
+ printf("error in reading render result: NULL result pointer\n");
+ IMB_exr_close(exrhandle);
+ return 0;
+ }
+
+ for (rl = rr->layers.first; rl; rl = rl->next) {
+ if (rl_single && rl_single != rl)
+ continue;
+
+ /* passes are allocated in sync */
+ for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
+ const int xstride = rpass->channels;
+ int a;
+ char fullname[EXR_PASS_MAXNAME];
+
+ for (a = 0; a < xstride; a++) {
+ set_pass_full_name(fullname, rpass->name, a, rpass->view, rpass->chan_id);
+ IMB_exr_set_channel(
+ exrhandle, rl->name, fullname, xstride, xstride * rectx, rpass->rect + a);
+ }
+
+ set_pass_full_name(rpass->fullname, rpass->name, -1, rpass->view, rpass->chan_id);
+ }
+ }
+
+ IMB_exr_read_channels(exrhandle);
+ IMB_exr_close(exrhandle);
+
+ return 1;
}
static void render_result_exr_file_cache_path(Scene *sce, const char *root, char *r_path)
{
- char filename_full[FILE_MAX + MAX_ID_NAME + 100], filename[FILE_MAXFILE], dirname[FILE_MAXDIR];
- char path_digest[16] = {0};
- char path_hexdigest[33];
-
- /* If root is relative, use either current .blend file dir, or temp one if not saved. */
- const char *blendfile_path = BKE_main_blendfile_path_from_global();
- if (blendfile_path[0] != '\0') {
- BLI_split_dirfile(blendfile_path, dirname, filename, sizeof(dirname), sizeof(filename));
- BLI_path_extension_replace(filename, sizeof(filename), ""); /* strip '.blend' */
- BLI_hash_md5_buffer(blendfile_path, strlen(blendfile_path), path_digest);
- }
- else {
- BLI_strncpy(dirname, BKE_tempdir_base(), sizeof(dirname));
- BLI_strncpy(filename, "UNSAVED", sizeof(filename));
- }
- BLI_hash_md5_to_hexdigest(path_digest, path_hexdigest);
-
- /* Default to *non-volatile* tmp dir. */
- if (*root == '\0') {
- root = BKE_tempdir_base();
- }
-
- BLI_snprintf(filename_full, sizeof(filename_full), "cached_RR_%s_%s_%s.exr",
- filename, sce->id.name + 2, path_hexdigest);
- BLI_make_file_string(dirname, r_path, root, filename_full);
+ char filename_full[FILE_MAX + MAX_ID_NAME + 100], filename[FILE_MAXFILE], dirname[FILE_MAXDIR];
+ char path_digest[16] = {0};
+ char path_hexdigest[33];
+
+ /* If root is relative, use either current .blend file dir, or temp one if not saved. */
+ const char *blendfile_path = BKE_main_blendfile_path_from_global();
+ if (blendfile_path[0] != '\0') {
+ BLI_split_dirfile(blendfile_path, dirname, filename, sizeof(dirname), sizeof(filename));
+ BLI_path_extension_replace(filename, sizeof(filename), ""); /* strip '.blend' */
+ BLI_hash_md5_buffer(blendfile_path, strlen(blendfile_path), path_digest);
+ }
+ else {
+ BLI_strncpy(dirname, BKE_tempdir_base(), sizeof(dirname));
+ BLI_strncpy(filename, "UNSAVED", sizeof(filename));
+ }
+ BLI_hash_md5_to_hexdigest(path_digest, path_hexdigest);
+
+ /* Default to *non-volatile* tmp dir. */
+ if (*root == '\0') {
+ root = BKE_tempdir_base();
+ }
+
+ BLI_snprintf(filename_full,
+ sizeof(filename_full),
+ "cached_RR_%s_%s_%s.exr",
+ filename,
+ sce->id.name + 2,
+ path_hexdigest);
+ BLI_make_file_string(dirname, r_path, root, filename_full);
}
void render_result_exr_file_cache_write(Render *re)
{
- RenderResult *rr = re->result;
- char str[FILE_MAXFILE + FILE_MAXFILE + MAX_ID_NAME + 100];
- char *root = U.render_cachedir;
+ RenderResult *rr = re->result;
+ char str[FILE_MAXFILE + FILE_MAXFILE + MAX_ID_NAME + 100];
+ char *root = U.render_cachedir;
- render_result_exr_file_cache_path(re->scene, root, str);
- printf("Caching exr file, %dx%d, %s\n", rr->rectx, rr->recty, str);
+ render_result_exr_file_cache_path(re->scene, root, str);
+ printf("Caching exr file, %dx%d, %s\n", rr->rectx, rr->recty, str);
- RE_WriteRenderResult(NULL, rr, str, NULL, NULL, -1);
+ RE_WriteRenderResult(NULL, rr, str, NULL, NULL, -1);
}
/* For cache, makes exact copy of render result */
bool render_result_exr_file_cache_read(Render *re)
{
- char str[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = "";
- char *root = U.render_cachedir;
+ char str[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = "";
+ char *root = U.render_cachedir;
- RE_FreeRenderResult(re->result);
- re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
+ RE_FreeRenderResult(re->result);
+ re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
- /* First try cache. */
- render_result_exr_file_cache_path(re->scene, root, str);
+ /* First try cache. */
+ render_result_exr_file_cache_path(re->scene, root, str);
- printf("read exr cache file: %s\n", str);
- if (!render_result_exr_file_read_path(re->result, NULL, str)) {
- printf("cannot read: %s\n", str);
- return false;
- }
- return true;
+ printf("read exr cache file: %s\n", str);
+ if (!render_result_exr_file_read_path(re->result, NULL, str)) {
+ printf("cannot read: %s\n", str);
+ return false;
+ }
+ return true;
}
/*************************** Combined Pixel Rect *****************************/
ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd, const int view_id)
{
- ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0);
- RenderView *rv = RE_RenderViewGetById(rr, view_id);
-
- /* if not exists, BKE_imbuf_write makes one */
- ibuf->rect = (unsigned int *)rv->rect32;
- ibuf->rect_float = rv->rectf;
- ibuf->zbuf_float = rv->rectz;
-
- /* float factor for random dither, imbuf takes care of it */
- ibuf->dither = rd->dither_intensity;
-
- /* prepare to gamma correct to sRGB color space
- * note that sequence editor can generate 8bpc render buffers
- */
- if (ibuf->rect) {
- if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32)) {
- if (rd->im_format.depth == R_IMF_CHAN_DEPTH_8) {
- /* Higher depth bits are supported but not needed for current file output. */
- ibuf->rect_float = NULL;
- }
- else {
- IMB_float_from_rect(ibuf);
- }
- }
- else {
- /* ensure no float buffer remained from previous frame */
- ibuf->rect_float = NULL;
- }
- }
-
- /* color -> grayscale */
- /* editing directly would alter the render view */
- if (rd->im_format.planes == R_IMF_PLANES_BW) {
- ImBuf *ibuf_bw = IMB_dupImBuf(ibuf);
- IMB_color_to_bw(ibuf_bw);
- IMB_freeImBuf(ibuf);
- ibuf = ibuf_bw;
- }
-
- return ibuf;
+ ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0);
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
+
+ /* if not exists, BKE_imbuf_write makes one */
+ ibuf->rect = (unsigned int *)rv->rect32;
+ ibuf->rect_float = rv->rectf;
+ ibuf->zbuf_float = rv->rectz;
+
+ /* float factor for random dither, imbuf takes care of it */
+ ibuf->dither = rd->dither_intensity;
+
+ /* prepare to gamma correct to sRGB color space
+ * note that sequence editor can generate 8bpc render buffers
+ */
+ if (ibuf->rect) {
+ if (BKE_imtype_valid_depths(rd->im_format.imtype) &
+ (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32)) {
+ if (rd->im_format.depth == R_IMF_CHAN_DEPTH_8) {
+ /* Higher depth bits are supported but not needed for current file output. */
+ ibuf->rect_float = NULL;
+ }
+ else {
+ IMB_float_from_rect(ibuf);
+ }
+ }
+ else {
+ /* ensure no float buffer remained from previous frame */
+ ibuf->rect_float = NULL;
+ }
+ }
+
+ /* color -> grayscale */
+ /* editing directly would alter the render view */
+ if (rd->im_format.planes == R_IMF_PLANES_BW) {
+ ImBuf *ibuf_bw = IMB_dupImBuf(ibuf);
+ IMB_color_to_bw(ibuf_bw);
+ IMB_freeImBuf(ibuf);
+ ibuf = ibuf_bw;
+ }
+
+ return ibuf;
}
-void RE_render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf, const int view_id)
+void RE_render_result_rect_from_ibuf(RenderResult *rr,
+ RenderData *UNUSED(rd),
+ ImBuf *ibuf,
+ const int view_id)
{
- RenderView *rv = RE_RenderViewGetById(rr, view_id);
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
- if (ibuf->rect_float) {
- rr->have_combined = true;
+ if (ibuf->rect_float) {
+ rr->have_combined = true;
- if (!rv->rectf)
- rv->rectf = MEM_mallocN(4 * sizeof(float) * rr->rectx * rr->recty, "render_seq rectf");
+ if (!rv->rectf)
+ rv->rectf = MEM_mallocN(4 * sizeof(float) * rr->rectx * rr->recty, "render_seq rectf");
- memcpy(rv->rectf, ibuf->rect_float, 4 * sizeof(float) * rr->rectx * rr->recty);
+ memcpy(rv->rectf, ibuf->rect_float, 4 * sizeof(float) * rr->rectx * rr->recty);
- /* TSK! Since sequence render doesn't free the *rr render result, the old rect32
- * can hang around when sequence render has rendered a 32 bits one before */
- MEM_SAFE_FREE(rv->rect32);
- }
- else if (ibuf->rect) {
- rr->have_combined = true;
+ /* TSK! Since sequence render doesn't free the *rr render result, the old rect32
+ * can hang around when sequence render has rendered a 32 bits one before */
+ MEM_SAFE_FREE(rv->rect32);
+ }
+ else if (ibuf->rect) {
+ rr->have_combined = true;
- if (!rv->rect32)
- rv->rect32 = MEM_mallocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
+ if (!rv->rect32)
+ rv->rect32 = MEM_mallocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
- memcpy(rv->rect32, ibuf->rect, 4 * rr->rectx * rr->recty);
+ memcpy(rv->rect32, ibuf->rect, 4 * rr->rectx * rr->recty);
- /* Same things as above, old rectf can hang around from previous render. */
- MEM_SAFE_FREE(rv->rectf);
- }
+ /* Same things as above, old rectf can hang around from previous render. */
+ MEM_SAFE_FREE(rv->rectf);
+ }
}
void render_result_rect_fill_zero(RenderResult *rr, const int view_id)
{
- RenderView *rv = RE_RenderViewGetById(rr, view_id);
-
- if (rv->rectf)
- memset(rv->rectf, 0, 4 * sizeof(float) * rr->rectx * rr->recty);
- else if (rv->rect32)
- memset(rv->rect32, 0, 4 * rr->rectx * rr->recty);
- else
- rv->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
+
+ if (rv->rectf)
+ memset(rv->rectf, 0, 4 * sizeof(float) * rr->rectx * rr->recty);
+ else if (rv->rect32)
+ memset(rv->rect32, 0, 4 * rr->rectx * rr->recty);
+ else
+ rv->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
}
-void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rectx, int recty,
- const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings,
+void render_result_rect_get_pixels(RenderResult *rr,
+ unsigned int *rect,
+ int rectx,
+ int recty,
+ const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings,
const int view_id)
{
- RenderView *rv = RE_RenderViewGetById(rr, view_id);
-
- if (rv->rect32)
- memcpy(rect, rv->rect32, sizeof(int) * rr->rectx * rr->recty);
- else if (rv->rectf)
- IMB_display_buffer_transform_apply((unsigned char *)rect, rv->rectf, rr->rectx, rr->recty, 4,
- view_settings, display_settings, true);
- else
- /* else fill with black */
- memset(rect, 0, sizeof(int) * rectx * recty);
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
+
+ if (rv->rect32)
+ memcpy(rect, rv->rect32, sizeof(int) * rr->rectx * rr->recty);
+ else if (rv->rectf)
+ IMB_display_buffer_transform_apply((unsigned char *)rect,
+ rv->rectf,
+ rr->rectx,
+ rr->recty,
+ 4,
+ view_settings,
+ display_settings,
+ true);
+ else
+ /* else fill with black */
+ memset(rect, 0, sizeof(int) * rectx * recty);
}
-
/*************************** multiview functions *****************************/
bool RE_HasCombinedLayer(RenderResult *res)
{
- RenderView *rv;
+ RenderView *rv;
- if (res == NULL)
- return false;
+ if (res == NULL)
+ return false;
- rv = res->views.first;
- if (rv == NULL)
- return false;
+ rv = res->views.first;
+ if (rv == NULL)
+ return false;
- return (rv->rect32 || rv->rectf);
+ return (rv->rect32 || rv->rectf);
}
bool RE_HasFloatPixels(RenderResult *res)
{
- RenderView *rview;
+ RenderView *rview;
- for (rview = res->views.first; rview; rview = rview->next) {
- if (rview->rect32 && !rview->rectf) {
- return false;
- }
- }
+ for (rview = res->views.first; rview; rview = rview->next) {
+ if (rview->rect32 && !rview->rectf) {
+ return false;
+ }
+ }
- return true;
+ return true;
}
bool RE_RenderResult_is_stereo(RenderResult *res)
{
- if (!BLI_findstring(&res->views, STEREO_LEFT_NAME, offsetof(RenderView, name))) {
- return false;
- }
+ if (!BLI_findstring(&res->views, STEREO_LEFT_NAME, offsetof(RenderView, name))) {
+ return false;
+ }
- if (!BLI_findstring(&res->views, STEREO_RIGHT_NAME, offsetof(RenderView, name))) {
- return false;
- }
+ if (!BLI_findstring(&res->views, STEREO_RIGHT_NAME, offsetof(RenderView, name))) {
+ return false;
+ }
- return true;
+ return true;
}
RenderView *RE_RenderViewGetById(RenderResult *res, const int view_id)
{
- RenderView *rv = BLI_findlink(&res->views, view_id);
- BLI_assert(res->views.first);
- return rv ? rv : res->views.first;
+ RenderView *rv = BLI_findlink(&res->views, view_id);
+ BLI_assert(res->views.first);
+ return rv ? rv : res->views.first;
}
RenderView *RE_RenderViewGetByName(RenderResult *res, const char *viewname)
{
- RenderView *rv = BLI_findstring(&res->views, viewname, offsetof(RenderView, name));
- BLI_assert(res->views.first);
- return rv ? rv : res->views.first;
+ RenderView *rv = BLI_findstring(&res->views, viewname, offsetof(RenderView, name));
+ BLI_assert(res->views.first);
+ return rv ? rv : res->views.first;
}
static RenderPass *duplicate_render_pass(RenderPass *rpass)
{
- RenderPass *new_rpass = MEM_mallocN(sizeof(RenderPass), "new render pass");
- *new_rpass = *rpass;
- new_rpass->next = new_rpass->prev = NULL;
- if (new_rpass->rect != NULL) {
- new_rpass->rect = MEM_dupallocN(new_rpass->rect);
- }
- return new_rpass;
+ RenderPass *new_rpass = MEM_mallocN(sizeof(RenderPass), "new render pass");
+ *new_rpass = *rpass;
+ new_rpass->next = new_rpass->prev = NULL;
+ if (new_rpass->rect != NULL) {
+ new_rpass->rect = MEM_dupallocN(new_rpass->rect);
+ }
+ return new_rpass;
}
static RenderLayer *duplicate_render_layer(RenderLayer *rl)
{
- RenderLayer *new_rl = MEM_mallocN(sizeof(RenderLayer), "new render layer");
- *new_rl = *rl;
- new_rl->next = new_rl->prev = NULL;
- new_rl->passes.first = new_rl->passes.last = NULL;
- new_rl->exrhandle = NULL;
- if (new_rl->acolrect != NULL) {
- new_rl->acolrect = MEM_dupallocN(new_rl->acolrect);
- }
- if (new_rl->scolrect != NULL) {
- new_rl->scolrect = MEM_dupallocN(new_rl->scolrect);
- }
- if (new_rl->display_buffer != NULL) {
- new_rl->display_buffer = MEM_dupallocN(new_rl->display_buffer);
- }
- for (RenderPass *rpass = rl->passes.first; rpass != NULL; rpass = rpass->next) {
- RenderPass *new_rpass = duplicate_render_pass(rpass);
- BLI_addtail(&new_rl->passes, new_rpass);
- }
- return new_rl;
+ RenderLayer *new_rl = MEM_mallocN(sizeof(RenderLayer), "new render layer");
+ *new_rl = *rl;
+ new_rl->next = new_rl->prev = NULL;
+ new_rl->passes.first = new_rl->passes.last = NULL;
+ new_rl->exrhandle = NULL;
+ if (new_rl->acolrect != NULL) {
+ new_rl->acolrect = MEM_dupallocN(new_rl->acolrect);
+ }
+ if (new_rl->scolrect != NULL) {
+ new_rl->scolrect = MEM_dupallocN(new_rl->scolrect);
+ }
+ if (new_rl->display_buffer != NULL) {
+ new_rl->display_buffer = MEM_dupallocN(new_rl->display_buffer);
+ }
+ for (RenderPass *rpass = rl->passes.first; rpass != NULL; rpass = rpass->next) {
+ RenderPass *new_rpass = duplicate_render_pass(rpass);
+ BLI_addtail(&new_rl->passes, new_rpass);
+ }
+ return new_rl;
}
static RenderView *duplicate_render_view(RenderView *rview)
{
- RenderView *new_rview = MEM_mallocN(sizeof(RenderView), "new render view");
- *new_rview = *rview;
- if (new_rview->rectf != NULL) {
- new_rview->rectf = MEM_dupallocN(new_rview->rectf);
- }
- if (new_rview->rectz != NULL) {
- new_rview->rectz = MEM_dupallocN(new_rview->rectz);
- }
- if (new_rview->rect32 != NULL) {
- new_rview->rect32 = MEM_dupallocN(new_rview->rect32);
- }
- return new_rview;
+ RenderView *new_rview = MEM_mallocN(sizeof(RenderView), "new render view");
+ *new_rview = *rview;
+ if (new_rview->rectf != NULL) {
+ new_rview->rectf = MEM_dupallocN(new_rview->rectf);
+ }
+ if (new_rview->rectz != NULL) {
+ new_rview->rectz = MEM_dupallocN(new_rview->rectz);
+ }
+ if (new_rview->rect32 != NULL) {
+ new_rview->rect32 = MEM_dupallocN(new_rview->rect32);
+ }
+ return new_rview;
}
RenderResult *RE_DuplicateRenderResult(RenderResult *rr)
{
- RenderResult *new_rr = MEM_mallocN(sizeof(RenderResult), "new duplicated render result");
- *new_rr = *rr;
- new_rr->next = new_rr->prev = NULL;
- new_rr->layers.first = new_rr->layers.last = NULL;
- new_rr->views.first = new_rr->views.last = NULL;
- for (RenderLayer *rl = rr->layers.first; rl != NULL; rl = rl->next) {
- RenderLayer *new_rl = duplicate_render_layer(rl);
- BLI_addtail(&new_rr->layers, new_rl);
- }
- for (RenderView *rview = rr->views.first; rview != NULL; rview = rview->next) {
- RenderView *new_rview = duplicate_render_view(rview);
- BLI_addtail(&new_rr->views, new_rview);
- }
- if (new_rr->rect32 != NULL) {
- new_rr->rect32 = MEM_dupallocN(new_rr->rect32);
- }
- if (new_rr->rectf != NULL) {
- new_rr->rectf = MEM_dupallocN(new_rr->rectf);
- }
- if (new_rr->rectz != NULL) {
- new_rr->rectz = MEM_dupallocN(new_rr->rectz);
- }
- new_rr->stamp_data = BKE_stamp_data_copy(new_rr->stamp_data);
- return new_rr;
+ RenderResult *new_rr = MEM_mallocN(sizeof(RenderResult), "new duplicated render result");
+ *new_rr = *rr;
+ new_rr->next = new_rr->prev = NULL;
+ new_rr->layers.first = new_rr->layers.last = NULL;
+ new_rr->views.first = new_rr->views.last = NULL;
+ for (RenderLayer *rl = rr->layers.first; rl != NULL; rl = rl->next) {
+ RenderLayer *new_rl = duplicate_render_layer(rl);
+ BLI_addtail(&new_rr->layers, new_rl);
+ }
+ for (RenderView *rview = rr->views.first; rview != NULL; rview = rview->next) {
+ RenderView *new_rview = duplicate_render_view(rview);
+ BLI_addtail(&new_rr->views, new_rview);
+ }
+ if (new_rr->rect32 != NULL) {
+ new_rr->rect32 = MEM_dupallocN(new_rr->rect32);
+ }
+ if (new_rr->rectf != NULL) {
+ new_rr->rectf = MEM_dupallocN(new_rr->rectf);
+ }
+ if (new_rr->rectz != NULL) {
+ new_rr->rectz = MEM_dupallocN(new_rr->rectz);
+ }
+ new_rr->stamp_data = BKE_stamp_data_copy(new_rr->stamp_data);
+ return new_rr;
}
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index 7678e69caad..0400ad7ee95 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -21,7 +21,6 @@
* \ingroup render
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -64,96 +63,97 @@
static RNG_THREAD_ARRAY *random_tex_array;
-
void RE_texture_rng_init(void)
{
- random_tex_array = BLI_rng_threaded_new();
+ random_tex_array = BLI_rng_threaded_new();
}
void RE_texture_rng_exit(void)
{
- BLI_rng_threaded_free(random_tex_array);
+ BLI_rng_threaded_free(random_tex_array);
}
-
/* ------------------------------------------------------------------------- */
-
/* this allows colorbanded textures to control normals as well */
static void tex_normal_derivate(Tex *tex, TexResult *texres)
{
- if (tex->flag & TEX_COLORBAND) {
- float col[4];
- if (BKE_colorband_evaluate(tex->coba, texres->tin, col)) {
- float fac0, fac1, fac2, fac3;
-
- fac0 = (col[0] + col[1] + col[2]);
- BKE_colorband_evaluate(tex->coba, texres->nor[0], col);
- fac1 = (col[0] + col[1] + col[2]);
- BKE_colorband_evaluate(tex->coba, texres->nor[1], col);
- fac2 = (col[0] + col[1] + col[2]);
- BKE_colorband_evaluate(tex->coba, texres->nor[2], col);
- fac3 = (col[0] + col[1] + col[2]);
-
- texres->nor[0] = (fac0 - fac1) / 3.0f;
- texres->nor[1] = (fac0 - fac2) / 3.0f;
- texres->nor[2] = (fac0 - fac3) / 3.0f;
-
- return;
- }
- }
- texres->nor[0] = texres->tin - texres->nor[0];
- texres->nor[1] = texres->tin - texres->nor[1];
- texres->nor[2] = texres->tin - texres->nor[2];
+ if (tex->flag & TEX_COLORBAND) {
+ float col[4];
+ if (BKE_colorband_evaluate(tex->coba, texres->tin, col)) {
+ float fac0, fac1, fac2, fac3;
+
+ fac0 = (col[0] + col[1] + col[2]);
+ BKE_colorband_evaluate(tex->coba, texres->nor[0], col);
+ fac1 = (col[0] + col[1] + col[2]);
+ BKE_colorband_evaluate(tex->coba, texres->nor[1], col);
+ fac2 = (col[0] + col[1] + col[2]);
+ BKE_colorband_evaluate(tex->coba, texres->nor[2], col);
+ fac3 = (col[0] + col[1] + col[2]);
+
+ texres->nor[0] = (fac0 - fac1) / 3.0f;
+ texres->nor[1] = (fac0 - fac2) / 3.0f;
+ texres->nor[2] = (fac0 - fac3) / 3.0f;
+
+ return;
+ }
+ }
+ texres->nor[0] = texres->tin - texres->nor[0];
+ texres->nor[1] = texres->tin - texres->nor[1];
+ texres->nor[2] = texres->tin - texres->nor[2];
}
-
-
static int blend(Tex *tex, const float texvec[3], TexResult *texres)
{
- float x, y, t;
-
- if (tex->flag & TEX_FLIPBLEND) {
- x = texvec[1];
- y = texvec[0];
- }
- else {
- x = texvec[0];
- y = texvec[1];
- }
-
- if (tex->stype == TEX_LIN) { /* lin */
- texres->tin = (1.0f + x) / 2.0f;
- }
- else if (tex->stype == TEX_QUAD) { /* quad */
- texres->tin = (1.0f + x) / 2.0f;
- if (texres->tin < 0.0f) texres->tin = 0.0f;
- else texres->tin *= texres->tin;
- }
- else if (tex->stype == TEX_EASE) { /* ease */
- texres->tin = (1.0f + x) / 2.0f;
- if (texres->tin <= 0.0f) texres->tin = 0.0f;
- else if (texres->tin >= 1.0f) texres->tin = 1.0f;
- else {
- t = texres->tin * texres->tin;
- texres->tin = (3.0f * t - 2.0f * t * texres->tin);
- }
- }
- else if (tex->stype == TEX_DIAG) { /* diag */
- texres->tin = (2.0f + x + y) / 4.0f;
- }
- else if (tex->stype == TEX_RAD) { /* radial */
- texres->tin = (atan2f(y, x) / (float)(2 * M_PI) + 0.5f);
- }
- else { /* sphere TEX_SPHERE */
- texres->tin = 1.0f - sqrtf(x * x + y * y + texvec[2] * texvec[2]);
- if (texres->tin < 0.0f) texres->tin = 0.0f;
- if (tex->stype == TEX_HALO) texres->tin *= texres->tin; /* halo */
- }
-
- BRICONT;
-
- return TEX_INT;
+ float x, y, t;
+
+ if (tex->flag & TEX_FLIPBLEND) {
+ x = texvec[1];
+ y = texvec[0];
+ }
+ else {
+ x = texvec[0];
+ y = texvec[1];
+ }
+
+ if (tex->stype == TEX_LIN) { /* lin */
+ texres->tin = (1.0f + x) / 2.0f;
+ }
+ else if (tex->stype == TEX_QUAD) { /* quad */
+ texres->tin = (1.0f + x) / 2.0f;
+ if (texres->tin < 0.0f)
+ texres->tin = 0.0f;
+ else
+ texres->tin *= texres->tin;
+ }
+ else if (tex->stype == TEX_EASE) { /* ease */
+ texres->tin = (1.0f + x) / 2.0f;
+ if (texres->tin <= 0.0f)
+ texres->tin = 0.0f;
+ else if (texres->tin >= 1.0f)
+ texres->tin = 1.0f;
+ else {
+ t = texres->tin * texres->tin;
+ texres->tin = (3.0f * t - 2.0f * t * texres->tin);
+ }
+ }
+ else if (tex->stype == TEX_DIAG) { /* diag */
+ texres->tin = (2.0f + x + y) / 4.0f;
+ }
+ else if (tex->stype == TEX_RAD) { /* radial */
+ texres->tin = (atan2f(y, x) / (float)(2 * M_PI) + 0.5f);
+ }
+ else { /* sphere TEX_SPHERE */
+ texres->tin = 1.0f - sqrtf(x * x + y * y + texvec[2] * texvec[2]);
+ if (texres->tin < 0.0f)
+ texres->tin = 0.0f;
+ if (tex->stype == TEX_HALO)
+ texres->tin *= texres->tin; /* halo */
+ }
+
+ BRICONT;
+
+ return TEX_INT;
}
/* ------------------------------------------------------------------------- */
@@ -163,245 +163,293 @@ static int blend(Tex *tex, const float texvec[3], TexResult *texres)
static int clouds(Tex *tex, const float texvec[3], TexResult *texres)
{
- int rv = TEX_INT;
-
- texres->tin = BLI_gTurbulence(tex->noisesize, texvec[0], texvec[1], texvec[2], tex->noisedepth, (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
-
- if (texres->nor != NULL) {
- /* calculate bumpnormal */
- texres->nor[0] = BLI_gTurbulence(tex->noisesize, texvec[0] + tex->nabla, texvec[1], texvec[2], tex->noisedepth, (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
- texres->nor[1] = BLI_gTurbulence(tex->noisesize, texvec[0], texvec[1] + tex->nabla, texvec[2], tex->noisedepth, (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
- texres->nor[2] = BLI_gTurbulence(tex->noisesize, texvec[0], texvec[1], texvec[2] + tex->nabla, tex->noisedepth, (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
-
- tex_normal_derivate(tex, texres);
- rv |= TEX_NOR;
- }
-
- if (tex->stype == TEX_COLOR) {
- /* in this case, int. value should really be computed from color,
- * and bumpnormal from that, would be too slow, looks ok as is */
- texres->tr = texres->tin;
- texres->tg = BLI_gTurbulence(tex->noisesize, texvec[1], texvec[0], texvec[2], tex->noisedepth, (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
- texres->tb = BLI_gTurbulence(tex->noisesize, texvec[1], texvec[2], texvec[0], tex->noisedepth, (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
- BRICONTRGB;
- texres->ta = 1.0;
- return (rv | TEX_RGB);
- }
-
- BRICONT;
-
- return rv;
-
+ int rv = TEX_INT;
+
+ texres->tin = BLI_gTurbulence(tex->noisesize,
+ texvec[0],
+ texvec[1],
+ texvec[2],
+ tex->noisedepth,
+ (tex->noisetype != TEX_NOISESOFT),
+ tex->noisebasis);
+
+ if (texres->nor != NULL) {
+ /* calculate bumpnormal */
+ texres->nor[0] = BLI_gTurbulence(tex->noisesize,
+ texvec[0] + tex->nabla,
+ texvec[1],
+ texvec[2],
+ tex->noisedepth,
+ (tex->noisetype != TEX_NOISESOFT),
+ tex->noisebasis);
+ texres->nor[1] = BLI_gTurbulence(tex->noisesize,
+ texvec[0],
+ texvec[1] + tex->nabla,
+ texvec[2],
+ tex->noisedepth,
+ (tex->noisetype != TEX_NOISESOFT),
+ tex->noisebasis);
+ texres->nor[2] = BLI_gTurbulence(tex->noisesize,
+ texvec[0],
+ texvec[1],
+ texvec[2] + tex->nabla,
+ tex->noisedepth,
+ (tex->noisetype != TEX_NOISESOFT),
+ tex->noisebasis);
+
+ tex_normal_derivate(tex, texres);
+ rv |= TEX_NOR;
+ }
+
+ if (tex->stype == TEX_COLOR) {
+ /* in this case, int. value should really be computed from color,
+ * and bumpnormal from that, would be too slow, looks ok as is */
+ texres->tr = texres->tin;
+ texres->tg = BLI_gTurbulence(tex->noisesize,
+ texvec[1],
+ texvec[0],
+ texvec[2],
+ tex->noisedepth,
+ (tex->noisetype != TEX_NOISESOFT),
+ tex->noisebasis);
+ texres->tb = BLI_gTurbulence(tex->noisesize,
+ texvec[1],
+ texvec[2],
+ texvec[0],
+ tex->noisedepth,
+ (tex->noisetype != TEX_NOISESOFT),
+ tex->noisebasis);
+ BRICONTRGB;
+ texres->ta = 1.0;
+ return (rv | TEX_RGB);
+ }
+
+ BRICONT;
+
+ return rv;
}
/* creates a sine wave */
static float tex_sin(float a)
{
- a = 0.5f + 0.5f * sinf(a);
+ a = 0.5f + 0.5f * sinf(a);
- return a;
+ return a;
}
/* creates a saw wave */
static float tex_saw(float a)
{
- const float b = 2 * M_PI;
+ const float b = 2 * M_PI;
- int n = (int)(a / b);
- a -= n * b;
- if (a < 0) a += b;
- return a / b;
+ int n = (int)(a / b);
+ a -= n * b;
+ if (a < 0)
+ a += b;
+ return a / b;
}
/* creates a triangle wave */
static float tex_tri(float a)
{
- const float b = 2 * M_PI;
- const float rmax = 1.0;
+ const float b = 2 * M_PI;
+ const float rmax = 1.0;
- a = rmax - 2.0f * fabsf(floorf((a * (1.0f / b)) + 0.5f) - (a * (1.0f / b)));
+ a = rmax - 2.0f * fabsf(floorf((a * (1.0f / b)) + 0.5f) - (a * (1.0f / b)));
- return a;
+ return a;
}
/* computes basic wood intensity value at x,y,z */
static float wood_int(Tex *tex, float x, float y, float z)
{
- float wi = 0;
- short wf = tex->noisebasis2; /* wave form: TEX_SIN=0, TEX_SAW=1, TEX_TRI=2 */
- short wt = tex->stype; /* wood type: TEX_BAND=0, TEX_RING=1, TEX_BANDNOISE=2, TEX_RINGNOISE=3 */
-
- float (*waveform[3])(float); /* create array of pointers to waveform functions */
- waveform[0] = tex_sin; /* assign address of tex_sin() function to pointer array */
- waveform[1] = tex_saw;
- waveform[2] = tex_tri;
-
- if ((wf > TEX_TRI) || (wf < TEX_SIN)) wf = 0; /* check to be sure noisebasis2 is initialized ahead of time */
-
- if (wt == TEX_BAND) {
- wi = waveform[wf]((x + y + z) * 10.0f);
- }
- else if (wt == TEX_RING) {
- wi = waveform[wf](sqrtf(x * x + y * y + z * z) * 20.0f);
- }
- else if (wt == TEX_BANDNOISE) {
- wi = tex->turbul * BLI_gNoise(tex->noisesize, x, y, z, (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
- wi = waveform[wf]((x + y + z) * 10.0f + wi);
- }
- else if (wt == TEX_RINGNOISE) {
- wi = tex->turbul * BLI_gNoise(tex->noisesize, x, y, z, (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
- wi = waveform[wf](sqrtf(x * x + y * y + z * z) * 20.0f + wi);
- }
-
- return wi;
+ float wi = 0;
+ short wf =
+ tex->noisebasis2; /* wave form: TEX_SIN=0, TEX_SAW=1, TEX_TRI=2 */
+ short wt =
+ tex->stype; /* wood type: TEX_BAND=0, TEX_RING=1, TEX_BANDNOISE=2, TEX_RINGNOISE=3 */
+
+ float (*waveform[3])(float); /* create array of pointers to waveform functions */
+ waveform[0] = tex_sin; /* assign address of tex_sin() function to pointer array */
+ waveform[1] = tex_saw;
+ waveform[2] = tex_tri;
+
+ if ((wf > TEX_TRI) || (wf < TEX_SIN))
+ wf = 0; /* check to be sure noisebasis2 is initialized ahead of time */
+
+ if (wt == TEX_BAND) {
+ wi = waveform[wf]((x + y + z) * 10.0f);
+ }
+ else if (wt == TEX_RING) {
+ wi = waveform[wf](sqrtf(x * x + y * y + z * z) * 20.0f);
+ }
+ else if (wt == TEX_BANDNOISE) {
+ wi = tex->turbul *
+ BLI_gNoise(tex->noisesize, x, y, z, (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
+ wi = waveform[wf]((x + y + z) * 10.0f + wi);
+ }
+ else if (wt == TEX_RINGNOISE) {
+ wi = tex->turbul *
+ BLI_gNoise(tex->noisesize, x, y, z, (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
+ wi = waveform[wf](sqrtf(x * x + y * y + z * z) * 20.0f + wi);
+ }
+
+ return wi;
}
static int wood(Tex *tex, const float texvec[3], TexResult *texres)
{
- int rv = TEX_INT;
+ int rv = TEX_INT;
- texres->tin = wood_int(tex, texvec[0], texvec[1], texvec[2]);
- if (texres->nor != NULL) {
- /* calculate bumpnormal */
- texres->nor[0] = wood_int(tex, texvec[0] + tex->nabla, texvec[1], texvec[2]);
- texres->nor[1] = wood_int(tex, texvec[0], texvec[1] + tex->nabla, texvec[2]);
- texres->nor[2] = wood_int(tex, texvec[0], texvec[1], texvec[2] + tex->nabla);
+ texres->tin = wood_int(tex, texvec[0], texvec[1], texvec[2]);
+ if (texres->nor != NULL) {
+ /* calculate bumpnormal */
+ texres->nor[0] = wood_int(tex, texvec[0] + tex->nabla, texvec[1], texvec[2]);
+ texres->nor[1] = wood_int(tex, texvec[0], texvec[1] + tex->nabla, texvec[2]);
+ texres->nor[2] = wood_int(tex, texvec[0], texvec[1], texvec[2] + tex->nabla);
- tex_normal_derivate(tex, texres);
- rv |= TEX_NOR;
- }
+ tex_normal_derivate(tex, texres);
+ rv |= TEX_NOR;
+ }
- BRICONT;
+ BRICONT;
- return rv;
+ return rv;
}
/* computes basic marble intensity at x,y,z */
static float marble_int(Tex *tex, float x, float y, float z)
{
- float n, mi;
- short wf = tex->noisebasis2; /* wave form: TEX_SIN=0, TEX_SAW=1, TEX_TRI=2 */
- short mt = tex->stype; /* marble type: TEX_SOFT=0, TEX_SHARP=1, TEX_SHAPER=2 */
-
- float (*waveform[3])(float); /* create array of pointers to waveform functions */
- waveform[0] = tex_sin; /* assign address of tex_sin() function to pointer array */
- waveform[1] = tex_saw;
- waveform[2] = tex_tri;
-
- if ((wf > TEX_TRI) || (wf < TEX_SIN)) wf = 0; /* check to be sure noisebasis2 isn't initialized ahead of time */
-
- n = 5.0f * (x + y + z);
-
- mi = n + tex->turbul * BLI_gTurbulence(tex->noisesize, x, y, z, tex->noisedepth, (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
-
- if (mt >= TEX_SOFT) { /* TEX_SOFT always true */
- mi = waveform[wf](mi);
- if (mt == TEX_SHARP) {
- mi = sqrtf(mi);
- }
- else if (mt == TEX_SHARPER) {
- mi = sqrtf(sqrtf(mi));
- }
- }
-
- return mi;
+ float n, mi;
+ short wf = tex->noisebasis2; /* wave form: TEX_SIN=0, TEX_SAW=1, TEX_TRI=2 */
+ short mt = tex->stype; /* marble type: TEX_SOFT=0, TEX_SHARP=1, TEX_SHAPER=2 */
+
+ float (*waveform[3])(float); /* create array of pointers to waveform functions */
+ waveform[0] = tex_sin; /* assign address of tex_sin() function to pointer array */
+ waveform[1] = tex_saw;
+ waveform[2] = tex_tri;
+
+ if ((wf > TEX_TRI) || (wf < TEX_SIN))
+ wf = 0; /* check to be sure noisebasis2 isn't initialized ahead of time */
+
+ n = 5.0f * (x + y + z);
+
+ mi = n + tex->turbul * BLI_gTurbulence(tex->noisesize,
+ x,
+ y,
+ z,
+ tex->noisedepth,
+ (tex->noisetype != TEX_NOISESOFT),
+ tex->noisebasis);
+
+ if (mt >= TEX_SOFT) { /* TEX_SOFT always true */
+ mi = waveform[wf](mi);
+ if (mt == TEX_SHARP) {
+ mi = sqrtf(mi);
+ }
+ else if (mt == TEX_SHARPER) {
+ mi = sqrtf(sqrtf(mi));
+ }
+ }
+
+ return mi;
}
static int marble(Tex *tex, const float texvec[3], TexResult *texres)
{
- int rv = TEX_INT;
+ int rv = TEX_INT;
- texres->tin = marble_int(tex, texvec[0], texvec[1], texvec[2]);
+ texres->tin = marble_int(tex, texvec[0], texvec[1], texvec[2]);
- if (texres->nor != NULL) {
- /* calculate bumpnormal */
- texres->nor[0] = marble_int(tex, texvec[0] + tex->nabla, texvec[1], texvec[2]);
- texres->nor[1] = marble_int(tex, texvec[0], texvec[1] + tex->nabla, texvec[2]);
- texres->nor[2] = marble_int(tex, texvec[0], texvec[1], texvec[2] + tex->nabla);
+ if (texres->nor != NULL) {
+ /* calculate bumpnormal */
+ texres->nor[0] = marble_int(tex, texvec[0] + tex->nabla, texvec[1], texvec[2]);
+ texres->nor[1] = marble_int(tex, texvec[0], texvec[1] + tex->nabla, texvec[2]);
+ texres->nor[2] = marble_int(tex, texvec[0], texvec[1], texvec[2] + tex->nabla);
- tex_normal_derivate(tex, texres);
+ tex_normal_derivate(tex, texres);
- rv |= TEX_NOR;
- }
+ rv |= TEX_NOR;
+ }
- BRICONT;
+ BRICONT;
- return rv;
+ return rv;
}
/* ------------------------------------------------------------------------- */
static int magic(Tex *tex, const float texvec[3], TexResult *texres)
{
- float x, y, z, turb;
- int n;
-
- n = tex->noisedepth;
- turb = tex->turbul / 5.0f;
-
- x = sinf((texvec[0] + texvec[1] + texvec[2]) * 5.0f);
- y = cosf((-texvec[0] + texvec[1] - texvec[2]) * 5.0f);
- z = -cosf((-texvec[0] - texvec[1] + texvec[2]) * 5.0f);
- if (n > 0) {
- x *= turb;
- y *= turb;
- z *= turb;
- y = -cosf(x - y + z);
- y *= turb;
- if (n > 1) {
- x = cosf(x - y - z);
- x *= turb;
- if (n > 2) {
- z = sinf(-x - y - z);
- z *= turb;
- if (n > 3) {
- x = -cosf(-x + y - z);
- x *= turb;
- if (n > 4) {
- y = -sinf(-x + y + z);
- y *= turb;
- if (n > 5) {
- y = -cosf(-x + y + z);
- y *= turb;
- if (n > 6) {
- x = cosf(x + y + z);
- x *= turb;
- if (n > 7) {
- z = sinf(x + y - z);
- z *= turb;
- if (n > 8) {
- x = -cosf(-x - y + z);
- x *= turb;
- if (n > 9) {
- y = -sinf(x - y + z);
- y *= turb;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- if (turb != 0.0f) {
- turb *= 2.0f;
- x /= turb;
- y /= turb;
- z /= turb;
- }
- texres->tr = 0.5f - x;
- texres->tg = 0.5f - y;
- texres->tb = 0.5f - z;
-
- texres->tin = (1.0f / 3.0f) * (texres->tr + texres->tg + texres->tb);
-
- BRICONTRGB;
- texres->ta = 1.0f;
-
- return TEX_RGB;
+ float x, y, z, turb;
+ int n;
+
+ n = tex->noisedepth;
+ turb = tex->turbul / 5.0f;
+
+ x = sinf((texvec[0] + texvec[1] + texvec[2]) * 5.0f);
+ y = cosf((-texvec[0] + texvec[1] - texvec[2]) * 5.0f);
+ z = -cosf((-texvec[0] - texvec[1] + texvec[2]) * 5.0f);
+ if (n > 0) {
+ x *= turb;
+ y *= turb;
+ z *= turb;
+ y = -cosf(x - y + z);
+ y *= turb;
+ if (n > 1) {
+ x = cosf(x - y - z);
+ x *= turb;
+ if (n > 2) {
+ z = sinf(-x - y - z);
+ z *= turb;
+ if (n > 3) {
+ x = -cosf(-x + y - z);
+ x *= turb;
+ if (n > 4) {
+ y = -sinf(-x + y + z);
+ y *= turb;
+ if (n > 5) {
+ y = -cosf(-x + y + z);
+ y *= turb;
+ if (n > 6) {
+ x = cosf(x + y + z);
+ x *= turb;
+ if (n > 7) {
+ z = sinf(x + y - z);
+ z *= turb;
+ if (n > 8) {
+ x = -cosf(-x - y + z);
+ x *= turb;
+ if (n > 9) {
+ y = -sinf(x - y + z);
+ y *= turb;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (turb != 0.0f) {
+ turb *= 2.0f;
+ x /= turb;
+ y /= turb;
+ z /= turb;
+ }
+ texres->tr = 0.5f - x;
+ texres->tg = 0.5f - y;
+ texres->tb = 0.5f - z;
+
+ texres->tin = (1.0f / 3.0f) * (texres->tr + texres->tg + texres->tb);
+
+ BRICONTRGB;
+ texres->ta = 1.0f;
+
+ return TEX_RGB;
}
/* ------------------------------------------------------------------------- */
@@ -409,41 +457,62 @@ static int magic(Tex *tex, const float texvec[3], TexResult *texres)
/* newnoise: stucci also modified to use different noisebasis */
static int stucci(Tex *tex, const float texvec[3], TexResult *texres)
{
- float nor[3], b2, ofs;
- int retval = TEX_INT;
-
- b2 = BLI_gNoise(tex->noisesize, texvec[0], texvec[1], texvec[2], (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
-
- ofs = tex->turbul / 200.0f;
-
- if (tex->stype) ofs *= (b2 * b2);
- nor[0] = BLI_gNoise(tex->noisesize, texvec[0] + ofs, texvec[1], texvec[2], (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
- nor[1] = BLI_gNoise(tex->noisesize, texvec[0], texvec[1] + ofs, texvec[2], (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
- nor[2] = BLI_gNoise(tex->noisesize, texvec[0], texvec[1], texvec[2] + ofs, (tex->noisetype != TEX_NOISESOFT), tex->noisebasis);
-
- texres->tin = nor[2];
-
- if (texres->nor) {
-
- copy_v3_v3(texres->nor, nor);
- tex_normal_derivate(tex, texres);
-
- if (tex->stype == TEX_WALLOUT) {
- texres->nor[0] = -texres->nor[0];
- texres->nor[1] = -texres->nor[1];
- texres->nor[2] = -texres->nor[2];
- }
-
- retval |= TEX_NOR;
- }
-
- if (tex->stype == TEX_WALLOUT)
- texres->tin = 1.0f - texres->tin;
-
- if (texres->tin < 0.0f)
- texres->tin = 0.0f;
-
- return retval;
+ float nor[3], b2, ofs;
+ int retval = TEX_INT;
+
+ b2 = BLI_gNoise(tex->noisesize,
+ texvec[0],
+ texvec[1],
+ texvec[2],
+ (tex->noisetype != TEX_NOISESOFT),
+ tex->noisebasis);
+
+ ofs = tex->turbul / 200.0f;
+
+ if (tex->stype)
+ ofs *= (b2 * b2);
+ nor[0] = BLI_gNoise(tex->noisesize,
+ texvec[0] + ofs,
+ texvec[1],
+ texvec[2],
+ (tex->noisetype != TEX_NOISESOFT),
+ tex->noisebasis);
+ nor[1] = BLI_gNoise(tex->noisesize,
+ texvec[0],
+ texvec[1] + ofs,
+ texvec[2],
+ (tex->noisetype != TEX_NOISESOFT),
+ tex->noisebasis);
+ nor[2] = BLI_gNoise(tex->noisesize,
+ texvec[0],
+ texvec[1],
+ texvec[2] + ofs,
+ (tex->noisetype != TEX_NOISESOFT),
+ tex->noisebasis);
+
+ texres->tin = nor[2];
+
+ if (texres->nor) {
+
+ copy_v3_v3(texres->nor, nor);
+ tex_normal_derivate(tex, texres);
+
+ if (tex->stype == TEX_WALLOUT) {
+ texres->nor[0] = -texres->nor[0];
+ texres->nor[1] = -texres->nor[1];
+ texres->nor[2] = -texres->nor[2];
+ }
+
+ retval |= TEX_NOR;
+ }
+
+ if (tex->stype == TEX_WALLOUT)
+ texres->tin = 1.0f - texres->tin;
+
+ if (texres->tin < 0.0f)
+ texres->tin = 0.0f;
+
+ return retval;
}
/* ------------------------------------------------------------------------- */
@@ -451,253 +520,355 @@ static int stucci(Tex *tex, const float texvec[3], TexResult *texres)
static float mg_mFractalOrfBmTex(Tex *tex, const float texvec[3], TexResult *texres)
{
- int rv = TEX_INT;
- float (*mgravefunc)(float, float, float, float, float, float, int);
-
- if (tex->stype == TEX_MFRACTAL)
- mgravefunc = mg_MultiFractal;
- else
- mgravefunc = mg_fBm;
-
- texres->tin = tex->ns_outscale * mgravefunc(texvec[0], texvec[1], texvec[2], tex->mg_H, tex->mg_lacunarity, tex->mg_octaves, tex->noisebasis);
-
- if (texres->nor != NULL) {
- float offs = tex->nabla / tex->noisesize; /* also scaling of texvec */
-
- /* calculate bumpnormal */
- texres->nor[0] = tex->ns_outscale * mgravefunc(texvec[0] + offs, texvec[1], texvec[2], tex->mg_H, tex->mg_lacunarity, tex->mg_octaves, tex->noisebasis);
- texres->nor[1] = tex->ns_outscale * mgravefunc(texvec[0], texvec[1] + offs, texvec[2], tex->mg_H, tex->mg_lacunarity, tex->mg_octaves, tex->noisebasis);
- texres->nor[2] = tex->ns_outscale * mgravefunc(texvec[0], texvec[1], texvec[2] + offs, tex->mg_H, tex->mg_lacunarity, tex->mg_octaves, tex->noisebasis);
-
- tex_normal_derivate(tex, texres);
- rv |= TEX_NOR;
- }
-
- BRICONT;
-
- return rv;
-
+ int rv = TEX_INT;
+ float (*mgravefunc)(float, float, float, float, float, float, int);
+
+ if (tex->stype == TEX_MFRACTAL)
+ mgravefunc = mg_MultiFractal;
+ else
+ mgravefunc = mg_fBm;
+
+ texres->tin = tex->ns_outscale * mgravefunc(texvec[0],
+ texvec[1],
+ texvec[2],
+ tex->mg_H,
+ tex->mg_lacunarity,
+ tex->mg_octaves,
+ tex->noisebasis);
+
+ if (texres->nor != NULL) {
+ float offs = tex->nabla / tex->noisesize; /* also scaling of texvec */
+
+ /* calculate bumpnormal */
+ texres->nor[0] = tex->ns_outscale * mgravefunc(texvec[0] + offs,
+ texvec[1],
+ texvec[2],
+ tex->mg_H,
+ tex->mg_lacunarity,
+ tex->mg_octaves,
+ tex->noisebasis);
+ texres->nor[1] = tex->ns_outscale * mgravefunc(texvec[0],
+ texvec[1] + offs,
+ texvec[2],
+ tex->mg_H,
+ tex->mg_lacunarity,
+ tex->mg_octaves,
+ tex->noisebasis);
+ texres->nor[2] = tex->ns_outscale * mgravefunc(texvec[0],
+ texvec[1],
+ texvec[2] + offs,
+ tex->mg_H,
+ tex->mg_lacunarity,
+ tex->mg_octaves,
+ tex->noisebasis);
+
+ tex_normal_derivate(tex, texres);
+ rv |= TEX_NOR;
+ }
+
+ BRICONT;
+
+ return rv;
}
static float mg_ridgedOrHybridMFTex(Tex *tex, const float texvec[3], TexResult *texres)
{
- int rv = TEX_INT;
- float (*mgravefunc)(float, float, float, float, float, float, float, float, int);
-
- if (tex->stype == TEX_RIDGEDMF)
- mgravefunc = mg_RidgedMultiFractal;
- else
- mgravefunc = mg_HybridMultiFractal;
-
- texres->tin = tex->ns_outscale * mgravefunc(texvec[0], texvec[1], texvec[2], tex->mg_H, tex->mg_lacunarity, tex->mg_octaves, tex->mg_offset, tex->mg_gain, tex->noisebasis);
-
- if (texres->nor != NULL) {
- float offs = tex->nabla / tex->noisesize; /* also scaling of texvec */
-
- /* calculate bumpnormal */
- texres->nor[0] = tex->ns_outscale * mgravefunc(texvec[0] + offs, texvec[1], texvec[2], tex->mg_H, tex->mg_lacunarity, tex->mg_octaves, tex->mg_offset, tex->mg_gain, tex->noisebasis);
- texres->nor[1] = tex->ns_outscale * mgravefunc(texvec[0], texvec[1] + offs, texvec[2], tex->mg_H, tex->mg_lacunarity, tex->mg_octaves, tex->mg_offset, tex->mg_gain, tex->noisebasis);
- texres->nor[2] = tex->ns_outscale * mgravefunc(texvec[0], texvec[1], texvec[2] + offs, tex->mg_H, tex->mg_lacunarity, tex->mg_octaves, tex->mg_offset, tex->mg_gain, tex->noisebasis);
-
- tex_normal_derivate(tex, texres);
- rv |= TEX_NOR;
- }
-
- BRICONT;
-
- return rv;
-
+ int rv = TEX_INT;
+ float (*mgravefunc)(float, float, float, float, float, float, float, float, int);
+
+ if (tex->stype == TEX_RIDGEDMF)
+ mgravefunc = mg_RidgedMultiFractal;
+ else
+ mgravefunc = mg_HybridMultiFractal;
+
+ texres->tin = tex->ns_outscale * mgravefunc(texvec[0],
+ texvec[1],
+ texvec[2],
+ tex->mg_H,
+ tex->mg_lacunarity,
+ tex->mg_octaves,
+ tex->mg_offset,
+ tex->mg_gain,
+ tex->noisebasis);
+
+ if (texres->nor != NULL) {
+ float offs = tex->nabla / tex->noisesize; /* also scaling of texvec */
+
+ /* calculate bumpnormal */
+ texres->nor[0] = tex->ns_outscale * mgravefunc(texvec[0] + offs,
+ texvec[1],
+ texvec[2],
+ tex->mg_H,
+ tex->mg_lacunarity,
+ tex->mg_octaves,
+ tex->mg_offset,
+ tex->mg_gain,
+ tex->noisebasis);
+ texres->nor[1] = tex->ns_outscale * mgravefunc(texvec[0],
+ texvec[1] + offs,
+ texvec[2],
+ tex->mg_H,
+ tex->mg_lacunarity,
+ tex->mg_octaves,
+ tex->mg_offset,
+ tex->mg_gain,
+ tex->noisebasis);
+ texres->nor[2] = tex->ns_outscale * mgravefunc(texvec[0],
+ texvec[1],
+ texvec[2] + offs,
+ tex->mg_H,
+ tex->mg_lacunarity,
+ tex->mg_octaves,
+ tex->mg_offset,
+ tex->mg_gain,
+ tex->noisebasis);
+
+ tex_normal_derivate(tex, texres);
+ rv |= TEX_NOR;
+ }
+
+ BRICONT;
+
+ return rv;
}
-
static float mg_HTerrainTex(Tex *tex, const float texvec[3], TexResult *texres)
{
- int rv = TEX_INT;
-
- texres->tin = tex->ns_outscale * mg_HeteroTerrain(texvec[0], texvec[1], texvec[2], tex->mg_H, tex->mg_lacunarity, tex->mg_octaves, tex->mg_offset, tex->noisebasis);
-
- if (texres->nor != NULL) {
- float offs = tex->nabla / tex->noisesize; /* also scaling of texvec */
-
- /* calculate bumpnormal */
- texres->nor[0] = tex->ns_outscale * mg_HeteroTerrain(texvec[0] + offs, texvec[1], texvec[2], tex->mg_H, tex->mg_lacunarity, tex->mg_octaves, tex->mg_offset, tex->noisebasis);
- texres->nor[1] = tex->ns_outscale * mg_HeteroTerrain(texvec[0], texvec[1] + offs, texvec[2], tex->mg_H, tex->mg_lacunarity, tex->mg_octaves, tex->mg_offset, tex->noisebasis);
- texres->nor[2] = tex->ns_outscale * mg_HeteroTerrain(texvec[0], texvec[1], texvec[2] + offs, tex->mg_H, tex->mg_lacunarity, tex->mg_octaves, tex->mg_offset, tex->noisebasis);
-
- tex_normal_derivate(tex, texres);
- rv |= TEX_NOR;
- }
-
- BRICONT;
-
- return rv;
-
+ int rv = TEX_INT;
+
+ texres->tin = tex->ns_outscale * mg_HeteroTerrain(texvec[0],
+ texvec[1],
+ texvec[2],
+ tex->mg_H,
+ tex->mg_lacunarity,
+ tex->mg_octaves,
+ tex->mg_offset,
+ tex->noisebasis);
+
+ if (texres->nor != NULL) {
+ float offs = tex->nabla / tex->noisesize; /* also scaling of texvec */
+
+ /* calculate bumpnormal */
+ texres->nor[0] = tex->ns_outscale * mg_HeteroTerrain(texvec[0] + offs,
+ texvec[1],
+ texvec[2],
+ tex->mg_H,
+ tex->mg_lacunarity,
+ tex->mg_octaves,
+ tex->mg_offset,
+ tex->noisebasis);
+ texres->nor[1] = tex->ns_outscale * mg_HeteroTerrain(texvec[0],
+ texvec[1] + offs,
+ texvec[2],
+ tex->mg_H,
+ tex->mg_lacunarity,
+ tex->mg_octaves,
+ tex->mg_offset,
+ tex->noisebasis);
+ texres->nor[2] = tex->ns_outscale * mg_HeteroTerrain(texvec[0],
+ texvec[1],
+ texvec[2] + offs,
+ tex->mg_H,
+ tex->mg_lacunarity,
+ tex->mg_octaves,
+ tex->mg_offset,
+ tex->noisebasis);
+
+ tex_normal_derivate(tex, texres);
+ rv |= TEX_NOR;
+ }
+
+ BRICONT;
+
+ return rv;
}
-
static float mg_distNoiseTex(Tex *tex, const float texvec[3], TexResult *texres)
{
- int rv = TEX_INT;
-
- texres->tin = mg_VLNoise(texvec[0], texvec[1], texvec[2], tex->dist_amount, tex->noisebasis, tex->noisebasis2);
-
- if (texres->nor != NULL) {
- float offs = tex->nabla / tex->noisesize; /* also scaling of texvec */
-
- /* calculate bumpnormal */
- texres->nor[0] = mg_VLNoise(texvec[0] + offs, texvec[1], texvec[2], tex->dist_amount, tex->noisebasis, tex->noisebasis2);
- texres->nor[1] = mg_VLNoise(texvec[0], texvec[1] + offs, texvec[2], tex->dist_amount, tex->noisebasis, tex->noisebasis2);
- texres->nor[2] = mg_VLNoise(texvec[0], texvec[1], texvec[2] + offs, tex->dist_amount, tex->noisebasis, tex->noisebasis2);
-
- tex_normal_derivate(tex, texres);
- rv |= TEX_NOR;
- }
-
- BRICONT;
-
-
- return rv;
-
+ int rv = TEX_INT;
+
+ texres->tin = mg_VLNoise(
+ texvec[0], texvec[1], texvec[2], tex->dist_amount, tex->noisebasis, tex->noisebasis2);
+
+ if (texres->nor != NULL) {
+ float offs = tex->nabla / tex->noisesize; /* also scaling of texvec */
+
+ /* calculate bumpnormal */
+ texres->nor[0] = mg_VLNoise(texvec[0] + offs,
+ texvec[1],
+ texvec[2],
+ tex->dist_amount,
+ tex->noisebasis,
+ tex->noisebasis2);
+ texres->nor[1] = mg_VLNoise(texvec[0],
+ texvec[1] + offs,
+ texvec[2],
+ tex->dist_amount,
+ tex->noisebasis,
+ tex->noisebasis2);
+ texres->nor[2] = mg_VLNoise(texvec[0],
+ texvec[1],
+ texvec[2] + offs,
+ tex->dist_amount,
+ tex->noisebasis,
+ tex->noisebasis2);
+
+ tex_normal_derivate(tex, texres);
+ rv |= TEX_NOR;
+ }
+
+ BRICONT;
+
+ return rv;
}
-
/* ------------------------------------------------------------------------- */
/* newnoise: Voronoi texture type, probably the slowest, especially with minkovsky, bumpmapping, could be done another way */
static float voronoiTex(Tex *tex, const float texvec[3], TexResult *texres)
{
- int rv = TEX_INT;
- float da[4], pa[12]; /* distance and point coordinate arrays of 4 nearest neighbors */
- float aw1 = fabsf(tex->vn_w1);
- float aw2 = fabsf(tex->vn_w2);
- float aw3 = fabsf(tex->vn_w3);
- float aw4 = fabsf(tex->vn_w4);
- float sc = (aw1 + aw2 + aw3 + aw4);
- if (sc != 0.f) sc = tex->ns_outscale / sc;
-
- voronoi(texvec[0], texvec[1], texvec[2], da, pa, tex->vn_mexp, tex->vn_distm);
- texres->tin = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] + tex->vn_w4 * da[3]);
-
- if (tex->vn_coltype) {
- float ca[3]; /* cell color */
- cellNoiseV(pa[0], pa[1], pa[2], ca);
- texres->tr = aw1 * ca[0];
- texres->tg = aw1 * ca[1];
- texres->tb = aw1 * ca[2];
- cellNoiseV(pa[3], pa[4], pa[5], ca);
- texres->tr += aw2 * ca[0];
- texres->tg += aw2 * ca[1];
- texres->tb += aw2 * ca[2];
- cellNoiseV(pa[6], pa[7], pa[8], ca);
- texres->tr += aw3 * ca[0];
- texres->tg += aw3 * ca[1];
- texres->tb += aw3 * ca[2];
- cellNoiseV(pa[9], pa[10], pa[11], ca);
- texres->tr += aw4 * ca[0];
- texres->tg += aw4 * ca[1];
- texres->tb += aw4 * ca[2];
- if (tex->vn_coltype >= 2) {
- float t1 = (da[1] - da[0]) * 10;
- if (t1 > 1) t1 = 1;
- if (tex->vn_coltype == 3) t1 *= texres->tin; else t1 *= sc;
- texres->tr *= t1;
- texres->tg *= t1;
- texres->tb *= t1;
- }
- else {
- texres->tr *= sc;
- texres->tg *= sc;
- texres->tb *= sc;
- }
- }
-
- if (texres->nor != NULL) {
- float offs = tex->nabla / tex->noisesize; /* also scaling of texvec */
-
- /* calculate bumpnormal */
- voronoi(texvec[0] + offs, texvec[1], texvec[2], da, pa, tex->vn_mexp, tex->vn_distm);
- texres->nor[0] = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] + tex->vn_w4 * da[3]);
- voronoi(texvec[0], texvec[1] + offs, texvec[2], da, pa, tex->vn_mexp, tex->vn_distm);
- texres->nor[1] = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] + tex->vn_w4 * da[3]);
- voronoi(texvec[0], texvec[1], texvec[2] + offs, da, pa, tex->vn_mexp, tex->vn_distm);
- texres->nor[2] = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] + tex->vn_w4 * da[3]);
-
- tex_normal_derivate(tex, texres);
- rv |= TEX_NOR;
- }
-
- if (tex->vn_coltype) {
- BRICONTRGB;
- texres->ta = 1.0;
- return (rv | TEX_RGB);
- }
-
- BRICONT;
-
- return rv;
-
+ int rv = TEX_INT;
+ float da[4], pa[12]; /* distance and point coordinate arrays of 4 nearest neighbors */
+ float aw1 = fabsf(tex->vn_w1);
+ float aw2 = fabsf(tex->vn_w2);
+ float aw3 = fabsf(tex->vn_w3);
+ float aw4 = fabsf(tex->vn_w4);
+ float sc = (aw1 + aw2 + aw3 + aw4);
+ if (sc != 0.f)
+ sc = tex->ns_outscale / sc;
+
+ voronoi(texvec[0], texvec[1], texvec[2], da, pa, tex->vn_mexp, tex->vn_distm);
+ texres->tin = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] +
+ tex->vn_w4 * da[3]);
+
+ if (tex->vn_coltype) {
+ float ca[3]; /* cell color */
+ cellNoiseV(pa[0], pa[1], pa[2], ca);
+ texres->tr = aw1 * ca[0];
+ texres->tg = aw1 * ca[1];
+ texres->tb = aw1 * ca[2];
+ cellNoiseV(pa[3], pa[4], pa[5], ca);
+ texres->tr += aw2 * ca[0];
+ texres->tg += aw2 * ca[1];
+ texres->tb += aw2 * ca[2];
+ cellNoiseV(pa[6], pa[7], pa[8], ca);
+ texres->tr += aw3 * ca[0];
+ texres->tg += aw3 * ca[1];
+ texres->tb += aw3 * ca[2];
+ cellNoiseV(pa[9], pa[10], pa[11], ca);
+ texres->tr += aw4 * ca[0];
+ texres->tg += aw4 * ca[1];
+ texres->tb += aw4 * ca[2];
+ if (tex->vn_coltype >= 2) {
+ float t1 = (da[1] - da[0]) * 10;
+ if (t1 > 1)
+ t1 = 1;
+ if (tex->vn_coltype == 3)
+ t1 *= texres->tin;
+ else
+ t1 *= sc;
+ texres->tr *= t1;
+ texres->tg *= t1;
+ texres->tb *= t1;
+ }
+ else {
+ texres->tr *= sc;
+ texres->tg *= sc;
+ texres->tb *= sc;
+ }
+ }
+
+ if (texres->nor != NULL) {
+ float offs = tex->nabla / tex->noisesize; /* also scaling of texvec */
+
+ /* calculate bumpnormal */
+ voronoi(texvec[0] + offs, texvec[1], texvec[2], da, pa, tex->vn_mexp, tex->vn_distm);
+ texres->nor[0] = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] +
+ tex->vn_w4 * da[3]);
+ voronoi(texvec[0], texvec[1] + offs, texvec[2], da, pa, tex->vn_mexp, tex->vn_distm);
+ texres->nor[1] = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] +
+ tex->vn_w4 * da[3]);
+ voronoi(texvec[0], texvec[1], texvec[2] + offs, da, pa, tex->vn_mexp, tex->vn_distm);
+ texres->nor[2] = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] +
+ tex->vn_w4 * da[3]);
+
+ tex_normal_derivate(tex, texres);
+ rv |= TEX_NOR;
+ }
+
+ if (tex->vn_coltype) {
+ BRICONTRGB;
+ texres->ta = 1.0;
+ return (rv | TEX_RGB);
+ }
+
+ BRICONT;
+
+ return rv;
}
/* ------------------------------------------------------------------------- */
static int texnoise(Tex *tex, TexResult *texres, int thread)
{
- float div = 3.0;
- int val, ran, loop, shift = 29;
+ float div = 3.0;
+ int val, ran, loop, shift = 29;
- ran = BLI_rng_thread_rand(random_tex_array, thread);
+ ran = BLI_rng_thread_rand(random_tex_array, thread);
- loop = tex->noisedepth;
+ loop = tex->noisedepth;
- /* start from top bits since they have more variance */
- val = ((ran >> shift) & 3);
+ /* start from top bits since they have more variance */
+ val = ((ran >> shift) & 3);
- while (loop--) {
- shift -= 2;
- val *= ((ran >> shift) & 3);
- div *= 3.0f;
- }
+ while (loop--) {
+ shift -= 2;
+ val *= ((ran >> shift) & 3);
+ div *= 3.0f;
+ }
- texres->tin = ((float)val) / div;
+ texres->tin = ((float)val) / div;
- BRICONT;
- return TEX_INT;
+ BRICONT;
+ return TEX_INT;
}
/* ------------------------------------------------------------------------- */
static int cubemap_glob(const float n[3], float x, float y, float z, float *adr1, float *adr2)
{
- float x1, y1, z1, nor[3];
- int ret;
-
- if (n == NULL) {
- nor[0] = x; nor[1] = y; nor[2] = z; /* use local render coord */
- }
- else {
- copy_v3_v3(nor, n);
- }
-
- x1 = fabsf(nor[0]);
- y1 = fabsf(nor[1]);
- z1 = fabsf(nor[2]);
-
- if (z1 >= x1 && z1 >= y1) {
- *adr1 = (x + 1.0f) / 2.0f;
- *adr2 = (y + 1.0f) / 2.0f;
- ret = 0;
- }
- else if (y1 >= x1 && y1 >= z1) {
- *adr1 = (x + 1.0f) / 2.0f;
- *adr2 = (z + 1.0f) / 2.0f;
- ret = 1;
- }
- else {
- *adr1 = (y + 1.0f) / 2.0f;
- *adr2 = (z + 1.0f) / 2.0f;
- ret = 2;
- }
- return ret;
+ float x1, y1, z1, nor[3];
+ int ret;
+
+ if (n == NULL) {
+ nor[0] = x;
+ nor[1] = y;
+ nor[2] = z; /* use local render coord */
+ }
+ else {
+ copy_v3_v3(nor, n);
+ }
+
+ x1 = fabsf(nor[0]);
+ y1 = fabsf(nor[1]);
+ z1 = fabsf(nor[2]);
+
+ if (z1 >= x1 && z1 >= y1) {
+ *adr1 = (x + 1.0f) / 2.0f;
+ *adr2 = (y + 1.0f) / 2.0f;
+ ret = 0;
+ }
+ else if (y1 >= x1 && y1 >= z1) {
+ *adr1 = (x + 1.0f) / 2.0f;
+ *adr2 = (z + 1.0f) / 2.0f;
+ ret = 1;
+ }
+ else {
+ *adr1 = (y + 1.0f) / 2.0f;
+ *adr2 = (z + 1.0f) / 2.0f;
+ ret = 2;
+ }
+ return ret;
}
/* ------------------------------------------------------------------------- */
@@ -705,232 +876,246 @@ static int cubemap_glob(const float n[3], float x, float y, float z, float *adr1
/* ------------------------------------------------------------------------- */
static void do_2d_mapping(
- const MTex *mtex, float texvec[3], const float n[3], float dxt[3], float dyt[3])
+ const MTex *mtex, float texvec[3], const float n[3], float dxt[3], float dyt[3])
{
- Tex *tex;
- float fx, fy, fac1, area[8];
- int ok, proj, areaflag = 0, wrap;
-
- /* mtex variables localized, only cubemap doesn't cooperate yet... */
- wrap = mtex->mapping;
- tex = mtex->tex;
-
- if (!(dxt && dyt)) {
-
- if (wrap == MTEX_FLAT) {
- fx = (texvec[0] + 1.0f) / 2.0f;
- fy = (texvec[1] + 1.0f) / 2.0f;
- }
- else if (wrap == MTEX_TUBE) map_to_tube(&fx, &fy, texvec[0], texvec[1], texvec[2]);
- else if (wrap == MTEX_SPHERE) map_to_sphere(&fx, &fy, texvec[0], texvec[1], texvec[2]);
- else {
- cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy);
- }
-
- /* repeat */
- if (tex->extend == TEX_REPEAT) {
- if (tex->xrepeat > 1) {
- float origf = fx *= tex->xrepeat;
-
- if (fx > 1.0f) fx -= (int)(fx);
- else if (fx < 0.0f) fx += 1 - (int)(fx);
-
- if (tex->flag & TEX_REPEAT_XMIR) {
- int orig = (int)floor(origf);
- if (orig & 1)
- fx = 1.0f - fx;
- }
- }
- if (tex->yrepeat > 1) {
- float origf = fy *= tex->yrepeat;
-
- if (fy > 1.0f) fy -= (int)(fy);
- else if (fy < 0.0f) fy += 1 - (int)(fy);
-
- if (tex->flag & TEX_REPEAT_YMIR) {
- int orig = (int)floor(origf);
- if (orig & 1)
- fy = 1.0f - fy;
- }
- }
- }
- /* crop */
- if (tex->cropxmin != 0.0f || tex->cropxmax != 1.0f) {
- fac1 = tex->cropxmax - tex->cropxmin;
- fx = tex->cropxmin + fx * fac1;
- }
- if (tex->cropymin != 0.0f || tex->cropymax != 1.0f) {
- fac1 = tex->cropymax - tex->cropymin;
- fy = tex->cropymin + fy * fac1;
- }
-
- texvec[0] = fx;
- texvec[1] = fy;
- }
- else {
-
- if (wrap == MTEX_FLAT) {
- fx = (texvec[0] + 1.0f) / 2.0f;
- fy = (texvec[1] + 1.0f) / 2.0f;
- dxt[0] /= 2.0f;
- dxt[1] /= 2.0f;
- dxt[2] /= 2.0f;
- dyt[0] /= 2.0f;
- dyt[1] /= 2.0f;
- dyt[2] /= 2.0f;
- }
- else if (ELEM(wrap, MTEX_TUBE, MTEX_SPHERE)) {
- /* exception: the seam behind (y<0.0) */
- ok = 1;
- if (texvec[1] <= 0.0f) {
- fx = texvec[0] + dxt[0];
- fy = texvec[0] + dyt[0];
- if (fx >= 0.0f && fy >= 0.0f && texvec[0] >= 0.0f) {
- /* pass */
- }
- else if (fx <= 0.0f && fy <= 0.0f && texvec[0] <= 0.0f) {
- /* pass */
- }
- else {
- ok = 0;
- }
- }
-
- if (ok) {
- if (wrap == MTEX_TUBE) {
- map_to_tube(area, area + 1, texvec[0], texvec[1], texvec[2]);
- map_to_tube(area + 2, area + 3, texvec[0] + dxt[0], texvec[1] + dxt[1], texvec[2] + dxt[2]);
- map_to_tube(area + 4, area + 5, texvec[0] + dyt[0], texvec[1] + dyt[1], texvec[2] + dyt[2]);
- }
- else {
- map_to_sphere(area, area + 1, texvec[0], texvec[1], texvec[2]);
- map_to_sphere(area + 2, area + 3, texvec[0] + dxt[0], texvec[1] + dxt[1], texvec[2] + dxt[2]);
- map_to_sphere(area + 4, area + 5, texvec[0] + dyt[0], texvec[1] + dyt[1], texvec[2] + dyt[2]);
- }
- areaflag = 1;
- }
- else {
- if (wrap == MTEX_TUBE) map_to_tube(&fx, &fy, texvec[0], texvec[1], texvec[2]);
- else map_to_sphere(&fx, &fy, texvec[0], texvec[1], texvec[2]);
- dxt[0] /= 2.0f;
- dxt[1] /= 2.0f;
- dyt[0] /= 2.0f;
- dyt[1] /= 2.0f;
- }
- }
- else {
-
- proj = cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy);
-
- if (proj == 1) {
- SWAP(float, dxt[1], dxt[2]);
- SWAP(float, dyt[1], dyt[2]);
- }
- else if (proj == 2) {
- float f1 = dxt[0], f2 = dyt[0];
- dxt[0] = dxt[1];
- dyt[0] = dyt[1];
- dxt[1] = dxt[2];
- dyt[1] = dyt[2];
- dxt[2] = f1;
- dyt[2] = f2;
- }
-
- dxt[0] *= 0.5f;
- dxt[1] *= 0.5f;
- dxt[2] *= 0.5f;
-
- dyt[0] *= 0.5f;
- dyt[1] *= 0.5f;
- dyt[2] *= 0.5f;
-
- }
-
- /* if area, then reacalculate dxt[] and dyt[] */
- if (areaflag) {
- fx = area[0];
- fy = area[1];
- dxt[0] = area[2] - fx;
- dxt[1] = area[3] - fy;
- dyt[0] = area[4] - fx;
- dyt[1] = area[5] - fy;
- }
-
- /* repeat */
- if (tex->extend == TEX_REPEAT) {
- float max = 1.0f;
- if (tex->xrepeat > 1) {
- float origf = fx *= tex->xrepeat;
-
- /* TXF: omit mirror here, see comments in do_material_tex() after do_2d_mapping() call */
- if (tex->texfilter == TXF_BOX) {
- if (fx > 1.0f) fx -= (int)(fx);
- else if (fx < 0.0f) fx += 1 - (int)(fx);
-
- if (tex->flag & TEX_REPEAT_XMIR) {
- int orig = (int)floor(origf);
- if (orig & 1)
- fx = 1.0f - fx;
- }
- }
-
- max = tex->xrepeat;
-
- dxt[0] *= tex->xrepeat;
- dyt[0] *= tex->xrepeat;
- }
- if (tex->yrepeat > 1) {
- float origf = fy *= tex->yrepeat;
-
- /* TXF: omit mirror here, see comments in do_material_tex() after do_2d_mapping() call */
- if (tex->texfilter == TXF_BOX) {
- if (fy > 1.0f) fy -= (int)(fy);
- else if (fy < 0.0f) fy += 1 - (int)(fy);
-
- if (tex->flag & TEX_REPEAT_YMIR) {
- int orig = (int)floor(origf);
- if (orig & 1)
- fy = 1.0f - fy;
- }
- }
-
- if (max < tex->yrepeat)
- max = tex->yrepeat;
-
- dxt[1] *= tex->yrepeat;
- dyt[1] *= tex->yrepeat;
- }
- if (max != 1.0f) {
- dxt[2] *= max;
- dyt[2] *= max;
- }
-
- }
- /* crop */
- if (tex->cropxmin != 0.0f || tex->cropxmax != 1.0f) {
- fac1 = tex->cropxmax - tex->cropxmin;
- fx = tex->cropxmin + fx * fac1;
- dxt[0] *= fac1;
- dyt[0] *= fac1;
- }
- if (tex->cropymin != 0.0f || tex->cropymax != 1.0f) {
- fac1 = tex->cropymax - tex->cropymin;
- fy = tex->cropymin + fy * fac1;
- dxt[1] *= fac1;
- dyt[1] *= fac1;
- }
-
- texvec[0] = fx;
- texvec[1] = fy;
-
- }
+ Tex *tex;
+ float fx, fy, fac1, area[8];
+ int ok, proj, areaflag = 0, wrap;
+
+ /* mtex variables localized, only cubemap doesn't cooperate yet... */
+ wrap = mtex->mapping;
+ tex = mtex->tex;
+
+ if (!(dxt && dyt)) {
+
+ if (wrap == MTEX_FLAT) {
+ fx = (texvec[0] + 1.0f) / 2.0f;
+ fy = (texvec[1] + 1.0f) / 2.0f;
+ }
+ else if (wrap == MTEX_TUBE)
+ map_to_tube(&fx, &fy, texvec[0], texvec[1], texvec[2]);
+ else if (wrap == MTEX_SPHERE)
+ map_to_sphere(&fx, &fy, texvec[0], texvec[1], texvec[2]);
+ else {
+ cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy);
+ }
+
+ /* repeat */
+ if (tex->extend == TEX_REPEAT) {
+ if (tex->xrepeat > 1) {
+ float origf = fx *= tex->xrepeat;
+
+ if (fx > 1.0f)
+ fx -= (int)(fx);
+ else if (fx < 0.0f)
+ fx += 1 - (int)(fx);
+
+ if (tex->flag & TEX_REPEAT_XMIR) {
+ int orig = (int)floor(origf);
+ if (orig & 1)
+ fx = 1.0f - fx;
+ }
+ }
+ if (tex->yrepeat > 1) {
+ float origf = fy *= tex->yrepeat;
+
+ if (fy > 1.0f)
+ fy -= (int)(fy);
+ else if (fy < 0.0f)
+ fy += 1 - (int)(fy);
+
+ if (tex->flag & TEX_REPEAT_YMIR) {
+ int orig = (int)floor(origf);
+ if (orig & 1)
+ fy = 1.0f - fy;
+ }
+ }
+ }
+ /* crop */
+ if (tex->cropxmin != 0.0f || tex->cropxmax != 1.0f) {
+ fac1 = tex->cropxmax - tex->cropxmin;
+ fx = tex->cropxmin + fx * fac1;
+ }
+ if (tex->cropymin != 0.0f || tex->cropymax != 1.0f) {
+ fac1 = tex->cropymax - tex->cropymin;
+ fy = tex->cropymin + fy * fac1;
+ }
+
+ texvec[0] = fx;
+ texvec[1] = fy;
+ }
+ else {
+
+ if (wrap == MTEX_FLAT) {
+ fx = (texvec[0] + 1.0f) / 2.0f;
+ fy = (texvec[1] + 1.0f) / 2.0f;
+ dxt[0] /= 2.0f;
+ dxt[1] /= 2.0f;
+ dxt[2] /= 2.0f;
+ dyt[0] /= 2.0f;
+ dyt[1] /= 2.0f;
+ dyt[2] /= 2.0f;
+ }
+ else if (ELEM(wrap, MTEX_TUBE, MTEX_SPHERE)) {
+ /* exception: the seam behind (y<0.0) */
+ ok = 1;
+ if (texvec[1] <= 0.0f) {
+ fx = texvec[0] + dxt[0];
+ fy = texvec[0] + dyt[0];
+ if (fx >= 0.0f && fy >= 0.0f && texvec[0] >= 0.0f) {
+ /* pass */
+ }
+ else if (fx <= 0.0f && fy <= 0.0f && texvec[0] <= 0.0f) {
+ /* pass */
+ }
+ else {
+ ok = 0;
+ }
+ }
+
+ if (ok) {
+ if (wrap == MTEX_TUBE) {
+ map_to_tube(area, area + 1, texvec[0], texvec[1], texvec[2]);
+ map_to_tube(
+ area + 2, area + 3, texvec[0] + dxt[0], texvec[1] + dxt[1], texvec[2] + dxt[2]);
+ map_to_tube(
+ area + 4, area + 5, texvec[0] + dyt[0], texvec[1] + dyt[1], texvec[2] + dyt[2]);
+ }
+ else {
+ map_to_sphere(area, area + 1, texvec[0], texvec[1], texvec[2]);
+ map_to_sphere(
+ area + 2, area + 3, texvec[0] + dxt[0], texvec[1] + dxt[1], texvec[2] + dxt[2]);
+ map_to_sphere(
+ area + 4, area + 5, texvec[0] + dyt[0], texvec[1] + dyt[1], texvec[2] + dyt[2]);
+ }
+ areaflag = 1;
+ }
+ else {
+ if (wrap == MTEX_TUBE)
+ map_to_tube(&fx, &fy, texvec[0], texvec[1], texvec[2]);
+ else
+ map_to_sphere(&fx, &fy, texvec[0], texvec[1], texvec[2]);
+ dxt[0] /= 2.0f;
+ dxt[1] /= 2.0f;
+ dyt[0] /= 2.0f;
+ dyt[1] /= 2.0f;
+ }
+ }
+ else {
+
+ proj = cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy);
+
+ if (proj == 1) {
+ SWAP(float, dxt[1], dxt[2]);
+ SWAP(float, dyt[1], dyt[2]);
+ }
+ else if (proj == 2) {
+ float f1 = dxt[0], f2 = dyt[0];
+ dxt[0] = dxt[1];
+ dyt[0] = dyt[1];
+ dxt[1] = dxt[2];
+ dyt[1] = dyt[2];
+ dxt[2] = f1;
+ dyt[2] = f2;
+ }
+
+ dxt[0] *= 0.5f;
+ dxt[1] *= 0.5f;
+ dxt[2] *= 0.5f;
+
+ dyt[0] *= 0.5f;
+ dyt[1] *= 0.5f;
+ dyt[2] *= 0.5f;
+ }
+
+ /* if area, then reacalculate dxt[] and dyt[] */
+ if (areaflag) {
+ fx = area[0];
+ fy = area[1];
+ dxt[0] = area[2] - fx;
+ dxt[1] = area[3] - fy;
+ dyt[0] = area[4] - fx;
+ dyt[1] = area[5] - fy;
+ }
+
+ /* repeat */
+ if (tex->extend == TEX_REPEAT) {
+ float max = 1.0f;
+ if (tex->xrepeat > 1) {
+ float origf = fx *= tex->xrepeat;
+
+ /* TXF: omit mirror here, see comments in do_material_tex() after do_2d_mapping() call */
+ if (tex->texfilter == TXF_BOX) {
+ if (fx > 1.0f)
+ fx -= (int)(fx);
+ else if (fx < 0.0f)
+ fx += 1 - (int)(fx);
+
+ if (tex->flag & TEX_REPEAT_XMIR) {
+ int orig = (int)floor(origf);
+ if (orig & 1)
+ fx = 1.0f - fx;
+ }
+ }
+
+ max = tex->xrepeat;
+
+ dxt[0] *= tex->xrepeat;
+ dyt[0] *= tex->xrepeat;
+ }
+ if (tex->yrepeat > 1) {
+ float origf = fy *= tex->yrepeat;
+
+ /* TXF: omit mirror here, see comments in do_material_tex() after do_2d_mapping() call */
+ if (tex->texfilter == TXF_BOX) {
+ if (fy > 1.0f)
+ fy -= (int)(fy);
+ else if (fy < 0.0f)
+ fy += 1 - (int)(fy);
+
+ if (tex->flag & TEX_REPEAT_YMIR) {
+ int orig = (int)floor(origf);
+ if (orig & 1)
+ fy = 1.0f - fy;
+ }
+ }
+
+ if (max < tex->yrepeat)
+ max = tex->yrepeat;
+
+ dxt[1] *= tex->yrepeat;
+ dyt[1] *= tex->yrepeat;
+ }
+ if (max != 1.0f) {
+ dxt[2] *= max;
+ dyt[2] *= max;
+ }
+ }
+ /* crop */
+ if (tex->cropxmin != 0.0f || tex->cropxmax != 1.0f) {
+ fac1 = tex->cropxmax - tex->cropxmin;
+ fx = tex->cropxmin + fx * fac1;
+ dxt[0] *= fac1;
+ dyt[0] *= fac1;
+ }
+ if (tex->cropymin != 0.0f || tex->cropymax != 1.0f) {
+ fac1 = tex->cropymax - tex->cropymin;
+ fy = tex->cropymin + fy * fac1;
+ dxt[1] *= fac1;
+ dyt[1] *= fac1;
+ }
+
+ texvec[0] = fx;
+ texvec[1] = fy;
+ }
}
/* ************************************** */
static int multitex(Tex *tex,
float texvec[3],
- float dxt[3], float dyt[3],
+ float dxt[3],
+ float dyt[3],
int osatex,
TexResult *texres,
const short thread,
@@ -940,240 +1125,266 @@ static int multitex(Tex *tex,
const bool texnode_preview,
const bool use_nodes)
{
- float tmpvec[3];
- int retval = 0; /* return value, int:0, col:1, nor:2, everything:3 */
-
- texres->talpha = false; /* is set when image texture returns alpha (considered premul) */
-
- if (use_nodes && tex->use_nodes && tex->nodetree) {
- const float cfra = 1.0f; /* This was only set for Blender Internal render before. */
- retval = ntreeTexExecTree(tex->nodetree, texres, texvec, dxt, dyt, osatex, thread,
- tex, which_output, cfra, texnode_preview, NULL);
- }
- else {
- switch (tex->type) {
- case 0:
- texres->tin = 0.0f;
- return 0;
- case TEX_CLOUDS:
- retval = clouds(tex, texvec, texres);
- break;
- case TEX_WOOD:
- retval = wood(tex, texvec, texres);
- break;
- case TEX_MARBLE:
- retval = marble(tex, texvec, texres);
- break;
- case TEX_MAGIC:
- retval = magic(tex, texvec, texres);
- break;
- case TEX_BLEND:
- retval = blend(tex, texvec, texres);
- break;
- case TEX_STUCCI:
- retval = stucci(tex, texvec, texres);
- break;
- case TEX_NOISE:
- retval = texnoise(tex, texres, thread);
- break;
- case TEX_IMAGE:
- if (osatex) retval = imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres, pool, skip_load_image);
- else retval = imagewrap(tex, tex->ima, NULL, texvec, texres, pool, skip_load_image);
- if (tex->ima) {
- BKE_image_tag_time(tex->ima);
- }
- break;
- case TEX_MUSGRAVE:
- /* newnoise: musgrave types */
-
- /* ton: added this, for Blender convention reason.
- * artificer: added the use of tmpvec to avoid scaling texvec
- */
- copy_v3_v3(tmpvec, texvec);
- mul_v3_fl(tmpvec, 1.0f / tex->noisesize);
-
- switch (tex->stype) {
- case TEX_MFRACTAL:
- case TEX_FBM:
- retval = mg_mFractalOrfBmTex(tex, tmpvec, texres);
- break;
- case TEX_RIDGEDMF:
- case TEX_HYBRIDMF:
- retval = mg_ridgedOrHybridMFTex(tex, tmpvec, texres);
- break;
- case TEX_HTERRAIN:
- retval = mg_HTerrainTex(tex, tmpvec, texres);
- break;
- }
- break;
- /* newnoise: voronoi type */
- case TEX_VORONOI:
- /* ton: added this, for Blender convention reason.
- * artificer: added the use of tmpvec to avoid scaling texvec
- */
- copy_v3_v3(tmpvec, texvec);
- mul_v3_fl(tmpvec, 1.0f / tex->noisesize);
-
- retval = voronoiTex(tex, tmpvec, texres);
- break;
- case TEX_DISTNOISE:
- /* ton: added this, for Blender convention reason.
- * artificer: added the use of tmpvec to avoid scaling texvec
- */
- copy_v3_v3(tmpvec, texvec);
- mul_v3_fl(tmpvec, 1.0f / tex->noisesize);
-
- retval = mg_distNoiseTex(tex, tmpvec, texres);
- break;
- }
- }
-
- if (tex->flag & TEX_COLORBAND) {
- float col[4];
- if (BKE_colorband_evaluate(tex->coba, texres->tin, col)) {
- texres->talpha = true;
- texres->tr = col[0];
- texres->tg = col[1];
- texres->tb = col[2];
- texres->ta = col[3];
- retval |= TEX_RGB;
- }
- }
- return retval;
+ float tmpvec[3];
+ int retval = 0; /* return value, int:0, col:1, nor:2, everything:3 */
+
+ texres->talpha = false; /* is set when image texture returns alpha (considered premul) */
+
+ if (use_nodes && tex->use_nodes && tex->nodetree) {
+ const float cfra = 1.0f; /* This was only set for Blender Internal render before. */
+ retval = ntreeTexExecTree(tex->nodetree,
+ texres,
+ texvec,
+ dxt,
+ dyt,
+ osatex,
+ thread,
+ tex,
+ which_output,
+ cfra,
+ texnode_preview,
+ NULL);
+ }
+ else {
+ switch (tex->type) {
+ case 0:
+ texres->tin = 0.0f;
+ return 0;
+ case TEX_CLOUDS:
+ retval = clouds(tex, texvec, texres);
+ break;
+ case TEX_WOOD:
+ retval = wood(tex, texvec, texres);
+ break;
+ case TEX_MARBLE:
+ retval = marble(tex, texvec, texres);
+ break;
+ case TEX_MAGIC:
+ retval = magic(tex, texvec, texres);
+ break;
+ case TEX_BLEND:
+ retval = blend(tex, texvec, texres);
+ break;
+ case TEX_STUCCI:
+ retval = stucci(tex, texvec, texres);
+ break;
+ case TEX_NOISE:
+ retval = texnoise(tex, texres, thread);
+ break;
+ case TEX_IMAGE:
+ if (osatex)
+ retval = imagewraposa(
+ tex, tex->ima, NULL, texvec, dxt, dyt, texres, pool, skip_load_image);
+ else
+ retval = imagewrap(tex, tex->ima, NULL, texvec, texres, pool, skip_load_image);
+ if (tex->ima) {
+ BKE_image_tag_time(tex->ima);
+ }
+ break;
+ case TEX_MUSGRAVE:
+ /* newnoise: musgrave types */
+
+ /* ton: added this, for Blender convention reason.
+ * artificer: added the use of tmpvec to avoid scaling texvec
+ */
+ copy_v3_v3(tmpvec, texvec);
+ mul_v3_fl(tmpvec, 1.0f / tex->noisesize);
+
+ switch (tex->stype) {
+ case TEX_MFRACTAL:
+ case TEX_FBM:
+ retval = mg_mFractalOrfBmTex(tex, tmpvec, texres);
+ break;
+ case TEX_RIDGEDMF:
+ case TEX_HYBRIDMF:
+ retval = mg_ridgedOrHybridMFTex(tex, tmpvec, texres);
+ break;
+ case TEX_HTERRAIN:
+ retval = mg_HTerrainTex(tex, tmpvec, texres);
+ break;
+ }
+ break;
+ /* newnoise: voronoi type */
+ case TEX_VORONOI:
+ /* ton: added this, for Blender convention reason.
+ * artificer: added the use of tmpvec to avoid scaling texvec
+ */
+ copy_v3_v3(tmpvec, texvec);
+ mul_v3_fl(tmpvec, 1.0f / tex->noisesize);
+
+ retval = voronoiTex(tex, tmpvec, texres);
+ break;
+ case TEX_DISTNOISE:
+ /* ton: added this, for Blender convention reason.
+ * artificer: added the use of tmpvec to avoid scaling texvec
+ */
+ copy_v3_v3(tmpvec, texvec);
+ mul_v3_fl(tmpvec, 1.0f / tex->noisesize);
+
+ retval = mg_distNoiseTex(tex, tmpvec, texres);
+ break;
+ }
+ }
+
+ if (tex->flag & TEX_COLORBAND) {
+ float col[4];
+ if (BKE_colorband_evaluate(tex->coba, texres->tin, col)) {
+ texres->talpha = true;
+ texres->tr = col[0];
+ texres->tg = col[1];
+ texres->tb = col[2];
+ texres->ta = col[3];
+ retval |= TEX_RGB;
+ }
+ }
+ return retval;
}
static int multitex_nodes_intern(Tex *tex,
float texvec[3],
- float dxt[3], float dyt[3],
+ float dxt[3],
+ float dyt[3],
int osatex,
TexResult *texres,
const short thread,
short which_output,
- MTex *mtex, struct
- ImagePool *pool,
+ MTex *mtex,
+ struct ImagePool *pool,
const bool scene_color_manage,
const bool skip_load_image,
const bool texnode_preview,
const bool use_nodes)
{
- if (tex == NULL) {
- memset(texres, 0, sizeof(TexResult));
- return 0;
- }
-
- if (mtex)
- which_output = mtex->which_output;
-
- if (tex->type == TEX_IMAGE) {
- int rgbnor;
-
- if (mtex) {
- /* we have mtex, use it for 2d mapping images only */
- do_2d_mapping(mtex, texvec, NULL, dxt, dyt);
- rgbnor = multitex(tex,
- texvec,
- dxt, dyt,
- osatex,
- texres,
- thread,
- which_output,
- pool,
- skip_load_image,
- texnode_preview,
- use_nodes);
-
- if (mtex->mapto & (MAP_COL)) {
- ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
-
- /* don't linearize float buffers, assumed to be linear */
- if (ibuf != NULL &&
- ibuf->rect_float == NULL &&
- (rgbnor & TEX_RGB) &&
- scene_color_manage)
- {
- IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace);
- }
-
- BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
- }
- }
- else {
- /* we don't have mtex, do default flat 2d projection */
- MTex localmtex;
- float texvec_l[3], dxt_l[3], dyt_l[3];
-
- localmtex.mapping = MTEX_FLAT;
- localmtex.tex = tex;
- localmtex.object = NULL;
- localmtex.texco = TEXCO_ORCO;
-
- copy_v3_v3(texvec_l, texvec);
- if (dxt && dyt) {
- copy_v3_v3(dxt_l, dxt);
- copy_v3_v3(dyt_l, dyt);
- }
- else {
- zero_v3(dxt_l);
- zero_v3(dyt_l);
- }
-
- do_2d_mapping(&localmtex, texvec_l, NULL, dxt_l, dyt_l);
- rgbnor = multitex(tex,
- texvec_l,
- dxt_l, dyt_l,
- osatex,
- texres,
- thread,
- which_output,
- pool,
- skip_load_image,
- texnode_preview,
- use_nodes);
-
- {
- ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
-
- /* don't linearize float buffers, assumed to be linear */
- if (ibuf != NULL &&
- ibuf->rect_float == NULL &&
- (rgbnor & TEX_RGB) &&
- scene_color_manage)
- {
- IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace);
- }
-
- BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
- }
- }
-
- return rgbnor;
- }
- else {
- return multitex(tex,
- texvec,
- dxt, dyt,
- osatex,
- texres,
- thread,
- which_output,
- pool,
- skip_load_image,
- texnode_preview,
- use_nodes);
- }
+ if (tex == NULL) {
+ memset(texres, 0, sizeof(TexResult));
+ return 0;
+ }
+
+ if (mtex)
+ which_output = mtex->which_output;
+
+ if (tex->type == TEX_IMAGE) {
+ int rgbnor;
+
+ if (mtex) {
+ /* we have mtex, use it for 2d mapping images only */
+ do_2d_mapping(mtex, texvec, NULL, dxt, dyt);
+ rgbnor = multitex(tex,
+ texvec,
+ dxt,
+ dyt,
+ osatex,
+ texres,
+ thread,
+ which_output,
+ pool,
+ skip_load_image,
+ texnode_preview,
+ use_nodes);
+
+ if (mtex->mapto & (MAP_COL)) {
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
+
+ /* don't linearize float buffers, assumed to be linear */
+ if (ibuf != NULL && ibuf->rect_float == NULL && (rgbnor & TEX_RGB) && scene_color_manage) {
+ IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace);
+ }
+
+ BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
+ }
+ }
+ else {
+ /* we don't have mtex, do default flat 2d projection */
+ MTex localmtex;
+ float texvec_l[3], dxt_l[3], dyt_l[3];
+
+ localmtex.mapping = MTEX_FLAT;
+ localmtex.tex = tex;
+ localmtex.object = NULL;
+ localmtex.texco = TEXCO_ORCO;
+
+ copy_v3_v3(texvec_l, texvec);
+ if (dxt && dyt) {
+ copy_v3_v3(dxt_l, dxt);
+ copy_v3_v3(dyt_l, dyt);
+ }
+ else {
+ zero_v3(dxt_l);
+ zero_v3(dyt_l);
+ }
+
+ do_2d_mapping(&localmtex, texvec_l, NULL, dxt_l, dyt_l);
+ rgbnor = multitex(tex,
+ texvec_l,
+ dxt_l,
+ dyt_l,
+ osatex,
+ texres,
+ thread,
+ which_output,
+ pool,
+ skip_load_image,
+ texnode_preview,
+ use_nodes);
+
+ {
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
+
+ /* don't linearize float buffers, assumed to be linear */
+ if (ibuf != NULL && ibuf->rect_float == NULL && (rgbnor & TEX_RGB) && scene_color_manage) {
+ IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace);
+ }
+
+ BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
+ }
+ }
+
+ return rgbnor;
+ }
+ else {
+ return multitex(tex,
+ texvec,
+ dxt,
+ dyt,
+ osatex,
+ texres,
+ thread,
+ which_output,
+ pool,
+ skip_load_image,
+ texnode_preview,
+ use_nodes);
+ }
}
/* this is called from the shader and texture nodes
* Use it from render pipeline only!
*/
-int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres,
- const short thread, short which_output, MTex *mtex, struct ImagePool *pool)
+int multitex_nodes(Tex *tex,
+ float texvec[3],
+ float dxt[3],
+ float dyt[3],
+ int osatex,
+ TexResult *texres,
+ const short thread,
+ short which_output,
+ MTex *mtex,
+ struct ImagePool *pool)
{
- return multitex_nodes_intern(tex, texvec, dxt, dyt, osatex, texres,
- thread, which_output, mtex, pool, true,
- false,
- false,
- true);
+ return multitex_nodes_intern(tex,
+ texvec,
+ dxt,
+ dyt,
+ osatex,
+ texres,
+ thread,
+ which_output,
+ mtex,
+ pool,
+ true,
+ false,
+ false,
+ true);
}
/* Warning, if the texres's values are not declared zero, check the return value to be sure
@@ -1183,7 +1394,8 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os
*/
int multitex_ext(Tex *tex,
float texvec[3],
- float dxt[3], float dyt[3],
+ float dxt[3],
+ float dyt[3],
int osatex,
TexResult *texres,
const short thread,
@@ -1191,310 +1403,334 @@ int multitex_ext(Tex *tex,
bool scene_color_manage,
const bool skip_load_image)
{
- return multitex_nodes_intern(tex,
- texvec,
- dxt, dyt,
- osatex,
- texres,
- thread,
- 0,
- NULL,
- pool,
- scene_color_manage,
- skip_load_image,
- false,
- true);
+ return multitex_nodes_intern(tex,
+ texvec,
+ dxt,
+ dyt,
+ osatex,
+ texres,
+ thread,
+ 0,
+ NULL,
+ pool,
+ scene_color_manage,
+ skip_load_image,
+ false,
+ true);
}
/* extern-tex doesn't support nodes (ntreeBeginExec() can't be called when rendering is going on)\
*
* Use it for stuff which is out of render pipeline.
*/
-int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image)
+int multitex_ext_safe(Tex *tex,
+ float texvec[3],
+ TexResult *texres,
+ struct ImagePool *pool,
+ bool scene_color_manage,
+ const bool skip_load_image)
{
- return multitex_nodes_intern(tex,
- texvec,
- NULL, NULL,
- 0,
- texres,
- 0,
- 0,
- NULL,
- pool,
- scene_color_manage,
- skip_load_image,
- false,
- false);
+ return multitex_nodes_intern(tex,
+ texvec,
+ NULL,
+ NULL,
+ 0,
+ texres,
+ 0,
+ 0,
+ NULL,
+ pool,
+ scene_color_manage,
+ skip_load_image,
+ false,
+ false);
}
-
/* ------------------------------------------------------------------------- */
/* in = destination, tex = texture, out = previous color */
/* fact = texture strength, facg = button strength value */
-void texture_rgb_blend(float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype)
+void texture_rgb_blend(
+ float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype)
{
- float facm;
-
- switch (blendtype) {
- case MTEX_BLEND:
- fact *= facg;
- facm = 1.0f - fact;
-
- in[0] = (fact * tex[0] + facm * out[0]);
- in[1] = (fact * tex[1] + facm * out[1]);
- in[2] = (fact * tex[2] + facm * out[2]);
- break;
-
- case MTEX_MUL:
- fact *= facg;
- facm = 1.0f - fact;
- in[0] = (facm + fact * tex[0]) * out[0];
- in[1] = (facm + fact * tex[1]) * out[1];
- in[2] = (facm + fact * tex[2]) * out[2];
- break;
-
- case MTEX_SCREEN:
- fact *= facg;
- facm = 1.0f - fact;
- in[0] = 1.0f - (facm + fact * (1.0f - tex[0])) * (1.0f - out[0]);
- in[1] = 1.0f - (facm + fact * (1.0f - tex[1])) * (1.0f - out[1]);
- in[2] = 1.0f - (facm + fact * (1.0f - tex[2])) * (1.0f - out[2]);
- break;
-
- case MTEX_OVERLAY:
- fact *= facg;
- facm = 1.0f - fact;
-
- if (out[0] < 0.5f)
- in[0] = out[0] * (facm + 2.0f * fact * tex[0]);
- else
- in[0] = 1.0f - (facm + 2.0f * fact * (1.0f - tex[0])) * (1.0f - out[0]);
- if (out[1] < 0.5f)
- in[1] = out[1] * (facm + 2.0f * fact * tex[1]);
- else
- in[1] = 1.0f - (facm + 2.0f * fact * (1.0f - tex[1])) * (1.0f - out[1]);
- if (out[2] < 0.5f)
- in[2] = out[2] * (facm + 2.0f * fact * tex[2]);
- else
- in[2] = 1.0f - (facm + 2.0f * fact * (1.0f - tex[2])) * (1.0f - out[2]);
- break;
-
- case MTEX_SUB:
- fact = -fact;
- ATTR_FALLTHROUGH;
- case MTEX_ADD:
- fact *= facg;
- in[0] = (fact * tex[0] + out[0]);
- in[1] = (fact * tex[1] + out[1]);
- in[2] = (fact * tex[2] + out[2]);
- break;
-
- case MTEX_DIV:
- fact *= facg;
- facm = 1.0f - fact;
-
- if (tex[0] != 0.0f)
- in[0] = facm * out[0] + fact * out[0] / tex[0];
- if (tex[1] != 0.0f)
- in[1] = facm * out[1] + fact * out[1] / tex[1];
- if (tex[2] != 0.0f)
- in[2] = facm * out[2] + fact * out[2] / tex[2];
-
- break;
-
- case MTEX_DIFF:
- fact *= facg;
- facm = 1.0f - fact;
- in[0] = facm * out[0] + fact * fabsf(tex[0] - out[0]);
- in[1] = facm * out[1] + fact * fabsf(tex[1] - out[1]);
- in[2] = facm * out[2] + fact * fabsf(tex[2] - out[2]);
- break;
-
- case MTEX_DARK:
- fact *= facg;
- facm = 1.0f - fact;
-
- in[0] = min_ff(out[0], tex[0]) * fact + out[0] * facm;
- in[1] = min_ff(out[1], tex[1]) * fact + out[1] * facm;
- in[2] = min_ff(out[2], tex[2]) * fact + out[2] * facm;
- break;
-
- case MTEX_LIGHT:
- fact *= facg;
-
- in[0] = max_ff(fact * tex[0], out[0]);
- in[1] = max_ff(fact * tex[1], out[1]);
- in[2] = max_ff(fact * tex[2], out[2]);
- break;
-
- case MTEX_BLEND_HUE:
- fact *= facg;
- copy_v3_v3(in, out);
- ramp_blend(MA_RAMP_HUE, in, fact, tex);
- break;
- case MTEX_BLEND_SAT:
- fact *= facg;
- copy_v3_v3(in, out);
- ramp_blend(MA_RAMP_SAT, in, fact, tex);
- break;
- case MTEX_BLEND_VAL:
- fact *= facg;
- copy_v3_v3(in, out);
- ramp_blend(MA_RAMP_VAL, in, fact, tex);
- break;
- case MTEX_BLEND_COLOR:
- fact *= facg;
- copy_v3_v3(in, out);
- ramp_blend(MA_RAMP_COLOR, in, fact, tex);
- break;
- case MTEX_SOFT_LIGHT:
- fact *= facg;
- copy_v3_v3(in, out);
- ramp_blend(MA_RAMP_SOFT, in, fact, tex);
- break;
- case MTEX_LIN_LIGHT:
- fact *= facg;
- copy_v3_v3(in, out);
- ramp_blend(MA_RAMP_LINEAR, in, fact, tex);
- break;
- }
+ float facm;
+
+ switch (blendtype) {
+ case MTEX_BLEND:
+ fact *= facg;
+ facm = 1.0f - fact;
+
+ in[0] = (fact * tex[0] + facm * out[0]);
+ in[1] = (fact * tex[1] + facm * out[1]);
+ in[2] = (fact * tex[2] + facm * out[2]);
+ break;
+
+ case MTEX_MUL:
+ fact *= facg;
+ facm = 1.0f - fact;
+ in[0] = (facm + fact * tex[0]) * out[0];
+ in[1] = (facm + fact * tex[1]) * out[1];
+ in[2] = (facm + fact * tex[2]) * out[2];
+ break;
+
+ case MTEX_SCREEN:
+ fact *= facg;
+ facm = 1.0f - fact;
+ in[0] = 1.0f - (facm + fact * (1.0f - tex[0])) * (1.0f - out[0]);
+ in[1] = 1.0f - (facm + fact * (1.0f - tex[1])) * (1.0f - out[1]);
+ in[2] = 1.0f - (facm + fact * (1.0f - tex[2])) * (1.0f - out[2]);
+ break;
+
+ case MTEX_OVERLAY:
+ fact *= facg;
+ facm = 1.0f - fact;
+
+ if (out[0] < 0.5f)
+ in[0] = out[0] * (facm + 2.0f * fact * tex[0]);
+ else
+ in[0] = 1.0f - (facm + 2.0f * fact * (1.0f - tex[0])) * (1.0f - out[0]);
+ if (out[1] < 0.5f)
+ in[1] = out[1] * (facm + 2.0f * fact * tex[1]);
+ else
+ in[1] = 1.0f - (facm + 2.0f * fact * (1.0f - tex[1])) * (1.0f - out[1]);
+ if (out[2] < 0.5f)
+ in[2] = out[2] * (facm + 2.0f * fact * tex[2]);
+ else
+ in[2] = 1.0f - (facm + 2.0f * fact * (1.0f - tex[2])) * (1.0f - out[2]);
+ break;
+
+ case MTEX_SUB:
+ fact = -fact;
+ ATTR_FALLTHROUGH;
+ case MTEX_ADD:
+ fact *= facg;
+ in[0] = (fact * tex[0] + out[0]);
+ in[1] = (fact * tex[1] + out[1]);
+ in[2] = (fact * tex[2] + out[2]);
+ break;
+
+ case MTEX_DIV:
+ fact *= facg;
+ facm = 1.0f - fact;
+
+ if (tex[0] != 0.0f)
+ in[0] = facm * out[0] + fact * out[0] / tex[0];
+ if (tex[1] != 0.0f)
+ in[1] = facm * out[1] + fact * out[1] / tex[1];
+ if (tex[2] != 0.0f)
+ in[2] = facm * out[2] + fact * out[2] / tex[2];
+
+ break;
+
+ case MTEX_DIFF:
+ fact *= facg;
+ facm = 1.0f - fact;
+ in[0] = facm * out[0] + fact * fabsf(tex[0] - out[0]);
+ in[1] = facm * out[1] + fact * fabsf(tex[1] - out[1]);
+ in[2] = facm * out[2] + fact * fabsf(tex[2] - out[2]);
+ break;
+
+ case MTEX_DARK:
+ fact *= facg;
+ facm = 1.0f - fact;
+
+ in[0] = min_ff(out[0], tex[0]) * fact + out[0] * facm;
+ in[1] = min_ff(out[1], tex[1]) * fact + out[1] * facm;
+ in[2] = min_ff(out[2], tex[2]) * fact + out[2] * facm;
+ break;
+
+ case MTEX_LIGHT:
+ fact *= facg;
+
+ in[0] = max_ff(fact * tex[0], out[0]);
+ in[1] = max_ff(fact * tex[1], out[1]);
+ in[2] = max_ff(fact * tex[2], out[2]);
+ break;
+
+ case MTEX_BLEND_HUE:
+ fact *= facg;
+ copy_v3_v3(in, out);
+ ramp_blend(MA_RAMP_HUE, in, fact, tex);
+ break;
+ case MTEX_BLEND_SAT:
+ fact *= facg;
+ copy_v3_v3(in, out);
+ ramp_blend(MA_RAMP_SAT, in, fact, tex);
+ break;
+ case MTEX_BLEND_VAL:
+ fact *= facg;
+ copy_v3_v3(in, out);
+ ramp_blend(MA_RAMP_VAL, in, fact, tex);
+ break;
+ case MTEX_BLEND_COLOR:
+ fact *= facg;
+ copy_v3_v3(in, out);
+ ramp_blend(MA_RAMP_COLOR, in, fact, tex);
+ break;
+ case MTEX_SOFT_LIGHT:
+ fact *= facg;
+ copy_v3_v3(in, out);
+ ramp_blend(MA_RAMP_SOFT, in, fact, tex);
+ break;
+ case MTEX_LIN_LIGHT:
+ fact *= facg;
+ copy_v3_v3(in, out);
+ ramp_blend(MA_RAMP_LINEAR, in, fact, tex);
+ break;
+ }
}
float texture_value_blend(float tex, float out, float fact, float facg, int blendtype)
{
- float in = 0.0, facm, col, scf;
- int flip = (facg < 0.0f);
-
- facg = fabsf(facg);
-
- fact *= facg;
- facm = 1.0f - fact;
- if (flip) SWAP(float, fact, facm);
-
- switch (blendtype) {
- case MTEX_BLEND:
- in = fact * tex + facm * out;
- break;
-
- case MTEX_MUL:
- facm = 1.0f - facg;
- in = (facm + fact * tex) * out;
- break;
-
- case MTEX_SCREEN:
- facm = 1.0f - facg;
- in = 1.0f - (facm + fact * (1.0f - tex)) * (1.0f - out);
- break;
-
- case MTEX_OVERLAY:
- facm = 1.0f - facg;
- if (out < 0.5f)
- in = out * (facm + 2.0f * fact * tex);
- else
- in = 1.0f - (facm + 2.0f * fact * (1.0f - tex)) * (1.0f - out);
- break;
-
- case MTEX_SUB:
- fact = -fact;
- ATTR_FALLTHROUGH;
- case MTEX_ADD:
- in = fact * tex + out;
- break;
-
- case MTEX_DIV:
- if (tex != 0.0f)
- in = facm * out + fact * out / tex;
- break;
-
- case MTEX_DIFF:
- in = facm * out + fact * fabsf(tex - out);
- break;
-
- case MTEX_DARK:
- in = min_ff(out, tex) * fact + out * facm;
- break;
-
- case MTEX_LIGHT:
- col = fact * tex;
- if (col > out) in = col; else in = out;
- break;
-
- case MTEX_SOFT_LIGHT:
- scf = 1.0f - (1.0f - tex) * (1.0f - out);
- in = facm * out + fact * ((1.0f - out) * tex * out) + (out * scf);
- break;
-
- case MTEX_LIN_LIGHT:
- if (tex > 0.5f)
- in = out + fact * (2.0f * (tex - 0.5f));
- else
- in = out + fact * (2.0f * tex - 1.0f);
- break;
- }
-
- return in;
+ float in = 0.0, facm, col, scf;
+ int flip = (facg < 0.0f);
+
+ facg = fabsf(facg);
+
+ fact *= facg;
+ facm = 1.0f - fact;
+ if (flip)
+ SWAP(float, fact, facm);
+
+ switch (blendtype) {
+ case MTEX_BLEND:
+ in = fact * tex + facm * out;
+ break;
+
+ case MTEX_MUL:
+ facm = 1.0f - facg;
+ in = (facm + fact * tex) * out;
+ break;
+
+ case MTEX_SCREEN:
+ facm = 1.0f - facg;
+ in = 1.0f - (facm + fact * (1.0f - tex)) * (1.0f - out);
+ break;
+
+ case MTEX_OVERLAY:
+ facm = 1.0f - facg;
+ if (out < 0.5f)
+ in = out * (facm + 2.0f * fact * tex);
+ else
+ in = 1.0f - (facm + 2.0f * fact * (1.0f - tex)) * (1.0f - out);
+ break;
+
+ case MTEX_SUB:
+ fact = -fact;
+ ATTR_FALLTHROUGH;
+ case MTEX_ADD:
+ in = fact * tex + out;
+ break;
+
+ case MTEX_DIV:
+ if (tex != 0.0f)
+ in = facm * out + fact * out / tex;
+ break;
+
+ case MTEX_DIFF:
+ in = facm * out + fact * fabsf(tex - out);
+ break;
+
+ case MTEX_DARK:
+ in = min_ff(out, tex) * fact + out * facm;
+ break;
+
+ case MTEX_LIGHT:
+ col = fact * tex;
+ if (col > out)
+ in = col;
+ else
+ in = out;
+ break;
+
+ case MTEX_SOFT_LIGHT:
+ scf = 1.0f - (1.0f - tex) * (1.0f - out);
+ in = facm * out + fact * ((1.0f - out) * tex * out) + (out * scf);
+ break;
+
+ case MTEX_LIN_LIGHT:
+ if (tex > 0.5f)
+ in = out + fact * (2.0f * (tex - 0.5f));
+ else
+ in = out + fact * (2.0f * tex - 1.0f);
+ break;
+ }
+
+ return in;
}
/* ------------------------------------------------------------------------- */
int externtex(const MTex *mtex,
const float vec[3],
- float *tin, float *tr, float *tg, float *tb, float *ta,
+ float *tin,
+ float *tr,
+ float *tg,
+ float *tb,
+ float *ta,
const int thread,
struct ImagePool *pool,
const bool skip_load_image,
const bool texnode_preview)
{
- Tex *tex;
- TexResult texr;
- float dxt[3], dyt[3], texvec[3];
- int rgb;
-
- tex = mtex->tex;
- if (tex == NULL) return 0;
- texr.nor = NULL;
-
- /* placement */
- if (mtex->projx) texvec[0] = mtex->size[0] * (vec[mtex->projx - 1] + mtex->ofs[0]);
- else texvec[0] = mtex->size[0] * (mtex->ofs[0]);
-
- if (mtex->projy) texvec[1] = mtex->size[1] * (vec[mtex->projy - 1] + mtex->ofs[1]);
- else texvec[1] = mtex->size[1] * (mtex->ofs[1]);
-
- if (mtex->projz) texvec[2] = mtex->size[2] * (vec[mtex->projz - 1] + mtex->ofs[2]);
- else texvec[2] = mtex->size[2] * (mtex->ofs[2]);
-
- /* texture */
- if (tex->type == TEX_IMAGE) {
- do_2d_mapping(mtex, texvec, NULL, dxt, dyt);
- }
-
- rgb = multitex(tex,
- texvec,
- dxt, dyt,
- 0, &texr,
- thread,
- mtex->which_output,
- pool,
- skip_load_image,
- texnode_preview,
- true);
-
- if (rgb) {
- texr.tin = IMB_colormanagement_get_luminance(&texr.tr);
- }
- else {
- texr.tr = mtex->r;
- texr.tg = mtex->g;
- texr.tb = mtex->b;
- }
-
- *tin = texr.tin;
- *tr = texr.tr;
- *tg = texr.tg;
- *tb = texr.tb;
- *ta = texr.ta;
-
- return (rgb != 0);
+ Tex *tex;
+ TexResult texr;
+ float dxt[3], dyt[3], texvec[3];
+ int rgb;
+
+ tex = mtex->tex;
+ if (tex == NULL)
+ return 0;
+ texr.nor = NULL;
+
+ /* placement */
+ if (mtex->projx)
+ texvec[0] = mtex->size[0] * (vec[mtex->projx - 1] + mtex->ofs[0]);
+ else
+ texvec[0] = mtex->size[0] * (mtex->ofs[0]);
+
+ if (mtex->projy)
+ texvec[1] = mtex->size[1] * (vec[mtex->projy - 1] + mtex->ofs[1]);
+ else
+ texvec[1] = mtex->size[1] * (mtex->ofs[1]);
+
+ if (mtex->projz)
+ texvec[2] = mtex->size[2] * (vec[mtex->projz - 1] + mtex->ofs[2]);
+ else
+ texvec[2] = mtex->size[2] * (mtex->ofs[2]);
+
+ /* texture */
+ if (tex->type == TEX_IMAGE) {
+ do_2d_mapping(mtex, texvec, NULL, dxt, dyt);
+ }
+
+ rgb = multitex(tex,
+ texvec,
+ dxt,
+ dyt,
+ 0,
+ &texr,
+ thread,
+ mtex->which_output,
+ pool,
+ skip_load_image,
+ texnode_preview,
+ true);
+
+ if (rgb) {
+ texr.tin = IMB_colormanagement_get_luminance(&texr.tr);
+ }
+ else {
+ texr.tr = mtex->r;
+ texr.tg = mtex->g;
+ texr.tb = mtex->b;
+ }
+
+ *tin = texr.tin;
+ *tr = texr.tr;
+ *tg = texr.tg;
+ *tb = texr.tb;
+ *ta = texr.ta;
+
+ return (rgb != 0);
}
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index 05944df770a..e8c97661547 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -21,8 +21,6 @@
* \ingroup render
*/
-
-
/*---------------------------------------------------------------------------*/
/* Common includes */
/*---------------------------------------------------------------------------*/
@@ -46,109 +44,121 @@
/* each zbuffer has coordinates transformed to local rect coordinates, so we can simply clip */
void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty)
{
- memset(zspan, 0, sizeof(ZSpan));
+ memset(zspan, 0, sizeof(ZSpan));
- zspan->rectx = rectx;
- zspan->recty = recty;
+ zspan->rectx = rectx;
+ zspan->recty = recty;
- zspan->span1 = MEM_mallocN(recty * sizeof(float), "zspan");
- zspan->span2 = MEM_mallocN(recty * sizeof(float), "zspan");
+ zspan->span1 = MEM_mallocN(recty * sizeof(float), "zspan");
+ zspan->span2 = MEM_mallocN(recty * sizeof(float), "zspan");
}
void zbuf_free_span(ZSpan *zspan)
{
- if (zspan) {
- if (zspan->span1) MEM_freeN(zspan->span1);
- if (zspan->span2) MEM_freeN(zspan->span2);
- zspan->span1 = zspan->span2 = NULL;
- }
+ if (zspan) {
+ if (zspan->span1)
+ MEM_freeN(zspan->span1);
+ if (zspan->span2)
+ MEM_freeN(zspan->span2);
+ zspan->span1 = zspan->span2 = NULL;
+ }
}
/* reset range for clipping */
static void zbuf_init_span(ZSpan *zspan)
{
- zspan->miny1 = zspan->miny2 = zspan->recty + 1;
- zspan->maxy1 = zspan->maxy2 = -1;
- zspan->minp1 = zspan->maxp1 = zspan->minp2 = zspan->maxp2 = NULL;
+ zspan->miny1 = zspan->miny2 = zspan->recty + 1;
+ zspan->maxy1 = zspan->maxy2 = -1;
+ zspan->minp1 = zspan->maxp1 = zspan->minp2 = zspan->maxp2 = NULL;
}
static void zbuf_add_to_span(ZSpan *zspan, const float v1[2], const float v2[2])
{
- const float *minv, *maxv;
- float *span;
- float xx1, dx0, xs0;
- int y, my0, my2;
-
- if (v1[1] < v2[1]) {
- minv = v1; maxv = v2;
- }
- else {
- minv = v2; maxv = v1;
- }
-
- my0 = ceil(minv[1]);
- my2 = floor(maxv[1]);
-
- if (my2 < 0 || my0 >= zspan->recty) return;
-
- /* clip top */
- if (my2 >= zspan->recty) my2 = zspan->recty - 1;
- /* clip bottom */
- if (my0 < 0) my0 = 0;
-
- if (my0 > my2) return;
- /* if (my0>my2) should still fill in, that way we get spans that skip nicely */
-
- xx1 = maxv[1] - minv[1];
- if (xx1 > FLT_EPSILON) {
- dx0 = (minv[0] - maxv[0]) / xx1;
- xs0 = dx0 * (minv[1] - my2) + minv[0];
- }
- else {
- dx0 = 0.0f;
- xs0 = min_ff(minv[0], maxv[0]);
- }
-
- /* empty span */
- if (zspan->maxp1 == NULL) {
- span = zspan->span1;
- }
- else { /* does it complete left span? */
- if (maxv == zspan->minp1 || minv == zspan->maxp1) {
- span = zspan->span1;
- }
- else {
- span = zspan->span2;
- }
- }
-
- if (span == zspan->span1) {
-// printf("left span my0 %d my2 %d\n", my0, my2);
- if (zspan->minp1 == NULL || zspan->minp1[1] > minv[1]) {
- zspan->minp1 = minv;
- }
- if (zspan->maxp1 == NULL || zspan->maxp1[1] < maxv[1]) {
- zspan->maxp1 = maxv;
- }
- if (my0 < zspan->miny1) zspan->miny1 = my0;
- if (my2 > zspan->maxy1) zspan->maxy1 = my2;
- }
- else {
-// printf("right span my0 %d my2 %d\n", my0, my2);
- if (zspan->minp2 == NULL || zspan->minp2[1] > minv[1]) {
- zspan->minp2 = minv;
- }
- if (zspan->maxp2 == NULL || zspan->maxp2[1] < maxv[1]) {
- zspan->maxp2 = maxv;
- }
- if (my0 < zspan->miny2) zspan->miny2 = my0;
- if (my2 > zspan->maxy2) zspan->maxy2 = my2;
- }
-
- for (y = my2; y >= my0; y--, xs0 += dx0) {
- /* xs0 is the xcoord! */
- span[y] = xs0;
- }
+ const float *minv, *maxv;
+ float *span;
+ float xx1, dx0, xs0;
+ int y, my0, my2;
+
+ if (v1[1] < v2[1]) {
+ minv = v1;
+ maxv = v2;
+ }
+ else {
+ minv = v2;
+ maxv = v1;
+ }
+
+ my0 = ceil(minv[1]);
+ my2 = floor(maxv[1]);
+
+ if (my2 < 0 || my0 >= zspan->recty)
+ return;
+
+ /* clip top */
+ if (my2 >= zspan->recty)
+ my2 = zspan->recty - 1;
+ /* clip bottom */
+ if (my0 < 0)
+ my0 = 0;
+
+ if (my0 > my2)
+ return;
+ /* if (my0>my2) should still fill in, that way we get spans that skip nicely */
+
+ xx1 = maxv[1] - minv[1];
+ if (xx1 > FLT_EPSILON) {
+ dx0 = (minv[0] - maxv[0]) / xx1;
+ xs0 = dx0 * (minv[1] - my2) + minv[0];
+ }
+ else {
+ dx0 = 0.0f;
+ xs0 = min_ff(minv[0], maxv[0]);
+ }
+
+ /* empty span */
+ if (zspan->maxp1 == NULL) {
+ span = zspan->span1;
+ }
+ else { /* does it complete left span? */
+ if (maxv == zspan->minp1 || minv == zspan->maxp1) {
+ span = zspan->span1;
+ }
+ else {
+ span = zspan->span2;
+ }
+ }
+
+ if (span == zspan->span1) {
+ // printf("left span my0 %d my2 %d\n", my0, my2);
+ if (zspan->minp1 == NULL || zspan->minp1[1] > minv[1]) {
+ zspan->minp1 = minv;
+ }
+ if (zspan->maxp1 == NULL || zspan->maxp1[1] < maxv[1]) {
+ zspan->maxp1 = maxv;
+ }
+ if (my0 < zspan->miny1)
+ zspan->miny1 = my0;
+ if (my2 > zspan->maxy1)
+ zspan->maxy1 = my2;
+ }
+ else {
+ // printf("right span my0 %d my2 %d\n", my0, my2);
+ if (zspan->minp2 == NULL || zspan->minp2[1] > minv[1]) {
+ zspan->minp2 = minv;
+ }
+ if (zspan->maxp2 == NULL || zspan->maxp2[1] < maxv[1]) {
+ zspan->maxp2 = maxv;
+ }
+ if (my0 < zspan->miny2)
+ zspan->miny2 = my0;
+ if (my2 > zspan->maxy2)
+ zspan->maxy2 = my2;
+ }
+
+ for (y = my2; y >= my0; y--, xs0 += dx0) {
+ /* xs0 is the xcoord! */
+ span[y] = xs0;
+ }
}
/*-----------------------------------------------------------*/
@@ -157,81 +167,91 @@ static void zbuf_add_to_span(ZSpan *zspan, const float v1[2], const float v2[2])
/* scanconvert for strand triangles, calls func for each x, y coordinate and gives UV barycentrics and z */
-void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float) )
+void zspan_scanconvert(ZSpan *zspan,
+ void *handle,
+ float *v1,
+ float *v2,
+ float *v3,
+ void (*func)(void *, int, int, float, float))
{
- float x0, y0, x1, y1, x2, y2, z0, z1, z2;
- float u, v, uxd, uyd, vxd, vyd, uy0, vy0, xx1;
- const float *span1, *span2;
- int i, j, x, y, sn1, sn2, rectx = zspan->rectx, my0, my2;
+ float x0, y0, x1, y1, x2, y2, z0, z1, z2;
+ float u, v, uxd, uyd, vxd, vyd, uy0, vy0, xx1;
+ const float *span1, *span2;
+ int i, j, x, y, sn1, sn2, rectx = zspan->rectx, my0, my2;
- /* init */
- zbuf_init_span(zspan);
+ /* init */
+ zbuf_init_span(zspan);
- /* set spans */
- zbuf_add_to_span(zspan, v1, v2);
- zbuf_add_to_span(zspan, v2, v3);
- zbuf_add_to_span(zspan, v3, v1);
+ /* set spans */
+ zbuf_add_to_span(zspan, v1, v2);
+ zbuf_add_to_span(zspan, v2, v3);
+ zbuf_add_to_span(zspan, v3, v1);
- /* clipped */
- if (zspan->minp2 == NULL || zspan->maxp2 == NULL) return;
+ /* clipped */
+ if (zspan->minp2 == NULL || zspan->maxp2 == NULL)
+ return;
- my0 = max_ii(zspan->miny1, zspan->miny2);
- my2 = min_ii(zspan->maxy1, zspan->maxy2);
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
- // printf("my %d %d\n", my0, my2);
- if (my2 < my0) return;
+ // printf("my %d %d\n", my0, my2);
+ if (my2 < my0)
+ return;
- /* ZBUF DX DY, in floats still */
- x1 = v1[0] - v2[0];
- x2 = v2[0] - v3[0];
- y1 = v1[1] - v2[1];
- y2 = v2[1] - v3[1];
+ /* ZBUF DX DY, in floats still */
+ x1 = v1[0] - v2[0];
+ x2 = v2[0] - v3[0];
+ y1 = v1[1] - v2[1];
+ y2 = v2[1] - v3[1];
- z1 = 1.0f; /* (u1 - u2) */
- z2 = 0.0f; /* (u2 - u3) */
+ z1 = 1.0f; /* (u1 - u2) */
+ z2 = 0.0f; /* (u2 - u3) */
- x0 = y1 * z2 - z1 * y2;
- y0 = z1 * x2 - x1 * z2;
- z0 = x1 * y2 - y1 * x2;
+ x0 = y1 * z2 - z1 * y2;
+ y0 = z1 * x2 - x1 * z2;
+ z0 = x1 * y2 - y1 * x2;
- if (z0 == 0.0f) return;
+ if (z0 == 0.0f)
+ return;
- xx1 = (x0 * v1[0] + y0 * v1[1]) / z0 + 1.0f;
- uxd = -(double)x0 / (double)z0;
- uyd = -(double)y0 / (double)z0;
- uy0 = ((double)my2) * uyd + (double)xx1;
+ xx1 = (x0 * v1[0] + y0 * v1[1]) / z0 + 1.0f;
+ uxd = -(double)x0 / (double)z0;
+ uyd = -(double)y0 / (double)z0;
+ uy0 = ((double)my2) * uyd + (double)xx1;
- z1 = -1.0f; /* (v1 - v2) */
- z2 = 1.0f; /* (v2 - v3) */
+ z1 = -1.0f; /* (v1 - v2) */
+ z2 = 1.0f; /* (v2 - v3) */
- x0 = y1 * z2 - z1 * y2;
- y0 = z1 * x2 - x1 * z2;
+ x0 = y1 * z2 - z1 * y2;
+ y0 = z1 * x2 - x1 * z2;
- xx1 = (x0 * v1[0] + y0 * v1[1]) / z0;
- vxd = -(double)x0 / (double)z0;
- vyd = -(double)y0 / (double)z0;
- vy0 = ((double)my2) * vyd + (double)xx1;
+ xx1 = (x0 * v1[0] + y0 * v1[1]) / z0;
+ vxd = -(double)x0 / (double)z0;
+ vyd = -(double)y0 / (double)z0;
+ vy0 = ((double)my2) * vyd + (double)xx1;
- /* correct span */
- span1 = zspan->span1 + my2;
- span2 = zspan->span2 + my2;
+ /* correct span */
+ span1 = zspan->span1 + my2;
+ span2 = zspan->span2 + my2;
- for (i = 0, y = my2; y >= my0; i++, y--, span1--, span2--) {
+ for (i = 0, y = my2; y >= my0; i++, y--, span1--, span2--) {
- sn1 = floor(min_ff(*span1, *span2));
- sn2 = floor(max_ff(*span1, *span2));
- sn1++;
+ sn1 = floor(min_ff(*span1, *span2));
+ sn2 = floor(max_ff(*span1, *span2));
+ sn1++;
- if (sn2 >= rectx) sn2 = rectx - 1;
- if (sn1 < 0) sn1 = 0;
+ if (sn2 >= rectx)
+ sn2 = rectx - 1;
+ if (sn1 < 0)
+ sn1 = 0;
- u = (((double)sn1 * uxd) + uy0) - (i * uyd);
- v = (((double)sn1 * vxd) + vy0) - (i * vyd);
+ u = (((double)sn1 * uxd) + uy0) - (i * uyd);
+ v = (((double)sn1 * vxd) + vy0) - (i * vyd);
- for (j = 0, x = sn1; x <= sn2; j++, x++) {
- func(handle, x, y, u + (j * uxd), v + (j * vxd));
- }
- }
+ for (j = 0, x = sn1; x <= sn2; j++, x++) {
+ func(handle, x, y, u + (j * uxd), v + (j * vxd));
+ }
+ }
}
/* end of zbuf.c */