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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/CMakeLists.txt8
-rw-r--r--source/blender/render/SConscript8
-rw-r--r--source/blender/render/extern/include/RE_bake.h10
-rw-r--r--source/blender/render/extern/include/RE_engine.h13
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h90
-rw-r--r--source/blender/render/extern/include/RE_render_ext.h16
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h11
-rw-r--r--source/blender/render/intern/include/envmap.h2
-rw-r--r--source/blender/render/intern/include/initrender.h1
-rw-r--r--source/blender/render/intern/include/occlusion.h3
-rw-r--r--source/blender/render/intern/include/pixelshading.h1
-rw-r--r--source/blender/render/intern/include/pointdensity.h4
-rw-r--r--source/blender/render/intern/include/rayintersection.h2
-rw-r--r--source/blender/render/intern/include/render_result.h23
-rw-r--r--source/blender/render/intern/include/render_types.h18
-rw-r--r--source/blender/render/intern/include/rendercore.h3
-rw-r--r--source/blender/render/intern/include/shadbuf.h4
-rw-r--r--source/blender/render/intern/include/shading.h1
-rw-r--r--source/blender/render/intern/include/sss.h1
-rw-r--r--source/blender/render/intern/include/strand.h3
-rw-r--r--source/blender/render/intern/include/texture.h9
-rw-r--r--source/blender/render/intern/include/zbuf.h1
-rw-r--r--source/blender/render/intern/raytrace/rayobject_instance.cpp2
-rw-r--r--source/blender/render/intern/raytrace/rayobject_octree.cpp3
-rw-r--r--source/blender/render/intern/source/bake.c29
-rw-r--r--source/blender/render/intern/source/bake_api.c152
-rw-r--r--source/blender/render/intern/source/convertblender.c153
-rw-r--r--source/blender/render/intern/source/envmap.c34
-rw-r--r--source/blender/render/intern/source/external_engine.c92
-rw-r--r--source/blender/render/intern/source/imagetexture.c32
-rw-r--r--source/blender/render/intern/source/initrender.c37
-rw-r--r--source/blender/render/intern/source/multires_bake.c368
-rw-r--r--source/blender/render/intern/source/occlusion.c8
-rw-r--r--source/blender/render/intern/source/pipeline.c1415
-rw-r--r--source/blender/render/intern/source/pixelblending.c1
-rw-r--r--source/blender/render/intern/source/pixelshading.c11
-rw-r--r--source/blender/render/intern/source/pointdensity.c442
-rw-r--r--source/blender/render/intern/source/rayshade.c65
-rw-r--r--source/blender/render/intern/source/render_result.c867
-rw-r--r--source/blender/render/intern/source/render_texture.c269
-rw-r--r--source/blender/render/intern/source/rendercore.c128
-rw-r--r--source/blender/render/intern/source/renderdatabase.c60
-rw-r--r--source/blender/render/intern/source/shadbuf.c1
-rw-r--r--source/blender/render/intern/source/shadeinput.c19
-rw-r--r--source/blender/render/intern/source/shadeoutput.c110
-rw-r--r--source/blender/render/intern/source/sss.c15
-rw-r--r--source/blender/render/intern/source/strand.c3
-rw-r--r--source/blender/render/intern/source/sunsky.c11
-rw-r--r--source/blender/render/intern/source/texture_ocean.c4
-rw-r--r--source/blender/render/intern/source/volume_precache.c2
-rw-r--r--source/blender/render/intern/source/volumetric.c12
-rw-r--r--source/blender/render/intern/source/voxeldata.c30
-rw-r--r--source/blender/render/intern/source/zbuf.c70
53 files changed, 3063 insertions, 1614 deletions
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index 8e326e770fc..9e40ab02ee4 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -27,12 +27,14 @@
set(INC
extern/include
intern/include
- ../blenfont
../blenkernel
../blenlib
+ ../blentranslation
../imbuf
+ ../depsgraph
../makesdna
../makesrna
+ ../physics
../../../intern/guardedalloc
../../../intern/mikktspace
../../../intern/smoke/extern
@@ -162,6 +164,10 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_CYCLES AND WITH_CYCLES_DEBUG)
+ add_definitions(-DWITH_CYCLES_DEBUG)
+endif()
+
if(APPLE)
# SSE math is enabled by default on x86_64
if(CMAKE_OSX_ARCHITECTURES MATCHES "i386")
diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript
index 297e4fcecd4..16d9b4a832d 100644
--- a/source/blender/render/SConscript
+++ b/source/blender/render/SConscript
@@ -34,13 +34,14 @@ incs = [
'extern/include',
'intern/include',
'#/intern/guardedalloc',
- '../blenfont',
'../blenkernel',
'../blenlib',
+ '../blentranslation',
'../imbuf',
- '../include',
+ '../depsgraph',
'../makesdna',
'../makesrna',
+ '../physics',
'../../../intern/mikktspace',
'../../../intern/smoke/extern',
]
@@ -103,6 +104,9 @@ if env['WITH_BF_GAMEENGINE']:
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
+if env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_DEBUG']:
+ defs.append('WITH_CYCLES_DEBUG')
+
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
diff --git a/source/blender/render/extern/include/RE_bake.h b/source/blender/render/extern/include/RE_bake.h
index 481da452529..0750ea1aa28 100644
--- a/source/blender/render/extern/include/RE_bake.h
+++ b/source/blender/render/extern/include/RE_bake.h
@@ -32,6 +32,7 @@
#ifndef __RE_BAKE_H__
#define __RE_BAKE_H__
+struct ImBuf;
struct Render;
struct Mesh;
@@ -49,29 +50,28 @@ typedef struct BakeImages {
} BakeImages;
typedef struct BakePixel {
- int primitive_id;
+ int primitive_id, object_id;
float uv[2];
float du_dx, du_dy;
float dv_dx, dv_dy;
} BakePixel;
typedef struct BakeHighPolyData {
- struct BakePixel *pixel_array;
struct Object *ob;
struct ModifierData *tri_mod;
struct Mesh *me;
char restrict_flag;
+ bool is_flip_object;
float obmat[4][4];
float imat[4][4];
- float rotmat[4][4];
} BakeHighPolyData;
/* external_engine.c */
bool RE_bake_has_engine(struct Render *re);
bool RE_bake_engine(
- struct Render *re, struct Object *object, const BakePixel pixel_array[],
+ struct Render *re, struct Object *object, const int object_id, const BakePixel pixel_array[],
const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]);
/* bake.c */
@@ -81,7 +81,7 @@ bool RE_bake_internal(
const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]);
bool RE_bake_pixels_populate_from_objects(
- struct Mesh *me_low, BakePixel pixel_array_from[],
+ 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);
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index 24f8cbee401..4e48060c54f 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -60,6 +60,8 @@ struct BakePixel;
#define RE_USE_SHADING_NODES 16
#define RE_USE_EXCLUDE_LAYERS 32
#define RE_USE_SAVE_BUFFERS 64
+#define RE_USE_TEXTURE_PREVIEW 128
+#define RE_USE_SHADING_NODES_CUSTOM 256
/* RenderEngine.flag */
#define RE_ENGINE_ANIMATION 1
@@ -87,7 +89,7 @@ typedef struct RenderEngineType {
void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Scene *scene);
void (*render)(struct RenderEngine *engine, struct Scene *scene);
- void (*bake)(struct RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type, const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result);
+ void (*bake)(struct RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type, 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);
@@ -134,15 +136,20 @@ 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);
-struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername);
+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_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int merge_results);
+void RE_engine_active_view_set(RenderEngine *engine, const char *viewname);
+float RE_engine_get_camera_shift_x(RenderEngine *engine, struct Object *camera);
+void RE_engine_get_camera_model_matrix(RenderEngine *engine, struct Object *camera, float *r_modelmat);
+
int RE_engine_test_break(RenderEngine *engine);
void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info);
void RE_engine_update_progress(RenderEngine *engine, float progress);
void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float mem_peak);
void RE_engine_report(RenderEngine *engine, int type, const char *msg);
+void RE_engine_set_error_message(RenderEngine *engine, const char *msg);
int RE_engine_render(struct Render *re, int do_all);
@@ -157,7 +164,7 @@ void RE_engines_exit(void);
RenderEngineType *RE_engines_find(const char *idname);
-void RE_engine_get_current_tiles(struct Render *re, int *total_tiles_r, rcti **tiles_r);
+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);
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 3b54de4c943..fd56c47c309 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -35,8 +35,10 @@
#include "DNA_listBase.h"
#include "DNA_vec_types.h"
+struct bMovieHandle;
struct bNodeTree;
struct Image;
+struct ImageFormatData;
struct Main;
struct NodeBlurData;
struct Object;
@@ -46,6 +48,8 @@ struct ReportList;
struct Scene;
struct SceneRenderLayer;
struct EnvMap;
+struct RenderResult;
+struct StampData;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* this include is what is exposed of render to outside world */
@@ -65,6 +69,19 @@ typedef struct Render Render;
* and how it's converted
*/
+typedef struct RenderView {
+ 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;
+
+} RenderView;
+
typedef struct RenderPass {
struct RenderPass *next, *prev;
int passtype, channels;
@@ -72,11 +89,23 @@ typedef struct RenderPass {
char chan_id[8]; /* amount defined in openexr_multi.h */
float *rect;
int rectx, recty;
+
+ char internal_name[64]; /* EXR_PASS_MAXNAME */
+ char view[64]; /* EXR_VIEW_MAXNAME */
+ int view_id; /* quick lookup */
+
+ int debug_type;
} RenderPass;
+enum {
+ RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS = 0,
+ RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES = 1,
+ RENDER_PASS_DEBUG_RAY_BOUNCES = 2,
+};
+
/* 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 rectf, for renderlayers read from files it is a real pass */
+/* 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;
@@ -87,8 +116,10 @@ typedef struct RenderLayer {
struct Material *mat_override;
struct Group *light_override;
-
- float *rectf; /* 4 float, standard rgba buffer (read not above!) */
+
+ /* 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
@@ -109,6 +140,9 @@ typedef struct RenderResult {
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 */
+
/* 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 */
@@ -124,6 +158,9 @@ typedef struct RenderResult {
/* the main buffers */
ListBase layers;
+ /* multiView maps to a StringVector in OpenEXR */
+ ListBase views;
+
/* allowing live updates: */
volatile rcti renrect;
volatile RenderLayer *renlay;
@@ -139,7 +176,9 @@ typedef struct RenderResult {
/* render info text */
char *text;
-
+ char *error;
+
+ struct StampData *stamp_data;
} RenderResult;
@@ -168,6 +207,10 @@ void RE_InitRenderCB(struct Render *re);
void RE_FreeRender(struct Render *re);
/* only called on exit */
void RE_FreeAllRender(void);
+/* Free memory used by persistent data.
+ * Invoked when loading new file.
+ */
+void RE_FreeAllPersistentData(void);
/* only call on file load */
void RE_FreeAllRenderResults(void);
/* for external render engines that can keep persistent data */
@@ -178,16 +221,18 @@ void RE_FreeRenderResult(struct RenderResult *rr);
struct RenderResult *RE_AcquireResultRead(struct Render *re);
struct RenderResult *RE_AcquireResultWrite(struct Render *re);
void RE_ReleaseResult(struct Render *re);
-void RE_AcquireResultImage(struct Render *re, struct RenderResult *rr);
+void RE_AcquireResultImageViews(struct Render *re, struct RenderResult *rr);
+void RE_ReleaseResultImageViews(struct Render *re, struct RenderResult *rr);
+void RE_AcquireResultImage(struct Render *re, struct RenderResult *rr, const int view_id);
void RE_ReleaseResultImage(struct Render *re);
void RE_SwapResult(struct Render *re, struct RenderResult **rr);
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);
+void RE_AcquiredResultGet32(struct Render *re, struct RenderResult *result, unsigned int *rect, const int view_id);
struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name);
-float *RE_RenderLayerGetPass(struct RenderLayer *rl, int passtype);
+float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, int passtype, const char *viewname);
/* obligatory initialize call, disprect is optional */
void RE_InitState(struct Render *re, struct Render *source, struct RenderData *rd,
@@ -198,6 +243,7 @@ void RE_ChangeModeFlag(struct Render *re, int flag, bool clear);
/* set up the viewplane/perspective matrix, three choices */
struct Object *RE_GetCamera(struct Render *re); /* return camera override if set */
+void RE_SetOverrideCamera(struct Render *re, struct Object *camera);
void RE_SetCamera(struct Render *re, struct Object *camera);
void RE_SetEnvmapCamera(struct Render *re, struct Object *cam_ob, float viewscale, float clipsta, float clipend);
void RE_SetWindow(struct Render *re, rctf *viewplane, float clipsta, float clipend);
@@ -227,6 +273,11 @@ void RE_init_threadcount(Render *re);
/* the main processor, assumes all was set OK! */
void RE_TileProcessor(struct 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, const size_t width, const size_t height, void **movie_ctx_arr,
+ const size_t totvideos, bool preview);
+
/* only RE_NewRender() needed, main Blender render calls */
void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene,
struct SceneRenderLayer *srl, struct Object *camera_override,
@@ -238,6 +289,9 @@ void RE_RenderFreestyleStrokes(struct Render *re, struct Main *bmain, struct Sce
void RE_RenderFreestyleExternal(struct Render *re);
#endif
+void RE_SetActiveRenderView(struct Render *re, const char *viewname);
+const char *RE_GetActiveRenderView(struct Render *re);
+
/* error reporting */
void RE_SetReports(struct Render *re, struct ReportList *reports);
@@ -245,7 +299,7 @@ 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, int compress);
+bool RE_WriteRenderResult(struct ReportList *reports, RenderResult *rr, const char *filename, struct ImageFormatData *imf, const bool multiview, const char *view);
struct RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty);
extern const float default_envmap_layout[];
@@ -271,6 +325,10 @@ void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nbd, int xsize, int ysize,
int RE_seq_render_active(struct Scene *scene, struct RenderData *rd);
+bool RE_layers_have_name(struct RenderResult *result);
+
+struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname);
+
/* shaded view or baking options */
#define RE_BAKE_LIGHT 0 /* not listed in rna_scene.c -> can't be enabled! */
#define RE_BAKE_ALL 1
@@ -292,6 +350,7 @@ void RE_Database_Baking(struct Render *re, struct Main *bmain, struct Scene *sce
void RE_DataBase_GetView(struct Render *re, float mat[4][4]);
void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[4][4]);
+void RE_GetCameraModelMatrix(struct Render *re, struct Object *camera, float r_mat[4][4]);
struct Scene *RE_GetScene(struct Render *re);
bool RE_force_single_renderlayer(struct Scene *scene);
@@ -299,5 +358,20 @@ bool RE_is_rendering_allowed(struct Scene *scene, struct Object *camera_override
bool RE_allow_render_generic_object(struct Object *ob);
+/******* defined in render_result.c *********/
+
+bool RE_HasFakeLayer(RenderResult *res);
+bool RE_RenderResult_is_stereo(RenderResult *res);
+struct RenderView *RE_RenderViewGetById(struct RenderResult *res, const int view_id);
+struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char *viewname);
+
+/******* Debug pass helper functions *********/
+
+#ifdef WITH_CYCLES_DEBUG
+int RE_debug_pass_num_channels_get(int pass_type);
+const char *RE_debug_pass_name_get(int pass_type);
+int RE_debug_pass_type_get(struct Render *re);
+#endif
+
#endif /* __RE_PIPELINE_H__ */
diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h
index eb861d440d8..6e1f128b7a5 100644
--- a/source/blender/render/extern/include/RE_render_ext.h
+++ b/source/blender/render/extern/include/RE_render_ext.h
@@ -39,13 +39,11 @@
/* called by meshtools */
struct DerivedMesh;
struct ImagePool;
-struct LinkNode;
struct MTex;
struct Scene;
-struct View3D;
/* particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */
-int externtex(struct MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool);
+int externtex(struct MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool, const bool skip_load_image);
/* particle.c */
void texture_rgb_blend(float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype);
@@ -58,8 +56,16 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove);
/* dynamicpaint.c */
struct Material *RE_init_sample_material(struct Material *orig_mat, struct Scene *scene);
void RE_free_sample_material(struct Material *mat);
-void RE_sample_material_color(struct Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3],
- int face_index, short hit_quad, struct DerivedMesh *orcoDm, struct Object *ob);
+void RE_sample_material_color(
+ struct Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3],
+ int tri_index, struct DerivedMesh *orcoDm, struct Object *ob);
+/* pointdensity.c */
+struct PointDensity;
+
+void RE_sample_point_density(struct Scene *scene, struct PointDensity *pd, int resolution, float *values);
+
+void RE_init_texture_rng(void);
+void RE_exit_texture_rng(void);
#endif /* __RE_RENDER_EXT_H__ */
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index da847d235f2..f78c0aa8cb2 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -86,12 +86,12 @@ struct ShadeInputCopy {
typedef struct ShadeInputUV {
float dxuv[3], dyuv[3], uv[3];
- char *name;
+ const char *name;
} ShadeInputUV;
typedef struct ShadeInputCol {
float col[4];
- char *name;
+ const char *name;
} ShadeInputCol;
/* localized renderloop data */
@@ -178,7 +178,7 @@ typedef struct ShadeInput {
int layflag, passflag, combinedflag;
struct Group *light_override;
struct Material *mat_override;
-
+
#ifdef RE_RAYCOUNTER
RayCounter raycounter;
#endif
@@ -198,14 +198,15 @@ struct ImagePool;
struct Object;
/* this one uses nodes */
-int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool, bool scene_color_manage);
+int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool, 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);
+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 ShadeInput *shi, struct MTex *mtex,
struct ImagePool *pool);
float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]);
+void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]);
/* shaded view and bake */
struct Render;
diff --git a/source/blender/render/intern/include/envmap.h b/source/blender/render/intern/include/envmap.h
index c813e88c656..627e6c0e1e6 100644
--- a/source/blender/render/intern/include/envmap.h
+++ b/source/blender/render/intern/include/envmap.h
@@ -47,7 +47,7 @@ struct TexResult;
struct ImagePool;
void make_envmaps(struct Render *re);
-int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool);
+int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool, const bool skip_image_load);
void env_rotate_scene(struct Render *re, float mat[4][4], int do_rotate);
#endif /* __ENVMAP_H__ */
diff --git a/source/blender/render/intern/include/initrender.h b/source/blender/render/intern/include/initrender.h
index 1f11cdc6729..87e2d2519d5 100644
--- a/source/blender/render/intern/include/initrender.h
+++ b/source/blender/render/intern/include/initrender.h
@@ -33,7 +33,6 @@
#ifndef __INITRENDER_H__
#define __INITRENDER_H__
-struct Object;
/* Functions */
diff --git a/source/blender/render/intern/include/occlusion.h b/source/blender/render/intern/include/occlusion.h
index 2f3ac2a7bff..4a70d691436 100644
--- a/source/blender/render/intern/include/occlusion.h
+++ b/source/blender/render/intern/include/occlusion.h
@@ -35,11 +35,8 @@
struct Render;
struct ShadeInput;
-struct ShadeResult;
struct RenderPart;
struct ShadeSample;
-struct DerivedMesh;
-struct ObjectRen;
void make_occ_tree(struct Render *re);
void free_occ(struct Render *re);
diff --git a/source/blender/render/intern/include/pixelshading.h b/source/blender/render/intern/include/pixelshading.h
index faf8c5f54f5..8f23455564f 100644
--- a/source/blender/render/intern/include/pixelshading.h
+++ b/source/blender/render/intern/include/pixelshading.h
@@ -32,7 +32,6 @@
#ifndef __PIXELSHADING_H__
#define __PIXELSHADING_H__
-struct ImagePool;
/**
* Render the pixel at (x,y) for object ap. Apply the jitter mask.
diff --git a/source/blender/render/intern/include/pointdensity.h b/source/blender/render/intern/include/pointdensity.h
index e0c293e2473..1d1e808e8d3 100644
--- a/source/blender/render/intern/include/pointdensity.h
+++ b/source/blender/render/intern/include/pointdensity.h
@@ -37,10 +37,12 @@
* Make point density kd-trees for all point density textures in the scene
*/
+struct PointDensity;
struct Render;
struct TexResult;
-void cache_pointdensity(struct Render *re, struct Tex *tex);
+void free_pointdensity(struct PointDensity *pd);
+void cache_pointdensity(struct Render *re, struct PointDensity *pd);
void make_pointdensities(struct Render *re);
void free_pointdensities(struct Render *re);
int pointdensitytex(struct Tex *tex, const float texvec[3], struct TexResult *texres);
diff --git a/source/blender/render/intern/include/rayintersection.h b/source/blender/render/intern/include/rayintersection.h
index 9c0835af56f..3607e66a237 100644
--- a/source/blender/render/intern/include/rayintersection.h
+++ b/source/blender/render/intern/include/rayintersection.h
@@ -121,7 +121,7 @@ typedef struct Isect {
/* arbitrary, but can't use e.g. FLT_MAX because of precision issues */
#define RE_RAYTRACE_MAXDIST 1e15f
-#define RE_RAYTRACE_EPSILON -FLT_EPSILON
+#define RE_RAYTRACE_EPSILON 0.0f
#ifdef __cplusplus
}
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
index 90ff69dbfbe..90ad0fa30d7 100644
--- a/source/blender/render/intern/include/render_result.h
+++ b/source/blender/render/intern/include/render_result.h
@@ -38,6 +38,7 @@
#define RR_USE_EXR 1
#define RR_ALL_LAYERS NULL
+#define RR_ALL_VIEWS NULL
struct ImBuf;
struct ListBase;
@@ -53,12 +54,15 @@ struct ColorManagedViewSettings;
/* New */
struct RenderResult *render_result_new(struct Render *re,
- struct rcti *partrct, int crop, int savebuffers, const char *layername);
+ struct rcti *partrct, int crop, int savebuffers, const char *layername, const char *viewname);
struct RenderResult *render_result_new_full_sample(struct Render *re,
- struct ListBase *lb, struct rcti *partrct, int crop, int savebuffers);
+ struct ListBase *lb, struct rcti *partrct, int crop, int savebuffers, const char *viewname);
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);
+
/* Merge */
void render_result_merge(struct RenderResult *rr, struct RenderResult *rrpart);
@@ -75,10 +79,11 @@ void render_result_single_layer_end(struct Render *re);
/* EXR Tile File Render */
+void render_result_save_empty_result_tiles(struct Render *re);
void render_result_exr_file_begin(struct Render *re);
void render_result_exr_file_end(struct Render *re);
-void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart);
+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_sample(struct Render *re, int sample);
@@ -91,15 +96,19 @@ 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);
+struct ImBuf *render_result_rect_to_ibuf(struct RenderResult *rr, struct RenderData *rd, const int view_id);
void render_result_rect_from_ibuf(struct RenderResult *rr, struct RenderData *rd,
- struct ImBuf *ibuf);
+ struct ImBuf *ibuf, const int view_id);
-void render_result_rect_fill_zero(struct RenderResult *rr);
+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 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);
#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 b87b1e6f367..3569cb2c168 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -58,7 +58,6 @@ struct MemArena;
struct VertTableNode;
struct VlakTableNode;
struct GHash;
-struct RenderBuckets;
struct ObjectInstanceRen;
struct RayObject;
struct RayFace;
@@ -123,8 +122,7 @@ enum {
};
/* controls state of render, everything that's read-only during render stage */
-struct Render
-{
+struct Render {
struct Render *next, *prev;
char name[RE_MAXNAME];
int slot;
@@ -194,6 +192,7 @@ struct Render
struct Object *camera_override;
unsigned int lay, layer_override;
+ ThreadRWMutex partsmutex;
ListBase parts;
/* render engine */
@@ -275,6 +274,9 @@ struct Render
struct ImagePool *pool;
struct EvaluationContext *eval_ctx;
+
+ void **movie_ctx_arr;
+ char viewname[MAX_NAME];
};
/* ------------------------------------------------------------------------- */
@@ -365,6 +367,14 @@ typedef struct ObjectInstanceRen {
struct RayObject *raytree;
int transform_primitives;
+ /* Particle info */
+ float part_index;
+ float part_age;
+ float part_lifetime;
+ float part_size;
+ float part_co[3];
+ float part_vel[3];
+ float part_avel[3];
} ObjectInstanceRen;
/* ------------------------------------------------------------------------- */
@@ -388,7 +398,6 @@ struct halosort {
/* ------------------------------------------------------------------------- */
struct Material;
-struct MTFace;
struct ImagePool;
typedef struct RadFace {
@@ -424,6 +433,7 @@ typedef struct HaloRen {
unsigned int lay;
struct Material *mat;
struct ImagePool *pool;
+ bool skip_load_image;
} HaloRen;
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
index 88b639c4ba9..308903c6c6d 100644
--- a/source/blender/render/intern/include/rendercore.h
+++ b/source/blender/render/intern/include/rendercore.h
@@ -34,14 +34,11 @@
#include "render_types.h"
-struct HaloRen;
struct ShadeInput;
struct ShadeResult;
struct World;
struct RenderPart;
struct RenderLayer;
-struct ObjectRen;
-struct ListBase;
struct RayObject;
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/include/shadbuf.h b/source/blender/render/intern/include/shadbuf.h
index 7c168baada7..ddf5de8d974 100644
--- a/source/blender/render/intern/include/shadbuf.h
+++ b/source/blender/render/intern/include/shadbuf.h
@@ -34,7 +34,6 @@
#include "render_types.h"
-struct ObjectRen;
/**
* Calculates shadowbuffers for a vector of shadow-giving lamps
@@ -57,8 +56,7 @@ void threaded_makeshadowbufs(struct Render *re);
float testshadowbuf(struct Render *re, struct ShadBuf *shb, const float rco[3], const float dxco[3], const float dyco[3], float inp, float mat_bias);
/**
- * Determines the shadow factor for lamp <lar>, between <p1>
- * and <p2>. (Which CS?)
+ * Determines the shadow factor for lamp \a lar, between \a p1 and \a p2. (Which CS?)
*/
float shadow_halo(LampRen *lar, const float p1[3], const float p2[3]);
diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h
index 4f6e005d742..11dcc9d9e80 100644
--- a/source/blender/render/intern/include/shading.h
+++ b/source/blender/render/intern/include/shading.h
@@ -33,7 +33,6 @@ struct RenderLayer;
struct PixStr;
struct LampRen;
struct VlakRen;
-struct StrandSegment;
struct StrandPoint;
struct ObjectInstanceRen;
struct Isect;
diff --git a/source/blender/render/intern/include/sss.h b/source/blender/render/intern/include/sss.h
index 91a8b91e638..0952c6bff65 100644
--- a/source/blender/render/intern/include/sss.h
+++ b/source/blender/render/intern/include/sss.h
@@ -55,7 +55,6 @@ void scatter_tree_free(ScatterTree *tree);
struct Render;
struct Material;
-struct VlakRen;
void make_sss_tree(struct Render *re);
void sss_add_points(Render *re, float (*co)[3], float (*color)[3], float *area, int totpoint);
diff --git a/source/blender/render/intern/include/strand.h b/source/blender/render/intern/include/strand.h
index fdcce687f54..5687ef3c837 100644
--- a/source/blender/render/intern/include/strand.h
+++ b/source/blender/render/intern/include/strand.h
@@ -34,9 +34,6 @@ struct StrandBuffer;
struct ShadeSample;
struct StrandPart;
struct Render;
-struct RenderPart;
-struct RenderBuckets;
-struct RenderPrimitiveIterator;
struct ZSpan;
struct ObjectInstanceRen;
struct StrandSurface;
diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h
index ff5004fd7f0..ed161e186b8 100644
--- a/source/blender/render/intern/include/texture.h
+++ b/source/blender/render/intern/include/texture.h
@@ -56,6 +56,11 @@
_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 HaloRen;
@@ -81,8 +86,8 @@ void render_realtime_texture(struct ShadeInput *shi, struct Image *ima);
/* imagetexture.h */
-int imagewraposa(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], const float dxt[2], const float dyt[2], struct TexResult *texres, struct ImagePool *pool);
-int imagewrap(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], struct TexResult *texres, 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 ec30c3241ab..cf804d75d70 100644
--- a/source/blender/render/intern/include/zbuf.h
+++ b/source/blender/render/intern/include/zbuf.h
@@ -36,7 +36,6 @@
struct RenderPart;
struct RenderLayer;
struct LampRen;
-struct VlakRen;
struct ListBase;
struct ZSpan;
struct APixstrand;
diff --git a/source/blender/render/intern/raytrace/rayobject_instance.cpp b/source/blender/render/intern/raytrace/rayobject_instance.cpp
index 01e592cba0c..d080ddcc375 100644
--- a/source/blender/render/intern/raytrace/rayobject_instance.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_instance.cpp
@@ -197,7 +197,7 @@ static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max)
//There must be a faster way than rotating all the 8 vertexs of the BB
for (i = 0; i < 8; i++) {
- for (j = 0; j < 3; j++) t[j] = i & (1 << j) ? M[j] : m[j];
+ for (j = 0; j < 3; j++) t[j] = (i & (1 << j)) ? M[j] : m[j];
mul_m4_v3(obj->target2global, t);
DO_MINMAX(t, min, max);
}
diff --git a/source/blender/render/intern/raytrace/rayobject_octree.cpp b/source/blender/render/intern/raytrace/rayobject_octree.cpp
index 6cbb0761358..b21197e728d 100644
--- a/source/blender/render/intern/raytrace/rayobject_octree.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_octree.cpp
@@ -119,7 +119,8 @@ static RayObjectAPI octree_api =
/* within one octree node, a set of 3x15 bits defines a 'boundbox' to OR with */
#define OCVALRES 15
-#define BROW16(min, max) (((max) >= OCVALRES ? 0xFFFF : (1 << (max + 1)) - 1) - ((min > 0) ? ((1 << (min)) - 1) : 0))
+#define BROW16(min, max) \
+ (((max) >= OCVALRES ? 0xFFFF : (1 << ((max) + 1)) - 1) - (((min) > 0) ? ((1 << (min)) - 1) : 0))
static void calc_ocval_face(float *v1, float *v2, float *v3, float *v4, short x, short y, short z, OcVal *ov)
{
diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c
index 15634c93491..0210bec5ab4 100644
--- a/source/blender/render/intern/source/bake.c
+++ b/source/blender/render/intern/source/bake.c
@@ -34,6 +34,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
+#include "BLI_rand.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
@@ -54,8 +55,6 @@
#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
-#include "RE_bake.h"
-
/* local include */
#include "rayintersection.h"
#include "rayobject.h"
@@ -77,6 +76,8 @@ extern struct Render R;
typedef struct BakeShade {
+ int thread;
+
ShadeSample ssamp;
ObjectInstanceRen *obi;
VlakRen *vlr;
@@ -374,8 +375,8 @@ static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist,
bs->vcol->b = col[2];
}
else {
- const char *imcol = (char *)(bs->rect + bs->rectx * y + x);
- copy_v4_v4_char((char *)imcol, (char *)col);
+ char *imcol = (char *)(bs->rect + bs->rectx * y + x);
+ copy_v4_v4_char(imcol, (char *)col);
}
}
if (bs->rect_mask) {
@@ -613,6 +614,10 @@ static int get_next_bake_face(BakeShade *bs)
for (; obi; obi = obi->next, v = 0) {
obr = obi->obr;
+ /* only allow non instances here */
+ if (obr->flag & R_INSTANCEABLE)
+ continue;
+
for (; v < obr->totvlak; v++) {
vlr = RE_findOrAddVlak(obr, v);
@@ -735,6 +740,9 @@ static void bake_single_vertex(BakeShade *bs, VertRen *vert, float u, float v)
MLoopCol *basevcol;
MLoop *mloop;
+ /* per vertex fixed seed */
+ BLI_thread_srandom(bs->thread, vert->index);
+
origindex = RE_vertren_get_origindex(bs->obi->obr, vert, 0);
if (!origindex || *origindex == ORIGINDEX_NONE)
return;
@@ -809,6 +817,9 @@ static void shade_tface(BakeShade *bs)
Image *ima = tface->tpage;
float vec[4][2];
int a, i1, i2, i3;
+
+ /* per face fixed seed */
+ BLI_thread_srandom(bs->thread, vlr->index);
/* check valid zspan */
if (ima != bs->ima) {
@@ -982,8 +993,12 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
int a, vdone = false, result = BAKE_RESULT_OK;
bool use_mask = false;
bool use_displacement_buffer = false;
- bool do_manage = BKE_scene_check_color_management_enabled(re->scene);
-
+ bool do_manage = false;
+
+ if (ELEM(type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
+ do_manage = BKE_scene_check_color_management_enabled(re->scene);
+ }
+
re->scene_color_manage = BKE_scene_check_color_management_enabled(re->scene);
/* initialize render global */
@@ -1031,6 +1046,8 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
/* get the threads running */
for (a = 0; a < re->r.threads; a++) {
+ handles[a].thread = a;
+
/* set defaults in handles */
handles[a].ssamp.shi[0].lay = re->lay;
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c
index 90deac2de32..dee75d43f36 100644
--- a/source/blender/render/intern/source/bake_api.c
+++ b/source/blender/render/intern/source/bake_api.c
@@ -30,10 +30,11 @@
*
* The Bake API is fully implemented with Python rna functions. The operator expects/call a function:
*
- * ``def bake(scene, object, pass_type, pixel_array, num_pixels, depth, result)``
+ * ``def bake(scene, object, pass_type, object_id, pixel_array, num_pixels, depth, result)``
* - scene: current scene (Python object)
* - object: object to render (Python object)
* - pass_type: pass to render (string, e.g., "COMBINED", "AO", "NORMAL", ...)
+ * - object_id: index of object to bake (to use with the pixel_array)
* - pixel_array: list of primitive ids and barycentric coordinates to bake(Python object, see bake_pixel)
* - num_pixels: size of pixel_array, number of pixels to bake (int)
* - depth: depth of pixels to return (int, assuming always 4 now)
@@ -45,17 +46,17 @@
*
* pixel_array is a Python object storing BakePixel elements:
*
- * <pre>
+ * \code{.c}
* struct BakePixel {
- * int primitive_id;
+ * int primitive_id, object_id;
* float uv[2];
* float du_dx, du_dy;
* float dv_dx, dv_dy;
* };
- * </pre>
+ * \endcode
*
* In python you have access to:
- * - ``primitive_id``, ``uv``, ``du_dx``, ``du_dy``, ``next``
+ * - ``primitive_id``, ``object_id``, ``uv``, ``du_dx``, ``du_dy``, ``next``
* - ``next()`` is a function that returns the next #BakePixel in the array.
*
* \note Pixels that should not be baked have ``primitive_id == -1``
@@ -63,6 +64,8 @@
* For a complete implementation example look at the Cycles Bake commit.
*/
+#include <limits.h>
+
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
@@ -72,6 +75,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_image.h"
#include "BKE_node.h"
+#include "BKE_mesh.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -126,12 +130,16 @@ static void store_bake_pixel(void *handle, int x, int y, float u, float v)
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. */
+
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;
}
void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, char *mask)
@@ -271,7 +279,7 @@ static void calc_barycentric_from_point(
* This function populates pixel_array and returns TRUE if things are correct
*/
static bool cast_ray_highpoly(
- BVHTreeFromMesh *treeData, TriTessFace *triangles[], BakeHighPolyData *highpoly,
+ BVHTreeFromMesh *treeData, TriTessFace *triangles[], BakePixel *pixel_array, BakeHighPolyData *highpoly,
const float co[3], const float dir[3], const int pixel_id, const int tot_highpoly,
const float du_dx, const float du_dy, const float dv_dx, const float dv_dy)
{
@@ -295,7 +303,7 @@ static bool cast_ray_highpoly(
mul_v3_m4v3(co_high, highpoly[i].imat, co);
/* rotates */
- mul_v3_m4v3(dir_high, highpoly[i].rotmat, dir);
+ mul_v3_mat3_m4v3(dir_high, highpoly[i].imat, dir);
normalize_v3(dir_high);
/* cast ray */
@@ -322,22 +330,22 @@ static bool cast_ray_highpoly(
}
}
- for (i = 0; i < tot_highpoly; i++) {
- if (hit_mesh == i) {
- calc_barycentric_from_point(triangles[i], hits[i].index, hits[i].co, &primitive_id, uv);
- highpoly[i].pixel_array[pixel_id].primitive_id = primitive_id;
- copy_v2_v2(highpoly[i].pixel_array[pixel_id].uv, uv);
-
- /* the differentials are relative to the UV/image space, so the highpoly differentials
- * are the same as the low poly differentials */
- highpoly[i].pixel_array[pixel_id].du_dx = du_dx;
- highpoly[i].pixel_array[pixel_id].du_dy = du_dy;
- highpoly[i].pixel_array[pixel_id].dv_dx = dv_dx;
- highpoly[i].pixel_array[pixel_id].dv_dy = dv_dy;
- }
- else {
- highpoly[i].pixel_array[pixel_id].primitive_id = -1;
- }
+ if (hit_mesh != -1) {
+ calc_barycentric_from_point(triangles[hit_mesh], hits[hit_mesh].index, hits[hit_mesh].co, &primitive_id, uv);
+ pixel_array[pixel_id].primitive_id = primitive_id;
+ pixel_array[pixel_id].object_id = hit_mesh;
+ copy_v2_v2(pixel_array[pixel_id].uv, uv);
+
+ /* the differentials are relative to the UV/image space, so the highpoly differentials
+ * are the same as the low poly differentials */
+ pixel_array[pixel_id].du_dx = du_dx;
+ pixel_array[pixel_id].du_dy = du_dy;
+ pixel_array[pixel_id].dv_dx = dv_dx;
+ pixel_array[pixel_id].dv_dy = dv_dy;
+ }
+ else {
+ pixel_array[pixel_id].primitive_id = -1;
+ pixel_array[pixel_id].object_id = -1;
}
MEM_freeN(hits);
@@ -352,99 +360,76 @@ static void mesh_calc_tri_tessface(
TriTessFace *triangles, Mesh *me, bool tangent, DerivedMesh *dm)
{
int i;
- int p_id;
- MFace *mface;
MVert *mvert;
TSpace *tspace;
float *precomputed_normals = NULL;
bool calculate_normal;
+ const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
+ MLoopTri *looptri;
+ /* calculate normal for each polygon only once */
+ unsigned int mpoly_prev = UINT_MAX;
+ float no[3];
- mface = CustomData_get_layer(&me->fdata, CD_MFACE);
mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
+ looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
if (tangent) {
DM_ensure_normals(dm);
- DM_add_tangent_layer(dm);
+ DM_calc_loop_tangents(dm);
- precomputed_normals = dm->getTessFaceDataArray(dm, CD_NORMAL);
+ precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL);
calculate_normal = precomputed_normals ? false : true;
- //mface = dm->getTessFaceArray(dm);
- //mvert = dm->getVertArray(dm);
-
- tspace = dm->getTessFaceDataArray(dm, CD_TANGENT);
+ tspace = dm->getLoopDataArray(dm, CD_TANGENT);
BLI_assert(tspace);
}
- p_id = -1;
- for (i = 0; i < me->totface; i++) {
- MFace *mf = &mface[i];
- TSpace *ts = tangent ? &tspace[i * 4] : NULL;
+ BKE_mesh_recalc_looptri(
+ me->mloop, me->mpoly,
+ me->mvert,
+ me->totloop, me->totpoly,
+ looptri);
- p_id++;
+ for (i = 0; i < tottri; i++) {
+ MLoopTri *lt = &looptri[i];
+ MPoly *mp = &me->mpoly[lt->poly];
- triangles[p_id].mverts[0] = &mvert[mf->v1];
- triangles[p_id].mverts[1] = &mvert[mf->v2];
- triangles[p_id].mverts[2] = &mvert[mf->v3];
- triangles[p_id].is_smooth = (mf->flag & ME_SMOOTH) != 0;
+ 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[p_id].tspace[0] = &ts[0];
- triangles[p_id].tspace[1] = &ts[1];
- triangles[p_id].tspace[2] = &ts[2];
+ 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 (mf->v4 != 0) {
- normal_quad_v3(triangles[p_id].normal,
- mvert[mf->v1].co,
- mvert[mf->v2].co,
- mvert[mf->v3].co,
- mvert[mf->v4].co);
- }
- else {
- normal_tri_v3(triangles[p_id].normal,
- triangles[p_id].mverts[0]->co,
- triangles[p_id].mverts[1]->co,
- triangles[p_id].mverts[2]->co);
+ if (lt->poly != mpoly_prev) {
+ const MPoly *mp = &me->mpoly[lt->poly];
+ 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[p_id].normal, &precomputed_normals[3 * i]);
- }
- }
-
- /* 4 vertices in the face */
- if (mf->v4 != 0) {
- p_id++;
-
- triangles[p_id].mverts[0] = &mvert[mf->v1];
- triangles[p_id].mverts[1] = &mvert[mf->v3];
- triangles[p_id].mverts[2] = &mvert[mf->v4];
- triangles[p_id].is_smooth = (mf->flag & ME_SMOOTH) != 0;
-
- if (tangent) {
- triangles[p_id].tspace[0] = &ts[0];
- triangles[p_id].tspace[1] = &ts[2];
- triangles[p_id].tspace[2] = &ts[3];
-
- /* same normal as the other "triangle" */
- copy_v3_v3(triangles[p_id].normal, triangles[p_id - 1].normal);
+ copy_v3_v3(triangles[i].normal, &precomputed_normals[lt->poly]);
}
}
}
- BLI_assert(p_id < me->totface * 2);
+ MEM_freeN(looptri);
}
bool RE_bake_pixels_populate_from_objects(
- struct Mesh *me_low, BakePixel pixel_array_from[],
+ 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];
+ float imat_low[4][4];
bool is_cage = me_cage != NULL;
bool result = true;
@@ -488,6 +473,7 @@ bool RE_bake_pixels_populate_from_objects(
mesh_calc_tri_tessface(tris_high[i], highpoly[i].me, false, NULL);
dm_highpoly[i] = CDDM_from_mesh(highpoly[i].me);
+ DM_ensure_tessface(dm_highpoly[i]);
if (dm_highpoly[i]->getNumTessFaces(dm_highpoly[i]) != 0) {
/* Create a bvh-tree for each highpoly object */
@@ -508,10 +494,7 @@ bool RE_bake_pixels_populate_from_objects(
primitive_id = pixel_array_from[i].primitive_id;
if (primitive_id == -1) {
- int j;
- for (j = 0; j < tot_highpoly; j++) {
- highpoly[j].pixel_array[i].primitive_id = -1;
- }
+ pixel_array_to[i].primitive_id = -1;
continue;
}
@@ -530,7 +513,7 @@ bool RE_bake_pixels_populate_from_objects(
}
/* cast ray */
- if (!cast_ray_highpoly(treeData, tris_high, highpoly, co, dir, i, tot_highpoly,
+ if (!cast_ray_highpoly(treeData, tris_high, pixel_array_to, highpoly, co, dir, i, tot_highpoly,
pixel_array_from[i].du_dx, pixel_array_from[i].du_dy,
pixel_array_from[i].dv_dx, pixel_array_from[i].dv_dy)) {
/* if it fails mask out the original pixel array */
@@ -928,7 +911,6 @@ bool RE_bake_internal(
case SCE_PASS_UV:
{
return bake_uv(pixel_array, num_pixels, depth, result);
- break;
}
default:
break;
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 69dd9607c3b..ee28c3b286f 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -44,7 +44,7 @@
# include "BLI_edgehash.h"
#endif
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "DNA_material_types.h"
#include "DNA_curve_types.h"
@@ -82,9 +82,7 @@
#include "BKE_particle.h"
#include "BKE_scene.h"
-
#include "PIL_time.h"
-#include "IMB_imbuf_types.h"
#include "envmap.h"
#include "occlusion.h"
@@ -103,8 +101,6 @@
#include "zbuf.h"
#include "sunsky.h"
-#include "RE_render_ext.h"
-
/* 10 times larger than normal epsilon, test it on default nurbs sphere with ray_transp (for quad detection) */
/* or for checking vertex normal flips */
#define FLT_EPSILON10 1.19209290e-06F
@@ -134,6 +130,9 @@
/* ------------------------------------------------------------------------- */
+#define CD_MASK_RENDER_INTERNAL \
+ (CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL)
+
static void split_v_renderfaces(ObjectRen *obr, int startvlak, int UNUSED(startvert), int UNUSED(usize), int vsize, int uIndex, int UNUSED(cyclu), int cyclv)
{
int vLen = vsize-1+(!!cyclv);
@@ -382,7 +381,7 @@ static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, bool do_verte
{
int a;
- /* clear all vertex normals */
+ /* clear all vertex normals */
if (do_vertex_normal) {
for (a=0; a<obr->totvert; a++) {
VertRen *ver= RE_findOrAddVert(obr, a);
@@ -390,8 +389,8 @@ static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, bool do_verte
}
}
- /* calculate cos of angles and point-masses, use as weight factor to
- * add face normal to vertex */
+ /* calculate cos of angles and point-masses, use as weight factor to
+ * add face normal to vertex */
for (a=0; a<obr->totvlak; a++) {
VlakRen *vlr= RE_findOrAddVlak(obr, a);
if (do_vertex_normal && vlr->flag & ME_SMOOTH) {
@@ -408,7 +407,7 @@ static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, bool do_verte
}
}
- /* do solid faces */
+ /* do solid faces */
for (a=0; a<obr->totvlak; a++) {
VlakRen *vlr= RE_findOrAddVlak(obr, a);
@@ -581,6 +580,17 @@ static void autosmooth(Render *UNUSED(re), ObjectRen *obr, float mat[4][4], shor
VlakRen *vlr;
int a, totvert;
+ float rot[3][3];
+
+ /* Note: For normals, we only want rotation, not scaling component.
+ * Negative scales (aka mirroring) give wrong results, see T44102. */
+ if (lnors) {
+ float mat3[3][3], size[3];
+
+ copy_m3_m4(mat3, mat);
+ mat3_to_rot_size(rot, size, mat3);
+ }
+
if (obr->totvert == 0)
return;
@@ -615,9 +625,8 @@ static void autosmooth(Render *UNUSED(re), ObjectRen *obr, float mat[4][4], shor
ver = RE_findOrAddVert(obr, a);
mul_m4_v3(mat, ver->co);
if (lnors) {
- mul_mat3_m4_v3(mat, ver->n);
+ mul_m3_v3(rot, ver->n);
negate_v3(ver->n);
- normalize_v3(ver->n);
}
}
for (a = 0; a < obr->totvlak; a++) {
@@ -1203,8 +1212,7 @@ static void particle_normal_ren(short ren_as, ParticleSettings *part, Render *re
sd->time = 0.0f;
sd->size = hasize;
- copy_v3_v3(vel, state->vel);
- mul_mat3_m4_v3(re->viewmat, vel);
+ mul_v3_mat3_m4v3(vel, re->viewmat, state->vel);
normalize_v3(vel);
if (part->draw & PART_DRAW_VEL_LENGTH)
@@ -1245,7 +1253,7 @@ static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int
/* get uvco */
if (sd->uvco && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
for (i=0; i<sd->totuv; i++) {
- if (num != DMCACHE_NOTFOUND) {
+ if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
MTFace *mtface = (MTFace*)CustomData_get_layer_n(&dm->faceData, CD_MTFACE, i);
mtface += num;
@@ -1262,7 +1270,7 @@ static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int
/* get mcol */
if (sd->mcol && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
for (i=0; i<sd->totcol; i++) {
- if (num != DMCACHE_NOTFOUND) {
+ if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
MCol *mc = (MCol*)CustomData_get_layer_n(&dm->faceData, CD_MCOL, i);
mc += num * 4;
@@ -1305,7 +1313,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
int totchild=0, step_nbr;
int seed, path_nbr=0, orco1=0, num;
int totface;
- const char **uv_name = NULL;
const int *index_mf_to_mpoly = NULL;
const int *index_mp_to_orig = NULL;
@@ -1326,6 +1333,9 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if ((re->r.scemode & R_VIEWPORT_PREVIEW) && (ob->mode & OB_MODE_PARTICLE_EDIT))
return 0;
+ if (part->ren_as == PART_DRAW_BB && part->bb_ob == NULL && RE_GetCamera(re) == NULL)
+ return 0;
+
/* 2. start initializing things */
/* last possibility to bail out! */
@@ -1349,11 +1359,13 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if (re->r.scemode & R_VIEWPORT_PREVIEW) { /* preview render */
totchild = (int)((float)totchild * (float)part->disp / 100.0f);
- step_nbr = part->draw_step;
+ step_nbr = 1 << part->draw_step;
}
else {
- step_nbr = part->ren_step;
+ step_nbr = 1 << part->ren_step;
}
+ if (ELEM(part->kink, PART_KINK_SPIRAL))
+ step_nbr += part->kink_extra_steps;
psys->flag |= PSYS_DRAWING;
@@ -1427,8 +1439,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
/* 2.5 setup matrices */
mul_m4_m4m4(mat, re->viewmat, ob->obmat);
invert_m4_m4(ob->imat, mat); /* need to be that way, for imat texture */
- copy_m3_m4(nmat, ob->imat);
- transpose_m3(nmat);
+ transpose_m3_m4(nmat, ob->imat);
if (psys->flag & PSYS_USE_IMAT) {
/* psys->imat is the original emitter's inverse matrix, ob->obmat is the duplicated object's matrix */
@@ -1438,7 +1449,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
/* 2.6 setup strand rendering */
if (part->ren_as == PART_DRAW_PATH && psys->pathcache) {
- path_nbr=(int)pow(2.0, (double) step_nbr);
+ path_nbr = step_nbr;
if (path_nbr) {
if (!ELEM(ma->material_type, MA_TYPE_HALO, MA_TYPE_WIRE)) {
@@ -1557,7 +1568,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if (path_nbr) {
cache = psys->pathcache[a];
- max_k = (int)cache->steps;
+ max_k = (int)cache->segments;
}
if (totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
@@ -1568,10 +1579,10 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if (path_nbr) {
cache = psys->childcache[a-totpart];
- if (cache->steps < 0)
+ if (cache->segments < 0)
continue;
- max_k = (int)cache->steps;
+ max_k = (int)cache->segments;
}
pa_time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
@@ -1855,9 +1866,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if (sd.mcol)
MEM_freeN(sd.mcol);
- if (uv_name)
- MEM_freeN(uv_name);
-
if (states)
MEM_freeN(states);
@@ -2652,8 +2660,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
negative_scale = is_negative_m4(mat);
/* local object -> world space transform for normals */
- copy_m4_m4(nmat, mat);
- transpose_m4(nmat);
+ transpose_m4_m4(nmat, mat);
invert_m4(nmat);
/* material array */
@@ -2731,12 +2738,13 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
vlr->v4= NULL;
/* to prevent float accuracy issues, we calculate normal in local object space (not world) */
- if (area_tri_v3(co3, co2, co1)>FLT_EPSILON) {
- if (negative_scale)
- normal_tri_v3(tmp, co1, co2, co3);
- else
- normal_tri_v3(tmp, co3, co2, co1);
- add_v3_v3(n, tmp);
+ if (normal_tri_v3(tmp, co1, co2, co3) > FLT_EPSILON) {
+ if (negative_scale == false) {
+ add_v3_v3(n, tmp);
+ }
+ else {
+ sub_v3_v3(n, tmp);
+ }
}
vlr->mat= matar[ dl->col ];
@@ -3170,7 +3178,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
/* origindex currently used when using autosmooth, or baking to vertex colors. */
need_origindex = (do_autosmooth || ((re->flag & R_BAKING) && (re->r.bake_flag & R_BAKE_VCOL)));
- mask= CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL;
+ mask = CD_MASK_RENDER_INTERNAL;
if (!timeoffset)
if (need_orco)
mask |= CD_MASK_ORCO;
@@ -3264,8 +3272,14 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
RE_set_customdata_names(obr, &dm->faceData);
/* add tangent layer if we need one */
- if (need_nmap_tangent!=0 && CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1)
- DM_add_tangent_layer(dm);
+ if (need_nmap_tangent!=0 && CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) {
+ bool generate_data = false;
+ if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) {
+ dm->calcLoopTangents(dm);
+ generate_data = true;
+ }
+ DM_generate_tangent_tessface_data(dm, generate_data);
+ }
/* still to do for keys: the correct local texture coordinate */
@@ -3274,12 +3288,13 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
for (a1=0; (a1<ob->totcol || (a1==0 && ob->totcol==0)); a1++) {
ma= give_render_material(re, ob, a1+1);
-
+
/* test for 100% transparent */
ok = 1;
if ((ma->alpha == 0.0f) &&
(ma->spectra == 0.0f) &&
- (ma->filter == 0.0f) &&
+ /* No need to test filter here, it's only active with MA_RAYTRANSP and we check against it below. */
+ /* (ma->filter == 0.0f) && */
(ma->mode & MA_TRANSP) &&
(ma->mode & (MA_RAYTRANSP | MA_RAYMIRROR)) == 0)
{
@@ -3323,7 +3338,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
v2= mface->v2;
v3= reverse_verts==0 ? mface->v3 : mface->v1;
v4= mface->v4;
- flag= mface->flag & ME_SMOOTH;
+ flag = do_autosmooth ? ME_SMOOTH : mface->flag & ME_SMOOTH;
vlr= RE_findOrAddVlak(obr, obr->totvlak++);
vlr->v1= RE_findOrAddVert(obr, vertofs+v1);
@@ -3807,7 +3822,9 @@ static GroupObject *add_render_lamp(Render *re, Object *ob)
}
/* set flag for spothalo en initvars */
- if (la->type==LA_SPOT && (la->mode & LA_HALO) && (la->buftype != LA_SHADBUF_DEEP)) {
+ if ((la->type == LA_SPOT) && (la->mode & LA_HALO) &&
+ (!(la->mode & LA_SHAD_BUF) || la->buftype != LA_SHADBUF_DEEP))
+ {
if (la->haint>0.0f) {
re->flag |= R_LAMPHALO;
@@ -3826,7 +3843,7 @@ static GroupObject *add_render_lamp(Render *re, Object *ob)
lar->sh_invcampos[2]*= lar->sh_zfac;
/* halfway shadow buffer doesn't work for volumetric effects */
- if (lar->buftype == LA_SHADBUF_HALFWAY)
+ if (ELEM(lar->buftype, LA_SHADBUF_HALFWAY, LA_SHADBUF_DEEP))
lar->buftype = LA_SHADBUF_REGULAR;
}
@@ -3917,7 +3934,15 @@ static bool is_object_hidden(Render *re, Object *ob)
if (re->r.scemode & R_VIEWPORT_PREVIEW) {
/* Mesh deform cages and so on mess up the preview. To avoid the problem,
* viewport doesn't show mesh object if its draw type is bounding box or wireframe.
+ * Unless it's an active smoke domain!
*/
+ ModifierData *md = NULL;
+
+ if ((md = modifiers_findByType(ob, eModifierType_Smoke)) &&
+ (modifier_isEnabled(re->scene, md, eModifierMode_Realtime)))
+ {
+ return false;
+ }
return ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE);
}
else {
@@ -4565,10 +4590,12 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset)
/* the emitter mesh wasn't rendered so the modifier stack wasn't
* evaluated with render settings */
DerivedMesh *dm;
+ const CustomDataMask mask = CD_MASK_RENDER_INTERNAL;
+
if (re->r.scemode & R_VIEWPORT_PREVIEW)
- dm = mesh_create_derived_view(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+ dm = mesh_create_derived_view(re->scene, ob, mask);
else
- dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+ dm = mesh_create_derived_render(re->scene, ob, mask);
dm->release(dm);
}
@@ -4868,7 +4895,7 @@ static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, in
/* this is to make sure we get render level duplis in groups:
* the derivedmesh must be created before init_render_mesh,
* since object_duplilist does dupliparticles before that */
- dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+ dm = mesh_create_derived_render(re->scene, ob, CD_MASK_RENDER_INTERNAL);
dm->release(dm);
for (psys=ob->particlesystem.first; psys; psys=psys->next)
@@ -4988,8 +5015,10 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
* system need to have render settings set for dupli particles */
dupli_render_particle_set(re, ob, timeoffset, 0, 1);
duplilist = object_duplilist(re->eval_ctx, re->scene, ob);
- duplilist_apply_data = duplilist_apply(ob, duplilist);
- dupli_render_particle_set(re, ob, timeoffset, 0, 0);
+ duplilist_apply_data = duplilist_apply(ob, NULL, duplilist);
+ /* postpone 'dupli_render_particle_set', since RE_addRenderInstance reads
+ * index values from 'dob->persistent_id[0]', referencing 'psys->child' which
+ * may be smaller once the particle system is restored, see: T45563. */
for (dob= duplilist->first, i = 0; dob; dob= dob->next, ++i) {
DupliExtraData *dob_extra = &duplilist_apply_data->extra[i];
@@ -5082,6 +5111,9 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
if (re->test_break(re->tbh)) break;
}
+ /* restore particle system */
+ dupli_render_particle_set(re, ob, timeoffset, 0, false);
+
if (duplilist_apply_data) {
duplilist_restore(duplilist, duplilist_apply_data);
duplilist_free_apply_data(duplilist_apply_data);
@@ -5136,8 +5168,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
re->lights.first= re->lights.last= NULL;
re->lampren.first= re->lampren.last= NULL;
-
- slurph_opt= 0;
+
re->i.partsdone = false; /* signal now in use for previewrender */
/* in localview, lamps are using normal layers, objects only local bits */
@@ -5156,8 +5187,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
* above call to BKE_scene_update_for_newframe, fixes bug. [#22702].
* following calls don't depend on 'RE_SetCamera' */
RE_SetCamera(re, camera);
-
- normalize_m4_m4(mat, camera->obmat);
+ RE_GetCameraModelMatrix(re, camera, mat);
invert_m4(mat);
RE_SetView(re, mat);
@@ -5180,7 +5210,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
/* still bad... doing all */
init_render_textures(re);
copy_v3_v3(amb, &re->wrld.ambr);
- init_render_materials(re->main, re->r.mode, amb);
+ init_render_materials(re->main, re->r.mode, amb, (re->r.scemode & R_BUTS_PREVIEW) == 0);
set_node_shader_lamp_loop(shade_material_loop);
/* MAKE RENDER DATA */
@@ -5199,8 +5229,6 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
re->i.totlamp= re->totlamp;
re->stats_draw(re->sdh, &re->i);
}
-
- slurph_opt= 1;
}
void RE_Database_Preprocess(Render *re)
@@ -5240,7 +5268,7 @@ void RE_Database_Preprocess(Render *re)
}
if (!re->test_break(re->tbh))
- project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1);
+ project_renderdata(re, projectverto, (re->r.mode & R_PANORAMA) != 0, 0, 1);
/* Occlusion */
if ((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && !re->test_break(re->tbh))
@@ -5318,8 +5346,6 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la
re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
re->i.totface=re->i.totvert=re->i.totstrand=re->i.totlamp=re->i.tothalo= 0;
re->lights.first= re->lights.last= NULL;
-
- slurph_opt= 0;
/* in localview, lamps are using normal layers, objects only local bits */
if (re->lay & 0xFF000000)
@@ -5331,7 +5357,8 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la
/* if no camera, viewmat should have been set! */
if (camera) {
- normalize_m4_m4(mat, camera->obmat);
+ RE_GetCameraModelMatrix(re, camera, mat);
+ normalize_m4(mat);
invert_m4(mat);
RE_SetView(re, mat);
}
@@ -5340,7 +5367,7 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la
database_init_objects(re, lay, 0, 0, NULL, timeoffset);
if (!re->test_break(re->tbh))
- project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1);
+ project_renderdata(re, projectverto, (re->r.mode & R_PANORAMA) != 0, 0, 1);
/* do this in end, particles for example need cfra */
scene->r.cfra -= timeoffset;
@@ -5842,9 +5869,11 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
/* renderdata setup and exceptions */
BLI_freelistN(&re->r.layers);
+ BLI_freelistN(&re->r.views);
re->r = scene->r;
BLI_duplicatelist(&re->r.layers, &scene->r.layers);
-
+ BLI_duplicatelist(&re->r.views, &scene->r.views);
+
RE_init_threadcount(re);
re->flag |= R_BAKING;
@@ -5912,7 +5941,7 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
init_render_textures(re);
copy_v3_v3(amb, &re->wrld.ambr);
- init_render_materials(re->main, re->r.mode, amb);
+ init_render_materials(re->main, re->r.mode, amb, true);
set_node_shader_lamp_loop(shade_material_loop);
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index 06be00a5a5e..b9b908f550b 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -37,7 +37,7 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h" /* for rectcpy */
@@ -55,14 +55,10 @@
/* this module */
#include "render_types.h"
-#include "renderpipeline.h"
#include "envmap.h"
-#include "rendercore.h"
#include "renderdatabase.h"
#include "texture.h"
#include "zbuf.h"
-#include "initrender.h"
-
/* ------------------------------------------------------------------------- */
@@ -74,7 +70,7 @@ static void envmap_split_ima(EnvMap *env, ImBuf *ibuf)
BLI_lock_thread(LOCK_IMAGE);
if (env->cube[1] == NULL) {
- BKE_free_envmapdata(env);
+ BKE_texture_envmap_free_data(env);
dx = ibuf->y;
dx /= 2;
@@ -145,6 +141,7 @@ static Render *envmap_render_copy(Render *re, EnvMap *env)
envre->r = re->r;
envre->r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR);
BLI_listbase_clear(&envre->r.layers);
+ BLI_listbase_clear(&envre->r.views);
envre->r.filtertype = 0;
envre->r.tilex = envre->r.xsch / 2;
envre->r.tiley = envre->r.ysch / 2;
@@ -499,9 +496,12 @@ static void render_envmap(Render *re, EnvMap *env)
RenderLayer *rl = envre->result->layers.first;
int y;
float *alpha;
-
+ float *rect;
+
+ /* envmap is rendered independently of multiview */
+ rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, "");
ibuf = IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect | IB_rectfloat);
- memcpy(ibuf->rect_float, rl->rectf, ibuf->channels * ibuf->x * ibuf->y * sizeof(float));
+ memcpy(ibuf->rect_float, rect, ibuf->channels * ibuf->x * ibuf->y * sizeof(float));
/* envmap renders without alpha */
alpha = ibuf->rect_float + 3;
@@ -515,7 +515,7 @@ static void render_envmap(Render *re, EnvMap *env)
}
- if (re->test_break(re->tbh)) BKE_free_envmapdata(env);
+ if (re->test_break(re->tbh)) BKE_texture_envmap_free_data(env);
else {
if (envre->r.mode & R_OSA) env->ok = ENV_OSA;
else env->ok = ENV_NORMAL;
@@ -576,13 +576,13 @@ void make_envmaps(Render *re)
if (env->ok) {
/* free when OSA, and old one isn't OSA */
if ((re->r.mode & R_OSA) && env->ok == ENV_NORMAL)
- BKE_free_envmapdata(env);
+ BKE_texture_envmap_free_data(env);
/* free when size larger */
else if (env->lastsize < re->r.size)
- BKE_free_envmapdata(env);
+ BKE_texture_envmap_free_data(env);
/* free when env is in recalcmode */
else if (env->recalc)
- BKE_free_envmapdata(env);
+ BKE_texture_envmap_free_data(env);
}
if (env->ok == 0 && depth == 0) env->recalc = 1;
@@ -698,7 +698,7 @@ static void set_dxtdyt(float r_dxt[3], float r_dyt[3], const float dxt[3], const
/* ------------------------------------------------------------------------- */
-int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool)
+int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool, const bool skip_load_image)
{
extern Render R; /* only in this call */
/* texvec should be the already reflected normal */
@@ -754,7 +754,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
mul_mat3_m4_v3(R.viewinv, dyt);
}
set_dxtdyt(dxts, dyts, dxt, dyt, face);
- imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres, pool);
+ imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres, pool, skip_load_image);
/* edges? */
@@ -771,7 +771,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
if (face != face1) {
ibuf = env->cube[face1];
set_dxtdyt(dxts, dyts, dxt, dyt, face1);
- imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1, pool);
+ imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1, pool, skip_load_image);
}
else texr1.tr = texr1.tg = texr1.tb = texr1.ta = 0.0;
@@ -784,7 +784,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
if (face != face1) {
ibuf = env->cube[face1];
set_dxtdyt(dxts, dyts, dxt, dyt, face1);
- imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2, pool);
+ imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2, pool, skip_load_image);
}
else texr2.tr = texr2.tg = texr2.tb = texr2.ta = 0.0;
@@ -800,7 +800,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
}
}
else {
- imagewrap(tex, NULL, ibuf, sco, texres, pool);
+ imagewrap(tex, NULL, ibuf, sco, texres, pool, skip_load_image);
}
return 1;
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 54f142184e1..fef453efce2 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -36,19 +36,17 @@
#include "MEM_guardedalloc.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BKE_camera.h"
#include "BKE_global.h"
#include "BKE_report.h"
#include "BKE_scene.h"
-#include "IMB_imbuf.h"
-#include "IMB_imbuf_types.h"
-
#include "RNA_access.h"
#ifdef WITH_PYTHON
@@ -184,7 +182,7 @@ static RenderPart *get_part_from_result(Render *re, RenderResult *result)
return NULL;
}
-RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername)
+RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
{
Render *re = engine->re;
RenderResult *result;
@@ -207,7 +205,7 @@ RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w,
disprect.ymin = y;
disprect.ymax = y + h;
- result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername);
+ result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername, viewname);
/* todo: make this thread safe */
@@ -272,7 +270,7 @@ void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel
if (!cancel || merge_results) {
if (re->result->do_exr_tile) {
if (!cancel) {
- render_result_exr_file_merge(re->result, result);
+ render_result_exr_file_merge(re->result, result, re->viewname);
}
}
else if (!(re->test_break(re->tbh) && (re->r.scemode & R_BUTS_PREVIEW)))
@@ -358,28 +356,69 @@ void RE_engine_report(RenderEngine *engine, int type, const char *msg)
BKE_report(engine->reports, type, msg);
}
-void RE_engine_get_current_tiles(Render *re, int *total_tiles_r, rcti **tiles_r)
+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->error != NULL) {
+ MEM_freeN(rr->error);
+ }
+ rr->error = BLI_strdup(msg);
+ RE_ReleaseResult(re);
+ }
+}
+
+void RE_engine_active_view_set(RenderEngine *engine, const char *viewname)
{
+ Render *re = engine->re;
+ RE_SetActiveRenderView(re, viewname);
+}
+
+float RE_engine_get_camera_shift_x(RenderEngine *engine, Object *camera)
+{
+ Render *re = engine->re;
+ return BKE_camera_multiview_shift_x(re ? &re->r : NULL, camera, re->viewname);
+}
+
+void RE_engine_get_camera_model_matrix(RenderEngine *engine, Object *camera, float *r_modelmat)
+{
+ Render *re = engine->re;
+ BKE_camera_multiview_model_matrix(re ? &re->r : NULL, camera, re->viewname, (float (*)[4])r_modelmat);
+}
+
+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 = NULL;
- int allocation_size = 0, allocation_step = BLENDER_MAX_THREADS;
+ 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) {
- *total_tiles_r = 0;
- *tiles_r = NULL;
- return;
+ *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) {
- if (tiles == NULL)
+ /* Just in case we're using crazy network rendering with more
+ * slaves as BLENDER_MAX_THREADS.
+ */
+ if (tiles == tiles_static)
tiles = MEM_mallocN(allocation_step * sizeof(rcti), "current engine tiles");
else
tiles = MEM_reallocN(tiles, (total_tiles + allocation_step) * sizeof(rcti));
allocation_size += allocation_step;
+ *r_needs_free = true;
}
tiles[total_tiles] = pa->disprect;
@@ -394,9 +433,9 @@ void RE_engine_get_current_tiles(Render *re, int *total_tiles_r, rcti **tiles_r)
total_tiles++;
}
}
-
- *total_tiles_r = total_tiles;
- *tiles_r = tiles;
+ BLI_rw_mutex_unlock(&re->partsmutex);
+ *r_total_tiles = total_tiles;
+ return tiles;
}
RenderData *RE_engine_get_render_data(Render *re)
@@ -415,6 +454,7 @@ void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Scene *scene)
* but it potentially leaves unfreed memory blocks
* not sure how to fix this yet -- dfelinto */
BLI_listbase_clear(&re->r.layers);
+ BLI_listbase_clear(&re->r.views);
}
bool RE_bake_has_engine(Render *re)
@@ -424,13 +464,14 @@ bool RE_bake_has_engine(Render *re)
}
bool RE_bake_engine(
- Render *re, Object *object, const BakePixel pixel_array[],
+ Render *re, Object *object,
+ const int object_id, const BakePixel pixel_array[],
const size_t num_pixels, const int depth,
const ScenePassType pass_type, float result[])
{
RenderEngineType *type = RE_engines_find(re->r.engine);
RenderEngine *engine;
- int persistent_data = re->r.mode & R_PERSISTENT_DATA;
+ bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
/* set render info */
re->i.cfra = re->scene->r.cfra;
@@ -462,12 +503,14 @@ bool RE_bake_engine(
type->update(engine, re->main, re->scene);
if (type->bake)
- type->bake(engine, re->scene, object, pass_type, pixel_array, num_pixels, depth, result);
+ type->bake(engine, re->scene, object, pass_type, object_id, pixel_array, num_pixels, depth, result);
engine->tile_x = 0;
engine->tile_y = 0;
engine->flag &= ~RE_ENGINE_RENDERING;
+ 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);
@@ -475,6 +518,7 @@ bool RE_bake_engine(
}
RE_parts_free(re);
+ BLI_rw_mutex_unlock(&re->partsmutex);
if (BKE_reports_contain(re->reports, RPT_ERROR))
G.is_break = true;
@@ -522,7 +566,7 @@ int RE_engine_render(Render *re, int do_all)
{
RenderEngineType *type = RE_engines_find(re->r.engine);
RenderEngine *engine;
- int persistent_data = re->r.mode & R_PERSISTENT_DATA;
+ bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
/* verify if we can render */
if (!type->render)
@@ -589,7 +633,7 @@ int RE_engine_render(Render *re, int do_all)
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);
+ re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS, RR_ALL_VIEWS);
}
BLI_rw_mutex_unlock(&re->resultmutex);
@@ -653,6 +697,8 @@ int RE_engine_render(Render *re, int do_all)
render_result_free_list(&engine->fullresult, engine->fullresult.first);
+ 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);
@@ -661,6 +707,7 @@ int RE_engine_render(Render *re, int do_all)
if (re->result->do_exr_tile) {
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ render_result_save_empty_result_tiles(re);
render_result_exr_file_end(re);
BLI_rw_mutex_unlock(&re->resultmutex);
}
@@ -672,6 +719,7 @@ int RE_engine_render(Render *re, int do_all)
}
RE_parts_free(re);
+ BLI_rw_mutex_unlock(&re->partsmutex);
if (BKE_reports_contain(re->reports, RPT_ERROR))
G.is_break = true;
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index 12701099e18..b44c0135420 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -50,12 +50,10 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BKE_main.h"
#include "BKE_image.h"
#include "RE_render_ext.h"
-#include "renderpipeline.h"
#include "render_types.h"
#include "texture.h"
@@ -105,7 +103,7 @@ static void ibuf_get_color(float col[4], struct ImBuf *ibuf, int x, int y)
}
}
-int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres, struct ImagePool *pool)
+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;
@@ -122,7 +120,7 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
if (ima) {
/* hack for icon render */
- if ((R.r.scemode & R_NO_IMAGE_LOAD) && !BKE_image_has_loaded_ibuf(ima))
+ if (skip_load_image && !BKE_image_has_loaded_ibuf(ima))
return retval;
ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
@@ -791,14 +789,6 @@ static void area_sample(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata
texr->ta = texr->talpha ? texr->ta*xsd : (clip ? cw*xsd : 1.f);
}
-/* test if a float value is 'nan'
- * there is a C99 function for this: isnan(), but blender seems to use C90 (according to gcc warns),
- * and may not be supported by other compilers either */
-/* TODO(sergey): Consider using isnan(), it's used in the other areas. */
-#ifndef ISNAN
-# define ISNAN(x) ((x) != (x))
-#endif
-
typedef struct ReadEWAData {
ImBuf *ibuf;
afdata_t *AFD;
@@ -922,7 +912,7 @@ static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
}
-static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[2], float dyt[2], TexResult *texres, struct ImagePool *pool)
+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;
@@ -952,7 +942,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
if (ibuf==NULL && ima==NULL) return retval;
if (ima) { /* hack for icon render */
- if ((R.r.scemode & R_NO_IMAGE_LOAD) && !BKE_image_has_loaded_ibuf(ima)) {
+ if (skip_load_image && !BKE_image_has_loaded_ibuf(ima)) {
return retval;
}
ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
@@ -1155,7 +1145,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
ImBuf *previbuf, *curibuf;
float levf;
int maxlev;
- ImBuf *mipmaps[IB_MIPMAP_LEVELS + 1];
+ 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
@@ -1195,7 +1185,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
curmap = 0;
maxlev = 1;
mipmaps[0] = ibuf;
- while (curmap < IB_MIPMAP_LEVELS) {
+ while (curmap < IMB_MIPMAP_LEVELS) {
mipmaps[curmap + 1] = ibuf->mipmap[curmap];
if (ibuf->mipmap[curmap]) maxlev++;
curmap++;
@@ -1212,7 +1202,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
if (tex->texfilter == TXF_FELINE) AFD.iProbes = 1;
}
else {
- const int lev = ISNAN(levf) ? 0 : (int)levf;
+ const int lev = isnan(levf) ? 0 : (int)levf;
curibuf = mipmaps[lev];
previbuf = mipmaps[lev + 1];
levf -= floorf(levf);
@@ -1348,7 +1338,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
}
-int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[2], const float DYT[2], TexResult *texres, struct ImagePool *pool)
+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];
@@ -1362,7 +1352,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
/* anisotropic filtering */
if (tex->texfilter != TXF_BOX)
- return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres, pool);
+ 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;
@@ -1375,7 +1365,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
if (ima) {
/* hack for icon render */
- if ((R.r.scemode & R_NO_IMAGE_LOAD) && !BKE_image_has_loaded_ibuf(ima))
+ if (skip_load_image && !BKE_image_has_loaded_ibuf(ima))
return retval;
ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
@@ -1595,7 +1585,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
curmap= 0;
previbuf= curibuf= ibuf;
- while (curmap<IB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) {
+ while (curmap < IMB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) {
if (maxd < pixsize) break;
previbuf= curibuf;
curibuf= ibuf->mipmap[curmap];
diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c
index 353ba5d5caa..970a3937657 100644
--- a/source/blender/render/intern/source/initrender.c
+++ b/source/blender/render/intern/source/initrender.c
@@ -36,8 +36,6 @@
#include "MEM_guardedalloc.h"
-#include "PIL_time.h"
-
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_jitter.h"
@@ -48,12 +46,8 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-
#include "BKE_camera.h"
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-
#ifdef WITH_QUICKTIME
#include "quicktime_export.h"
#endif
@@ -62,10 +56,6 @@
#include "renderpipeline.h"
#include "render_types.h"
-#include "rendercore.h"
-#include "pixelshading.h"
-#include "zbuf.h"
-
/* Own includes */
#include "initrender.h"
@@ -164,8 +154,11 @@ float RE_filter_value(int type, float x)
return 1.0f - x;
case R_FILTER_GAUSS:
- x *= gaussfac;
- return (1.0f / expf(x * x) - 1.0f / expf(gaussfac * gaussfac * 2.25f));
+ {
+ 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);
@@ -433,10 +426,10 @@ void make_sample_tables(Render *re)
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-
struct Object *RE_GetCamera(Render *re)
{
- return re->camera_override ? re->camera_override : re->scene->camera;
+ 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, Object *cam_ob)
@@ -477,6 +470,16 @@ void RE_SetEnvmapCamera(Render *re, Object *cam_ob, float viewscale, float clips
re_camera_params_get(re, &params, cam_ob);
}
+void RE_SetOverrideCamera(Render *re, Object *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);
+}
+
/* 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)
@@ -486,6 +489,7 @@ void RE_SetCamera(Render *re, Object *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);
params.use_fields = (re->r.mode & R_FIELDS);
params.field_second = (re->flag & R_SEC_FIELD);
@@ -512,6 +516,11 @@ void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, flo
copy_m4_m4(mat, re->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);
+}
+
/* ~~~~~~~~~~~~~~~~ part (tile) calculus ~~~~~~~~~~~~~~~~~~~~~~ */
diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c
index 6ba85ea5329..dcc33b99742 100644
--- a/source/blender/render/intern/source/multires_bake.c
+++ b/source/blender/render/intern/source/multires_bake.c
@@ -45,6 +45,7 @@
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_mesh.h"
#include "BKE_multires.h"
#include "BKE_modifier.h"
#include "BKE_subsurf.h"
@@ -73,13 +74,15 @@ typedef struct MultiresBakeResult {
typedef struct {
MVert *mvert;
- MFace *mface;
- MTFace *mtface;
+ MPoly *mpoly;
+ MLoop *mloop;
+ MLoopUV *mloopuv;
+ const MLoopTri *mlooptri;
+ MTexPoly *mtpoly;
float *pvtangent;
const float *precomputed_normals;
int w, h;
- int face_index;
- int i0, i1, i2;
+ int tri_index;
DerivedMesh *lores_dm, *hires_dm;
int lvl;
void *thread_data;
@@ -102,12 +105,10 @@ typedef struct {
float *heights;
Image *ima;
DerivedMesh *ssdm;
- const int *orig_index_mf_to_mpoly;
const int *orig_index_mp_to_orig;
} MHeightBakeData;
typedef struct {
- const int *orig_index_mf_to_mpoly;
const int *orig_index_mp_to_orig;
} MNormalBakeData;
@@ -121,42 +122,26 @@ typedef struct {
RayObject *raytree;
RayFace *rayfaces;
- const int *orig_index_mf_to_mpoly;
const int *orig_index_mp_to_orig;
} MAOBakeData;
-static void multiresbake_get_normal(const MResolvePixelData *data, float norm[],const int face_num, const int vert_index)
+static void multiresbake_get_normal(const MResolvePixelData *data, float norm[],const int tri_num, const int vert_index)
{
- unsigned int indices[] = {data->mface[face_num].v1, data->mface[face_num].v2,
- data->mface[face_num].v3, data->mface[face_num].v4};
- const int smoothnormal = (data->mface[face_num].flag & ME_SMOOTH);
+ 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[3 * face_num]);
+ copy_v3_v3(norm, &data->precomputed_normals[poly_index]);
}
else {
- float nor[3];
- const float *p0, *p1, *p2;
- const int iGetNrVerts = data->mface[face_num].v4 != 0 ? 4 : 3;
-
- p0 = data->mvert[indices[0]].co;
- p1 = data->mvert[indices[1]].co;
- p2 = data->mvert[indices[2]].co;
-
- if (iGetNrVerts == 4) {
- const float *p3 = data->mvert[indices[3]].co;
- normal_quad_v3(nor, p0, p1, p2, p3);
- }
- else {
- normal_tri_v3(nor, p0, p1, p2);
- }
-
- copy_v3_v3(norm, nor);
+ BKE_mesh_calc_poly_normal(mp, &data->mloop[mp->loopstart], data->mvert, norm);
}
}
else {
- const short *no = data->mvert[indices[vert_index]].no;
+ 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);
@@ -188,17 +173,13 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
float u, v, w, sign;
int r;
- const int i0 = data->i0;
- const int i1 = data->i1;
- const int i2 = data->i2;
+ 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;
- st0 = data->mtface[data->face_index].uv[i0];
- st1 = data->mtface[data->face_index].uv[i1];
- st2 = data->mtface[data->face_index].uv[i2];
-
- multiresbake_get_normal(data, no0, data->face_index, i0); /* can optimize these 3 into one call */
- multiresbake_get_normal(data, no1, data->face_index, i1);
- multiresbake_get_normal(data, no2, data->face_index, i2);
+ 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);
@@ -207,9 +188,9 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
w = 1 - u - v;
if (data->pvtangent) {
- tang0 = data->pvtangent + data->face_index * 16 + i0 * 4;
- tang1 = data->pvtangent + data->face_index * 16 + i1 * 4;
- tang2 = data->pvtangent + data->face_index * 16 + i2 * 4;
+ 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. */
@@ -231,7 +212,7 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
}
data->pass_data(data->lores_dm, data->hires_dm, data->thread_data, data->bake_data,
- data->ibuf, data->face_index, data->lvl, st, to_tang, x, y);
+ 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)
@@ -344,8 +325,8 @@ static int multiresbake_test_break(MultiresBakeRender *bkr)
/* **** Threading routines **** */
typedef struct MultiresBakeQueue {
- int cur_face;
- int tot_face;
+ int cur_tri;
+ int tot_tri;
SpinLock spin;
} MultiresBakeQueue;
@@ -364,7 +345,7 @@ typedef struct MultiresBakeThread {
float height_min, height_max;
} MultiresBakeThread;
-static int multires_bake_queue_next_face(MultiresBakeQueue *queue)
+static int multires_bake_queue_next_tri(MultiresBakeQueue *queue)
{
int face = -1;
@@ -373,9 +354,9 @@ static int multires_bake_queue_next_face(MultiresBakeQueue *queue)
*/
BLI_spin_lock(&queue->spin);
- if (queue->cur_face < queue->tot_face) {
- face = queue->cur_face;
- queue->cur_face++;
+ if (queue->cur_tri < queue->tot_tri) {
+ face = queue->cur_tri;
+ queue->cur_tri++;
}
BLI_spin_unlock(&queue->spin);
@@ -388,44 +369,28 @@ static void *do_multires_bake_thread(void *data_v)
MResolvePixelData *data = &handle->data;
MBakeRast *bake_rast = &handle->bake_rast;
MultiresBakeRender *bkr = handle->bkr;
- int f;
+ int tri_index;
- while ((f = multires_bake_queue_next_face(handle->queue)) >= 0) {
- MTFace *mtfate = &data->mtface[f];
- int verts[3][2], nr_tris, t;
+ while ((tri_index = multires_bake_queue_next_tri(handle->queue)) >= 0) {
+ const MLoopTri *lt = &data->mlooptri[tri_index];
+ MTexPoly *mtpoly = &data->mtpoly[lt->poly];
+ MLoopUV *mloopuv = data->mloopuv;
if (multiresbake_test_break(bkr))
break;
- if (mtfate->tpage != handle->image)
+ if (mtpoly->tpage != handle->image)
continue;
- data->face_index = f;
-
- /* might support other forms of diagonal splits later on such as
- * split by shortest diagonal.*/
- verts[0][0] = 0;
- verts[1][0] = 1;
- verts[2][0] = 2;
+ data->tri_index = tri_index;
- verts[0][1] = 0;
- verts[1][1] = 2;
- verts[2][1] = 3;
+ bake_rasterize(bake_rast, mloopuv[lt->tri[0]].uv, mloopuv[lt->tri[1]].uv, mloopuv[lt->tri[2]].uv);
- nr_tris = data->mface[f].v4 != 0 ? 2 : 1;
- for (t = 0; t < nr_tris; t++) {
- data->i0 = verts[0][t];
- data->i1 = verts[1][t];
- data->i2 = verts[2][t];
+ /* tag image buffer for refresh */
+ if (data->ibuf->rect_float)
+ data->ibuf->userflags |= IB_RECT_INVALID;
- bake_rasterize(bake_rast, mtfate->uv[data->i0], mtfate->uv[data->i1], mtfate->uv[data->i2]);
-
- /* 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);
@@ -435,7 +400,7 @@ static void *do_multires_bake_thread(void *data_v)
*bkr->do_update = true;
if (bkr->progress)
- *bkr->progress = ((float)bkr->baked_objects + (float)bkr->baked_faces / handle->queue->tot_face) / bkr->tot_obj;
+ *bkr->progress = ((float)bkr->baked_objects + (float)bkr->baked_faces / handle->queue->tot_tri) / bkr->tot_obj;
BLI_spin_unlock(&handle->queue->spin);
}
@@ -467,18 +432,21 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t
MInitBakeData initBakeData, MFreeBakeData freeBakeData, MultiresBakeResult *result)
{
DerivedMesh *dm = bkr->lores_dm;
+ const MLoopTri *mlooptri = dm->getLoopTriArray(dm);
const int lvl = bkr->lvl;
- const int tot_face = dm->getNumTessFaces(dm);
+ int tot_tri = dm->getNumLoopTri(dm);
- if (tot_face > 0) {
+ if (tot_tri > 0) {
MultiresBakeThread *handles;
MultiresBakeQueue queue;
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
MVert *mvert = dm->getVertArray(dm);
- MFace *mface = dm->getTessFaceArray(dm);
- MTFace *mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);
- const float *precomputed_normals = dm->getTessFaceDataArray(dm, CD_NORMAL);
+ MPoly *mpoly = dm->getPolyArray(dm);
+ MLoop *mloop = dm->getLoopArray(dm);
+ MLoopUV *mloopuv = dm->getLoopDataArray(dm, CD_MLOOPUV);
+ MTexPoly *mtpoly = dm->getPolyDataArray(dm, CD_MTEXPOLY);
+ const float *precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL);
float *pvtangent = NULL;
ListBase threads;
@@ -487,10 +455,10 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t
void *bake_data = NULL;
if (require_tangent) {
- if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1)
- DM_add_tangent_layer(dm);
+ if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1)
+ DM_calc_loop_tangents(dm);
- pvtangent = DM_get_tessface_data_layer(dm, CD_TANGENT);
+ pvtangent = DM_get_loop_data_layer(dm, CD_TANGENT);
}
/* all threads shares the same custom bake data */
@@ -505,8 +473,8 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t
init_ccgdm_arrays(bkr->hires_dm);
/* faces queue */
- queue.cur_face = 0;
- queue.tot_face = tot_face;
+ queue.cur_tri = 0;
+ queue.tot_tri = tot_tri;
BLI_spin_init(&queue.spin);
/* fill in threads handles */
@@ -517,9 +485,12 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t
handle->image = ima;
handle->queue = &queue;
- handle->data.mface = mface;
+ handle->data.mpoly = mpoly;
handle->data.mvert = mvert;
- handle->data.mtface = mtface;
+ handle->data.mloopuv = mloopuv;
+ handle->data.mlooptri = mlooptri;
+ handle->data.mtpoly = mtpoly;
+ handle->data.mloop = mloop;
handle->data.pvtangent = pvtangent;
handle->data.precomputed_normals = precomputed_normals; /* don't strictly need this */
handle->data.w = ibuf->x;
@@ -602,40 +573,48 @@ static void interp_bilinear_grid(CCGKey *key, CCGElem *grid, float crn_x, float
}
static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm,
- const int *index_mf_to_mpoly, const int *index_mp_to_orig,
- const int lvl, const int face_index, const float u, const float v, float co[3], float n[3])
+ const int *index_mp_to_orig,
+ const int lvl, const MLoopTri *lt, const float u, const float v, float co[3], float n[3])
{
- MFace mface;
CCGElem **grid_data;
CCGKey key;
float crn_x, crn_y;
int grid_size, S, face_side;
int *grid_offset, g_index;
-
- lodm->getTessFace(lodm, face_index, &mface);
+ int poly_index = lt->poly;
grid_size = hidm->getGridSize(hidm);
grid_data = hidm->getGridData(hidm);
grid_offset = hidm->getGridOffset(hidm);
hidm->getGridKey(hidm, &key);
- face_side = (grid_size << 1) - 1;
-
if (lvl == 0) {
- g_index = grid_offset[face_index];
- S = mdisp_rot_face_to_crn(mface.v4 ? 4 : 3, face_side, u * (face_side - 1), v * (face_side - 1), &crn_x, &crn_y);
+ 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 {
- int side = (1 << (lvl - 1)) + 1;
- int grid_index = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, face_index);
- int loc_offs = face_index % (1 << (2 * lvl));
- int cell_index = loc_offs % ((side - 1) * (side - 1));
- int cell_side = (grid_size - 1) / (side - 1);
- int row = cell_index / (side - 1);
- int col = cell_index % (side - 1);
-
- S = face_index / (1 << (2 * (lvl - 1))) - grid_offset[grid_index];
- g_index = grid_offset[grid_index];
+ /* 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;
@@ -653,41 +632,40 @@ static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm,
/* mode = 0: interpolate normals,
* mode = 1: interpolate coord */
-static void interp_bilinear_mface(DerivedMesh *dm, MFace *mface, 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, mface->v1, data[0]);
- dm->getVertNo(dm, mface->v2, data[1]);
- dm->getVertNo(dm, mface->v3, data[2]);
- dm->getVertNo(dm, mface->v4, data[3]);
+ 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, mface->v1, data[0]);
- dm->getVertCo(dm, mface->v2, data[1]);
- dm->getVertCo(dm, mface->v3, data[2]);
- dm->getVertCo(dm, mface->v4, data[3]);
+ 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);
}
-/* mode = 0: interpolate normals,
- * mode = 1: interpolate coord */
-static void interp_barycentric_mface(DerivedMesh *dm, MFace *mface, 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, mface->v1, data[0]);
- dm->getVertNo(dm, mface->v2, data[1]);
- dm->getVertNo(dm, mface->v3, data[2]);
+ 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, mface->v1, data[0]);
- dm->getVertCo(dm, mface->v2, data[1]);
- dm->getVertCo(dm, mface->v3, data[2]);
+ 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);
@@ -728,7 +706,6 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima)
}
}
- height_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX);
height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
BKE_image_release_ibuf(ima, ibuf, NULL);
@@ -753,52 +730,55 @@ static void free_heights_data(void *bake_data)
* 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 face_index, const int lvl, const float st[2],
+ ImBuf *ibuf, const int tri_index, const int lvl, const float st[2],
float UNUSED(tangmat[3][3]), const int x, const int y)
{
- MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
- MFace mface;
+ 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;
- lores_dm->getTessFace(lores_dm, face_index, &mface);
-
- st0 = mtface[face_index].uv[0];
- st1 = mtface[face_index].uv[1];
- st2 = mtface[face_index].uv[2];
-
- if (mface.v4) {
- st3 = mtface[face_index].uv[3];
+ /* 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
+ 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_mf_to_mpoly, height_data->orig_index_mp_to_orig,
- lvl, face_index, uv[0], uv[1], p1, NULL);
+ 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_mf_to_mpoly, height_data->orig_index_mp_to_orig,
- 0, face_index, uv[0], uv[1], p0, n);
+ height_data->orig_index_mp_to_orig,
+ 0, lt, uv[0], uv[1], p0, n);
}
else {
- lores_dm->getTessFace(lores_dm, face_index, &mface);
-
- if (mface.v4) {
- interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 1, p0);
- interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 0, n);
+ 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_mface(lores_dm, &mface, uv[0], uv[1], 1, p0);
- interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 0, n);
+ 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);
}
}
@@ -831,7 +811,6 @@ static void *init_normal_data(MultiresBakeRender *bkr, Image *UNUSED(ima))
normal_data = MEM_callocN(sizeof(MNormalBakeData), "MultiresBake normalData");
- normal_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX);
normal_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
return (void *)normal_data;
@@ -850,35 +829,39 @@ 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 face_index, const int lvl,
+ 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)
{
- MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
- MFace mface;
+ 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};
- lores_dm->getTessFace(lores_dm, face_index, &mface);
-
- st0 = mtface[face_index].uv[0];
- st1 = mtface[face_index].uv[1];
- st2 = mtface[face_index].uv[2];
-
- if (mface.v4) {
- st3 = mtface[face_index].uv[3];
+ /* 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
+ 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_mf_to_mpoly, normal_data->orig_index_mp_to_orig,
- lvl, face_index, uv[0], uv[1], NULL, n);
+ normal_data->orig_index_mp_to_orig,
+ lvl, lt, uv[0], uv[1], NULL, n);
mul_v3_m3v3(vec, tangmat, n);
normalize_v3(vec);
@@ -1016,7 +999,6 @@ static void *init_ao_data(MultiresBakeRender *bkr, Image *UNUSED(ima))
ao_data->number_of_rays = bkr->number_of_rays;
ao_data->bias = bkr->bias;
- ao_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX);
ao_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
create_ao_raytree(bkr, ao_data);
@@ -1088,12 +1070,13 @@ static int trace_ao_ray(MAOBakeData *ao_data, float ray_start[3], float ray_dire
}
static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *UNUSED(thread_data),
- void *bake_data, ImBuf *ibuf, const int face_index, const int lvl,
+ 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;
- MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
- MFace mface;
int i, k, perm_offs;
float pos[3], nrm[3];
@@ -1104,25 +1087,28 @@ static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void
int pixel = ibuf->x * y + x;
float uv[2], *st0, *st1, *st2, *st3;
- lores_dm->getTessFace(lores_dm, face_index, &mface);
-
- st0 = mtface[face_index].uv[0];
- st1 = mtface[face_index].uv[1];
- st2 = mtface[face_index].uv[2];
-
- if (mface.v4) {
- st3 = mtface[face_index].uv[3];
+ /* 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
+ 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_mf_to_mpoly, ao_data->orig_index_mp_to_orig,
- lvl, face_index, uv[0], uv[1], pos, nrm);
+ 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++)
@@ -1193,20 +1179,20 @@ static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void
static void count_images(MultiresBakeRender *bkr)
{
- int a, totface;
+ int a, totpoly;
DerivedMesh *dm = bkr->lores_dm;
- MTFace *mtface = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ MTexPoly *mtexpoly = CustomData_get_layer(&dm->polyData, CD_MTEXPOLY);
BLI_listbase_clear(&bkr->image);
bkr->tot_image = 0;
- totface = dm->getNumTessFaces(dm);
+ totpoly = dm->getNumPolys(dm);
- for (a = 0; a < totface; a++)
- mtface[a].tpage->id.flag &= ~LIB_DOIT;
+ for (a = 0; a < totpoly; a++)
+ mtexpoly[a].tpage->id.flag &= ~LIB_DOIT;
- for (a = 0; a < totface; a++) {
- Image *ima = mtface[a].tpage;
+ for (a = 0; a < totpoly; a++) {
+ Image *ima = mtexpoly[a].tpage;
if ((ima->id.flag & LIB_DOIT) == 0) {
LinkData *data = BLI_genericNodeN(ima);
BLI_addtail(&bkr->image, data);
@@ -1215,8 +1201,8 @@ static void count_images(MultiresBakeRender *bkr)
}
}
- for (a = 0; a < totface; a++)
- mtface[a].tpage->id.flag &= ~LIB_DOIT;
+ for (a = 0; a < totpoly; a++)
+ mtexpoly[a].tpage->id.flag &= ~LIB_DOIT;
}
static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c
index 0c6341fe9e5..c5c3b6bbf94 100644
--- a/source/blender/render/intern/source/occlusion.c
+++ b/source/blender/render/intern/source/occlusion.c
@@ -43,7 +43,7 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_node.h"
#include "BKE_scene.h"
@@ -56,9 +56,7 @@
#include "render_types.h"
#include "rendercore.h"
#include "renderdatabase.h"
-#include "pixelshading.h"
#include "shading.h"
-#include "zbuf.h"
/* ------------------------- Declarations --------------------------- */
@@ -476,9 +474,7 @@ static void occ_build_split(OcclusionTree *tree, int begin, int end, int *split)
if (tree->co[a][axis] > mid) {
enda--;
SWAP(OccFace, tree->face[a], tree->face[enda]);
- SWAP(float, tree->co[a][0], tree->co[enda][0]);
- SWAP(float, tree->co[a][1], tree->co[enda][1]);
- SWAP(float, tree->co[a][2], tree->co[enda][2]);
+ swap_v3_v3(tree->co[a], tree->co[enda]);
}
else
a++;
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 2a07474a5dd..ad0856497c3 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -49,12 +49,13 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_path_util.h"
+#include "BLI_timecode.h"
#include "BLI_fileops.h"
#include "BLI_threads.h"
#include "BLI_rand.h"
#include "BLI_callbacks.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_animsys.h" /* <------ should this be here?, needed for sequencer update */
#include "BKE_camera.h"
@@ -70,6 +71,7 @@
#include "BKE_scene.h"
#include "BKE_sequencer.h"
#include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */
+#include "BKE_object.h"
#include "PIL_time.h"
#include "IMB_colormanagement.h"
@@ -83,6 +85,8 @@
# include "FRS_freestyle.h"
#endif
+#include "DEG_depsgraph.h"
+
/* internal */
#include "render_result.h"
#include "render_types.h"
@@ -90,7 +94,6 @@
#include "renderdatabase.h"
#include "rendercore.h"
#include "initrender.h"
-#include "shadbuf.h"
#include "pixelblending.h"
#include "zbuf.h"
@@ -132,7 +135,7 @@ Render R;
/* ********* alloc and free ******** */
-static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override);
+static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const size_t totvideos, const char *name_override);
static volatile int g_break = 0;
static int thread_break(void *UNUSED(arg))
@@ -152,6 +155,7 @@ 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();
@@ -169,8 +173,11 @@ static void stats_background(void *UNUSED(arg), RenderStats *rs)
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);
+ fprintf(stdout, "%s", rs->infostr);
}
else {
if (rs->tothalo)
@@ -180,6 +187,9 @@ static void stats_background(void *UNUSED(arg), RenderStats *rs)
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);
+
BLI_callback_exec(G.main, NULL, BLI_CB_EVT_RENDER_STATS);
fputc('\n', stdout);
@@ -191,14 +201,10 @@ void RE_FreeRenderResult(RenderResult *res)
render_result_free(res);
}
-float *RE_RenderLayerGetPass(RenderLayer *rl, int passtype)
+float *RE_RenderLayerGetPass(volatile RenderLayer *rl, int passtype, const char *viewname)
{
- RenderPass *rpass;
-
- for (rpass = rl->passes.first; rpass; rpass = rpass->next)
- if (rpass->passtype == passtype)
- return rpass->rect;
- return NULL;
+ RenderPass *rpass = RE_pass_find_by_type(rl, passtype, viewname);
+ return rpass ? rpass->rect : NULL;
}
RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name)
@@ -257,7 +263,7 @@ Render *RE_GetRender(const char *name)
/* search for existing renders */
for (re = RenderGlobal.renderlist.first; re; re = re->next)
- if (strncmp(re->name, name, RE_MAXNAME) == 0)
+ if (STREQLEN(re->name, name, RE_MAXNAME))
break;
return re;
@@ -308,8 +314,71 @@ Scene *RE_GetScene(Render *re)
return NULL;
}
+/**
+ * Same as #RE_AcquireResultImage but creating the necessary views to store the result
+ * fill provided result struct with a copy of thew views of what is done so far the
+ * #RenderResult.views #ListBase needs to be freed after with #RE_ReleaseResultImageViews
+*/
+void RE_AcquireResultImageViews(Render *re, RenderResult *rr)
+{
+ memset(rr, 0, sizeof(RenderResult));
+
+ if (re) {
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ);
+
+ if (re->result) {
+ RenderLayer *rl;
+ RenderView *rv, *rview;
+
+ rr->rectx = re->result->rectx;
+ rr->recty = re->result->recty;
+
+ /* creates a temporary duplication of views */
+ render_result_views_shallowcopy(rr, re->result);
+
+ rv = rr->views.first;
+
+ /* 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, SCE_PASS_COMBINED, rview->name);
+ }
+ }
+
+ if (rv->rectz == NULL) {
+ for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) {
+ rview->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rview->name);
+ }
+ }
+ }
+
+ rr->have_combined = (rv->rectf != NULL);
+ 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);
+ }
+}
+
/* fill provided result struct with what's currently active or done */
-void RE_AcquireResultImage(Render *re, RenderResult *rr)
+/* this RenderResult struct is the only exception to the rule of a RenderResult */
+/* always having at least one RenderView */
+void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id)
{
memset(rr, 0, sizeof(RenderResult));
@@ -318,27 +387,33 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr)
if (re->result) {
RenderLayer *rl;
+ RenderView *rv;
rr->rectx = re->result->rectx;
rr->recty = re->result->recty;
- rr->rectf = re->result->rectf;
- rr->rectz = re->result->rectz;
- rr->rect32 = re->result->rect32;
-
+ /* actview view */
+ rv = RE_RenderViewGetById(re->result, view_id);
+
+ rr->rectf = rv->rectf;
+ rr->rectz = rv->rectz;
+ rr->rect32 = rv->rect32;
+
/* active layer */
rl = render_get_active_layer(re, re->result);
if (rl) {
- if (rr->rectf == NULL)
- rr->rectf = rl->rectf;
- if (rr->rectz == NULL)
- rr->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z);
+ if (rv->rectf == NULL)
+ rr->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rv->name);
+
+ if (rv->rectz == NULL)
+ rr->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rv->name);
}
- rr->have_combined = (re->result->rectf != NULL);
+ rr->have_combined = (rv->rectf != NULL);
rr->layers = re->result->layers;
-
+ rr->views = re->result->views;
+
rr->xof = re->disprect.xmin;
rr->yof = re->disprect.ymin;
}
@@ -355,17 +430,18 @@ void RE_ReleaseResultImage(Render *re)
void RE_ResultGet32(Render *re, unsigned int *rect)
{
RenderResult rres;
-
- RE_AcquireResultImage(re, &rres);
- render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings);
- RE_ReleaseResultImage(re);
+ const size_t 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);
}
/* 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)
+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);
+ 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)
@@ -386,8 +462,8 @@ Render *RE_NewRender(const char *name)
BLI_addtail(&RenderGlobal.renderlist, re);
BLI_strncpy(re->name, name, RE_MAXNAME);
BLI_rw_mutex_init(&re->resultmutex);
- re->eval_ctx = MEM_callocN(sizeof(EvaluationContext), "re->eval_ctx");
- re->eval_ctx->mode = DAG_EVAL_RENDER;
+ BLI_rw_mutex_init(&re->partsmutex);
+ re->eval_ctx = DEG_evaluation_context_new(DAG_EVAL_RENDER);
}
RE_InitRenderCB(re);
@@ -424,9 +500,11 @@ void RE_FreeRender(Render *re)
RE_engine_free(re->engine);
BLI_rw_mutex_end(&re->resultmutex);
+ BLI_rw_mutex_end(&re->partsmutex);
BLI_freelistN(&re->r.layers);
-
+ BLI_freelistN(&re->r.views);
+
/* main dbase can already be invalid now, some database-free code checks it */
re->main = NULL;
re->scene = NULL;
@@ -455,6 +533,17 @@ void RE_FreeAllRender(void)
#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;
+ }
+ }
+}
+
/* on file load, free all re */
void RE_FreeAllRenderResults(void)
{
@@ -492,6 +581,12 @@ static int check_mode_full_sample(RenderData *rd)
{
int scemode = rd->scemode;
+ if (!STREQ(rd->engine, RE_engine_id_BLENDER_RENDER) &&
+ !STREQ(rd->engine, RE_engine_id_BLENDER_GAME))
+ {
+ scemode &= ~R_FULL_SAMPLE;
+ }
+
if ((rd->mode & R_OSA) == 0)
scemode &= ~R_FULL_SAMPLE;
@@ -567,8 +662,10 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
/* copy render data and render layers for thread safety */
BLI_freelistN(&re->r.layers);
+ BLI_freelistN(&re->r.views);
re->r = *rd;
BLI_duplicatelist(&re->r.layers, &rd->layers);
+ BLI_duplicatelist(&re->r.views, &rd->views);
if (source) {
/* reuse border flags from source renderer */
@@ -659,6 +756,7 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
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, "new temporary view");
}
if (re->r.scemode & R_VIEWPORT_PREVIEW)
@@ -676,18 +774,23 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
RE_init_threadcount(re);
}
+/* 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;
- src_rectf = result->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 = rl->rectf;
+ src_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, NULL);
}
}
@@ -697,32 +800,34 @@ static void render_result_rescale(Render *re)
&re->disprect,
0,
RR_USE_MEM,
- RR_ALL_LAYERS);
-
- dst_rectf = re->result->rectf;
- if (dst_rectf == NULL) {
- RenderLayer *rl;
- rl = render_get_active_layer(re, re->result);
- if (rl != NULL) {
- dst_rectf = rl->rectf;
+ 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, SCE_PASS_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,
- src_y = y * scale_y;
- int dst_index = y * re->result->rectx + x,
- src_index = src_y * result->rectx + src_x;
- copy_v4_v4(dst_rectf + dst_index * 4,
- src_rectf + src_index * 4);
+ 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);
}
-
- render_result_free(result);
}
void RE_ChangeResolution(Render *re, int winx, int winy, rcti *disprect)
@@ -769,6 +874,10 @@ void render_update_anim_renderdata(Render *re, RenderData *rd)
/* render layers */
BLI_freelistN(&re->r.layers);
BLI_duplicatelist(&re->r.layers, &rd->layers);
+
+ /* render views */
+ BLI_freelistN(&re->r.views);
+ BLI_duplicatelist(&re->r.views, &rd->views);
}
void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend)
@@ -901,9 +1010,9 @@ static void *do_part_thread(void *pa_v)
if (R.test_break(R.tbh) == 0) {
if (!R.sss_points && (R.r.scemode & R_FULL_SAMPLE))
- pa->result = render_result_new_full_sample(&R, &pa->fullresult, &pa->disprect, pa->crop, RR_USE_MEM);
+ pa->result = render_result_new_full_sample(&R, &pa->fullresult, &pa->disprect, pa->crop, RR_USE_MEM, R.viewname);
else
- pa->result = render_result_new(&R, &pa->disprect, pa->crop, RR_USE_MEM, RR_ALL_LAYERS);
+ pa->result = render_result_new(&R, &pa->disprect, pa->crop, RR_USE_MEM, RR_ALL_LAYERS, R.viewname);
/* Copy EXR tile settings, so pipeline knows whether this is a result
* for Save Buffers enabled rendering.
@@ -926,7 +1035,7 @@ static void *do_part_thread(void *pa_v)
/* merge too on break! */
if (R.result->do_exr_tile) {
- render_result_exr_file_merge(R.result, pa->result);
+ render_result_exr_file_merge(R.result, pa->result, R.viewname);
}
else if (render_display_update_enabled(&R)) {
/* on break, don't merge in result for preview renders, looks nicer */
@@ -1022,13 +1131,28 @@ static bool find_next_pano_slice(Render *re, int *slice, int *minx, rctf *viewpl
return found;
}
-static RenderPart *find_next_part(Render *re, int minx)
+typedef struct SortRenderPart {
+ RenderPart *pa;
+ long long int dist;
+} SortRenderPart;
+
+static int sort_render_part(const void *pa1, const void *pa2) {
+ const SortRenderPart *rpa1 = pa1;
+ const SortRenderPart *rpa2 = pa2;
+
+ if (rpa1->dist > rpa2->dist) return 1;
+ else if (rpa1->dist < rpa2->dist) return -1;
+
+ return 0;
+}
+
+static int sort_and_queue_parts(Render *re, int minx, ThreadQueue *workqueue)
{
- RenderPart *pa, *best = NULL;
+ RenderPart *pa;
/* long long int's needed because of overflow [#24414] */
long long int centx = re->winx / 2, centy = re->winy / 2, tot = 1;
- long long int mindist = (long long int)re->winx * (long long int)re->winy;
+ int totsort = 0;
/* find center of rendered parts, image center counts for 1 too */
for (pa = re->parts.first; pa; pa = pa->next) {
@@ -1037,31 +1161,48 @@ static RenderPart *find_next_part(Render *re, int minx)
centy += BLI_rcti_cent_y(&pa->disprect);
tot++;
}
+ else if (pa->status == PART_STATUS_NONE && pa->nr == 0) {
+ if (!(re->r.mode & R_PANORAMA) || pa->disprect.xmin == minx) {
+ totsort++;
+ }
+ }
}
centx /= tot;
centy /= tot;
- /* closest of the non-rendering parts */
- for (pa = re->parts.first; pa; pa = pa->next) {
- if (pa->status == PART_STATUS_NONE && pa->nr == 0) {
- long long int distx = centx - BLI_rcti_cent_x(&pa->disprect);
- long long int disty = centy - BLI_rcti_cent_y(&pa->disprect);
- distx = (long long int)sqrt(distx * distx + disty * disty);
- if (distx < mindist) {
- if (re->r.mode & R_PANORAMA) {
- if (pa->disprect.xmin == minx) {
- best = pa;
- mindist = distx;
- }
- }
- else {
- best = pa;
- mindist = distx;
+ if (totsort > 0) {
+ SortRenderPart *sortlist = MEM_mallocN(sizeof(*sortlist) * totsort, "renderpartsort");
+ long int i = 0;
+
+ /* prepare the list */
+ for (pa = re->parts.first; pa; pa = pa->next) {
+ if (pa->status == PART_STATUS_NONE && pa->nr == 0) {
+ if (!(re->r.mode & R_PANORAMA) || pa->disprect.xmin == minx) {
+ long long int distx = centx - BLI_rcti_cent_x(&pa->disprect);
+ long long int disty = centy - BLI_rcti_cent_y(&pa->disprect);
+ sortlist[i].dist = (long long int)sqrt(distx * distx + disty * disty);
+ sortlist[i].pa = pa;
+ i++;
}
}
}
+
+ /* Now sort it */
+ qsort(sortlist, totsort, sizeof(*sortlist), sort_render_part);
+
+ /* Finally flush it to the workqueue */
+ for (i = 0; i < totsort; i++) {
+ pa = sortlist[i].pa;
+ pa->nr = i + 1; /* for nicest part, and for stats */
+ BLI_thread_queue_push(workqueue, pa);
+ }
+
+ MEM_freeN(sortlist);
+
+ return totsort;
}
- return best;
+
+ return 0;
}
static void print_part_stats(Render *re, RenderPart *pa)
@@ -1106,16 +1247,23 @@ static void *do_render_thread(void *thread_v)
return NULL;
}
-static void threaded_tile_processor(Render *re)
+static void main_render_result_end(Render *re)
+{
+ if (re->result->do_exr_tile) {
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ render_result_exr_file_end(re);
+ BLI_rw_mutex_unlock(&re->resultmutex);
+ }
+
+ 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);
+ }
+}
+
+static void main_render_result_new(Render *re)
{
- RenderThread thread[BLENDER_MAX_THREADS];
- ThreadQueue *workqueue, *donequeue;
- ListBase threads;
- RenderPart *pa;
- rctf viewplane = re->viewplane;
- double lastdraw, elapsed, redrawtime = 1.0f;
- int totpart = 0, minx = 0, slice = 0, a, wait;
-
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
/* first step; free the entire render result, make new, and/or prepare exr buffer saving */
@@ -1123,25 +1271,38 @@ static void threaded_tile_processor(Render *re)
render_result_free(re->result);
if (re->sss_points && render_display_update_enabled(re))
- re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
+ re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
else if (re->r.scemode & R_FULL_SAMPLE)
- re->result = render_result_new_full_sample(re, &re->fullresult, &re->disprect, 0, RR_USE_EXR);
+ re->result = render_result_new_full_sample(re, &re->fullresult, &re->disprect, 0, RR_USE_EXR, RR_ALL_VIEWS);
else
re->result = render_result_new(re, &re->disprect, 0,
- (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM, RR_ALL_LAYERS);
+ (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
}
BLI_rw_mutex_unlock(&re->resultmutex);
+
+ if (re->result) {
+ if (re->result->do_exr_tile) {
+ render_result_exr_file_begin(re);
+ }
+ }
+}
+
+static void threaded_tile_processor(Render *re)
+{
+ RenderThread thread[BLENDER_MAX_THREADS];
+ ThreadQueue *workqueue, *donequeue;
+ ListBase threads;
+ RenderPart *pa;
+ rctf viewplane = re->viewplane;
+ double lastdraw, elapsed, redrawtime = 1.0f;
+ int totpart = 0, minx = 0, slice = 0, a, wait;
if (re->result == NULL)
return;
/* warning; no return here without closing exr file */
-
RE_parts_init(re, true);
-
- if (re->result->do_exr_tile)
- render_result_exr_file_begin(re);
/* assuming no new data gets added to dbase... */
R = *re;
@@ -1156,11 +1317,7 @@ static void threaded_tile_processor(Render *re)
/* for panorama we loop over slices */
while (find_next_pano_slice(re, &slice, &minx, &viewplane)) {
/* gather parts into queue */
- while ((pa = find_next_part(re, minx))) {
- pa->nr = totpart + 1; /* for nicest part, and for stats */
- totpart++;
- BLI_thread_queue_push(workqueue, pa);
- }
+ totpart = sort_and_queue_parts(re, minx, workqueue);
BLI_thread_queue_nowait(workqueue);
@@ -1246,27 +1403,23 @@ static void threaded_tile_processor(Render *re)
BLI_thread_queue_free(donequeue);
BLI_thread_queue_free(workqueue);
-
- if (re->result->do_exr_tile) {
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- render_result_exr_file_end(re);
- BLI_rw_mutex_unlock(&re->resultmutex);
- }
- if (re->r.scemode & R_EXR_CACHE_FILE) {
+ if (re->result->do_exr_tile) {
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- render_result_exr_file_cache_write(re);
+ render_result_save_empty_result_tiles(re);
BLI_rw_mutex_unlock(&re->resultmutex);
}
/* unset threadsafety */
g_break = 0;
-
+ BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
RE_parts_free(re);
+ BLI_rw_mutex_unlock(&re->partsmutex);
re->viewplane = viewplane; /* restore viewplane, modified by pano render */
}
#ifdef WITH_FREESTYLE
+static void init_freestyle(Render *re);
static void add_freestyle(Render *re, int render);
static void free_all_freestyle_renders(void);
#endif
@@ -1274,6 +1427,7 @@ static void free_all_freestyle_renders(void);
/* currently only called by preview renders and envmap */
void RE_TileProcessor(Render *re)
{
+ main_render_result_new(re);
threaded_tile_processor(re);
re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
@@ -1283,8 +1437,8 @@ void RE_TileProcessor(Render *re)
/* Freestyle */
if (re->r.mode & R_EDGE_FRS) {
if (!re->test_break(re->tbh)) {
+ init_freestyle(re);
add_freestyle(re, 1);
-
free_all_freestyle_renders();
re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
@@ -1299,6 +1453,7 @@ void RE_TileProcessor(Render *re)
static void do_render_3d(Render *re)
{
+ RenderView *rv;
int cfra_backup;
re->current_scene_update(re->suh, re->scene);
@@ -1315,40 +1470,55 @@ static void do_render_3d(Render *re)
BKE_scene_frame_set(re->scene, (double)re->scene->r.cfra + (double)re->mblur_offs + (double)re->field_offs);
- /* lock drawing in UI during data phase */
- if (re->draw_lock)
- re->draw_lock(re->dlh, 1);
-
- /* make render verts/faces/halos/lamps */
- if (render_scene_needs_vector(re)) {
- RE_Database_FromScene_Vectors(re, re->main, re->scene, re->lay);
- }
- else {
- RE_Database_FromScene(re, re->main, re->scene, re->lay, 1);
- RE_Database_Preprocess(re);
+ /* init main render result */
+ main_render_result_new(re);
+
+#ifdef WITH_FREESTYLE
+ if (re->r.mode & R_EDGE_FRS) {
+ init_freestyle(re);
}
+#endif
+
+ /* we need a new database for each view */
+ for (rv = re->result->views.first; rv; rv = rv->next) {
+ RE_SetActiveRenderView(re, rv->name);
+
+ /* lock drawing in UI during data phase */
+ if (re->draw_lock)
+ re->draw_lock(re->dlh, 1);
+
+ /* make render verts/faces/halos/lamps */
+ if (render_scene_needs_vector(re))
+ RE_Database_FromScene_Vectors(re, re->main, re->scene, re->lay);
+ else {
+ RE_Database_FromScene(re, re->main, re->scene, re->lay, 1);
+ RE_Database_Preprocess(re);
+ }
- /* clear UI drawing locks */
- if (re->draw_lock)
- re->draw_lock(re->dlh, 0);
+ /* clear UI drawing locks */
+ if (re->draw_lock)
+ re->draw_lock(re->dlh, 0);
- threaded_tile_processor(re);
+ threaded_tile_processor(re);
#ifdef WITH_FREESTYLE
- /* Freestyle */
- if (re->r.mode & R_EDGE_FRS)
- if (!re->test_break(re->tbh))
- add_freestyle(re, 1);
+ /* Freestyle */
+ if (re->r.mode & R_EDGE_FRS)
+ if (!re->test_break(re->tbh))
+ add_freestyle(re, 1);
#endif
- /* do left-over 3d post effects (flares) */
- if (re->flag & R_HALO)
- if (!re->test_break(re->tbh))
- add_halo_flare(re);
-
- /* free all render verts etc */
- RE_Database_Free(re);
-
+ /* do left-over 3d post effects (flares) */
+ if (re->flag & R_HALO)
+ if (!re->test_break(re->tbh))
+ add_halo_flare(re);
+
+ /* free all render verts etc */
+ RE_Database_Free(re);
+ }
+
+ main_render_result_end(re);
+
re->scene->r.cfra = cfra_backup;
re->scene->r.subframe = 0.f;
}
@@ -1421,19 +1591,13 @@ static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float b
rl1 = brr->layers.first;
for (rl = rr->layers.first; rl && rl1; rl = rl->next, rl1 = rl1->next) {
-
- /* combined */
- if (rl->rectf && rl1->rectf) {
- if (key_alpha)
- addblur_rect_key(rr, rl->rectf, rl1->rectf, blurfac);
- else
- addblur_rect(rr, rl->rectf, rl1->rectf, blurfac, 4);
- }
-
/* passes are allocated in sync */
rpass1 = rl1->passes.first;
for (rpass = rl->passes.first; rpass && rpass1; rpass = rpass->next, rpass1 = rpass1->next) {
- addblur_rect(rr, rpass->rect, rpass1->rect, blurfac, rpass->channels);
+ if ((rpass->passtype & SCE_PASS_COMBINED) && key_alpha)
+ addblur_rect_key(rr, rpass->rect, rpass1->rect, blurfac);
+ else
+ addblur_rect(rr, rpass->rect, rpass1->rect, blurfac, rpass->channels);
}
}
}
@@ -1446,7 +1610,7 @@ static void do_render_blur_3d(Render *re)
int blur = re->r.mblur_samples;
/* create accumulation render result */
- rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
+ rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
/* do the blur steps */
while (blur--) {
@@ -1508,10 +1672,6 @@ static void merge_renderresult_fields(RenderResult *rr, RenderResult *rr1, Rende
rl2 = rr2->layers.first;
for (rl = rr->layers.first; rl && rl1 && rl2; rl = rl->next, rl1 = rl1->next, rl2 = rl2->next) {
- /* combined */
- if (rl->rectf && rl1->rectf && rl2->rectf)
- interleave_rect(rr, rl->rectf, rl1->rectf, rl2->rectf, 4);
-
/* passes are allocated in sync */
rpass1 = rl1->passes.first;
rpass2 = rl2->passes.first;
@@ -1579,7 +1739,7 @@ static void do_render_fields_3d(Render *re)
re->disprect.ymax *= 2;
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
+ re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
if (rr2) {
if (re->r.mode & R_ODDFIELD)
@@ -1651,7 +1811,7 @@ static void do_render_fields_blur_3d(Render *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);
+ rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
render_result_merge(rres, re->result);
render_result_free(re->result);
@@ -1946,7 +2106,7 @@ static void ntree_render_scenes(Render *re)
}
/* bad call... need to think over proper method still */
-static void render_composit_stats(void *UNUSED(arg), char *str)
+static void render_composit_stats(void *UNUSED(arg), const char *str)
{
R.i.infostr = str;
R.stats_draw(R.sdh, &R.i);
@@ -1954,6 +2114,23 @@ static void render_composit_stats(void *UNUSED(arg), char *str)
}
#ifdef WITH_FREESTYLE
+/* init Freestyle renderer */
+static void init_freestyle(Render *re)
+{
+ 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;
+
+ FRS_init_stroke_renderer(re);
+}
+
/* invokes Freestyle stroke rendering */
static void add_freestyle(Render *re, int render)
{
@@ -1964,18 +2141,7 @@ static void add_freestyle(Render *re, int render)
actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
- 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;
-
- FRS_init_stroke_rendering(re);
+ FRS_begin_stroke_rendering(re);
for (srl = (SceneRenderLayer *)re->r.layers.first; srl; srl = srl->next) {
if (do_link) {
@@ -1991,7 +2157,7 @@ static void add_freestyle(Render *re, int render)
}
}
- FRS_finish_stroke_rendering(re);
+ FRS_end_stroke_rendering(re);
/* restore the global R value (invalidated by nested execution of the internal renderer) */
R = *re;
@@ -2001,28 +2167,32 @@ static void add_freestyle(Render *re, int render)
static void composite_freestyle_renders(Render *re, int sample)
{
Render *freestyle_render;
+ RenderView *rv;
SceneRenderLayer *srl, *actsrl;
LinkData *link;
actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
link = (LinkData *)re->freestyle_renders.first;
- for (srl= (SceneRenderLayer *)re->r.layers.first; srl; srl= srl->next) {
- if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl)
- continue;
- if (FRS_is_freestyle_enabled(srl)) {
- freestyle_render = (Render *)link->data;
+ for (rv = re->result->views.first; rv; rv = rv->next) {
+ for (srl = (SceneRenderLayer *)re->r.layers.first; srl; srl = srl->next) {
+ if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl)
+ continue;
- /* may be NULL in case of empty render layer */
- if (freestyle_render) {
- render_result_exr_file_read_sample(freestyle_render, sample);
- FRS_composite_result(re, srl, freestyle_render);
- RE_FreeRenderResult(freestyle_render->result);
- freestyle_render->result = NULL;
+ if (FRS_is_freestyle_enabled(srl)) {
+ freestyle_render = (Render *)link->data;
+
+ /* may be NULL in case of empty render layer */
+ if (freestyle_render) {
+ render_result_exr_file_read_sample(freestyle_render, sample);
+ FRS_composite_result(re, srl, freestyle_render);
+ RE_FreeRenderResult(freestyle_render->result);
+ freestyle_render->result = NULL;
+ }
}
+ link = link->next;
}
- link = link->next;
}
}
@@ -2049,7 +2219,7 @@ static void free_all_freestyle_renders(void)
/* detach the window manager from freestyle bmain (see comments
* in add_freestyle() for more detail)
*/
- re1->freestyle_bmain->wm.first = re1->freestyle_bmain->wm.last = NULL;
+ BLI_listbase_clear(&re1->freestyle_bmain->wm);
BKE_main_free(re1->freestyle_bmain);
re1->freestyle_bmain = NULL;
@@ -2058,11 +2228,14 @@ static void free_all_freestyle_renders(void)
}
#endif
-/* reads all buffers, calls optional composite, merges in first result->rectf */
+/* reads all buffers, calls optional composite, merges in first result->views rectf */
static void do_merge_fullsample(Render *re, bNodeTree *ntree)
{
+ ListBase *rectfs;
+ RenderView *rv;
float *rectf, filt[3][3];
int x, y, sample;
+ int nr, numviews;
/* interaction callbacks */
if (ntree) {
@@ -2077,9 +2250,18 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
/* filtmask needs it */
R = *re;
- /* we accumulate in here */
- rectf = MEM_mapallocN(re->rectx * re->recty * sizeof(float) * 4, "fullsample rgba");
-
+ /* temporary storage of the acccumulation buffers */
+ rectfs = MEM_callocN(sizeof(ListBase), "fullsample accumulation buffers");
+
+ numviews = BLI_listbase_count(&re->result->views);
+ for (nr = 0; nr < numviews; nr++) {
+ rv = MEM_callocN(sizeof(RenderView), "fullsample renderview");
+
+ /* we accumulate in here */
+ rv->rectf = MEM_mapallocN(re->rectx * re->recty * sizeof(float) * 4, "fullsample rgba");
+ BLI_addtail(rectfs, rv);
+ }
+
for (sample = 0; sample < re->r.osa; sample++) {
Scene *sce;
Render *re1;
@@ -2116,54 +2298,70 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
if (ntree) {
ntreeCompositTagRender(re->scene);
ntreeCompositTagAnimated(ntree);
-
- ntreeCompositExecTree(re->scene, ntree, &re->r, true, G.background == 0, &re->scene->view_settings, &re->scene->display_settings);
+
+ 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);
+ }
}
-
- /* ensure we get either composited result or the active layer */
- RE_AcquireResultImage(re, &rres);
-
- /* accumulate with filter, and clip */
- mask = (1 << sample);
- mask_array(mask, filt);
- for (y = 0; y < re->recty; y++) {
- float *rf = rectf + 4 * y * re->rectx;
- float *col = rres.rectf + 4 * y * re->rectx;
-
- for (x = 0; x < re->rectx; x++, rf += 4, col += 4) {
- /* clamping to 1.0 is needed for correct AA */
- if (col[0] < 0.0f) col[0] = 0.0f; else if (col[0] > 1.0f) col[0] = 1.0f;
- if (col[1] < 0.0f) col[1] = 0.0f; else if (col[1] > 1.0f) col[1] = 1.0f;
- if (col[2] < 0.0f) col[2] = 0.0f; else if (col[2] > 1.0f) col[2] = 1.0f;
+ for (nr = 0, rv = rectfs->first; rv; rv = rv->next, nr++) {
+ rectf = rv->rectf;
+
+ /* ensure we get either composited result or the active layer */
+ RE_AcquireResultImage(re, &rres, nr);
+
+ /* accumulate with filter, and clip */
+ mask = (1 << sample);
+ mask_array(mask, filt);
+
+ for (y = 0; y < re->recty; y++) {
+ float *rf = rectf + 4 * y * re->rectx;
+ float *col = rres.rectf + 4 * y * re->rectx;
- add_filt_fmask_coord(filt, col, rf, re->rectx, re->recty, x, y);
+ for (x = 0; x < re->rectx; x++, rf += 4, col += 4) {
+ /* clamping to 1.0 is needed for correct AA */
+ CLAMP(col[0], 0.0f, 1.0f);
+ CLAMP(col[1], 0.0f, 1.0f);
+ CLAMP(col[2], 0.0f, 1.0f);
+
+ add_filt_fmask_coord(filt, col, rf, re->rectx, re->recty, x, y);
+ }
}
- }
- RE_ReleaseResultImage(re);
+ RE_ReleaseResultImage(re);
- /* show stuff */
- if (sample != re->osa - 1) {
- /* weak... the display callback wants an active renderlayer pointer... */
- re->result->renlay = render_get_active_layer(re, re->result);
- re->display_update(re->duh, re->result, NULL);
+ /* show stuff */
+ if (sample != re->osa - 1) {
+ /* weak... the display callback wants an active renderlayer pointer... */
+ re->result->renlay = render_get_active_layer(re, re->result);
+ RE_SetActiveRenderView(re, rv->name);
+ re->display_update(re->duh, re->result, NULL);
+ }
}
-
- if (re->test_break(re->tbh))
- break;
}
- /* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */
- for (y = 0; y < re->recty; y++) {
- float *rf = rectf + 4 * y * re->rectx;
+ for (nr = 0; nr < numviews; nr++) {
+ rectf = ((RenderView *)BLI_findlink(rectfs, nr))->rectf;
+
+ /* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */
+ for (y = 0; y < re->recty; y++) {
+ float *rf = rectf + 4 * y * re->rectx;
- for (x = 0; x < re->rectx; x++, rf += 4) {
- rf[0] = MAX2(rf[0], 0.0f);
- rf[1] = MAX2(rf[1], 0.0f);
- rf[2] = MAX2(rf[2], 0.0f);
- CLAMP(rf[3], 0.0f, 1.0f);
+ for (x = 0; x < re->rectx; x++, rf += 4) {
+ rf[0] = MAX2(rf[0], 0.0f);
+ rf[1] = MAX2(rf[1], 0.0f);
+ rf[2] = MAX2(rf[2], 0.0f);
+ CLAMP(rf[3], 0.0f, 1.0f);
+ }
}
+
+ /* store the final result */
+ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+ rv = RE_RenderViewGetById(re->result, nr);
+ if (rv->rectf)
+ MEM_freeN(rv->rectf);
+ rv->rectf = rectf;
+ BLI_rw_mutex_unlock(&re->resultmutex);
}
/* clear interaction callbacks */
@@ -2176,12 +2374,14 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
/* disable full sample print */
R.i.curfsa = 0;
-
- BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- if (re->result->rectf)
- MEM_freeN(re->result->rectf);
- re->result->rectf = rectf;
- BLI_rw_mutex_unlock(&re->resultmutex);
+
+ /* garbage collection */
+ while (rectfs->first) {
+ RenderView *rv = rectfs->first;
+ BLI_remlink(rectfs, rv);
+ MEM_freeN(rv);
+ }
+ MEM_freeN(rectfs);
}
/* called externally, via compositor */
@@ -2234,8 +2434,10 @@ void RE_MergeFullSample(Render *re, Main *bmain, Scene *sce, bNodeTree *ntree)
re->display_clear(re->dch, re->result);
#ifdef WITH_FREESTYLE
- if (re->r.mode & R_EDGE_FRS)
+ if (re->r.mode & R_EDGE_FRS) {
+ init_freestyle(re);
add_freestyle(re, 0);
+ }
#endif
do_merge_fullsample(re, ntree);
@@ -2257,7 +2459,11 @@ static void do_render_composite_fields_blur_3d(Render *re)
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_fields_blur_3d(re);
}
else {
@@ -2270,7 +2476,7 @@ static void do_render_composite_fields_blur_3d(Render *re)
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);
+ re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
BLI_rw_mutex_unlock(&re->resultmutex);
@@ -2308,6 +2514,8 @@ static void do_render_composite_fields_blur_3d(Render *re)
/* in case it was never initialized */
R.sdh = re->sdh;
R.stats_draw = re->stats_draw;
+ R.i.starttime = re->i.starttime;
+ R.i.cfra = re->i.cfra;
if (update_newframe)
BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, re->lay);
@@ -2315,7 +2523,10 @@ static void do_render_composite_fields_blur_3d(Render *re)
if (re->r.scemode & R_FULL_SAMPLE)
do_merge_fullsample(re, ntree);
else {
- ntreeCompositExecTree(re->scene, ntree, &re->r, true, G.background == 0, &re->scene->view_settings, &re->scene->display_settings);
+ 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;
@@ -2340,11 +2551,17 @@ static void do_render_composite_fields_blur_3d(Render *re)
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 */
- RE_AcquireResultImage(re, &rres);
- BKE_stamp_buf(re->scene, RE_GetCamera(re), (unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty, 4);
- RE_ReleaseResultImage(re);
+ 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), (unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty, 4);
+ RE_ReleaseResultImage(re);
+ }
}
int RE_seq_render_active(Scene *scene, RenderData *rd)
@@ -2368,10 +2585,13 @@ int RE_seq_render_active(Scene *scene, RenderData *rd)
static void do_render_seq(Render *re)
{
static int recurs_depth = 0;
- struct ImBuf *ibuf, *out;
+ 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;
+ size_t view_id, tot_views;
+ struct ImBuf **ibuf_arr;
+ int re_x, re_y;
re->i.cfra = cfra;
@@ -2385,48 +2605,82 @@ static void do_render_seq(Render *re)
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 */
- context = BKE_sequencer_new_render_data(re->eval_ctx, re->main, re->scene,
- re->winx, re->winy, 100);
+ re_x = re->winx;
+ re_y = re->winy;
}
else {
- context = BKE_sequencer_new_render_data(re->eval_ctx, re->main, re->scene,
- re->result->rectx, re->result->recty, 100);
+ re_x = re->result->rectx;
+ re_y = re->result->recty;
}
- out = BKE_sequencer_give_ibuf(&context, cfra, 0);
+ tot_views = BKE_scene_multiview_num_views_get(&re->r);
+ ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * tot_views, "Sequencer Views ImBufs");
- if (out) {
- ibuf = IMB_dupImBuf(out);
- IMB_freeImBuf(out);
- BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf);
- }
- else {
- ibuf = NULL;
- }
+ BKE_sequencer_new_render_data(
+ re->eval_ctx, re->main, re->scene,
+ re_x, re_y, 100,
+ &context);
- recurs_depth--;
+ /* 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);
- if (ibuf) {
- /* copy ibuf into combined pixel rect */
- render_result_rect_from_ibuf(rr, &re->r, ibuf);
-
- 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);
+ 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 */
+ 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]);
}
- IMB_freeImBuf(ibuf);
- }
- else {
- /* render result is delivered empty in most cases, nevertheless we handle all cases */
- render_result_rect_fill_zero(rr);
+ 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);
}
- BLI_rw_mutex_unlock(&re->resultmutex);
+ MEM_freeN(ibuf_arr);
+
+ recurs_depth--;
/* just in case this flag went missing at some point */
re->r.scemode |= R_DOSEQ;
@@ -2436,9 +2690,6 @@ static void do_render_seq(Render *re)
re->progress(re->prh, (float)(cfra - re->r.sfra) / (re->r.efra - re->r.sfra));
else
re->progress(re->prh, 1.0f);
-
- /* would mark display buffers as invalid */
- re->display_update(re->duh, re->result, NULL);
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
@@ -2446,6 +2697,9 @@ static void do_render_seq(Render *re)
/* main loop: doing sequence + fields + blur + 3d render + compositing */
static void do_render_all_options(Render *re)
{
+ Object *camera;
+ bool render_seq = false;
+
re->current_scene_update(re->suh, re->scene);
BKE_scene_camera_switch_update(re->scene);
@@ -2460,8 +2714,10 @@ static void do_render_all_options(Render *re)
}
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))
+ 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);
@@ -2479,6 +2735,12 @@ static void do_render_all_options(Render *re)
re->stats_draw(re->sdh, &re->i);
+ /* save render result stamp if needed */
+ 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);
@@ -2525,11 +2787,50 @@ static bool check_valid_compositing_camera(Scene *scene, Object *camera_override
}
}
+static bool check_valid_camera_multiview(Scene *scene, Object *camera, ReportList *reports)
+{
+ SceneRenderView *srv;
+ bool active_view = false;
+
+ if ((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;
+
+ 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 (!active_view) {
+ BKE_reportf(reports, RPT_ERROR, "No active view found in scene \"%s\"", scene->id.name + 2);
+ return false;
+ }
+
+ return true;
+}
+
static int check_valid_camera(Scene *scene, Object *camera_override, ReportList *reports)
{
if (camera_override == NULL && scene->camera == NULL)
scene->camera = BKE_scene_camera_find(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;
@@ -2547,6 +2848,8 @@ static int check_valid_camera(Scene *scene, Object *camera_override, ReportList
}
}
}
+ else if (!check_valid_camera_multiview(seq->scene, seq->scene_camera, reports))
+ return false;
}
seq = seq->next;
@@ -2711,6 +3014,17 @@ static void update_physics_cache(Render *re, Scene *scene, int UNUSED(anim_init)
BKE_ptcache_bake(&baker);
}
+
+void RE_SetActiveRenderView(Render *re, const char *viewname)
+{
+ BLI_strncpy(re->viewname, viewname, sizeof(re->viewname));
+}
+
+const char *RE_GetActiveRenderView(Render *re)
+{
+ return re->viewname;
+}
+
/* evaluating scene options for general Blender render */
static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, Scene *scene, SceneRenderLayer *srl,
Object *camera_override, unsigned int lay_override, int anim, int anim_init)
@@ -2746,7 +3060,8 @@ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain,
re->lay = lay_override ? lay_override : scene->lay;
re->layer_override = lay_override;
re->i.localview = (re->lay & 0xFF000000) != 0;
-
+ re->viewname[0] = '\0';
+
/* not too nice, but it survives anim-border render */
if (anim) {
render_update_anim_renderdata(re, &scene->r);
@@ -2818,15 +3133,19 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr
}
else {
char name[FILE_MAX];
- BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false);
+ BKE_image_path_from_imformat(
+ name, scene->r.pic, bmain->name, 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, name);
+ 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);
@@ -2851,111 +3170,287 @@ void RE_RenderFreestyleExternal(Render *re)
if (!re->test_break(re->tbh)) {
RE_Database_FromScene(re, re->main, re->scene, re->lay, 1);
RE_Database_Preprocess(re);
+ init_freestyle(re);
add_freestyle(re, 1);
RE_Database_Free(re);
}
}
#endif
-static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override)
+bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scene, const bool stamp, char *name)
{
- char name[FILE_MAX];
- RenderResult rres;
- Object *camera = RE_GetCamera(re);
- double render_time;
- int ok = 1;
-
- RE_AcquireResultImage(re, &rres);
+ bool is_mono;
+ bool ok = true;
+ RenderData *rd = &scene->r;
- /* write movie or image */
- if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
- bool do_free = false;
- ImBuf *ibuf = render_result_rect_to_ibuf(&rres, &scene->r);
+ if (!rr)
+ return false;
- /* note; the way it gets 32 bits rects is weak... */
- if (ibuf->rect == NULL) {
- ibuf->rect = MEM_mapallocN(sizeof(int) * rres.rectx * rres.recty, "temp 32 bits rect");
- ibuf->mall |= IB_rect;
- RE_AcquiredResultGet32(re, &rres, ibuf->rect);
- do_free = true;
- }
+ is_mono = BLI_listbase_count_ex(&rr->views, 2) < 2;
+ if (ELEM(rd->im_format.imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) &&
+ rd->im_format.views_format == R_IMF_VIEWS_MULTIVIEW)
+ {
+ RE_WriteRenderResult(reports, rr, name, &rd->im_format, true, NULL);
+ printf("Saved: %s\n", name);
+ }
- IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
- &scene->display_settings, &scene->r.im_format);
+ /* mono, legacy code */
+ else if (is_mono || (rd->im_format.views_format == R_IMF_VIEWS_INDIVIDUAL))
+ {
+ RenderView *rv;
+ size_t view_id;
+ char filepath[FILE_MAX];
- ok = mh->append_movie(&re->r, scene->r.sfra, scene->r.cfra, (int *) ibuf->rect,
- ibuf->x, ibuf->y, re->reports);
- if (do_free) {
- MEM_freeN(ibuf->rect);
- ibuf->rect = NULL;
- ibuf->mall &= ~IB_rect;
- }
+ BLI_strncpy(filepath, name, sizeof(filepath));
- /* imbuf knows which rects are not part of ibuf */
- IMB_freeImBuf(ibuf);
+ 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);
+ }
- printf("Append frame %d", scene->r.cfra);
- }
- else {
- if (name_override)
- BLI_strncpy(name, name_override, sizeof(name));
- else
- BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true);
-
- if (re->r.im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
- if (re->result) {
- RE_WriteRenderResult(re->reports, re->result, name, scene->r.im_format.exr_codec);
- printf("Saved: %s", name);
+ if (rd->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
+ RE_WriteRenderResult(reports, rr, name, &rd->im_format, false, rv->name);
+ printf("Saved: %s\n", name);
+ }
+ 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);
+
+ if (stamp) {
+ /* writes the name of the individual cameras */
+ ok = BKE_imbuf_write_stamp(scene, rr, ibuf, name, &rd->im_format);
+ }
+ else {
+ ok = BKE_imbuf_write(ibuf, name, &rd->im_format);
+ }
+
+ if (ok == false) {
+ printf("Render error: cannot save %s\n", name);
+ }
+ else printf("Saved: %s\n", name);
+
+ /* optional preview images for exr */
+ if (ok && rd->im_format.imtype == R_IMF_IMTYPE_OPENEXR && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
+ ImageFormatData imf = rd->im_format;
+ imf.imtype = R_IMF_IMTYPE_JPEG90;
+
+ if (BLI_testextensie(name, ".exr"))
+ name[strlen(name) - 4] = 0;
+ BKE_image_path_ensure_ext_from_imformat(name, &imf);
+ ibuf->planes = 24;
+
+ IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
+ &scene->display_settings, &imf);
+
+ 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);
+ }
+ printf("Saved: %s\n", name);
+ }
+
+ /* 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 support for MultiLayer image: %s\n", name);
+ }
else {
- ImBuf *ibuf = render_result_rect_to_ibuf(&rres, &scene->r);
+ 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]);
+ }
- IMB_colormanagement_imbuf_for_write(ibuf, 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 = BKE_imbuf_write_stamp(scene, camera, ibuf, name, &scene->r.im_format);
-
- if (ok == 0) {
+ if (stamp)
+ ok = BKE_imbuf_write_stamp(scene, rr, ibuf_arr[2], name, &rd->im_format);
+ else
+ ok = BKE_imbuf_write(ibuf_arr[2], name, &rd->im_format);
+
+ if (ok == false)
printf("Render error: cannot save %s\n", name);
- }
- else printf("Saved: %s", name);
-
+ else
+ printf("Saved: %s\n", name);
+
/* optional preview images for exr */
- if (ok && scene->r.im_format.imtype == R_IMF_IMTYPE_OPENEXR && (scene->r.im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
- ImageFormatData imf = scene->r.im_format;
+ if (ok && rd->im_format.imtype == R_IMF_IMTYPE_OPENEXR &&
+ (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG))
+ {
+ ImageFormatData imf = rd->im_format;
imf.imtype = R_IMF_IMTYPE_JPEG90;
if (BLI_testextensie(name, ".exr"))
name[strlen(name) - 4] = 0;
- BKE_add_image_extension(name, &imf);
- ibuf->planes = 24;
- IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
+ BKE_image_path_ensure_ext_from_imformat(name, &imf);
+ ibuf_arr[2]->planes = 24;
+
+ IMB_colormanagement_imbuf_for_write(ibuf_arr[2], true, false, &scene->view_settings,
&scene->display_settings, &imf);
- BKE_imbuf_write_stamp(scene, camera, ibuf, name, &imf);
- printf("\nSaved: %s", name);
+ if (stamp)
+ ok = BKE_imbuf_write_stamp(scene, rr, ibuf_arr[2], name, &rd->im_format);
+ else
+ ok = BKE_imbuf_write(ibuf_arr[2], name, &imf);
+
+ printf("Saved: %s\n", name);
}
-
+
+ /* 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,
+ const size_t width, const size_t height, void **movie_ctx_arr, const size_t totvideos, bool preview)
+{
+ bool is_mono;
+ bool ok = true;
+
+ if (!rr)
+ return false;
+
+ is_mono = BLI_listbase_count_ex(&rr->views, 2) < 2;
+
+ if (is_mono || (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) {
+ size_t view_id;
+ for (view_id = 0; view_id < totvideos; view_id++) {
+ bool do_free = false;
+ 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);
+
+ /* note; the way it gets 32 bits rects is weak... */
+ if (ibuf->rect == NULL) {
+ ibuf->rect = MEM_mapallocN(sizeof(int) * rr->rectx * rr->recty, "temp 32 bits rect");
+ ibuf->mall |= IB_rect;
+ render_result_rect_get_pixels(rr, ibuf->rect, width, height, &scene->view_settings, &scene->display_settings, view_id);
+ do_free = true;
+ }
+
+ 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);
+
+ if (do_free) {
+ MEM_freeN(ibuf->rect);
+ ibuf->rect = NULL;
+ ibuf->mall &= ~IB_rect;
+ }
+
/* 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};
+ bool do_free[2] = {false, false};
+ size_t 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);
+
+ /* note; the way it gets 32 bits rects is weak... */
+ if (ibuf_arr[i]->rect == NULL) {
+ ibuf_arr[i]->rect = MEM_mapallocN(sizeof(int) * width * height, "temp 32 bits rect");
+ ibuf_arr[i]->mall |= IB_rect;
+ render_result_rect_get_pixels(rr, ibuf_arr[i]->rect, width, height, &scene->view_settings, &scene->display_settings, view_id);
+ do_free[i] = true;
+ }
+
+ 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 < 2; i++) {
+ if (do_free[i]) {
+ MEM_freeN(ibuf_arr[i]->rect);
+ ibuf_arr[i]->rect = NULL;
+ ibuf_arr[i]->mall &= ~IB_rect;
+ }
+
+ /* 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 size_t 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->rectx, re->recty, 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, bmain->name, 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_ReleaseResultImage(re);
+ RE_ReleaseResultImageViews(re, &rres);
render_time = re->i.lastframetime;
re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
- BLI_timestr(re->i.lastframetime, name, sizeof(name));
+ 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);
+
BLI_callback_exec(G.main, NULL, BLI_CB_EVT_RENDER_STATS);
- BLI_timestr(re->i.lastframetime - render_time, name, sizeof(name));
+ BLI_timecode_string_from_time_simple(name, sizeof(name), re->i.lastframetime - render_time);
printf(" (Saving: %s)\n", name);
fputc('\n', stdout);
@@ -2964,20 +3459,51 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
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);
+}
+
/* saves images to disk */
void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_override,
unsigned int lay_override, int sfra, int efra, int tfra)
{
RenderData rd = scene->r;
- bMovieHandle *mh = BKE_movie_handle_get(scene->r.im_format.imtype);
+ bMovieHandle *mh = NULL;
int cfrao = scene->r.cfra;
int nfra, totrendered = 0, totskipped = 0;
-
+ const size_t 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, NULL, camera_override, lay_override, 0, 1))
return;
+
+ /* we don't support Frame Server and streaming of individual views */
+ if ((rd.im_format.imtype == R_IMF_IMTYPE_FRAMESERVER) && (totvideos > 1)) {
+ BKE_report(re->reports, RPT_ERROR, "Frame Server only support stereo output for multiview rendering");
+ return;
+ }
/* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */
/* is also set by caller renderwin.c */
@@ -2985,30 +3511,38 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
re->flag |= R_ANIMATION;
- if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
- int 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;
+ if (is_movie) {
+ size_t i, width, height;
+
+ 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;
}
- if (!mh->start_movie(scene, &re->r, width, height, re->reports))
- G.is_break = true;
+ 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))
+ G.is_break = true;
+ }
}
- if (mh->get_next_frame) {
+ if (mh && mh->get_next_frame) {
+ /* MULTIVIEW_TODO:
+ * in case a new video format is added that implements get_next_frame multiview has to be addressed
+ * or the error throwing for R_IMF_IMTYPE_FRAMESERVER has to be extended for those cases as well
+ */
+ BLI_assert(totvideos < 2);
+
while (!(G.is_break == 1)) {
- int nf = mh->get_next_frame(&re->r, re->reports);
+ int nf = mh->get_next_frame(re->movie_ctx_arr[0], &re->r, re->reports);
if (nf >= 0 && nf >= scene->r.sfra && nf <= scene->r.efra) {
scene->r.cfra = re->r.cfra = nf;
@@ -3018,12 +3552,13 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
totrendered++;
if (re->test_break(re->tbh) == 0) {
- if (!do_write_image_or_movie(re, bmain, scene, mh, NULL))
+ if (!do_write_image_or_movie(re, bmain, scene, mh, totvideos, NULL))
G.is_break = true;
}
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);
}
}
else {
@@ -3060,19 +3595,67 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
nfra += tfra;
/* Touch/NoOverwrite options are only valid for image's */
- if (BKE_imtype_is_movie(scene->r.im_format.imtype) == 0) {
+ if (is_movie == false) {
if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH))
- BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true);
+ BKE_image_path_from_imformat(
+ name, scene->r.pic, bmain->name, 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];
- if (scene->r.mode & R_NO_OVERWRITE && BLI_exists(name)) {
- printf("skipping existing frame \"%s\"\n", name);
- totskipped++;
- continue;
+ 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 && !BLI_exists(name)) {
- BLI_make_existing_file(name); /* makes the dir if its not there */
- BLI_file_touch(name);
+
+ 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);
+ }
+ }
+ }
}
}
@@ -3087,7 +3670,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
if (re->test_break(re->tbh) == 0) {
if (!G.is_break)
- if (!do_write_image_or_movie(re, bmain, scene, mh, NULL))
+ if (!do_write_image_or_movie(re, bmain, scene, mh, totvideos, NULL))
G.is_break = true;
}
else
@@ -3095,9 +3678,30 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
if (G.is_break == true) {
/* remove touched file */
- if (BKE_imtype_is_movie(scene->r.im_format.imtype) == 0) {
- if (scene->r.mode & R_TOUCH && BLI_exists(name) && BLI_file_size(name) == 0) {
- BLI_delete(name, false, false);
+ 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);
+ }
+ }
+ }
}
}
@@ -3106,13 +3710,23 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
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 (BKE_imtype_is_movie(scene->r.im_format.imtype))
- mh->end_movie();
+ if (is_movie) {
+ size_t i;
+ for (i = 0; i < totvideos; i++) {
+ mh->end_movie(re->movie_ctx_arr[i]);
+ mh->context_free(re->movie_ctx_arr[i]);
+ }
+
+ if (re->movie_ctx_arr) {
+ MEM_freeN(re->movie_ctx_arr);
+ }
+ }
if (totskipped && totrendered == 0)
BKE_report(re->reports, RPT_INFO, "No frames rendered, skipped to not overwrite");
@@ -3210,13 +3824,22 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char
{
/* 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 (rpass->passtype == SCE_PASS_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(layer->rectf, ibuf->rect_float, sizeof(float) * 4 * layer->rectx * layer->recty);
+ 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)) {
@@ -3229,29 +3852,29 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char
if (ibuf_clip) {
IMB_rectcpy(ibuf_clip, ibuf, 0, 0, x, y, layer->rectx, layer->recty);
- memcpy(layer->rectf, ibuf_clip->rect_float, sizeof(float) * 4 * 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, "RE_result_rect_from_file: failed to allocate clip buffer '%s'", filename);
+ BKE_reportf(reports, RPT_ERROR, "%s: failed to allocate clip buffer '%s'", __func__, filename);
}
}
else {
- BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: incorrect dimensions for partial copy '%s'", filename);
+ BKE_reportf(reports, RPT_ERROR, "%s: incorrect dimensions for partial copy '%s'", __func__, filename);
}
}
IMB_freeImBuf(ibuf);
}
else {
- BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'", filename);
+ 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, "RE_result_rect_from_file: failed to load '%s'", filename);
+ BKE_reportf(reports, RPT_ERROR, "%s: failed to load '%s'", __func__, filename);
return;
}
}
@@ -3317,3 +3940,35 @@ bool RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env,
}
}
+/* used in the interface to decide whether to show layers */
+bool RE_layers_have_name(struct RenderResult *rr)
+{
+ switch (BLI_listbase_count_ex(&rr->layers, 2)) {
+ case 0:
+ return false;
+ break;
+ case 1:
+ return (((RenderLayer *)rr->layers.first)->name[0] != '\0');
+ break;
+ default:
+ return true;
+ break;
+ }
+ return false;
+}
+
+RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const char *viewname)
+{
+ RenderPass *rp = NULL;
+
+ for (rp = rl->passes.last; rp; rp = rp->prev) {
+ if (rp->passtype == passtype) {
+
+ if (viewname == NULL || viewname[0] == '\0')
+ break;
+ else if (STREQ(rp->view, viewname))
+ break;
+ }
+ }
+ return rp;
+}
diff --git a/source/blender/render/intern/source/pixelblending.c b/source/blender/render/intern/source/pixelblending.c
index 460a6814f07..32fb196e1f3 100644
--- a/source/blender/render/intern/source/pixelblending.c
+++ b/source/blender/render/intern/source/pixelblending.c
@@ -38,7 +38,6 @@
/* own includes */
#include "render_types.h"
-#include "renderpipeline.h"
#include "pixelblending.h"
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c
index 014df802a78..104cde0a0b5 100644
--- a/source/blender/render/intern/source/pixelshading.c
+++ b/source/blender/render/intern/source/pixelshading.c
@@ -36,8 +36,6 @@
#include "BLI_utildefines.h"
/* External modules: */
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "DNA_group_types.h"
#include "DNA_material_types.h"
@@ -51,14 +49,11 @@
/* own module */
#include "render_types.h"
-#include "renderpipeline.h"
#include "renderdatabase.h"
#include "texture.h"
-#include "pixelblending.h"
#include "rendercore.h"
#include "shadbuf.h"
#include "pixelshading.h"
-#include "shading.h"
#include "sunsky.h"
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
@@ -160,7 +155,7 @@ static void render_lighting_halo(HaloRen *har, float col_r[3])
x = max_ff(fabsf(lvrot[0]/lvrot[2]), fabsf(lvrot[1]/lvrot[2]));
/* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
- inpr = 1.0 / (sqrtf(1.0f + x * x));
+ inpr = 1.0f / (sqrtf(1.0f + x * x));
}
else inpr= 0.0;
}
@@ -206,7 +201,7 @@ static void render_lighting_halo(HaloRen *har, float col_r[3])
/* dot product and reflectivity*/
- inp = 1.0 - fabsf(dot_v3v3(vn, lv));
+ inp = 1.0f - fabsf(dot_v3v3(vn, lv));
/* inp= cos(0.5*M_PI-acos(inp)); */
@@ -366,7 +361,7 @@ int shadeHaloFloat(HaloRen *har, float col[4], int zz,
else dist= dist/har->radsq;
if (har->type & HA_FLARECIRC) {
- dist = 0.5 + fabsf(dist - 0.5f);
+ dist = 0.5f + fabsf(dist - 0.5f);
}
if (har->hard>=30) {
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index ac2e85a33b3..b8d8cc37ae3 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -1,4 +1,4 @@
-/*
+/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -40,11 +40,12 @@
#include "BLI_kdopbvh.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_DerivedMesh.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
+#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_texture.h"
@@ -55,39 +56,50 @@
#include "DNA_particle_types.h"
#include "render_types.h"
-#include "renderdatabase.h"
#include "texture.h"
#include "pointdensity.h"
+#include "RE_render_ext.h"
+
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
/* only to be used here in this file, it's for speed */
extern struct Render R;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+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->noise_influence == TEX_PD_NOISE_VEL) || (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) || (pd->color_source == TEX_PD_COLOR_PARTVEL) || (pd->color_source == TEX_PD_COLOR_PARTSPEED))
+ if ((pd->noise_influence == TEX_PD_NOISE_VEL) ||
+ (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->noise_influence == TEX_PD_NOISE_AGE) || (pd->color_source == TEX_PD_COLOR_PARTAGE) || (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE))
+ }
+ if ((pd->noise_influence == TEX_PD_NOISE_AGE) ||
+ (pd->color_source == TEX_PD_COLOR_PARTAGE) ||
+ (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE))
+ {
pd_bitflag |= POINT_DATA_LIFE;
+ }
}
-
+
return pd_bitflag;
}
-/* additional data stored alongside the point density BVH,
- * accessible by point index number to retrieve other information
+/* additional data stored alongside the point density BVH,
+ * accessible by point index number to retrieve other information
* such as particle velocity or lifetime */
static void alloc_point_data(PointDensity *pd, int total_particles, int point_data_used)
{
int data_size = 0;
-
+
if (point_data_used & POINT_DATA_VEL) {
/* store 3 channels of velocity data */
data_size += 3;
@@ -97,60 +109,70 @@ static void alloc_point_data(PointDensity *pd, int total_particles, int point_da
data_size += 1;
}
- if (data_size)
- pd->point_data = MEM_mallocN(sizeof(float)*data_size*total_particles, "particle point data");
+ if (data_size) {
+ pd->point_data = MEM_mallocN(sizeof(float) * data_size * total_particles,
+ "particle point data");
+ }
}
-static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, ParticleSystem *psys)
+static void pointdensity_cache_psys(Scene *scene,
+ PointDensity *pd,
+ Object *ob,
+ ParticleSystem *psys,
+ float viewmat[4][4],
+ float winmat[4][4],
+ int winx, int winy)
{
- DerivedMesh* dm;
+ DerivedMesh *dm;
ParticleKey state;
ParticleCacheKey *cache;
- ParticleSimulationData sim= {NULL};
- ParticleData *pa=NULL;
- float cfra = BKE_scene_frame_get(re->scene);
+ ParticleSimulationData sim = {NULL};
+ ParticleData *pa = NULL;
+ float cfra = BKE_scene_frame_get(scene);
int i /*, childexists*/ /* UNUSED */;
- int total_particles, offset=0;
+ int total_particles, offset = 0;
int data_used = point_data_used(pd);
float partco[3];
- float obview[4][4];
-
+
/* init everything */
- if (!psys || !ob || !pd) return;
+ if (!psys || !ob || !pd) {
+ return;
+ }
- mul_m4_m4m4(obview, ob->obmat, re->viewinv);
-
/* Just to create a valid rendering context for particles */
- psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, 0);
-
- dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
-
+ psys_render_set(ob, psys, viewmat, winmat, winx, winy, 0);
+
+ dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
+
if ( !psys_check_enabled(ob, psys)) {
psys_render_restore(ob, psys);
return;
}
-
- sim.scene= re->scene;
- sim.ob= ob;
- sim.psys= psys;
+
+ 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;
+
+ 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);
alloc_point_data(pd, total_particles, data_used);
pd->totpoints = total_particles;
- if (data_used & POINT_DATA_VEL) offset = pd->totpoints*3;
-
+ if (data_used & POINT_DATA_VEL) {
+ offset = pd->totpoints * 3;
+ }
+
#if 0 /* UNUSED */
if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
childexists = 1;
#endif
- for (i=0, pa=psys->particles; i < total_particles; i++, pa++) {
+ for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
if (psys->part->type == PART_HAIR) {
/* hair particles */
@@ -161,7 +183,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa
else
continue;
- cache += cache->steps; /* use endpoint */
+ cache += cache->segments; /* use endpoint */
copy_v3_v3(state.co, cache->co);
zero_v3(state.vel);
@@ -176,19 +198,19 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa
if (data_used & POINT_DATA_LIFE) {
if (i < psys->totpart) {
- state.time = (cfra - pa->time)/pa->lifetime;
+ state.time = (cfra - pa->time) / pa->lifetime;
}
else {
- ChildParticle *cpa= (psys->child + i) - psys->totpart;
+ 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) {
@@ -197,48 +219,50 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa
else {
/* TEX_PD_WORLDSPACE */
}
-
+
BLI_bvhtree_insert(pd->point_tree, i, partco, 1);
-
+
if (data_used & POINT_DATA_VEL) {
- pd->point_data[i*3 + 0] = state.vel[0];
- pd->point_data[i*3 + 1] = state.vel[1];
- pd->point_data[i*3 + 2] = state.vel[2];
+ pd->point_data[i * 3 + 0] = state.vel[0];
+ pd->point_data[i * 3 + 1] = state.vel[1];
+ pd->point_data[i * 3 + 2] = state.vel[2];
}
if (data_used & POINT_DATA_LIFE) {
pd->point_data[offset + i] = state.time;
}
}
-
+
BLI_bvhtree_balance(pd->point_tree);
dm->release(dm);
-
+
if (psys->lattice_deform_data) {
end_latt_deform(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
-
+
psys_render_restore(ob, psys);
}
-static void pointdensity_cache_object(Render *re, PointDensity *pd, Object *ob)
+static void pointdensity_cache_object(Scene *scene, PointDensity *pd, Object *ob)
{
int i;
DerivedMesh *dm;
MVert *mvert = NULL;
-
- dm = mesh_create_derived_render(re->scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
- mvert= dm->getVertArray(dm); /* local object space */
-
- pd->totpoints= dm->getNumVerts(dm);
- if (pd->totpoints == 0) return;
+
+ dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
+ mvert = dm->getVertArray(dm); /* local object space */
+
+ pd->totpoints = dm->getNumVerts(dm);
+ if (pd->totpoints == 0) {
+ return;
+ }
pd->point_tree = BLI_bvhtree_new(pd->totpoints, 0.0, 4, 6);
-
- for (i=0; i < pd->totpoints; i++, mvert++) {
+
+ for (i = 0; i < pd->totpoints; i++, mvert++) {
float co[3];
-
+
copy_v3_v3(co, mvert->co);
switch (pd->ob_cache_space) {
@@ -256,47 +280,60 @@ static void pointdensity_cache_object(Render *re, PointDensity *pd, Object *ob)
BLI_bvhtree_insert(pd->point_tree, i, co, 1);
}
-
+
BLI_bvhtree_balance(pd->point_tree);
dm->release(dm);
}
-void cache_pointdensity(Render *re, Tex *tex)
+
+static void cache_pointdensity_ex(Scene *scene,
+ PointDensity *pd,
+ float viewmat[4][4],
+ float winmat[4][4],
+ int winx, int winy)
{
- PointDensity *pd = tex->pd;
-
- if (!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;
+ if (!ob || !pd->psys) {
+ return;
+ }
+
+ psys = BLI_findlink(&ob->particlesystem, pd->psys - 1);
+ if (!psys) {
+ return;
+ }
- psys= BLI_findlink(&ob->particlesystem, pd->psys-1);
- if (!psys) return;
-
- pointdensity_cache_psys(re, pd, ob, psys);
+ pointdensity_cache_psys(scene, pd, ob, psys, viewmat, winmat, winx, winy);
}
else if (pd->source == TEX_PD_OBJECT) {
Object *ob = pd->object;
if (ob && ob->type == OB_MESH)
- pointdensity_cache_object(re, pd, ob);
+ pointdensity_cache_object(scene, pd, ob);
}
}
-static void free_pointdensity(Render *UNUSED(re), Tex *tex)
+void cache_pointdensity(Render *re, PointDensity *pd)
{
- PointDensity *pd = tex->pd;
+ cache_pointdensity_ex(re->scene, pd, re->viewmat, re->winmat, re->winx, re->winy);
+}
+
+void free_pointdensity(PointDensity *pd)
+{
+ if (pd == NULL) {
+ return;
+ }
- if (!pd) return;
-
if (pd->point_tree) {
BLI_bvhtree_free(pd->point_tree);
pd->point_tree = NULL;
@@ -309,24 +346,23 @@ static void free_pointdensity(Render *UNUSED(re), Tex *tex)
pd->totpoints = 0;
}
-
-
void make_pointdensities(Render *re)
{
Tex *tex;
-
- if (re->scene->r.scemode & R_BUTS_PREVIEW)
+
+ if (re->scene->r.scemode & R_BUTS_PREVIEW) {
return;
-
+ }
+
re->i.infostr = IFACE_("Caching Point Densities");
re->stats_draw(re->sdh, &re->i);
- for (tex= re->main->tex.first; tex; tex= tex->id.next) {
- if (tex->id.us && tex->type==TEX_POINTDENSITY) {
- cache_pointdensity(re, tex);
+ for (tex = re->main->tex.first; tex != NULL; tex = tex->id.next) {
+ if (tex->id.us && tex->type == TEX_POINTDENSITY) {
+ cache_pointdensity(re, tex->pd);
}
}
-
+
re->i.infostr = NULL;
re->stats_draw(re->sdh, &re->i);
}
@@ -334,13 +370,13 @@ void make_pointdensities(Render *re)
void free_pointdensities(Render *re)
{
Tex *tex;
-
+
if (re->scene->r.scemode & R_BUTS_PREVIEW)
return;
-
- for (tex= re->main->tex.first; tex; tex= tex->id.next) {
- if (tex->id.us && tex->type==TEX_POINTDENSITY) {
- free_pointdensity(re, tex);
+
+ for (tex = re->main->tex.first; tex != NULL; tex = tex->id.next) {
+ if (tex->id.us && tex->type == TEX_POINTDENSITY) {
+ free_pointdensity(tex->pd);
}
}
}
@@ -365,20 +401,20 @@ static void accum_density(void *userdata, int index, float squared_dist)
PointDensityRangeData *pdr = (PointDensityRangeData *)userdata;
const float dist = (pdr->squared_radius - squared_dist) / pdr->squared_radius * 0.5f;
float density = 0.0f;
-
+
if (pdr->point_data_used & POINT_DATA_VEL) {
- pdr->vec[0] += pdr->point_data[index*3 + 0]; // * density;
- pdr->vec[1] += pdr->point_data[index*3 + 1]; // * density;
- pdr->vec[2] += pdr->point_data[index*3 + 2]; // * density;
+ pdr->vec[0] += pdr->point_data[index * 3 + 0]; // * density;
+ pdr->vec[1] += pdr->point_data[index * 3 + 1]; // * density;
+ pdr->vec[2] += pdr->point_data[index * 3 + 2]; // * density;
}
if (pdr->point_data_used & POINT_DATA_LIFE) {
*pdr->age += pdr->point_data[pdr->offset + index]; // * density;
}
-
+
if (pdr->falloff_type == TEX_PD_FALLOFF_STD)
density = dist;
else if (pdr->falloff_type == TEX_PD_FALLOFF_SMOOTH)
- density = 3.0f*dist*dist - 2.0f*dist*dist*dist;
+ density = 3.0f * dist * dist - 2.0f * dist * dist * dist;
else if (pdr->falloff_type == TEX_PD_FALLOFF_SOFT)
density = pow(dist, pdr->softness);
else if (pdr->falloff_type == TEX_PD_FALLOFF_CONSTANT)
@@ -387,30 +423,30 @@ static void accum_density(void *userdata, int index, float squared_dist)
density = sqrtf(dist);
else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE) {
if (pdr->point_data_used & POINT_DATA_LIFE)
- density = dist*MIN2(pdr->point_data[pdr->offset + index], 1.0f);
+ density = dist * MIN2(pdr->point_data[pdr->offset + index], 1.0f);
else
density = dist;
}
else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) {
if (pdr->point_data_used & POINT_DATA_VEL)
- density = dist*len_v3(pdr->point_data + index*3)*pdr->velscale;
+ density = dist * len_v3(pdr->point_data + index * 3) * pdr->velscale;
else
density = dist;
}
-
+
if (pdr->density_curve && dist != 0.0f) {
curvemapping_initialize(pdr->density_curve);
- density = curvemapping_evaluateF(pdr->density_curve, 0, density/dist)*dist;
+ density = curvemapping_evaluateF(pdr->density_curve, 0, density / dist) * dist;
}
-
+
*pdr->density += density;
}
-static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *pdr,
+static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *pdr,
float *density, float *vec, float *age, struct CurveMapping *density_curve, float velscale)
{
- pdr->squared_radius = pd->radius*pd->radius;
+ pdr->squared_radius = pd->radius * pd->radius;
pdr->density = density;
pdr->point_data = pd->point_data;
pdr->falloff_type = pd->falloff_type;
@@ -419,63 +455,69 @@ static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *
pdr->softness = pd->falloff_softness;
pdr->noise_influence = pd->noise_influence;
pdr->point_data_used = point_data_used(pd);
- pdr->offset = (pdr->point_data_used & POINT_DATA_VEL)?pd->totpoints*3:0;
+ pdr->offset = (pdr->point_data_used & POINT_DATA_VEL) ? pd->totpoints * 3 : 0;
pdr->density_curve = density_curve;
pdr->velscale = velscale;
}
-int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
+static int pointdensity(PointDensity *pd,
+ const float texvec[3],
+ TexResult *texres,
+ float *r_age,
+ float r_vec[3])
{
int retval = TEX_INT;
- PointDensity *pd = tex->pd;
PointDensityRangeData pdr;
- float density=0.0f, age=0.0f, time=0.0f;
+ float density = 0.0f, age = 0.0f, time = 0.0f;
float vec[3] = {0.0f, 0.0f, 0.0f}, co[3];
- float col[4];
float turb, noise_fac;
- int num=0;
-
+ int num = 0;
+
texres->tin = 0.0f;
-
+
if ((!pd) || (!pd->point_tree))
return 0;
-
- init_pointdensityrangedata(pd, &pdr, &density, vec, &age,
- (pd->flag&TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : NULL), pd->falloff_speed_scale*0.001f);
+
+ init_pointdensityrangedata(pd, &pdr, &density, vec, &age,
+ (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(vec, 1.0f / num);
}
-
+
/* reset */
density = vec[0] = vec[1] = vec[2] = 0.0f;
}
-
+
if (pd->flag & TEX_PD_TURBULENCE) {
-
+
if (pd->noise_influence == TEX_PD_NOISE_AGE) {
- turb = BLI_gTurbulence(pd->noise_size, texvec[0]+age, texvec[1]+age, texvec[2]+age, pd->noise_depth, 0, pd->noise_basis);
+ turb = BLI_gTurbulence(pd->noise_size, texvec[0] + age, texvec[1] + age, texvec[2] + age,
+ pd->noise_depth, 0, pd->noise_basis);
}
else if (pd->noise_influence == TEX_PD_NOISE_TIME) {
time = R.r.cfra / (float)R.r.efra;
- turb = BLI_gTurbulence(pd->noise_size, texvec[0]+time, texvec[1]+time, texvec[2]+time, pd->noise_depth, 0, pd->noise_basis);
+ turb = BLI_gTurbulence(pd->noise_size, texvec[0] + time, texvec[1] + time, texvec[2] + time,
+ pd->noise_depth, 0, pd->noise_basis);
//turb = BLI_turbulence(pd->noise_size, texvec[0]+time, texvec[1]+time, texvec[2]+time, pd->noise_depth);
}
else {
- 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 = 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;
@@ -486,17 +528,27 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
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(vec, 1.0f / num);
}
-
+
texres->tin = density;
- BRICONT;
-
- if (pd->color_source == TEX_PD_COLOR_CONSTANT)
- return retval;
-
+ if (r_age != NULL) {
+ *r_age = age;
+ }
+ if (r_vec != NULL) {
+ copy_v3_v3(r_vec, vec);
+ }
+
+ return retval;
+}
+
+static int pointdensity_color(PointDensity *pd, TexResult *texres, float age, const float vec[3])
+{
+ int retval = 0;
+ float col[4];
+
retval |= TEX_RGB;
-
+
switch (pd->color_source) {
case TEX_PD_COLOR_PARTAGE:
if (pd->coba) {
@@ -511,7 +563,7 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
case TEX_PD_COLOR_PARTSPEED:
{
float speed = len_v3(vec) * pd->speed_scale;
-
+
if (pd->coba) {
if (do_colorband(pd->coba, speed, col)) {
texres->talpha = true;
@@ -524,8 +576,7 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
}
case TEX_PD_COLOR_PARTVEL:
texres->talpha = true;
- mul_v3_fl(vec, pd->speed_scale);
- copy_v3_v3(&texres->tr, vec);
+ mul_v3_v3fl(&texres->tr, vec, pd->speed_scale);
texres->ta = texres->tin;
break;
case TEX_PD_COLOR_CONSTANT:
@@ -533,13 +584,130 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
texres->tr = texres->tg = texres->tb = texres->ta = 1.0f;
break;
}
- BRICONTRGB;
return retval;
-
+}
+
+int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
+{
+ PointDensity *pd = tex->pd;
+ float age = 0.0f;
+ float vec[3] = {0.0f, 0.0f, 0.0f};
+ int retval = pointdensity(pd, texvec, texres, &age, vec);
+
+ BRICONT;
+
+ retval |= pointdensity_color(pd, texres, age, vec);
+ BRICONTRGB;
+
+ return retval;
+
#if 0
if (texres->nor!=NULL) {
texres->nor[0] = texres->nor[1] = texres->nor[2] = 0.0f;
}
#endif
}
+
+static void sample_dummy_point_density(int resolution, float *values)
+{
+ memset(values, 0, sizeof(float) * 4 * resolution * resolution * resolution);
+}
+
+static void particle_system_minmax(Object *object,
+ ParticleSystem *psys,
+ float radius,
+ float min[3], float max[3])
+{
+ ParticleSettings *part = psys->part;
+ float imat[4][4];
+ float size[3] = {radius, radius, radius};
+ PARTICLE_P;
+ INIT_MINMAX(min, max);
+ if (part->type == PART_HAIR) {
+ /* TOOD(sergey): Not supported currently. */
+ return;
+ }
+ invert_m4_m4(imat, object->obmat);
+ LOOP_PARTICLES {
+ float co_object[3], co_min[3], co_max[3];
+ mul_v3_m4v3(co_object, imat, pa->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);
+ }
+}
+
+void RE_sample_point_density(Scene *scene, PointDensity *pd,
+ int resolution, float *values)
+{
+ const size_t resolution2 = resolution * resolution;
+ Object *object = pd->object;
+ size_t x, y, z;
+ float min[3], max[3], dim[3], mat[4][4];
+
+ if (object == NULL) {
+ sample_dummy_point_density(resolution, values);
+ return;
+ }
+
+ if (pd->source == TEX_PD_PSYS) {
+ ParticleSystem *psys;
+ if (pd->psys == 0) {
+ sample_dummy_point_density(resolution, values);
+ return;
+ }
+ psys = BLI_findlink(&object->particlesystem, pd->psys - 1);
+ if (psys == NULL) {
+ sample_dummy_point_density(resolution, values);
+ return;
+ }
+ particle_system_minmax(object, psys, pd->radius, min, max);
+ }
+ else {
+ float radius[3] = {pd->radius, pd->radius, pd->radius};
+ float *loc, *size;
+ BKE_object_obdata_texspace_get(pd->object, NULL, &loc, &size, NULL);
+ sub_v3_v3v3(min, loc, size);
+ add_v3_v3v3(max, loc, size);
+ /* Adjust texture space to include density points on the boundaries. */
+ sub_v3_v3(min, radius);
+ add_v3_v3(max, radius);
+ }
+
+ 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;
+ }
+
+ /* Same matricies/resolution as dupli_render_particle_set(). */
+ unit_m4(mat);
+
+ BLI_mutex_lock(&sample_mutex);
+ cache_pointdensity_ex(scene, pd, mat, mat, 1, 1);
+ for (z = 0; z < resolution; ++z) {
+ for (y = 0; y < resolution; ++y) {
+ for (x = 0; x < resolution; ++x) {
+ size_t index = z * resolution2 + y * resolution + x;
+ float texvec[3];
+ float age, vec[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, &age, vec);
+ pointdensity_color(pd, &texres, age, vec);
+
+ copy_v3_v3(&values[index*4 + 0], &texres.tr);
+ values[index*4 + 3] = texres.tin;
+ }
+ }
+ }
+ free_pointdensity(pd);
+ BLI_mutex_unlock(&sample_mutex);
+}
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index 05e83f35179..900312ee984 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -27,7 +27,6 @@
* \ingroup render
*/
-
#include <stdio.h>
#include <math.h>
#include <string.h>
@@ -46,29 +45,22 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "BKE_node.h"
-
-#include "PIL_time.h"
-
#include "render_result.h"
#include "render_types.h"
-#include "renderpipeline.h"
#include "rendercore.h"
#include "renderdatabase.h"
-#include "pixelblending.h"
#include "pixelshading.h"
#include "shading.h"
-#include "texture.h"
#include "volumetric.h"
#include "rayintersection.h"
#include "rayobject.h"
#include "raycounter.h"
-
#define RAY_TRA 1
#define RAY_INSIDE 2
@@ -314,22 +306,23 @@ static void makeraytree_single(Render *re)
RayObject *raytree;
RayFace *face = NULL;
VlakPrimitive *vlakprimitive = NULL;
- int faces = 0, obs = 0, special = 0;
+ int faces = 0, special = 0;
- for (obi=re->instancetable.first; obi; obi=obi->next)
- if (is_raytraceable(re, obi)) {
- ObjectRen *obr = obi->obr;
- obs++;
-
- if (has_special_rayobject(re, obi)) {
- special++;
- }
- else {
- int v;
- for (v=0;v<obr->totvlak;v++) {
- VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255);
- if (is_raytraceable_vlr(re, vlr))
- faces++;
+ for (obi = re->instancetable.first; obi; obi = obi->next) {
+ if (is_raytraceable(re, obi)) {
+ ObjectRen *obr = obi->obr;
+
+ if (has_special_rayobject(re, obi)) {
+ special++;
+ }
+ else {
+ int v;
+ for (v = 0;v < obr->totvlak; v++) {
+ VlakRen *vlr = obr->vlaknodes[v >> 8].vlak + (v&255);
+ if (is_raytraceable_vlr(re, vlr)) {
+ faces++;
+ }
+ }
}
}
}
@@ -743,6 +736,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, con
//shi.sample= 0; // memset above, so don't need this
shi.xs= origshi->xs;
shi.ys= origshi->ys;
+ shi.do_manage= origshi->do_manage;
shi.lay= origshi->lay;
shi.passflag= SCE_PASS_COMBINED; /* result of tracing needs no pass info */
shi.combinedflag= 0xFFFFFF; /* ray trace does all options */
@@ -802,7 +796,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, con
traceray(origshi, origshr, depth-1, shi.co, shi.view, tracol, shi.obi, shi.vlr, 0);
f= shr.alpha; f1= 1.0f-f;
- nf= d * shi.mat->filter;
+ nf= (shi.mat->mode & MA_RAYTRANSP) ? d * shi.mat->filter : 0.0f;
fr= 1.0f+ nf*(shi.r-1.0f);
fg= 1.0f+ nf*(shi.g-1.0f);
fb= 1.0f+ nf*(shi.b-1.0f);
@@ -1281,7 +1275,7 @@ static float get_avg_speed(ShadeInput *shi)
post_x = (shi->winspeed[2] == PASS_VECTOR_MAX)?0.0f:shi->winspeed[2];
post_y = (shi->winspeed[3] == PASS_VECTOR_MAX)?0.0f:shi->winspeed[3];
- speedavg = (sqrtf(pre_x * pre_x + pre_y * pre_y) + sqrtf(post_x * post_x + post_y * post_y)) / 2.0;
+ speedavg = (sqrtf(pre_x * pre_x + pre_y * pre_y) + sqrtf(post_x * post_x + post_y * post_y)) / 2.0f;
return speedavg;
}
@@ -1299,7 +1293,7 @@ static void trace_refract(float col[4], ShadeInput *shi, ShadeResult *shr)
float v_refract[3], v_refract_new[3];
float sampcol[4], colsq[4];
- float blur = powf(1.0f - shi->mat->gloss_tra, 3);
+ float blur = pow3f(1.0f - shi->mat->gloss_tra);
short max_samples = shi->mat->samp_gloss_tra;
float adapt_thresh = shi->mat->adapt_thresh_tra;
@@ -1400,7 +1394,7 @@ static void trace_reflect(float col[3], ShadeInput *shi, ShadeResult *shr, float
float v_nor_new[3], v_reflect[3];
float sampcol[4], colsq[4];
- float blur = powf(1.0f - shi->mat->gloss_mir, 3);
+ float blur = pow3f(1.0f - shi->mat->gloss_mir);
short max_samples = shi->mat->samp_gloss_mir;
float adapt_thresh = shi->mat->adapt_thresh_mir;
float aniso = 1.0f - shi->mat->aniso_gloss_mir;
@@ -1562,7 +1556,7 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr)
}
if (shi->combinedflag & SCE_PASS_REFLECT) {
- /* values in shr->spec can be greater then 1.0.
+ /* values in shr->spec can be greater than 1.0.
* In this case the mircol uses a zero blending factor, so ignoring it is ok.
* Fixes bug #18837 - when the spec is higher then 1.0,
* diff can become a negative color - Campbell */
@@ -1629,6 +1623,7 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int
shi.xs= origshi->xs;
shi.ys= origshi->ys;
+ shi.do_manage= origshi->do_manage;
shi.lay= origshi->lay;
shi.nodes= origshi->nodes;
@@ -1636,9 +1631,9 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int
shade_ray(is, &shi, &shr);
if (shi.mat->material_type == MA_TYPE_SURFACE) {
- const float d= (traflag & RAY_TRA) ?
- shade_by_transmission(is, &shi, &shr) :
- 1.0f;
+ const float d = (shi.mat->mode & MA_RAYTRANSP) ?
+ ((traflag & RAY_TRA) ? shade_by_transmission(is, &shi, &shr) : 1.0f) :
+ 0.0f;
/* mix colors based on shadfac (rgb + amount of light factor) */
addAlphaLight(col, shr.diff, shr.alpha, d*shi.mat->filter);
}
@@ -2371,9 +2366,9 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, const float lampco[
mul_m3_v3(lar->mat, vec);
/* set start and vec */
- isec->dir[0] = vec[0]+lampco[0]-isec->start[0];
- isec->dir[1] = vec[1]+lampco[1]-isec->start[1];
- isec->dir[2] = vec[2]+lampco[2]-isec->start[2];
+ isec->dir[0] = vec[0]+lampco[0]-shi->co[0];
+ isec->dir[1] = vec[1]+lampco[1]-shi->co[1];
+ isec->dir[2] = vec[2]+lampco[2]-shi->co[2];
RE_instance_rotate_ray_dir(shi->obi, isec);
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index d8410fbe257..27fc412e1cd 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -35,19 +35,21 @@
#include "MEM_guardedalloc.h"
+#include "BKE_appdir.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
-#include "BLI_md5.h"
+#include "BLI_hash_md5.h"
#include "BLI_path_util.h"
#include "BLI_rect.h"
#include "BLI_string.h"
-#include "BLI_system.h"
#include "BLI_threads.h"
#include "BKE_image.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_report.h"
+#include "BKE_camera.h"
+#include "BKE_scene.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -60,14 +62,32 @@
/********************************** Free *************************************/
+static void render_result_views_free(RenderResult *res)
+{
+ while (res->views.first) {
+ RenderView *rv = res->views.first;
+ BLI_remlink(&res->views, rv);
+
+ if (rv->rect32)
+ MEM_freeN(rv->rect32);
+
+ if (rv->rectz)
+ MEM_freeN(rv->rectz);
+
+ if (rv->rectf)
+ MEM_freeN(rv->rectf);
+
+ MEM_freeN(rv);
+ }
+}
+
void render_result_free(RenderResult *res)
{
if (res == NULL) return;
while (res->layers.first) {
RenderLayer *rl = res->layers.first;
-
- if (rl->rectf) MEM_freeN(rl->rectf);
+
/* 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);
@@ -82,7 +102,9 @@ void render_result_free(RenderResult *res)
BLI_remlink(&res->layers, rl);
MEM_freeN(rl);
}
-
+
+ render_result_views_free(res);
+
if (res->rect32)
MEM_freeN(res->rect32);
if (res->rectz)
@@ -91,7 +113,11 @@ void render_result_free(RenderResult *res)
MEM_freeN(res->rectf);
if (res->text)
MEM_freeN(res->text);
-
+ if (res->error)
+ MEM_freeN(res->error);
+ if (res->stamp_data)
+ MEM_freeN(res->stamp_data);
+
MEM_freeN(res);
}
@@ -110,13 +136,44 @@ void render_result_free_list(ListBase *lb, RenderResult *rr)
}
}
-/********************************* Names *************************************/
+/********************************* multiview *************************************/
-/* NOTE: OpenEXR only supports 32 chars for layer+pass names
- * In blender we now use max 10 chars for pass, max 20 for layer */
-static const char *get_pass_name(int passtype, int channel)
+/* create a new views Listbase in rr without duplicating the memory pointers */
+void render_result_views_shallowcopy(RenderResult *dst, RenderResult *src)
+{
+ RenderView *rview;
+
+ if (dst == NULL || src == NULL)
+ return;
+
+ for (rview = src->views.first; rview; rview = rview->next) {
+ RenderView *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;
+ }
+}
+
+/* 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);
+ }
+}
+
+static const char *name_from_passtype(int passtype, int channel)
{
-
if (passtype == SCE_PASS_COMBINED) {
if (channel == -1) return "Combined";
if (channel == 0) return "Combined.R";
@@ -303,122 +360,151 @@ static const char *get_pass_name(int passtype, int channel)
static int passtype_from_name(const char *str)
{
-
- if (strcmp(str, "Combined") == 0)
+ if (STRPREFIX(str, "Combined"))
return SCE_PASS_COMBINED;
- if (strcmp(str, "Depth") == 0)
+ if (STRPREFIX(str, "Depth"))
return SCE_PASS_Z;
- if (strcmp(str, "Vector") == 0)
+ if (STRPREFIX(str, "Vector"))
return SCE_PASS_VECTOR;
- if (strcmp(str, "Normal") == 0)
+ if (STRPREFIX(str, "Normal"))
return SCE_PASS_NORMAL;
- if (strcmp(str, "UV") == 0)
+ if (STRPREFIX(str, "UV"))
return SCE_PASS_UV;
- if (strcmp(str, "Color") == 0)
+ if (STRPREFIX(str, "Color"))
return SCE_PASS_RGBA;
- if (strcmp(str, "Emit") == 0)
+ if (STRPREFIX(str, "Emit"))
return SCE_PASS_EMIT;
- if (strcmp(str, "Diffuse") == 0)
+ if (STRPREFIX(str, "Diffuse"))
return SCE_PASS_DIFFUSE;
- if (strcmp(str, "Spec") == 0)
+ if (STRPREFIX(str, "Spec"))
return SCE_PASS_SPEC;
- if (strcmp(str, "Shadow") == 0)
+ if (STRPREFIX(str, "Shadow"))
return SCE_PASS_SHADOW;
- if (strcmp(str, "AO") == 0)
+ if (STRPREFIX(str, "AO"))
return SCE_PASS_AO;
- if (strcmp(str, "Env") == 0)
+ if (STRPREFIX(str, "Env"))
return SCE_PASS_ENVIRONMENT;
- if (strcmp(str, "Indirect") == 0)
+ if (STRPREFIX(str, "Indirect"))
return SCE_PASS_INDIRECT;
- if (strcmp(str, "Reflect") == 0)
+ if (STRPREFIX(str, "Reflect"))
return SCE_PASS_REFLECT;
- if (strcmp(str, "Refract") == 0)
+ if (STRPREFIX(str, "Refract"))
return SCE_PASS_REFRACT;
- if (strcmp(str, "IndexOB") == 0)
+ if (STRPREFIX(str, "IndexOB"))
return SCE_PASS_INDEXOB;
- if (strcmp(str, "IndexMA") == 0)
+ if (STRPREFIX(str, "IndexMA"))
return SCE_PASS_INDEXMA;
- if (strcmp(str, "Mist") == 0)
+ if (STRPREFIX(str, "Mist"))
return SCE_PASS_MIST;
- if (strcmp(str, "RayHits") == 0)
+ if (STRPREFIX(str, "RayHits"))
return SCE_PASS_RAYHITS;
- if (strcmp(str, "DiffDir") == 0)
+ if (STRPREFIX(str, "DiffDir"))
return SCE_PASS_DIFFUSE_DIRECT;
- if (strcmp(str, "DiffInd") == 0)
+ if (STRPREFIX(str, "DiffInd"))
return SCE_PASS_DIFFUSE_INDIRECT;
- if (strcmp(str, "DiffCol") == 0)
+ if (STRPREFIX(str, "DiffCol"))
return SCE_PASS_DIFFUSE_COLOR;
- if (strcmp(str, "GlossDir") == 0)
+ if (STRPREFIX(str, "GlossDir"))
return SCE_PASS_GLOSSY_DIRECT;
- if (strcmp(str, "GlossInd") == 0)
+ if (STRPREFIX(str, "GlossInd"))
return SCE_PASS_GLOSSY_INDIRECT;
- if (strcmp(str, "GlossCol") == 0)
+ if (STRPREFIX(str, "GlossCol"))
return SCE_PASS_GLOSSY_COLOR;
- if (strcmp(str, "TransDir") == 0)
+ if (STRPREFIX(str, "TransDir"))
return SCE_PASS_TRANSM_DIRECT;
- if (strcmp(str, "TransInd") == 0)
+ if (STRPREFIX(str, "TransInd"))
return SCE_PASS_TRANSM_INDIRECT;
- if (strcmp(str, "TransCol") == 0)
+ if (STRPREFIX(str, "TransCol"))
return SCE_PASS_TRANSM_COLOR;
- if (strcmp(str, "SubsurfaceDir") == 0)
+ if (STRPREFIX(str, "SubsurfaceDir"))
return SCE_PASS_SUBSURFACE_DIRECT;
- if (strcmp(str, "SubsurfaceInd") == 0)
+ if (STRPREFIX(str, "SubsurfaceInd"))
return SCE_PASS_SUBSURFACE_INDIRECT;
- if (strcmp(str, "SubsurfaceCol") == 0)
+ if (STRPREFIX(str, "SubsurfaceCol"))
return SCE_PASS_SUBSURFACE_COLOR;
return 0;
}
+
+static void set_pass_name(char *passname, int passtype, int channel, const char *view)
+{
+ const char delims[] = {'.', '\0'};
+ const char *sep;
+ const char *token;
+ size_t len;
+
+ const char *passtype_name = name_from_passtype(passtype, channel);
+
+ if (view == NULL || view[0] == '\0') {
+ BLI_strncpy(passname, passtype_name, EXR_PASS_MAXNAME);
+ return;
+ }
+
+ len = BLI_str_rpartition(passtype_name, delims, &sep, &token);
+
+ if (sep) {
+ BLI_snprintf(passname, EXR_PASS_MAXNAME, "%.*s.%s.%s", (int)len, passtype_name, view, token);
+ }
+ else {
+ BLI_snprintf(passname, EXR_PASS_MAXNAME, "%s.%s", passtype_name, view);
+ }
+}
+
/********************************** New **************************************/
-static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype)
+static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype, const char *viewname)
{
- const char *typestr = get_pass_name(passtype, 0);
+ const size_t view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name));
+ const char *typestr = name_from_passtype(passtype, -1);
RenderPass *rpass = MEM_callocN(sizeof(RenderPass), typestr);
- int rectsize = rr->rectx * rr->recty * channels;
+ size_t rectsize = ((size_t)rr->rectx) * rr->recty * channels;
BLI_addtail(&rl->passes, rpass);
rpass->passtype = passtype;
rpass->channels = channels;
rpass->rectx = rl->rectx;
rpass->recty = rl->recty;
- BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name));
+ rpass->view_id = view_id;
+
+ set_pass_name(rpass->name, rpass->passtype, -1, viewname);
+ BLI_strncpy(rpass->internal_name, typestr, sizeof(rpass->internal_name));
+ BLI_strncpy(rpass->view, viewname, sizeof(rpass->view));
if (rl->exrhandle) {
int a;
for (a = 0; a < channels; a++)
- IMB_exr_add_channel(rl->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL);
+ IMB_exr_add_channel(rl->exrhandle, rl->name, name_from_passtype(passtype, a), viewname, 0, 0, NULL, false);
}
else {
float *rect;
@@ -438,18 +524,64 @@ static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channel
rect[x] = 10e10;
}
}
+ return rpass;
}
+#ifdef WITH_CYCLES_DEBUG
+const char *RE_debug_pass_name_get(int debug_type)
+{
+ switch (debug_type) {
+ case RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS:
+ return "BVH Traversal Steps";
+ case RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES:
+ return "BVH Traversed Instances";
+ case RENDER_PASS_DEBUG_RAY_BOUNCES:
+ return "Ray Bounces";
+ }
+ return "Unknown";
+}
+
+int RE_debug_pass_num_channels_get(int UNUSED(debug_type))
+{
+ /* Only single case currently, might be handy for further debug passes. */
+ return 1;
+}
+
+static RenderPass *render_layer_add_debug_pass(RenderResult *rr,
+ RenderLayer *rl,
+ int pass_type,
+ int debug_type,
+ const char *view)
+{
+ const char *name = RE_debug_pass_name_get(debug_type);
+ int channels = RE_debug_pass_num_channels_get(debug_type);
+ RenderPass *rpass = render_layer_add_pass(rr, rl, channels, pass_type, view);
+ rpass->debug_type = debug_type;
+ BLI_strncpy(rpass->name,
+ name,
+ sizeof(rpass->name));
+ BLI_strncpy(rpass->internal_name, rpass->name, sizeof(rpass->internal_name));
+ return rpass;
+}
+
+int RE_debug_pass_type_get(Render *re)
+{
+ return re->r.debug_pass_type;
+}
+#endif
+
/* 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)
+RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers, const char *layername, const char *viewname)
{
RenderResult *rr;
RenderLayer *rl;
+ RenderView *rv;
SceneRenderLayer *srl;
- int rectx, recty, nr;
+ int rectx, recty;
+ int nr;
rectx = BLI_rcti_size_x(partrct);
recty = BLI_rcti_size_y(partrct);
@@ -474,11 +606,13 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
rr->do_exr_tile = true;
}
+ render_result_views_new(rr, &re->r);
+
/* check renderdata for amount of layers */
for (nr = 0, srl = re->r.layers.first; srl; srl = srl->next, nr++) {
if (layername && layername[0])
- if (strcmp(srl->name, layername) != 0)
+ if (!STREQ(srl->name, layername))
continue;
if (re->r.scemode & R_SINGLE_LAYER) {
@@ -507,77 +641,90 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
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();
+ }
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
+ 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);
+
+ /* a renderlayer should always have a Combined pass*/
+ render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view);
+
+ if (srl->passflag & SCE_PASS_Z)
+ render_layer_add_pass(rr, rl, 1, SCE_PASS_Z, view);
+ if (srl->passflag & SCE_PASS_VECTOR)
+ render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR, view);
+ if (srl->passflag & SCE_PASS_NORMAL)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL, view);
+ if (srl->passflag & SCE_PASS_UV)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_UV, view);
+ if (srl->passflag & SCE_PASS_RGBA)
+ render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA, view);
+ if (srl->passflag & SCE_PASS_EMIT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_EMIT, view);
+ if (srl->passflag & SCE_PASS_DIFFUSE)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE, view);
+ if (srl->passflag & SCE_PASS_SPEC)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC, view);
+ if (srl->passflag & SCE_PASS_AO)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_AO, view);
+ if (srl->passflag & SCE_PASS_ENVIRONMENT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_ENVIRONMENT, view);
+ if (srl->passflag & SCE_PASS_INDIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_INDIRECT, view);
+ if (srl->passflag & SCE_PASS_SHADOW)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW, view);
+ if (srl->passflag & SCE_PASS_REFLECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT, view);
+ if (srl->passflag & SCE_PASS_REFRACT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT, view);
+ if (srl->passflag & SCE_PASS_INDEXOB)
+ render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB, view);
+ if (srl->passflag & SCE_PASS_INDEXMA)
+ render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA, view);
+ if (srl->passflag & SCE_PASS_MIST)
+ render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST, view);
+ if (rl->passflag & SCE_PASS_RAYHITS)
+ render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS, view);
+ if (srl->passflag & SCE_PASS_DIFFUSE_DIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_DIRECT, view);
+ if (srl->passflag & SCE_PASS_DIFFUSE_INDIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_INDIRECT, view);
+ if (srl->passflag & SCE_PASS_DIFFUSE_COLOR)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_COLOR, view);
+ if (srl->passflag & SCE_PASS_GLOSSY_DIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_DIRECT, view);
+ if (srl->passflag & SCE_PASS_GLOSSY_INDIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_INDIRECT, view);
+ if (srl->passflag & SCE_PASS_GLOSSY_COLOR)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_COLOR, view);
+ if (srl->passflag & SCE_PASS_TRANSM_DIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_DIRECT, view);
+ if (srl->passflag & SCE_PASS_TRANSM_INDIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_INDIRECT, view);
+ if (srl->passflag & SCE_PASS_TRANSM_COLOR)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_COLOR, view);
+ if (srl->passflag & SCE_PASS_SUBSURFACE_DIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_DIRECT, view);
+ if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_INDIRECT, view);
+ if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR)
+ render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_COLOR, view);
+
+#ifdef WITH_CYCLES_DEBUG
+ if (BKE_scene_use_new_shading_nodes(re->scene)) {
+ render_layer_add_debug_pass(rr, rl, SCE_PASS_DEBUG,
+ re->r.debug_pass_type, view);
+ }
+#endif
}
- else
- rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba");
-
- if (srl->passflag & SCE_PASS_Z)
- render_layer_add_pass(rr, rl, 1, SCE_PASS_Z);
- if (srl->passflag & SCE_PASS_VECTOR)
- render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR);
- if (srl->passflag & SCE_PASS_NORMAL)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL);
- if (srl->passflag & SCE_PASS_UV)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_UV);
- if (srl->passflag & SCE_PASS_RGBA)
- render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA);
- if (srl->passflag & SCE_PASS_EMIT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_EMIT);
- if (srl->passflag & SCE_PASS_DIFFUSE)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE);
- if (srl->passflag & SCE_PASS_SPEC)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC);
- if (srl->passflag & SCE_PASS_AO)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_AO);
- if (srl->passflag & SCE_PASS_ENVIRONMENT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_ENVIRONMENT);
- if (srl->passflag & SCE_PASS_INDIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_INDIRECT);
- if (srl->passflag & SCE_PASS_SHADOW)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW);
- if (srl->passflag & SCE_PASS_REFLECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT);
- if (srl->passflag & SCE_PASS_REFRACT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT);
- if (srl->passflag & SCE_PASS_INDEXOB)
- render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB);
- if (srl->passflag & SCE_PASS_INDEXMA)
- render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA);
- if (srl->passflag & SCE_PASS_MIST)
- render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST);
- if (rl->passflag & SCE_PASS_RAYHITS)
- render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS);
- if (srl->passflag & SCE_PASS_DIFFUSE_DIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_DIRECT);
- if (srl->passflag & SCE_PASS_DIFFUSE_INDIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_INDIRECT);
- if (srl->passflag & SCE_PASS_DIFFUSE_COLOR)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_COLOR);
- if (srl->passflag & SCE_PASS_GLOSSY_DIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_DIRECT);
- if (srl->passflag & SCE_PASS_GLOSSY_INDIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_INDIRECT);
- if (srl->passflag & SCE_PASS_GLOSSY_COLOR)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_COLOR);
- if (srl->passflag & SCE_PASS_TRANSM_DIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_DIRECT);
- if (srl->passflag & SCE_PASS_TRANSM_INDIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_INDIRECT);
- if (srl->passflag & SCE_PASS_TRANSM_COLOR)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_COLOR);
- if (srl->passflag & SCE_PASS_SUBSURFACE_DIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_DIRECT);
- if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_INDIRECT);
- if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR)
- render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_COLOR);
}
/* sss, previewrender and envmap don't do layers, so we make a default one */
if (BLI_listbase_is_empty(&rr->layers) && !(layername && layername[0])) {
@@ -590,18 +737,23 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
/* 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();
-
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
- IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
}
- else {
- rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba");
+
+ 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 (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, SCE_PASS_COMBINED, view);
}
-
+
/* note, this has to be in sync with scene.c */
rl->lay = (1 << 20) - 1;
rl->layflag = 0x7FFF; /* solid ztra halo strand */
@@ -619,15 +771,15 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
}
/* allocate osa new results for samples */
-RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *partrct, int crop, int savebuffers)
+RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *partrct, int crop, int savebuffers, const char *viewname)
{
int a;
if (re->osa == 0)
- return render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS);
+ return render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS, viewname);
for (a = 0; a < re->osa; a++) {
- RenderResult *rr = render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS);
+ RenderResult *rr = render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS, viewname);
BLI_addtail(lb, rr);
rr->sample_nr = a;
}
@@ -648,28 +800,98 @@ static void *ml_addlayer_cb(void *base, const char *str)
return rl;
}
-static void ml_addpass_cb(void *UNUSED(base), void *lay, const char *str, float *rect, int totchan, const char *chan_id)
+static void ml_addpass_cb(void *base, void *lay, const char *str, 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");
int a;
BLI_addtail(&rl->passes, rpass);
rpass->channels = totchan;
-
rpass->passtype = passtype_from_name(str);
if (rpass->passtype == 0) printf("unknown pass %s\n", str);
rl->passflag |= rpass->passtype;
- BLI_strncpy(rpass->name, str, EXR_PASS_MAXNAME);
/* channel id chars */
for (a = 0; a < totchan; a++)
rpass->chan_id[a] = chan_id[a];
-
+
rpass->rect = rect;
+ if (view[0] != '\0') {
+ BLI_snprintf(rpass->name, sizeof(rpass->name), "%s.%s", str, view);
+ rpass->view_id = BLI_findstringindex(&rr->views, view, offsetof(RenderView, name));
+ }
+ else {
+ BLI_strncpy(rpass->name, str, sizeof(rpass->name));
+ rpass->view_id = 0;
+ }
+
+ BLI_strncpy(rpass->view, view, sizeof(rpass->view));
+ BLI_strncpy(rpass->internal_name, str, sizeof(rpass->internal_name));
+}
+
+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;
}
-/* from imbuf, if a handle was returned we convert this to render result */
+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;
+
+ if (rpa->passtype > rpb->passtype)
+ return 1;
+ else if (rpa->passtype < rpb->passtype)
+ 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 *rr = MEM_callocN(sizeof(RenderResult), __func__);
@@ -680,12 +902,14 @@ RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace
rr->rectx = rectx;
rr->recty = recty;
- IMB_exr_multilayer_convert(exrhandle, rr, ml_addlayer_cb, ml_addpass_cb);
+ 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;
@@ -700,26 +924,56 @@ RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace
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));
+}
+
+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_ex(&rr->views, 1) == 0) {
+ render_result_view_new(rr, "");
+ }
+}
+
/*********************************** Merge ***********************************/
static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize)
{
- int y, ofs, copylen, tilex, tiley;
+ 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 + rrpart->crop * tilex);
+ tile += pixsize * (rrpart->crop + ((size_t)rrpart->crop) * tilex);
copylen = tilex - 2 * rrpart->crop;
tiley -= 2 * rrpart->crop;
- ofs = (rrpart->tilerect.ymin + rrpart->crop) * rr->rectx + (rrpart->tilerect.xmin + rrpart->crop);
+ ofs = (((size_t)rrpart->tilerect.ymin) + rrpart->crop) * rr->rectx + (rrpart->tilerect.xmin + rrpart->crop);
target += pixsize * ofs;
}
else {
- ofs = (rrpart->tilerect.ymin * rr->rectx + rrpart->tilerect.xmin);
+ ofs = (((size_t)rrpart->tilerect.ymin) * rr->rectx + rrpart->tilerect.xmin);
target += pixsize * ofs;
}
@@ -745,16 +999,19 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart)
for (rl = rr->layers.first; rl; rl = rl->next) {
rlp = RE_GetRenderLayer(rrpart, rl->name);
if (rlp) {
- /* combined */
- if (rl->rectf && rlp->rectf)
- do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4);
-
/* passes are allocated in sync */
for (rpass = rl->passes.first, rpassp = rlp->passes.first;
rpass && rpassp;
- rpass = rpass->next, rpassp = rpassp->next)
+ rpass = rpass->next)
{
+ /* renderresult have all passes, renderpart only the active view's passes */
+ if (strcmp(rpassp->name, rpass->name) != 0)
+ continue;
+
do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels);
+
+ /* manually get next render pass */
+ rpassp = rpassp->next;
}
}
}
@@ -763,7 +1020,7 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart)
/* for passes read from files, these have names stored */
static char *make_pass_name(RenderPass *rpass, int chan)
{
- static char name[16];
+ static char name[EXR_PASS_MAXNAME];
int len;
BLI_strncpy(name, rpass->name, EXR_PASS_MAXNAME);
@@ -775,55 +1032,111 @@ static char *make_pass_name(RenderPass *rpass, int chan)
return name;
}
-/* filename already made absolute */
-/* called from within UI, saves both rendered result as a file-read result */
-bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, int compress)
+/* called from within UI and render pipeline, saves both rendered result as a file-read result
+ * if multiview is true saves all views in a multiview exr
+ * else if view is not NULL saves single view
+ * else saves stereo3d
+ */
+bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, ImageFormatData *imf, const bool multiview, const char *view)
{
RenderLayer *rl;
RenderPass *rpass;
+ RenderView *rview;
void *exrhandle = IMB_exr_get_handle();
bool success;
-
- BLI_make_existing_file(filename);
-
- /* composite result */
- if (rr->rectf) {
- IMB_exr_add_channel(exrhandle, "Composite", "Combined.R", 4, 4 * rr->rectx, rr->rectf);
- IMB_exr_add_channel(exrhandle, "Composite", "Combined.G", 4, 4 * rr->rectx, rr->rectf + 1);
- IMB_exr_add_channel(exrhandle, "Composite", "Combined.B", 4, 4 * rr->rectx, rr->rectf + 2);
- IMB_exr_add_channel(exrhandle, "Composite", "Combined.A", 4, 4 * rr->rectx, rr->rectf + 3);
+ int a, nr;
+ const char *chan_view = NULL;
+ int compress = (imf ? imf->exr_codec : 0);
+ size_t width, height;
+
+ const bool is_mono = view && !multiview;
+ const bool use_half_float = (imf != NULL) ? (imf->depth == R_IMF_CHAN_DEPTH_16) : false;
+
+ width = rr->rectx;
+ height = rr->recty;
+
+ if (imf && imf->imtype == R_IMF_IMTYPE_OPENEXR && multiview) {
+ /* single layer OpenEXR */
+ const char *RGBAZ[] = {"R", "G", "B", "A", "Z"};
+ for (nr = 0, rview = rr->views.first; rview; rview = rview->next, nr++) {
+ IMB_exr_add_view(exrhandle, rview->name);
+
+ if (rview->rectf) {
+ for (a = 0; a < 4; a++) {
+ IMB_exr_add_channel(exrhandle, "", RGBAZ[a],
+ rview->name, 4, 4 * width, rview->rectf + a,
+ use_half_float);
+ }
+ if (rview->rectz) {
+ /* Z pass is always stored as float. */
+ IMB_exr_add_channel(exrhandle, "", RGBAZ[4],
+ rview->name, 1, width, rview->rectz,
+ false);
+ }
+ }
+ }
}
-
- /* add layers/passes and assign channels */
- for (rl = rr->layers.first; rl; rl = rl->next) {
-
- /* combined */
- if (rl->rectf) {
- int a, xstride = 4;
- for (a = 0; a < xstride; a++) {
- IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a),
- xstride, xstride * rr->rectx, rl->rectf + a);
+ else {
+ for (nr = 0, rview = rr->views.first; rview; rview = rview->next, nr++) {
+ if (is_mono) {
+ if (!STREQ(view, rview->name)) {
+ continue;
+ }
+ chan_view = "";
+ }
+ else {
+ /* if rendered only one view, we treat as a a non-view render */
+ chan_view = rview->name;
+ }
+
+ IMB_exr_add_view(exrhandle, rview->name);
+
+ if (rview->rectf) {
+ for (a = 0; a < 4; a++) {
+ IMB_exr_add_channel(exrhandle, "Composite", name_from_passtype(SCE_PASS_COMBINED, a),
+ chan_view, 4, 4 * width, rview->rectf + a,
+ use_half_float);
+ }
}
}
-
- /* passes are allocated in sync */
- for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
- int a, xstride = rpass->channels;
- for (a = 0; a < xstride; a++) {
- if (rpass->passtype) {
- IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a),
- xstride, xstride * rr->rectx, rpass->rect + a);
+
+ /* add layers/passes and assign channels */
+ for (rl = rr->layers.first; rl; rl = rl->next) {
+
+ /* passes are allocated in sync */
+ for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
+ const int xstride = rpass->channels;
+
+ if (is_mono) {
+ if (!STREQ(view, rpass->view)) {
+ continue;
+ }
+ chan_view = "";
}
else {
- IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a),
- xstride, xstride * rr->rectx, rpass->rect + a);
+ /* if rendered only one view, we treat as a a non-view render */
+ chan_view = (nr > 1 ? rpass->view :"");
+ }
+
+ for (a = 0; a < xstride; a++) {
+ if (rpass->passtype) {
+ IMB_exr_add_channel(exrhandle, rl->name, name_from_passtype(rpass->passtype, a), chan_view,
+ xstride, xstride * width, rpass->rect + a,
+ rpass->passtype == SCE_PASS_Z ? false : use_half_float);
+ }
+ else {
+ IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), chan_view,
+ xstride, xstride * width, rpass->rect + a,
+ use_half_float);
+ }
}
}
}
}
- /* when the filename has no permissions, this can fail */
- if (IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress)) {
+ BLI_make_existing_file(filename);
+
+ if (IMB_exr_begin_write(exrhandle, filename, width, height, compress, rr->stamp_data)) {
IMB_exr_write_channels(exrhandle);
success = true;
}
@@ -832,8 +1145,8 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil
BKE_report(reports, RPT_ERROR, "Error writing render result (see console)");
success = false;
}
- IMB_exr_close(exrhandle);
+ IMB_exr_close(exrhandle);
return success;
}
@@ -894,7 +1207,7 @@ void render_result_single_layer_end(Render *re)
/************************* EXR Tile File Rendering ***************************/
-static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
+static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, const char *viewname)
{
RenderLayer *rlp, *rl;
RenderPass *rpassp;
@@ -917,21 +1230,17 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
else {
offs = 0;
}
-
- /* combined */
- if (rlp->rectf) {
- int a, xstride = 4;
- for (a = 0; a < xstride; a++) {
- IMB_exr_set_channel(rl->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a),
- xstride, xstride * rrpart->rectx, rlp->rectf + a + xstride * offs);
- }
- }
-
+
/* passes are allocated in sync */
for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) {
- int a, xstride = rpassp->channels;
+ const int xstride = rpassp->channels;
+ int a;
+ char passname[EXR_PASS_MAXNAME];
+
for (a = 0; a < xstride; a++) {
- IMB_exr_set_channel(rl->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a),
+ set_pass_name(passname, rpassp->passtype, a, rpassp->view);
+
+ IMB_exr_set_channel(rl->exrhandle, rlp->name, passname,
xstride, xstride * rrpart->rectx, rpassp->rect + a + xstride * offs);
}
}
@@ -950,13 +1259,13 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
continue;
}
- IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0);
+ IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, viewname);
}
BLI_unlock_thread(LOCK_IMAGE);
}
-static void save_empty_result_tiles(Render *re)
+void render_result_save_empty_result_tiles(Render *re)
{
RenderPart *pa;
RenderResult *rr;
@@ -964,13 +1273,13 @@ static void save_empty_result_tiles(Render *re)
for (rr = re->result; rr; rr = rr->next) {
for (rl = rr->layers.first; rl; rl = rl->next) {
- IMB_exrtile_clear_channels(rl->exrhandle);
+ IMB_exr_clear_channels(rl->exrhandle);
for (pa = re->parts.first; pa; pa = pa->next) {
if (pa->status != PART_STATUS_READY) {
int party = pa->disprect.ymin - re->disprect.ymin + pa->crop;
int partx = pa->disprect.xmin - re->disprect.xmin + pa->crop;
- IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0);
+ IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, re->viewname);
}
}
}
@@ -999,8 +1308,6 @@ void render_result_exr_file_end(Render *re)
RenderResult *rr;
RenderLayer *rl;
- save_empty_result_tiles(re);
-
for (rr = re->result; rr; rr = rr->next) {
for (rl = rr->layers.first; rl; rl = rl->next) {
IMB_exr_close(rl->exrhandle);
@@ -1017,18 +1324,18 @@ void render_result_exr_file_end(Render *re)
}
/* save part into exr file */
-void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart)
+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);
+ 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], fi[FILE_MAXFILE];
+ char name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100];
+ const char *fi = BLI_path_basename(G.main->name);
- BLI_split_file_part(G.main->name, fi, sizeof(fi));
if (sample == 0) {
BLI_snprintf(name, sizeof(name), "%s_%s_%s.exr", fi, scene->id.name + 2, layname);
}
@@ -1036,7 +1343,10 @@ void render_result_exr_file_path(Scene *scene, const char *layname, int sample,
BLI_snprintf(name, sizeof(name), "%s_%s_%s%d.exr", fi, scene->id.name + 2, layname, sample);
}
- BLI_make_file_string("/", filepath, BLI_temp_dir_session(), name);
+ /* Make name safe for paths, see T43275. */
+ BLI_filename_make_safe(name);
+
+ BLI_make_file_string("/", filepath, BKE_tempdir_session(), name);
}
/* only for temp buffer, makes exact copy of render result */
@@ -1047,7 +1357,7 @@ int render_result_exr_file_read_sample(Render *re, int sample)
bool success = true;
RE_FreeRenderResult(re->result);
- re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
+ re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
for (rl = re->result->layers.first; rl; rl = rl->next) {
render_result_exr_file_path(re->scene, rl->name, sample, str);
@@ -1088,23 +1398,20 @@ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, c
for (rl = rr->layers.first; rl; rl = rl->next) {
if (rl_single && rl_single != rl)
continue;
-
- /* combined */
- if (rl->rectf) {
- int a, xstride = 4;
- for (a = 0; a < xstride; a++)
- IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a),
- xstride, xstride * rectx, rl->rectf + a);
- }
/* passes are allocated in sync */
for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
- int a, xstride = rpass->channels;
- for (a = 0; a < xstride; a++)
- IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a),
+ const int xstride = rpass->channels;
+ int a;
+ char passname[EXR_PASS_MAXNAME];
+
+ for (a = 0; a < xstride; a++) {
+ set_pass_name(passname, rpass->passtype, a, rpass->view);
+ IMB_exr_set_channel(exrhandle, rl->name, passname,
xstride, xstride * rectx, rpass->rect + a);
+ }
- BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name));
+ set_pass_name(rpass->name, rpass->passtype, -1, rpass->view);
}
}
@@ -1124,17 +1431,17 @@ static void render_result_exr_file_cache_path(Scene *sce, const char *root, char
if (G.main->name[0]) {
BLI_split_dirfile(G.main->name, dirname, filename, sizeof(dirname), sizeof(filename));
BLI_replace_extension(filename, sizeof(filename), ""); /* strip '.blend' */
- md5_buffer(G.main->name, strlen(G.main->name), path_digest);
+ BLI_hash_md5_buffer(G.main->name, strlen(G.main->name), path_digest);
}
else {
- BLI_strncpy(dirname, BLI_temp_dir_base(), sizeof(dirname));
+ BLI_strncpy(dirname, BKE_tempdir_base(), sizeof(dirname));
BLI_strncpy(filename, "UNSAVED", sizeof(filename));
}
- md5_to_hexdigest(path_digest, path_hexdigest);
+ BLI_hash_md5_to_hexdigest(path_digest, path_hexdigest);
/* Default to *non-volatile* tmp dir. */
if (*root == '\0') {
- root = BLI_temp_dir_base();
+ root = BKE_tempdir_base();
}
BLI_snprintf(filename_full, sizeof(filename_full), "cached_RR_%s_%s_%s.exr",
@@ -1150,7 +1457,8 @@ void render_result_exr_file_cache_write(Render *re)
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, 0);
+
+ RE_WriteRenderResult(NULL, rr, str, NULL, true, NULL);
}
/* For cache, makes exact copy of render result */
@@ -1160,7 +1468,7 @@ bool render_result_exr_file_cache_read(Render *re)
char *root = U.render_cachedir;
RE_FreeRenderResult(re->result);
- re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
+ 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);
@@ -1175,15 +1483,16 @@ bool render_result_exr_file_cache_read(Render *re)
/*************************** Combined Pixel Rect *****************************/
-ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
+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 *)rr->rect32;
- ibuf->rect_float = rr->rectf;
- ibuf->zbuf_float = rr->rectz;
-
+ 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;
@@ -1218,57 +1527,97 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
return ibuf;
}
-void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf)
+void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf, const int view_id)
{
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
+
if (ibuf->rect_float) {
- if (!rr->rectf)
- rr->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(rr->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 */
- if (rr->rect32) {
- MEM_freeN(rr->rect32);
- rr->rect32 = NULL;
- }
+ MEM_SAFE_FREE(rv->rect32);
}
else if (ibuf->rect) {
- if (!rr->rect32)
- rr->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(rr->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. */
- if (rr->rectf) {
- MEM_freeN(rr->rectf);
- rr->rectf = NULL;
- }
+ MEM_SAFE_FREE(rv->rectf);
}
}
-void render_result_rect_fill_zero(RenderResult *rr)
+void render_result_rect_fill_zero(RenderResult *rr, const int view_id)
{
- if (rr->rectf)
- memset(rr->rectf, 0, 4 * sizeof(float) * rr->rectx * rr->recty);
- else if (rr->rect32)
- memset(rr->rect32, 0, 4 * rr->rectx * rr->recty);
+ 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
- rr->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
+ 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)
+ const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings,
+ const int view_id)
{
- if (rr->rect32) {
- memcpy(rect, rr->rect32, sizeof(int) * rr->rectx * rr->recty);
- }
- else if (rr->rectf) {
- IMB_display_buffer_transform_apply((unsigned char *) rect, rr->rectf, rr->rectx, rr->recty, 4,
+ 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_HasFakeLayer(RenderResult *res)
+{
+ RenderView *rv;
+
+ if (res == NULL)
+ return false;
+
+ rv = res->views.first;
+ if (rv == NULL)
+ return false;
+
+ return (rv->rect32 || rv->rectf);
+}
+
+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_RIGHT_NAME, offsetof(RenderView, name)))
+ return false;
+
+ 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 *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;
+}
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index ae01779e814..b282ec0593e 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -48,7 +48,6 @@
#include "DNA_node_types.h"
#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
#include "BKE_image.h"
@@ -68,9 +67,7 @@
#include "envmap.h"
#include "pointdensity.h"
#include "voxeldata.h"
-#include "renderpipeline.h"
#include "render_types.h"
-#include "rendercore.h"
#include "shading.h"
#include "texture.h"
#include "texture_ocean.h"
@@ -85,8 +82,19 @@
extern struct Render R;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+static RNG_THREAD_ARRAY *random_tex_array;
+void RE_init_texture_rng(void)
+{
+ random_tex_array = BLI_rng_threaded_new();
+}
+
+void RE_exit_texture_rng(void)
+{
+ BLI_rng_threaded_free(random_tex_array);
+}
+
static void init_render_texture(Render *re, Tex *tex)
{
@@ -108,7 +116,7 @@ static void init_render_texture(Render *re, Tex *tex)
if (G.is_rendering && re) {
if (re->r.mode & R_ENVMAP)
if (tex->env->stype==ENV_ANIM)
- BKE_free_envmapdata(tex->env);
+ BKE_texture_envmap_free_data(tex->env);
}
}
}
@@ -212,10 +220,10 @@ static int blend(Tex *tex, const float texvec[3], TexResult *texres)
texres->tin= (2.0f+x+y)/4.0f;
}
else if (tex->stype==TEX_RAD) { /* radial */
- texres->tin = (atan2f(y, x) / (2 * M_PI) + 0.5f);
+ texres->tin = (atan2f(y, x) / (float)(2 * M_PI) + 0.5f);
}
else { /* sphere TEX_SPHERE */
- texres->tin = 1.0 - sqrtf(x * x + y * y + texvec[2] * texvec[2]);
+ 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 */
}
@@ -266,7 +274,7 @@ static int clouds(Tex *tex, const float texvec[3], TexResult *texres)
/* creates a sine wave */
static float tex_sin(float a)
{
- a = 0.5 + 0.5 * sinf(a);
+ a = 0.5f + 0.5f * sinf(a);
return a;
}
@@ -709,19 +717,22 @@ static float voronoiTex(Tex *tex, const float texvec[3], TexResult *texres)
/* ------------------------------------------------------------------------- */
-static int texnoise(Tex *tex, TexResult *texres)
+static int texnoise(Tex *tex, TexResult *texres, int thread)
{
float div=3.0;
- int val, ran, loop;
+ int val, ran, loop, shift = 29;
- ran= BLI_rand();
- val= (ran & 3);
+ ran= BLI_rng_thread_rand(random_tex_array, thread);
loop= tex->noisedepth;
+
+ /* start from top bits since they have more variance */
+ val= ((ran >> shift) & 3);
+
while (loop--) {
- ran= (ran>>2);
- val*= (ran & 3);
- div*= 3.0f;
+ shift -= 2;
+ val *= ((ran >> shift) & 3);
+ div *= 3.0f;
}
texres->tin= ((float)val)/div;
@@ -1092,7 +1103,7 @@ static void do_2d_mapping(MTex *mtex, float texvec[3], VlakRen *vlr, const float
/* ************************************** */
-static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, short which_output, struct ImagePool *pool)
+static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, short which_output, struct ImagePool *pool, const bool skip_load_image)
{
float tmpvec[3];
int retval = 0; /* return value, int:0, col:1, nor:2, everything:3 */
@@ -1127,17 +1138,17 @@ static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int o
retval = stucci(tex, texvec, texres);
break;
case TEX_NOISE:
- retval = texnoise(tex, texres);
+ retval = texnoise(tex, texres, thread);
break;
case TEX_IMAGE:
- if (osatex) retval = imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres, pool);
- else retval = imagewrap(tex, tex->ima, NULL, texvec, texres, pool);
+ 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_ENVMAP:
- retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres, pool);
+ retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres, pool, skip_load_image);
break;
case TEX_MUSGRAVE:
/* newnoise: musgrave types */
@@ -1209,7 +1220,7 @@ static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int o
static int multitex_nodes_intern(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres,
const short thread, short which_output, ShadeInput *shi, MTex *mtex, struct ImagePool *pool,
- bool scene_color_manage)
+ bool scene_color_manage, const bool skip_load_image)
{
if (tex==NULL) {
memset(texres, 0, sizeof(TexResult));
@@ -1225,7 +1236,7 @@ static int multitex_nodes_intern(Tex *tex, float texvec[3], float dxt[3], float
if (mtex) {
/* we have mtex, use it for 2d mapping images only */
do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt);
- rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool);
+ rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool, skip_load_image);
if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) {
ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
@@ -1258,7 +1269,7 @@ static int multitex_nodes_intern(Tex *tex, float texvec[3], float dxt[3], float
}
do_2d_mapping(&localmtex, texvec_l, NULL, NULL, dxt_l, dyt_l);
- rgbnor = multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output, pool);
+ rgbnor = multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output, pool, skip_load_image);
{
ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
@@ -1274,7 +1285,7 @@ static int multitex_nodes_intern(Tex *tex, float texvec[3], float dxt[3], float
return rgbnor;
}
else {
- return multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool);
+ return multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool, skip_load_image);
}
}
@@ -1285,11 +1296,12 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os
const short thread, short which_output, ShadeInput *shi, MTex *mtex, struct ImagePool *pool)
{
return multitex_nodes_intern(tex, texvec, dxt, dyt, osatex, texres,
- thread, which_output, shi, mtex, pool, R.scene_color_manage);
+ thread, which_output, shi, mtex, pool, R.scene_color_manage,
+ (R.r.scemode & R_NO_IMAGE_LOAD) != 0);
}
/* this is called for surface shading */
-static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt[3], float dyt[3], TexResult *texres, struct ImagePool *pool)
+static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt[3], float dyt[3], TexResult *texres, struct ImagePool *pool, const bool skip_load_image)
{
Tex *tex = mtex->tex;
@@ -1300,7 +1312,7 @@ static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt
tex, mtex->which_output, R.r.cfra, (R.r.scemode & R_TEXNODE_PREVIEW) != 0, shi, mtex);
}
else {
- return multitex(mtex->tex, texvec, dxt, dyt, shi->osatex, texres, shi->thread, mtex->which_output, pool);
+ return multitex(mtex->tex, texvec, dxt, dyt, shi->osatex, texres, shi->thread, mtex->which_output, pool, skip_load_image);
}
}
@@ -1309,21 +1321,21 @@ static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt
*
* Use it for stuff which is out of render pipeline.
*/
-int multitex_ext(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool, bool scene_color_manage)
+int multitex_ext(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image)
{
- return multitex_nodes_intern(tex, texvec, dxt, dyt, osatex, texres, 0, 0, NULL, NULL, pool, scene_color_manage);
+ return multitex_nodes_intern(tex, texvec, dxt, dyt, osatex, texres, 0, 0, NULL, NULL, pool, scene_color_manage, skip_load_image);
}
/* 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)
+int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image)
{
int use_nodes= tex->use_nodes, retval;
tex->use_nodes = false;
- retval= multitex_nodes_intern(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL, pool, scene_color_manage);
+ retval= multitex_nodes_intern(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL, pool, scene_color_manage, skip_load_image);
tex->use_nodes= use_nodes;
return retval;
@@ -1336,7 +1348,7 @@ int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct Image
/* 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)
{
- float facm, col;
+ float facm;
switch (blendtype) {
case MTEX_BLEND:
@@ -1423,13 +1435,10 @@ void texture_rgb_blend(float in[3], const float tex[3], const float out[3], floa
case MTEX_LIGHT:
fact*= facg;
-
- col= fact*tex[0];
- if (col > out[0]) in[0]= col; else in[0]= out[0];
- col= fact*tex[1];
- if (col > out[1]) in[1]= col; else in[1]= out[1];
- col= fact*tex[2];
- if (col > out[2]) in[2]= col; else in[2]= out[2];
+
+ 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:
@@ -1707,7 +1716,7 @@ static void compatible_bump_uv_derivs(CompatibleBump *compat_bump, ShadeInput *s
static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres,
float Tnor, const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3],
- struct ImagePool *pool)
+ struct ImagePool *pool, const bool skip_load_image)
{
TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */
float tco[3], texv[3], cd, ud, vd, du, dv, idu, idv;
@@ -1760,7 +1769,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
/* center, main return value */
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool, skip_load_image);
cd = fromrgb ? (texres->tr + texres->tg + texres->tb) / 3.0f : texres->tin;
if (mtex->texco == TEXCO_UV) {
@@ -1774,7 +1783,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
tco[1] = co[1] + compat_bump->dvdnu*du;
tco[2] = 0.f;
texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
- multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
/* +v val */
@@ -1782,7 +1791,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
tco[1] = co[1] + compat_bump->dvdnv*du;
tco[2] = 0.f;
texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
- multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
vd = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
}
else {
@@ -1816,7 +1825,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
tco[1] = co[1] + tu[1]*du;
tco[2] = co[2] + tu[2]*du;
texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
- multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
/* +v val */
@@ -1824,7 +1833,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
tco[1] = co[1] + tv[1]*dv;
tco[2] = co[2] + tv[2]*dv;
texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
- multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
vd = idv*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
}
@@ -1866,7 +1875,8 @@ static void ntap_bump_init(NTapBump *ntap_bump)
static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres,
float Tnor, const float co[3], const float dx[3], const float dy[3],
- float texvec[3], float dxt[3], float dyt[3], struct ImagePool *pool)
+ float texvec[3], float dxt[3], float dyt[3], struct ImagePool *pool,
+ const bool skip_load_image)
{
TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */
@@ -1926,7 +1936,7 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
float dBdu, dBdv, auto_bump = 1.0f;
float s = 1; /* negate this if flipped texture coordinate */
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool, skip_load_image);
if (shi->obr->ob->derivedFinal) {
auto_bump = shi->obr->ob->derivedFinal->auto_bump_scale;
@@ -1968,15 +1978,15 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
}
/* use texres for the center sample, set rgbnor */
- rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres, pool);
- Hll = (fromrgb) ? rgb_to_grayscale(&texres->tr) : texres->tin;
+ rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres, pool, skip_load_image);
+ Hll = (fromrgb) ? IMB_colormanagement_get_luminance(&texres->tr) : texres->tin;
/* use ttexr for the other 2 taps */
- multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr, pool);
- Hlr = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
+ multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr, pool, skip_load_image);
+ Hlr = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
- multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr, pool);
- Hul = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
+ multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr, pool, skip_load_image);
+ Hul = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
dHdx = Hscale*(Hlr - Hll);
dHdy = Hscale*(Hul - Hll);
@@ -2006,18 +2016,18 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
}
/* use texres for the center sample, set rgbnor */
- rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres, pool);
- /* Hc = (fromrgb) ? rgb_to_grayscale(&texres->tr) : texres->tin; */ /* UNUSED */
+ rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres, pool, skip_load_image);
+ /* Hc = (fromrgb) ? IMB_colormanagement_get_luminance(&texres->tr) : texres->tin; */ /* UNUSED */
/* use ttexr for the other taps */
- multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr, pool);
- Hl = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
- multitex_mtex(shi, mtex, STr, dxt, dyt, &ttexr, pool);
- Hr = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
- multitex_mtex(shi, mtex, STd, dxt, dyt, &ttexr, pool);
- Hd = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
- multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr, pool);
- Hu = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
+ multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr, pool, skip_load_image);
+ Hl = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
+ multitex_mtex(shi, mtex, STr, dxt, dyt, &ttexr, pool, skip_load_image);
+ Hr = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
+ multitex_mtex(shi, mtex, STd, dxt, dyt, &ttexr, pool, skip_load_image);
+ Hd = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
+ multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr, pool, skip_load_image);
+ Hu = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
dHdx = Hscale*(Hr - Hl);
dHdy = Hscale*(Hu - Hd);
@@ -2126,6 +2136,7 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
void do_material_tex(ShadeInput *shi, Render *re)
{
+ const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0;
CompatibleBump compat_bump;
NTapBump ntap_bump;
MTex *mtex;
@@ -2238,7 +2249,7 @@ void do_material_tex(ShadeInput *shi, Render *re)
if (mtex->uvname[0] != 0) {
for (i = 0; i < shi->totuv; i++) {
- if (strcmp(shi->uv[i].name, mtex->uvname)==0) {
+ if (STREQ(shi->uv[i].name, mtex->uvname)) {
suv= &shi->uv[i];
break;
}
@@ -2294,27 +2305,27 @@ void do_material_tex(ShadeInput *shi, Render *re)
if (use_compat_bump) {
rgbnor = compatible_bump_compute(&compat_bump, shi, mtex, tex,
&texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt,
- re->pool);
+ re->pool, skip_load_image);
}
else if (use_ntap_bump) {
rgbnor = ntap_bump_compute(&ntap_bump, shi, mtex, tex,
&texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt,
- re->pool);
+ re->pool, skip_load_image);
}
else {
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool, skip_load_image);
}
}
else {
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool, skip_load_image);
}
/* texture output */
if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
- texres.tin = rgb_to_grayscale(&texres.tr);
+ texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
rgbnor -= TEX_RGB;
}
if (mtex->texflag & MTEX_NEGATIVE) {
@@ -2420,7 +2431,7 @@ void do_material_tex(ShadeInput *shi, Render *re)
BKE_image_pool_release_ibuf(ima, ibuf, re->pool);
}
-
+
if (mtex->mapto & MAP_COL) {
float colfac= mtex->colfac*stencilTin;
texture_rgb_blend(&shi->r, tcol, &shi->r, texres.tin, colfac, mtex->blendtype);
@@ -2554,7 +2565,7 @@ void do_material_tex(ShadeInput *shi, Render *re)
}
if (rgbnor & TEX_RGB) {
- texres.tin = rgb_to_grayscale(&texres.tr);
+ texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
}
factt= (0.5f-texres.tin)*mtex->dispfac*stencilTin; facmm= 1.0f-factt;
@@ -2582,7 +2593,7 @@ void do_material_tex(ShadeInput *shi, Render *re)
if (rgbnor & TEX_RGB) {
if (texres.talpha) texres.tin = texres.ta;
- else texres.tin = rgb_to_grayscale(&texres.tr);
+ else texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
}
if (mtex->mapto & MAP_REF) {
@@ -2660,6 +2671,7 @@ void do_material_tex(ShadeInput *shi, Render *re)
void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_r[3], float *val, Render *re)
{
+ const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
MTex *mtex;
Tex *tex;
TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
@@ -2747,12 +2759,12 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_
else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
}
- rgbnor = multitex(tex, texvec, NULL, NULL, 0, &texres, shi->thread, mtex->which_output, re->pool); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
+ rgbnor = multitex(tex, texvec, NULL, NULL, 0, &texres, shi->thread, mtex->which_output, re->pool, skip_load_image); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
/* texture output */
if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
- texres.tin = rgb_to_grayscale(&texres.tr);
+ texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
rgbnor -= TEX_RGB;
}
if (mtex->texflag & MTEX_NEGATIVE) {
@@ -2821,7 +2833,7 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_
/* convert RGB to intensity if intensity info isn't provided */
if (rgbnor & TEX_RGB) {
if (texres.talpha) texres.tin = texres.ta;
- else texres.tin = rgb_to_grayscale(&texres.tr);
+ else texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
}
if ((mapto_flag & MAP_EMISSION) && (mtex->mapto & MAP_EMISSION)) {
@@ -2858,6 +2870,7 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_
void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
{
+ const bool skip_load_image = har->skip_load_image;
MTex *mtex;
TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
float texvec[3], dxt[3], dyt[3], fact, facm, dx;
@@ -2914,11 +2927,11 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
if (mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
- rgb = multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres, 0, mtex->which_output, har->pool);
+ rgb = multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres, 0, mtex->which_output, har->pool, skip_load_image);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
- texres.tin = rgb_to_bw(&texres.tr);
+ texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
rgb= 0;
}
if (mtex->texflag & MTEX_NEGATIVE) {
@@ -2990,7 +3003,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
texres.tin = texres.ta;
}
else {
- texres.tin = rgb_to_bw(&texres.tr);
+ texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
}
}
@@ -3003,6 +3016,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
/* hor and zen are RGB vectors, blend is 1 float, should all be initialized */
void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float hor[3], float zen[3], float *blend, int skyflag, short thread)
{
+ const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0;
MTex *mtex;
Tex *tex;
TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
@@ -3039,7 +3053,7 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
switch (mtex->texco) {
case TEXCO_ANGMAP:
/* only works with texture being "real" */
- /* use saacos(), fixes bug [#22398], float precision caused lo[2] to be slightly less then -1.0 */
+ /* use saacos(), fixes bug [#22398], float precision caused lo[2] to be slightly less than -1.0 */
if (lo[0] || lo[1]) { /* check for zero case [#24807] */
fact= (1.0f/(float)M_PI)*saacos(lo[2])/(sqrtf(lo[0]*lo[0] + lo[1]*lo[1]));
tempvec[0]= lo[0]*fact;
@@ -3119,11 +3133,11 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
/* texture */
if (tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
- rgb = multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output, R.pool);
+ rgb = multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output, R.pool, skip_load_image);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
- texres.tin = rgb_to_bw(&texres.tr);
+ texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
rgb= 0;
}
if (mtex->texflag & MTEX_NEGATIVE) {
@@ -3198,7 +3212,7 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
}
}
if (mtex->mapto & WOMAP_BLEND) {
- if (rgb) texres.tin = rgb_to_bw(&texres.tr);
+ if (rgb) texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
*blend= texture_value_blend(mtex->def_var, *blend, texres.tin, mtex->blendfac, mtex->blendtype);
}
@@ -3211,6 +3225,7 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r[3], int effect)
{
+ const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0;
Object *ob;
MTex *mtex;
Tex *tex;
@@ -3334,11 +3349,11 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
}
- rgb = multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output, R.pool);
+ rgb = multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output, R.pool, skip_load_image);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
- texres.tin = rgb_to_bw(&texres.tr);
+ texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
rgb= 0;
}
if (mtex->texflag & MTEX_NEGATIVE) {
@@ -3396,8 +3411,11 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
col[0]= texres.tr*la->energy;
col[1]= texres.tg*la->energy;
col[2]= texres.tb*la->energy;
-
- texture_rgb_blend(col_r, col, col_r, texres.tin, mtex->colfac, mtex->blendtype);
+
+ if (effect & LA_SHAD_TEX)
+ texture_rgb_blend(col_r, col, col_r, texres.tin, mtex->shadowfac, mtex->blendtype);
+ else
+ texture_rgb_blend(col_r, col, col_r, texres.tin, mtex->colfac, mtex->blendtype);
}
}
}
@@ -3405,7 +3423,7 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
/* ------------------------------------------------------------------------- */
-int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool)
+int externtex(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)
{
Tex *tex;
TexResult texr;
@@ -3431,10 +3449,10 @@ int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg,
do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
}
- rgb = multitex(tex, texvec, dxt, dyt, 0, &texr, thread, mtex->which_output, pool);
+ rgb = multitex(tex, texvec, dxt, dyt, 0, &texr, thread, mtex->which_output, pool, skip_load_image);
if (rgb) {
- texr.tin = rgb_to_bw(&texr.tr);
+ texr.tin = IMB_colormanagement_get_luminance(&texr.tr);
}
else {
texr.tr= mtex->r;
@@ -3456,6 +3474,7 @@ int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg,
void render_realtime_texture(ShadeInput *shi, Image *ima)
{
+ const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0;
TexResult texr;
static Tex imatex[BLENDER_MAX_THREADS]; /* threadsafe */
static int firsttime= 1;
@@ -3471,7 +3490,7 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
if (firsttime) {
for (a=0; a<BLENDER_MAX_THREADS; a++) {
memset(&imatex[a], 0, sizeof(Tex));
- default_tex(&imatex[a]);
+ BKE_texture_default(&imatex[a]);
imatex[a].type= TEX_IMAGE;
}
@@ -3496,8 +3515,8 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
texr.nor= NULL;
- if (shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr, R.pool);
- else imagewrap(tex, ima, NULL, texvec, &texr, R.pool);
+ if (shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr, R.pool, skip_load_image);
+ else imagewrap(tex, ima, NULL, texvec, &texr, R.pool, skip_load_image);
shi->vcol[0]*= texr.tr;
shi->vcol[1]*= texr.tg;
@@ -3507,7 +3526,10 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
/* A modified part of shadeinput.c -> shade_input_set_uv()
* Used for sampling UV mapped texture color */
-static void textured_face_generate_uv(float *uv, const float normal[3], float *hit, float *v1, float *v2, float *v3)
+static void textured_face_generate_uv(
+ const float normal[3], const float hit[3],
+ const float v1[3], const float v2[3], const float v3[3],
+ float r_uv[2])
{
float detsh, t00, t10, t01, t11;
@@ -3524,12 +3546,12 @@ static void textured_face_generate_uv(float *uv, const float normal[3], float *h
t00*= detsh; t01*=detsh;
t10*=detsh; t11*=detsh;
- uv[0] = (hit[axis1]-v3[axis1])*t11-(hit[axis2]-v3[axis2])*t10;
- uv[1] = (hit[axis2]-v3[axis2])*t00-(hit[axis1]-v3[axis1])*t01;
+ r_uv[0] = (hit[axis1] - v3[axis1]) * t11 - (hit[axis2] - v3[axis2]) * t10;
+ r_uv[1] = (hit[axis2] - v3[axis2]) * t00 - (hit[axis1] - v3[axis1]) * t01;
/* u and v are in range -1 to 0, we allow a little bit extra but not too much, screws up speedvectors */
- CLAMP(uv[0], -2.0f, 1.0f);
- CLAMP(uv[1], -2.0f, 1.0f);
+ CLAMP(r_uv[0], -2.0f, 1.0f);
+ CLAMP(r_uv[1], -2.0f, 1.0f);
}
/* Generate an updated copy of material to use for color sampling. */
@@ -3592,7 +3614,7 @@ Material *RE_init_sample_material(Material *orig_mat, Scene *scene)
}
/* copy texture */
- tex= mtex->tex = localize_texture(cur_tex);
+ tex= mtex->tex = BKE_texture_localize(cur_tex);
/* update texture anims */
BKE_animsys_evaluate_animdata(scene, &tex->id, tex->adt, BKE_scene_frame_get(scene), ADT_RECALC_ANIM);
@@ -3609,7 +3631,7 @@ Material *RE_init_sample_material(Material *orig_mat, Scene *scene)
unit_m4(dummy_re.viewmat);
unit_m4(dummy_re.winmat);
dummy_re.winx = dummy_re.winy = 128;
- cache_pointdensity(&dummy_re, tex);
+ cache_pointdensity(&dummy_re, tex->pd);
}
/* update image sequences and movies */
@@ -3645,34 +3667,37 @@ void RE_free_sample_material(Material *mat)
MEM_freeN(mat);
}
-
-
/*
* Get material diffuse color and alpha (including linked textures) in given coordinates
*
* color,alpha : input/output color values
* volume_co : sample coordinate in global space. used by volumetric materials
* surface_co : sample surface coordinate in global space. used by "surface" materials
- * face_index : surface face index
- * hit_quad : whether point is on second "half" of a quad
+ * tri_index : surface tri index
* orcoDm : orco state derived mesh
*/
-void RE_sample_material_color(Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3], int face_index, short hit_quad, DerivedMesh *orcoDm, Object *ob)
+void RE_sample_material_color(
+ Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3],
+ int tri_index, DerivedMesh *orcoDm, Object *ob)
{
- MFace *mface;
int v1, v2, v3;
MVert *mvert;
+ MLoop *mloop;
+ const MLoopTri *mlooptri;
float uv[3], normal[3];
ShadeInput shi = {NULL};
Render re = {NULL};
/* Get face data */
mvert = orcoDm->getVertArray(orcoDm);
- mface = orcoDm->getTessFaceArray(orcoDm);
+ mloop = orcoDm->getLoopArray(orcoDm);
+ mlooptri = orcoDm->getLoopTriArray(orcoDm);
- if (!mvert || !mface || !mat) return;
- v1=mface[face_index].v1, v2=mface[face_index].v2, v3=mface[face_index].v3;
- if (hit_quad) { v2 = mface[face_index].v3; v3 = mface[face_index].v4; }
+ if (!mvert || !mlooptri || !mat) {
+ return;
+ }
+
+ v1=mloop[mlooptri[tri_index].tri[0]].v, v2=mloop[mlooptri[tri_index].tri[1]].v, v3=mloop[mlooptri[tri_index].tri[2]].v;
normal_tri_v3(normal, mvert[v1].co, mvert[v2].co, mvert[v3].co);
/* generate shadeinput with data required */
@@ -3689,7 +3714,7 @@ void RE_sample_material_color(Material *mat, float color[3], float *alpha, const
{
float l;
/* Get generated UV */
- textured_face_generate_uv(uv, normal, shi.co, mvert[v1].co, mvert[v2].co, mvert[v3].co);
+ textured_face_generate_uv(normal, shi.co, mvert[v1].co, mvert[v2].co, mvert[v3].co, uv);
l= 1.0f+uv[0]+uv[1];
/* calculate generated coordinate */
@@ -3699,35 +3724,37 @@ void RE_sample_material_color(Material *mat, float color[3], float *alpha, const
}
/* uv coordinates */
{
- int i, layers = CustomData_number_of_layers(&orcoDm->faceData, CD_MTFACE);
- int layer_index = CustomData_get_layer_index(&orcoDm->faceData, CD_MTFACE);
+ const int layers = CustomData_number_of_layers(&orcoDm->loopData, CD_MLOOPUV);
+ const int layer_index = CustomData_get_layer_index(&orcoDm->loopData, CD_MLOOPUV);
+ int i;
/* for every uv map set coords and name */
for (i=0; i<layers; i++) {
if (layer_index >= 0) {
const float *uv1, *uv2, *uv3;
+ const CustomData *data = &orcoDm->loopData;
+ const MLoopUV *mloopuv = data->layers[layer_index + i].data;
+ float uv[2];
float l;
- CustomData *data = &orcoDm->faceData;
- MTFace *tface = (MTFace *) data->layers[layer_index+i].data;
- float uv[3];
+
/* point layer name from actual layer data */
shi.uv[i].name = data->layers[i].name;
/* Get generated coordinates to calculate UV from */
- textured_face_generate_uv(uv, normal, shi.co, mvert[v1].co, mvert[v2].co, mvert[v3].co);
+ textured_face_generate_uv(normal, shi.co, mvert[v1].co, mvert[v2].co, mvert[v3].co, uv);
/* Get UV mapping coordinate */
l= 1.0f+uv[0]+uv[1];
-
- uv1= tface[face_index].uv[0];
- uv2= (hit_quad) ? tface[face_index].uv[2] : tface[face_index].uv[1];
- uv3= (hit_quad) ? tface[face_index].uv[3] : tface[face_index].uv[2];
-
+
+ uv1 = mloopuv[mlooptri[tri_index].tri[0]].uv;
+ uv2 = mloopuv[mlooptri[tri_index].tri[1]].uv;
+ uv3 = mloopuv[mlooptri[tri_index].tri[2]].uv;
+
shi.uv[i].uv[0]= -1.0f + 2.0f*(l*uv3[0]-uv[0]*uv1[0]-uv[1]*uv2[0]);
shi.uv[i].uv[1]= -1.0f + 2.0f*(l*uv3[1]-uv[0]*uv1[1]-uv[1]*uv2[1]);
shi.uv[i].uv[2]= 0.0f; /* texture.c assumes there are 3 coords */
}
}
/* active uv map */
- shi.actuv = CustomData_get_active_layer_index(&orcoDm->faceData, CD_MTFACE) - layer_index;
+ shi.actuv = CustomData_get_active_layer_index(&orcoDm->loopData, CD_MLOOPUV) - layer_index;
shi.totuv = layers;
}
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index a67140c6334..910ea16607e 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -50,15 +50,7 @@
#include "DNA_material_types.h"
#include "DNA_group_types.h"
-#include "BKE_main.h"
-
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-#include "IMB_colormanagement.h"
-
/* local include */
-#include "rayintersection.h"
-#include "rayobject.h"
#include "renderpipeline.h"
#include "render_result.h"
#include "render_types.h"
@@ -71,8 +63,6 @@
#include "sss.h"
#include "zbuf.h"
-#include "PIL_time.h"
-
/* own include */
#include "rendercore.h"
@@ -191,8 +181,10 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in
if (fullsample) {
for (sample=0; sample<totsample; sample++)
- if (ps->mask & (1 << sample))
- addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add);
+ if (ps->mask & (1 << sample)) {
+ float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ addalphaAddfacFloat(pass + od*4, col, har->add);
+ }
}
else {
fac= ((float)amountm)/(float)R.osa;
@@ -224,8 +216,10 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in
if (fullsample) {
for (sample=0; sample<totsample; sample++)
- if (!(mask & (1 << sample)))
- addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add);
+ if (!(mask & (1 << sample))) {
+ float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ addalphaAddfacFloat(pass + od*4, col, har->add);
+ }
}
else {
col[0]= accol[0];
@@ -233,8 +227,10 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in
col[2]= accol[2];
col[3]= accol[3];
- for (sample=0; sample<totsample; sample++)
- addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add);
+ for (sample=0; sample<totsample; sample++) {
+ float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ addalphaAddfacFloat(pass + od*4, col, har->add);
+ }
}
}
@@ -315,8 +311,10 @@ static void halo_tile(RenderPart *pa, RenderLayer *rl)
zz= calchalo_z(har, *rz);
if ((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) {
if (shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec)) {
- for (sample=0; sample<totsample; sample++)
- addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add);
+ for (sample=0; sample<totsample; sample++) {
+ float * rect= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ addalphaAddfacFloat(rect + od*4, col, har->add);
+ }
}
}
}
@@ -369,7 +367,8 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
if (fullsample) {
for (sample=0; sample<totsample; sample++) {
if (ps->mask & (1 << sample)) {
- pass= rlpp[sample]->rectf + od*4;
+ pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ pass += od * 4;
pass[0]+= col[0];
pass[1]+= col[1];
pass[2]+= col[2];
@@ -380,7 +379,8 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
}
else {
fac= ((float)count)/(float)R.osa;
- pass= rl->rectf + od*4;
+ pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+ pass += od * 4;
pass[0]+= fac*col[0];
pass[1]+= fac*col[1];
pass[2]+= fac*col[2];
@@ -400,7 +400,9 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
if (fullsample) {
for (sample=0; sample<totsample; sample++) {
if (!(mask & (1 << sample))) {
- pass= rlpp[sample]->rectf + od*4;
+
+ pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ pass += od * 4;
pass[0]+= col[0];
pass[1]+= col[1];
pass[2]+= col[2];
@@ -411,7 +413,8 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
}
else {
fac= ((float)R.osa-totsamp)/(float)R.osa;
- pass= rl->rectf + od*4;
+ pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+ pass += od * 4;
pass[0]+= fac*col[0];
pass[1]+= fac*col[1];
pass[2]+= fac*col[2];
@@ -430,7 +433,8 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
renderspothalo(&shi, col, 1.0f);
for (sample=0; sample<totsample; sample++) {
- pass= rlpp[sample]->rectf + od*4;
+ pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ pass += od * 4;
pass[0]+= col[0];
pass[1]+= col[1];
pass[2]+= col[2];
@@ -454,14 +458,14 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
{
RenderPass *rpass;
- /* combined rgb */
- add_filt_fmask(curmask, shr->combined, rl->rectf + 4*offset, rectx);
-
for (rpass= rl->passes.first; rpass; rpass= rpass->next) {
float *fp, *col= NULL;
int pixsize= 3;
switch (rpass->passtype) {
+ case SCE_PASS_COMBINED:
+ add_filt_fmask(curmask, shr->combined, rpass->rect + 4*offset, rectx);
+ break;
case SCE_PASS_Z:
fp= rpass->rect + offset;
*fp= shr->z;
@@ -544,9 +548,9 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
fp[2]= shr->winspeed[2];
fp[3]= shr->winspeed[3];
}
- }
- break;
+ break;
+ }
case SCE_PASS_RAYHITS:
/* */
col= shr->rayhits;
@@ -565,15 +569,16 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult
{
RenderPass *rpass;
float *fp;
-
- fp= rl->rectf + 4*offset;
- copy_v4_v4(fp, shr->combined);
-
+
for (rpass= rl->passes.first; rpass; rpass= rpass->next) {
float *col= NULL, uvcol[3];
int a, pixsize= 3;
switch (rpass->passtype) {
+ case SCE_PASS_COMBINED:
+ /* copy combined to use for preview */
+ copy_v4_v4(rpass->rect + 4*offset, shr->combined);
+ break;
case SCE_PASS_Z:
fp= rpass->rect + offset;
*fp= shr->z;
@@ -691,7 +696,8 @@ static void sky_tile(RenderPart *pa, RenderLayer *rl)
bool done = false;
for (sample= 0; sample<totsample; sample++) {
- float *pass= rlpp[sample]->rectf + od;
+ float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ pass += od;
if (pass[3]<1.0f) {
@@ -752,8 +758,8 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl)
int sample;
for (sample=0; sample<totsample; sample++) {
- const float *zrect= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_Z) + od;
- float *rgbrect = rlpp[sample]->rectf + 4*od;
+ const float *zrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_Z, R.viewname) + od;
+ float *rgbrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname) + 4*od;
float rgb[3] = {0};
bool done = false;
@@ -988,8 +994,8 @@ static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl)
return;
for (sample= 0; sample<totsample; sample++) {
- float *rectf= rlpp[sample]->rectf;
-
+ float *rectf = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+
for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) {
rectf[0] = MAX2(rectf[0], 0.0f);
rectf[1] = MAX2(rectf[1], 0.0f);
@@ -1070,7 +1076,7 @@ static void reset_sky_speed(RenderPart *pa, RenderLayer *rl)
totsample= get_sample_layers(pa, rl, rlpp);
for (sample= 0; sample<totsample; sample++) {
- fp= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_VECTOR);
+ fp= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_VECTOR, R.viewname);
if (fp==NULL) break;
for (a= 4*pa->rectx*pa->recty - 1; a>=0; a--)
@@ -1181,6 +1187,8 @@ void zbufshadeDA_tile(RenderPart *pa)
pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
for (rl= rr->layers.first; rl; rl= rl->next) {
+ float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+
if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK))
pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask");
@@ -1221,7 +1229,7 @@ void zbufshadeDA_tile(RenderPart *pa)
if (R.flag & R_ZTRA || R.totstrand) {
if (rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) {
if (pa->fullresult.first) {
- zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist);
+ zbuffer_transp_shade(pa, rl, rect, &psmlist);
}
else {
unsigned short *ztramask, *solidmask= NULL; /* 16 bits, MAX_OSA */
@@ -1230,9 +1238,9 @@ void zbufshadeDA_tile(RenderPart *pa)
rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer");
/* swap for live updates, and it is used in zbuf.c!!! */
- SWAP(float *, rl->acolrect, rl->rectf);
- ztramask= zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist);
- SWAP(float *, rl->acolrect, rl->rectf);
+ SWAP(float *, rl->acolrect, rect);
+ ztramask = zbuffer_transp_shade(pa, rl, rect, &psmlist);
+ SWAP(float *, rl->acolrect, rect);
/* zbuffer transp only returns ztramask if there's solid rendered */
if (ztramask)
@@ -1241,7 +1249,8 @@ void zbufshadeDA_tile(RenderPart *pa)
if (ztramask && solidmask) {
unsigned short *sps= solidmask, *spz= ztramask;
unsigned short fullmask= (1<<R.osa)-1;
- float *fcol= rl->rectf; float *acol= rl->acolrect;
+ float *fcol= rect;
+ float *acol= rl->acolrect;
int x;
for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4, sps++, spz++) {
@@ -1252,7 +1261,8 @@ void zbufshadeDA_tile(RenderPart *pa)
}
}
else {
- float *fcol= rl->rectf; float *acol= rl->acolrect;
+ float *fcol= rect;
+ float *acol= rl->acolrect;
int x;
for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) {
addAlphaOverFloat(fcol, acol);
@@ -1275,7 +1285,7 @@ void zbufshadeDA_tile(RenderPart *pa)
/* extra layers */
if (rl->layflag & SCE_LAY_EDGE)
if (R.r.mode & R_EDGE)
- edge_enhance_add(pa, rl->rectf, edgerect);
+ edge_enhance_add(pa, rect, edgerect);
if (rl->passflag & SCE_PASS_VECTOR)
reset_sky_speed(pa, rl);
@@ -1329,6 +1339,7 @@ void zbufshade_tile(RenderPart *pa)
pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
for (rl= rr->layers.first; rl; rl= rl->next) {
+ float *rect= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK))
pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask");
@@ -1352,7 +1363,7 @@ void zbufshade_tile(RenderPart *pa)
rr->renlay= rl;
if (rl->layflag & SCE_LAY_SOLID) {
- const float *fcol= rl->rectf;
+ const float *fcol = rect;
const int *ro= pa->recto, *rp= pa->rectp, *rz= pa->rectz;
int x, y, offs=0, seed;
@@ -1415,11 +1426,11 @@ void zbufshade_tile(RenderPart *pa)
rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer");
/* swap for live updates */
- SWAP(float *, rl->acolrect, rl->rectf);
- zbuffer_transp_shade(pa, rl, rl->rectf, NULL);
- SWAP(float *, rl->acolrect, rl->rectf);
+ SWAP(float *, rl->acolrect, rect);
+ zbuffer_transp_shade(pa, rl, rect, NULL);
+ SWAP(float *, rl->acolrect, rect);
- fcol= rl->rectf; acol= rl->acolrect;
+ fcol= rect; acol= rl->acolrect;
for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) {
addAlphaOverFloat(fcol, acol);
}
@@ -1437,7 +1448,7 @@ void zbufshade_tile(RenderPart *pa)
if (!R.test_break(R.tbh)) {
if (rl->layflag & SCE_LAY_EDGE)
if (R.r.mode & R_EDGE)
- edge_enhance_add(pa, rl->rectf, edgerect);
+ edge_enhance_add(pa, rect, edgerect);
}
if (rl->passflag & SCE_PASS_VECTOR)
@@ -1611,7 +1622,8 @@ void zbufshade_sss_tile(RenderPart *pa)
VlakRen *vlr;
Material *mat= re->sss_mat;
float (*co)[3], (*color)[3], *area, *fcol;
- int x, y, seed, quad, totpoint, display = !(re->r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW));
+ int x, y, seed, quad, totpoint;
+ const bool display = (re->r.scemode & (R_BUTS_PREVIEW | R_VIEWPORT_PREVIEW)) == 0;
int *ro, *rz, *rp, *rbo, *rbz, *rbp, lay;
#if 0
PixStr *ps;
@@ -1664,7 +1676,7 @@ void zbufshade_sss_tile(RenderPart *pa)
return;
}
- fcol= rl->rectf;
+ fcol= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo");
color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor");
@@ -1948,6 +1960,7 @@ void add_halo_flare(Render *re)
RenderLayer *rl;
HaloRen *har;
int a, mode;
+ float *rect;
/* for now, we get the first renderlayer in list with halos set */
for (rl= rr->layers.first; rl; rl= rl->next) {
@@ -1955,9 +1968,12 @@ void add_halo_flare(Render *re)
if ((rl->layflag & SCE_LAY_HALO) == 0)
continue;
- if (rl->rectf==NULL)
+
+ rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname);
+
+ if (rect==NULL)
continue;
-
+
mode= R.r.mode;
R.r.mode &= ~R_PANORAMA;
@@ -1968,7 +1984,7 @@ void add_halo_flare(Render *re)
if (har->flarec && (har->lay & rl->lay)) {
do_draw = true;
- renderflare(rr, rl->rectf, har);
+ renderflare(rr, rect, har);
}
}
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index 46c504aaabf..7a9b2d0903e 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -69,7 +69,8 @@
#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_texture_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_particle_types.h"
#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
@@ -78,11 +79,8 @@
#include "rayintersection.h"
#include "rayobject.h"
-#include "renderpipeline.h"
#include "render_types.h"
#include "renderdatabase.h"
-#include "texture.h"
-#include "strand.h"
#include "zbuf.h"
/* ------------------------------------------------------------------------- */
@@ -957,6 +955,7 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,
const float vec[3], const float vec1[3],
const float *orco, float hasize, float vectsize, int seed)
{
+ const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
HaloRen *har;
MTex *mtex;
float tin, tr, tg, tb, ta;
@@ -1048,7 +1047,7 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,
}
}
- externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool);
+ externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool, skip_load_image);
yn= tin*mtex->colfac;
//zn= tin*mtex->alphafac;
@@ -1068,6 +1067,7 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,
}
har->pool = re->pool;
+ har->skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
return har;
}
@@ -1076,6 +1076,7 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater
const float vec[3], const float vec1[3],
const float *orco, const float *uvco, float hasize, float vectsize, int seed, const float pa_co[3])
{
+ const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
HaloRen *har;
MTex *mtex;
float tin, tr, tg, tb, ta;
@@ -1179,7 +1180,7 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater
copy_v3_v3(texvec, orco);
}
- hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool);
+ hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool, skip_load_image);
//yn= tin*mtex->colfac;
//zn= tin*mtex->alphafac;
@@ -1223,6 +1224,7 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater
}
har->pool = re->pool;
+ har->skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
return har;
}
@@ -1374,6 +1376,38 @@ ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob,
obi->psysindex= psysindex;
obi->lay= lay;
+ /* Fill particle info */
+ if (obi->psysindex > 0) {
+ int psysindex = 1;
+ int index;
+ ParticleSystem *psys;
+ if (obi->par) {
+ for (psys = obi->par->particlesystem.first; psys; psys = psys->next) {
+ if (psysindex == obi->psysindex)
+ break;
+ ++psysindex;
+ }
+ if (psys) {
+ if (obi->index < psys->totpart)
+ index = obi->index;
+ else {
+ index = psys->child[obi->index - psys->totpart].parent;
+ }
+ if (index >= 0) {
+ ParticleData* p = &psys->particles[index];
+ obi->part_index = index;
+ obi->part_size = p->size;
+ obi->part_age = RE_GetStats(re)->cfra - p->time;
+ obi->part_lifetime = p->lifetime;
+
+ copy_v3_v3(obi->part_co, p->state.co);
+ copy_v3_v3(obi->part_vel, p->state.vel);
+ copy_v3_v3(obi->part_avel, p->state.ave);
+ }
+ }
+ }
+ }
+
if (mat) {
copy_m4_m4(obi->mat, mat);
copy_m3_m4(mat3, mat);
@@ -1387,6 +1421,18 @@ ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob,
return obi;
}
+void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3])
+{
+ *index = obi->part_index;
+ *age = obi->part_age;
+ *lifetime = obi->part_lifetime;
+ copy_v3_v3(co, obi->part_co);
+ *size = obi->part_size;
+ copy_v3_v3(vel, obi->part_vel);
+ copy_v3_v3(angvel, obi->part_avel);
+}
+
+
void RE_makeRenderInstances(Render *re)
{
ObjectInstanceRen *obi, *oldobi;
@@ -1394,7 +1440,7 @@ void RE_makeRenderInstances(Render *re)
int tot;
/* convert list of object instances to an array for index based lookup */
- tot= BLI_countlist(&re->instancetable);
+ tot= BLI_listbase_count(&re->instancetable);
re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance");
re->totinstance= tot;
newlist.first= newlist.last= NULL;
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 9d83ff1d7e8..0bd4815fb73 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -50,7 +50,6 @@
#include "PIL_time.h"
-#include "renderpipeline.h"
#include "render_types.h"
#include "renderdatabase.h"
#include "rendercore.h"
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index 7aca6b9ac87..08304533b95 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -39,6 +39,7 @@
#include "DNA_lamp_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_material_types.h"
+#include "DNA_particle_types.h"
#include "BKE_scene.h"
@@ -46,11 +47,9 @@
/* local include */
#include "raycounter.h"
-#include "renderpipeline.h"
#include "render_types.h"
#include "renderdatabase.h"
#include "rendercore.h"
-#include "shadbuf.h"
#include "shading.h"
#include "strand.h"
#include "texture.h"
@@ -157,9 +156,10 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr)
memset(&shi->raycounter, 0, sizeof(shi->raycounter));
#endif
- if (shi->mat->nodetree && shi->mat->use_nodes)
+ if (shi->mat->nodetree && shi->mat->use_nodes) {
compat = ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
-
+ }
+
/* also run this when node shaders fail, due to incompatible shader nodes */
if (compat == false) {
/* copy all relevant material vars, note, keep this synced with render_types.h */
@@ -425,14 +425,11 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert
}
if (texco & TEXCO_GLOB) {
- copy_v3_v3(shi->gl, shi->co);
- mul_m4_v3(R.viewinv, shi->gl);
+ mul_v3_m4v3(shi->gl, R.viewinv, shi->co);
if (shi->osatex) {
- copy_v3_v3(shi->dxgl, shi->dxco);
- mul_mat3_m4_v3(R.viewinv, shi->dxgl);
- copy_v3_v3(shi->dygl, shi->dyco);
- mul_mat3_m4_v3(R.viewinv, shi->dygl);
+ mul_v3_mat3_m4v3(shi->dxgl, R.viewinv, shi->dxco);
+ mul_v3_mat3_m4v3(shi->dygl, R.viewinv, shi->dyco);
}
}
@@ -635,7 +632,7 @@ void shade_input_calc_viewco(ShadeInput *shi, float x, float y, float z, float v
dyco[2] = 0.0f;
if (dxyview) {
- if (co[2] != 0.0f) fac = 1.0f / co[2]; else fac = 0.0f;
+ fac = (co[2] != 0.0f) ? (1.0f / co[2]) : 0.0f;
dxyview[0] = -R.viewdx * fac;
dxyview[1] = -R.viewdy * fac;
}
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index 6d6bba834ba..39dfa48d3f1 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -47,9 +47,7 @@
/* local include */
#include "occlusion.h"
-#include "renderpipeline.h"
#include "render_types.h"
-#include "pixelblending.h"
#include "rendercore.h"
#include "shadbuf.h"
#include "sss.h"
@@ -57,6 +55,8 @@
#include "shading.h" /* own include */
+#include "IMB_colormanagement.h"
+
/* could enable at some point but for now there are far too many conversions */
#ifdef __GNUC__
# pragma GCC diagnostic ignored "-Wdouble-promotion"
@@ -950,7 +950,7 @@ static void ramp_diffuse_result(float *diff, ShadeInput *shi)
if (ma->ramp_col) {
if (ma->rampin_col==MA_RAMP_IN_RESULT) {
- float fac = rgb_to_grayscale(diff);
+ float fac = IMB_colormanagement_get_luminance(diff);
do_colorband(ma->ramp_col, fac, col);
/* blending method */
@@ -962,7 +962,7 @@ static void ramp_diffuse_result(float *diff, ShadeInput *shi)
}
/* r,g,b denote energy, ramp is used with different values to make new material color */
-static void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, float g, float b)
+static void add_to_diffuse(float diff[3], const ShadeInput *shi, const float is, const float rgb[3])
{
Material *ma= shi->mat;
@@ -971,9 +971,9 @@ static void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, floa
/* MA_RAMP_IN_RESULT is exceptional */
if (ma->rampin_col==MA_RAMP_IN_RESULT) {
/* normal add */
- diff[0] += r * shi->r;
- diff[1] += g * shi->g;
- diff[2] += b * shi->b;
+ diff[0] += rgb[0] * shi->r;
+ diff[1] += rgb[1] * shi->g;
+ diff[2] += rgb[2] * shi->b;
}
else {
float colt[3], col[4];
@@ -982,40 +982,37 @@ static void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, floa
/* input */
switch (ma->rampin_col) {
case MA_RAMP_IN_ENERGY:
- /* should use 'rgb_to_grayscale' but we only have a vector version */
- fac= 0.3f*r + 0.58f*g + 0.12f*b;
+ fac = IMB_colormanagement_get_luminance(rgb);
break;
case MA_RAMP_IN_SHADER:
- fac= is;
+ fac = is;
break;
case MA_RAMP_IN_NOR:
- fac= shi->view[0]*shi->vn[0] + shi->view[1]*shi->vn[1] + shi->view[2]*shi->vn[2];
+ fac = dot_v3v3(shi->view, shi->vn);
break;
default:
- fac= 0.0f;
+ fac = 0.0f;
break;
}
do_colorband(ma->ramp_col, fac, col);
/* blending method */
- fac= col[3]*ma->rampfac_col;
- colt[0]= shi->r;
- colt[1]= shi->g;
- colt[2]= shi->b;
+ fac = col[3] * ma->rampfac_col;
+ copy_v3_v3(colt, &shi->r);
ramp_blend(ma->rampblend_col, colt, fac, col);
/* output to */
- diff[0] += r * colt[0];
- diff[1] += g * colt[1];
- diff[2] += b * colt[2];
+ diff[0] += rgb[0] * colt[0];
+ diff[1] += rgb[1] * colt[1];
+ diff[2] += rgb[2] * colt[2];
}
}
else {
- diff[0] += r * shi->r;
- diff[1] += g * shi->g;
- diff[2] += b * shi->b;
+ diff[0] += rgb[0] * shi->r;
+ diff[1] += rgb[1] * shi->g;
+ diff[2] += rgb[2] * shi->b;
}
}
@@ -1025,7 +1022,7 @@ static void ramp_spec_result(float spec_col[3], ShadeInput *shi)
if (ma->ramp_spec && (ma->rampin_spec==MA_RAMP_IN_RESULT)) {
float col[4];
- float fac = rgb_to_grayscale(spec_col);
+ float fac = IMB_colormanagement_get_luminance(spec_col);
do_colorband(ma->ramp_spec, fac, col);
@@ -1478,27 +1475,55 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int
i*= shadfac[3];
shr->shad[3] = shadfac[3]; /* store this for possible check in troublesome cases */
}
+ else {
+ shr->shad[3] = 1.0f; /* No shadow at all! */
+ }
}
}
/* in case 'no diffuse' we still do most calculus, spec can be in shadow.*/
if (!(lar->mode & LA_NO_DIFF)) {
if (i>0.0f) {
- if (ma->mode & MA_SHADOW_TRA)
- add_to_diffuse(shr->shad, shi, is, i*shadfac[0]*lacol[0], i*shadfac[1]*lacol[1], i*shadfac[2]*lacol[2]);
- else
- add_to_diffuse(shr->shad, shi, is, i*lacol[0], i*lacol[1], i*lacol[2]);
+ if (ma->mode & MA_SHADOW_TRA) {
+ const float tcol[3] = {
+ i * shadfac[0] * lacol[0],
+ i * shadfac[1] * lacol[1],
+ i * shadfac[2] * lacol[2],
+ };
+ add_to_diffuse(shr->shad, shi, is, tcol);
+ }
+ else {
+ const float tcol[3] = {
+ i * lacol[0],
+ i * lacol[1],
+ i * lacol[2],
+ };
+ add_to_diffuse(shr->shad, shi, is, tcol);
+ }
}
/* add light for colored shadow */
if (i_noshad>i && !(lashdw[0]==0 && lashdw[1]==0 && lashdw[2]==0)) {
- add_to_diffuse(shr->shad, shi, is, lashdw[0]*(i_noshad-i)*lacol[0], lashdw[1]*(i_noshad-i)*lacol[1], lashdw[2]*(i_noshad-i)*lacol[2]);
+ const float tcol[3] = {
+ lashdw[0] * (i_noshad - i) * lacol[0],
+ lashdw[1] * (i_noshad - i) * lacol[1],
+ lashdw[2] * (i_noshad - i) * lacol[2],
+ };
+ add_to_diffuse(shr->shad, shi, is, tcol);
}
if (i_noshad>0.0f) {
- if (passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW)) {
- add_to_diffuse(shr->diff, shi, is, i_noshad*lacol[0], i_noshad*lacol[1], i_noshad*lacol[2]);
+ if (passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW) ||
+ ((passflag & SCE_PASS_COMBINED) && !(shi->combinedflag & SCE_PASS_SHADOW)))
+ {
+ const float tcol[3] = {
+ i_noshad * lacol[0],
+ i_noshad * lacol[1],
+ i_noshad * lacol[2]
+ };
+ add_to_diffuse(shr->diff, shi, is, tcol);
}
- else
+ else {
copy_v3_v3(shr->diff, shr->shad);
+ }
}
}
@@ -1618,10 +1643,10 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr)
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
/* Old "Shadows Only" */
- accum+= (1.0f-visifac) + (visifac)*rgb_to_grayscale(shadfac)*shadfac[3];
+ accum+= (1.0f-visifac) + (visifac)*IMB_colormanagement_get_luminance(shadfac)*shadfac[3];
}
else {
- shaded += rgb_to_grayscale(shadfac)*shadfac[3] * visifac * lar->energy;
+ shaded += IMB_colormanagement_get_luminance(shadfac)*shadfac[3] * visifac * lar->energy;
if (shi->mat->shadowonly_flag == MA_SO_SHADOW) {
lightness += visifac * lar->energy;
@@ -1648,7 +1673,8 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr)
else { /* shadowonly_flag == MA_SO_SHADED */
/* Use shaded value */
accum = 1.0f - shaded;
- }}
+ }
+ }
shr->alpha= (shi->alpha)*(accum);
if (shr->alpha<0.0f) shr->alpha=0.0f;
@@ -1669,26 +1695,26 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr)
if (R.wrld.aomix==WO_AOADD) {
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
- f= f*(1.0f - rgb_to_grayscale(shi->ao));
+ f= f*(1.0f - IMB_colormanagement_get_luminance(shi->ao));
shr->alpha= (shr->alpha + f)*f;
}
else {
- shr->alpha -= f*rgb_to_grayscale(shi->ao);
+ shr->alpha -= f*IMB_colormanagement_get_luminance(shi->ao);
if (shr->alpha<0.0f) shr->alpha=0.0f;
}
}
else /* AO Multiply */
- shr->alpha= (1.0f - f)*shr->alpha + f*(1.0f - (1.0f - shr->alpha)*rgb_to_grayscale(shi->ao));
+ shr->alpha= (1.0f - f)*shr->alpha + f*(1.0f - (1.0f - shr->alpha)*IMB_colormanagement_get_luminance(shi->ao));
}
if (R.wrld.mode & WO_ENV_LIGHT) {
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
- f= R.wrld.ao_env_energy*shi->amb*(1.0f - rgb_to_grayscale(shi->env));
+ f= R.wrld.ao_env_energy*shi->amb*(1.0f - IMB_colormanagement_get_luminance(shi->env));
shr->alpha= (shr->alpha + f)*f;
}
else {
f= R.wrld.ao_env_energy*shi->amb;
- shr->alpha -= f*rgb_to_grayscale(shi->env);
+ shr->alpha -= f*IMB_colormanagement_get_luminance(shi->env);
if (shr->alpha<0.0f) shr->alpha=0.0f;
}
}
@@ -1714,7 +1740,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
*/
const int color_passes =
SCE_PASS_COMBINED | SCE_PASS_RGBA | SCE_PASS_DIFFUSE | SCE_PASS_SPEC |
- SCE_PASS_REFLECT | SCE_PASS_NORMAL | SCE_PASS_REFRACT | SCE_PASS_EMIT;
+ SCE_PASS_REFLECT | SCE_PASS_NORMAL | SCE_PASS_REFRACT | SCE_PASS_EMIT | SCE_PASS_SHADOW;
Material *ma= shi->mat;
int passflag= shi->passflag;
@@ -1889,7 +1915,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
}
if (shi->combinedflag & SCE_PASS_SHADOW)
- copy_v3_v3(shr->diffshad, shr->shad); /* note, no ';' ! */
+ copy_v3_v3(shr->diffshad, shr->shad);
else
copy_v3_v3(shr->diffshad, shr->diff);
@@ -2062,7 +2088,7 @@ float RE_lamp_get_data(ShadeInput *shi, Object *lamp_obj, float col[4], float lv
if (R.r.scemode & R_BUTS_PREVIEW) {
for (go = R.lights.first; go; go = go->next) {
/* "Lamp.002" is main key light of material preview */
- if (strcmp(go->ob->id.name + 2, "Lamp.002") == 0)
+ if (STREQ(go->ob->id.name + 2, "Lamp.002"))
return lamp_get_data_internal(shi, go, col, lv, dist, shadow);
}
return 0.0f;
diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c
index 7e9003aaee7..553710b4367 100644
--- a/source/blender/render/intern/source/sss.c
+++ b/source/blender/render/intern/source/sss.c
@@ -55,9 +55,8 @@
#include "BLI_ghash.h"
#include "BLI_memarena.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
-#include "PIL_time.h"
#include "DNA_material_types.h"
@@ -68,11 +67,7 @@
/* this module */
#include "render_types.h"
-#include "rendercore.h"
-#include "renderdatabase.h"
-#include "shading.h"
#include "sss.h"
-#include "zbuf.h"
/* Generic Multiple Scattering API */
@@ -1036,14 +1031,12 @@ void make_sss_tree(Render *re)
void free_sss(Render *re)
{
if (re->sss_hash) {
- GHashIterator *it= BLI_ghashIterator_new(re->sss_hash);
+ GHashIterator gh_iter;
- while (!BLI_ghashIterator_done(it)) {
- sss_free_tree(BLI_ghashIterator_getValue(it));
- BLI_ghashIterator_step(it);
+ GHASH_ITER (gh_iter, re->sss_hash) {
+ sss_free_tree(BLI_ghashIterator_getValue(&gh_iter));
}
- BLI_ghashIterator_free(it);
BLI_ghash_free(re->sss_hash, NULL, NULL);
re->sss_hash= NULL;
}
diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c
index 485680da76f..6b52d4aa419 100644
--- a/source/blender/render/intern/source/strand.c
+++ b/source/blender/render/intern/source/strand.c
@@ -47,11 +47,8 @@
#include "render_types.h"
-#include "initrender.h"
#include "rendercore.h"
#include "renderdatabase.h"
-#include "renderpipeline.h"
-#include "pixelblending.h"
#include "shading.h"
#include "strand.h"
#include "zbuf.h"
diff --git a/source/blender/render/intern/source/sunsky.c b/source/blender/render/intern/source/sunsky.c
index 1836b3f48a7..d4e53eb7305 100644
--- a/source/blender/render/intern/source/sunsky.c
+++ b/source/blender/render/intern/source/sunsky.c
@@ -254,14 +254,14 @@ void GetSkyXYZRadiance(struct SunSky *sunsky, float theta, float phi, float colo
float hfade = 1, nfade = 1;
- if (theta > (0.5f * (float)M_PI)) {
+ if (theta > (float)M_PI_2) {
hfade = 1.0f - (theta * (float)M_1_PI - 0.5f) * 2.0f;
hfade = hfade * hfade * (3.0f - 2.0f * hfade);
- theta = 0.5 * M_PI;
+ theta = M_PI_2;
}
- if (sunsky->theta > (0.5f * (float)M_PI)) {
- if (theta <= 0.5f * (float)M_PI) {
+ if (sunsky->theta > (float)M_PI_2) {
+ if (theta <= (float)M_PI_2) {
nfade = 1.0f - (0.5f - theta * (float)M_1_PI) * 2.0f;
nfade *= 1.0f - (sunsky->theta * (float)M_1_PI - 0.5f) * 2.0f;
nfade = nfade * nfade * (3.0f - 2.0f * nfade);
@@ -299,8 +299,7 @@ void GetSkyXYZRadiancef(struct SunSky *sunsky, const float varg[3], float color_
float theta, phi;
float v[3];
- copy_v3_v3(v, (float *)varg);
- normalize_v3(v);
+ normalize_v3_v3(v, varg);
if (v[2] < 0.001f) {
v[2] = 0.001f;
diff --git a/source/blender/render/intern/source/texture_ocean.c b/source/blender/render/intern/source/texture_ocean.c
index 55f4bf3794d..a932123243d 100644
--- a/source/blender/render/intern/source/texture_ocean.c
+++ b/source/blender/render/intern/source/texture_ocean.c
@@ -56,8 +56,6 @@ extern struct Render R;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-
-
/* ***** actual texture sampling ***** */
int ocean_texture(Tex *tex, const float texvec[2], TexResult *texres)
{
@@ -75,7 +73,7 @@ int ocean_texture(Tex *tex, const float texvec[2], TexResult *texres)
return 0;
}
else {
- const int do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
+ const bool do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS) != 0;
int cfra = R.r.cfra;
int retval = TEX_INT;
diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c
index 6135a8761bb..78ede01d6c1 100644
--- a/source/blender/render/intern/source/volume_precache.c
+++ b/source/blender/render/intern/source/volume_precache.c
@@ -44,7 +44,7 @@
#include "BLI_voxel.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "PIL_time.h"
diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c
index d5c4c407bf6..2c0917243a3 100644
--- a/source/blender/render/intern/source/volumetric.c
+++ b/source/blender/render/intern/source/volumetric.c
@@ -41,6 +41,8 @@
#include "RE_shader_ext.h"
+#include "IMB_colormanagement.h"
+
#include "DNA_material_types.h"
#include "DNA_group_types.h"
#include "DNA_lamp_types.h"
@@ -504,7 +506,7 @@ static void vol_shade_one_lamp(struct ShadeInput *shi, const float co[3], const
if (shi->mat->vol.shadeflag & MA_VOL_RECV_EXT_SHADOW) {
mul_v3_fl(lacol, vol_get_shadow(shi, lar, co));
- if (rgb_to_luma_y(lacol) < 0.001f) return;
+ if (IMB_colormanagement_get_luminance(lacol) < 0.001f) return;
}
/* find minimum of volume bounds, or lamp coord */
@@ -538,7 +540,7 @@ static void vol_shade_one_lamp(struct ShadeInput *shi, const float co[3], const
}
}
- if (rgb_to_luma_y(lacol) < 0.001f) return;
+ if (IMB_colormanagement_get_luminance(lacol) < 0.001f) return;
normalize_v3(lv);
p = vol_get_phasefunc(shi, shi->mat->vol.asymmetry, view, lv);
@@ -620,7 +622,7 @@ static void volumeintegrate(struct ShadeInput *shi, float col[4], const float co
if (t0 > t1 * 0.25f) {
/* only use depth cutoff after we've traced a little way into the volume */
- if (rgb_to_luma_y(tr) < shi->mat->vol.depth_cutoff) break;
+ if (IMB_colormanagement_get_luminance(tr) < shi->mat->vol.depth_cutoff) break;
}
vol_get_emission(shi, emit_col, p);
@@ -649,7 +651,7 @@ static void volumeintegrate(struct ShadeInput *shi, float col[4], const float co
add_v3_v3(col, radiance);
/* alpha <-- transmission luminance */
- col[3] = 1.0f - rgb_to_luma_y(tr);
+ col[3] = 1.0f - IMB_colormanagement_get_luminance(tr);
}
/* the main entry point for volume shading */
@@ -790,7 +792,7 @@ void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct
copy_v3_v3(shr->combined, tr);
- shr->combined[3] = 1.0f - rgb_to_luma_y(tr);
+ shr->combined[3] = 1.0f - IMB_colormanagement_get_luminance(tr);
shr->alpha = shr->combined[3];
}
diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c
index 50b5e392b3f..bb92a8f7e8a 100644
--- a/source/blender/render/intern/source/voxeldata.c
+++ b/source/blender/render/intern/source/voxeldata.c
@@ -46,27 +46,29 @@
#include "BLI_voxel.h"
#include "BLI_utildefines.h"
-#include "BLF_translation.h"
+#include "BLT_translation.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "BKE_cloth.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "smoke_API.h"
+#include "BPH_mass_spring.h"
#include "DNA_texture_types.h"
#include "DNA_object_force.h"
#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
#include "DNA_modifier_types.h"
#include "DNA_smoke_types.h"
#include "render_types.h"
-#include "renderdatabase.h"
#include "texture.h"
#include "voxeldata.h"
@@ -365,6 +367,27 @@ static void init_frame_smoke(VoxelData *vd, int cfra)
#endif
}
+static void init_frame_hair(VoxelData *vd, int UNUSED(cfra))
+{
+ Object *ob;
+ ModifierData *md;
+ bool found = false;
+
+ vd->dataset = NULL;
+ if (vd->object == NULL) return;
+ ob = vd->object;
+
+ if ((md = (ModifierData *)modifiers_findByType(ob, eModifierType_ParticleSystem))) {
+ ParticleSystemModifierData *pmd = (ParticleSystemModifierData *)md;
+
+ if (pmd->psys && pmd->psys->clmd) {
+ found |= BPH_cloth_solver_get_texture_data(ob, pmd->psys->clmd, vd);
+ }
+ }
+
+ vd->ok = found;
+}
+
void cache_voxeldata(Tex *tex, int scene_frame)
{
VoxelData *vd = tex->vd;
@@ -398,6 +421,9 @@ void cache_voxeldata(Tex *tex, int scene_frame)
case TEX_VD_SMOKE:
init_frame_smoke(vd, scene_frame);
return;
+ case TEX_VD_HAIR:
+ init_frame_hair(vd, scene_frame);
+ return;
case TEX_VD_BLENDERVOXEL:
BLI_path_abs(path, G.main->name);
if (!BLI_exists(path)) return;
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index 87e546ef24e..58ac34080b9 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -63,12 +63,10 @@
#include "pixelblending.h"
#include "render_result.h"
#include "render_types.h"
-#include "renderpipeline.h"
#include "renderdatabase.h"
#include "rendercore.h"
#include "shadbuf.h"
#include "shading.h"
-#include "sss.h"
#include "strand.h"
/* own includes */
@@ -332,8 +330,8 @@ static void zbuffillAc4(ZSpan *zspan, int obi, int zvlnr,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
if (my2<my0) return;
@@ -1075,8 +1073,8 @@ static void zbuffillGLinv4(ZSpan *zspan, int obi, int zvlnr,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ 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;
@@ -1198,8 +1196,8 @@ static void zbuffillGL4(ZSpan *zspan, int obi, int zvlnr,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ 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;
@@ -1326,8 +1324,8 @@ static void zbuffillGL_onlyZ(ZSpan *zspan, int UNUSED(obi), int UNUSED(zvlnr),
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ 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;
@@ -1428,8 +1426,8 @@ void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ 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;
@@ -1515,7 +1513,7 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, 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 x, y, sn1, sn2, rectx= zspan->rectx, my0, my2;
+ int i, j, x, y, sn1, sn2, rectx = zspan->rectx, my0, my2;
/* init */
zbuf_init_span(zspan);
@@ -1528,8 +1526,8 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ 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;
@@ -1576,7 +1574,7 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *
span2= zspan->span1+my2;
}
- for (y=my2; y>=my0; y--, span1--, span2--) {
+ for (i = 0, y = my2; y >= my0; i++, y--, span1--, span2--) {
sn1= floor(*span1);
sn2= floor(*span2);
@@ -1585,14 +1583,12 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *
if (sn2>=rectx) sn2= rectx-1;
if (sn1<0) sn1= 0;
- u= (double)sn1*uxd + uy0;
- v= (double)sn1*vxd + vy0;
+ u = (((double)sn1 * uxd) + uy0) - (i * uyd);
+ v = (((double)sn1 * vxd) + vy0) - (i * vyd);
- for (x= sn1; x<=sn2; x++, u+=uxd, v+=vxd)
- func(handle, x, y, u, v);
-
- uy0 -= uyd;
- vy0 -= vyd;
+ for (j = 0, x = sn1; x <= sn2; j++, x++) {
+ func(handle, x, y, u + (j * uxd), v + (j * vxd));
+ }
}
}
@@ -2065,8 +2061,6 @@ static void zmask_rect(int *rectz, int *rectp, int xs, int ys, int neg)
}
-
-
/* ***************** ZBUFFER MAIN ROUTINES **************** */
void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart *, ZSpan *, int, void *), void *data)
@@ -2083,8 +2077,8 @@ void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart *
unsigned int lay= rl->lay, lay_zmask= rl->lay_zmask;
int i, v, zvlnr, zsample, samples, c1, c2, c3, c4=0;
short nofill=0, env=0, wire=0, zmaskpass=0;
- short all_z= (rl->layflag & SCE_LAY_ALL_Z) && !(rl->layflag & SCE_LAY_ZMASK);
- short neg_zmask= (rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK);
+ const bool all_z = (rl->layflag & SCE_LAY_ALL_Z) && !(rl->layflag & SCE_LAY_ZMASK);
+ const bool neg_zmask = (rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK);
zbuf_make_winmat(&R, winmat);
@@ -2486,8 +2480,8 @@ static void zbuffill_sss(ZSpan *zspan, int obi, int zvlnr,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
if (my2<my0) return;
@@ -2687,8 +2681,8 @@ static void zbuf_fill_in_rgba(ZSpan *zspan, DrawBufPixel *col, float *v1, float
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ 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;
@@ -3965,7 +3959,7 @@ static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf
float *fp, *col;
int a;
- fp= RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR);
+ fp = RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR, R.viewname);
if (fp==NULL) return;
col= rectf+3;
@@ -4058,9 +4052,10 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
/* zero alpha pixels get speed vector max again */
if (addpassflag & SCE_PASS_VECTOR)
- if (rl->layflag & SCE_LAY_SOLID)
- reset_sky_speedvectors(pa, rl, rl->acolrect?rl->acolrect:rl->rectf); /* if acolrect is set we use it */
-
+ if (rl->layflag & SCE_LAY_SOLID) {
+ float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+ reset_sky_speedvectors(pa, rl, rl->acolrect ? rl->acolrect : rect); /* if acolrect is set we use it */
+ }
/* filtered render, for now we assume only 1 filter size */
if (pa->crop) {
crop= 1;
@@ -4245,8 +4240,9 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
alpha= samp_shr[a].combined[3];
if (alpha!=0.0f) {
RenderLayer *rl= ssamp.rlpp[a];
-
- addAlphaOverFloat(rl->rectf + 4*od, samp_shr[a].combined);
+
+ float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+ addAlphaOverFloat(rect + 4 * od, samp_shr[a].combined);
add_transp_passes(rl, od, &samp_shr[a], alpha);
if (addpassflag & SCE_PASS_VECTOR)