diff options
Diffstat (limited to 'source/blender/render')
33 files changed, 707 insertions, 10213 deletions
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index 36e18da00c7..359369228f8 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -36,6 +36,7 @@ set(INC ../makesrna ../nodes ../physics + ../draw ../../../intern/atomic ../../../intern/guardedalloc ../../../intern/mikktspace @@ -47,43 +48,15 @@ set(INC_SYS ) set(SRC - intern/raytrace/rayobject.cpp - intern/raytrace/rayobject_empty.cpp - intern/raytrace/rayobject_octree.cpp - intern/raytrace/rayobject_raycounter.cpp - intern/raytrace/rayobject_svbvh.cpp - intern/raytrace/rayobject_instance.cpp - intern/raytrace/rayobject_qbvh.cpp - intern/raytrace/rayobject_rtbuild.cpp - intern/raytrace/rayobject_vbvh.cpp - intern/source/bake.c intern/source/bake_api.c - intern/source/convertblender.c - intern/source/envmap.c intern/source/external_engine.c intern/source/imagetexture.c intern/source/initrender.c intern/source/multires_bake.c - intern/source/occlusion.c intern/source/pipeline.c - intern/source/pixelblending.c - intern/source/pixelshading.c intern/source/pointdensity.c - intern/source/rayshade.c - intern/source/rendercore.c intern/source/render_result.c intern/source/render_texture.c - intern/source/renderdatabase.c - intern/source/shadbuf.c - intern/source/shadeinput.c - intern/source/shadeoutput.c - intern/source/sss.c - intern/source/strand.c - intern/source/sunsky.c - intern/source/texture_ocean.c - intern/source/volume_precache.c - intern/source/volumetric.c - intern/source/voxeldata.c intern/source/zbuf.c extern/include/RE_engine.h @@ -92,38 +65,12 @@ set(SRC extern/include/RE_pipeline.h extern/include/RE_render_ext.h extern/include/RE_shader_ext.h - intern/include/envmap.h intern/include/initrender.h - intern/include/occlusion.h - intern/include/pixelblending.h - intern/include/pixelshading.h - intern/include/pointdensity.h - intern/include/raycounter.h - intern/include/rayobject.h - intern/include/rayintersection.h intern/include/render_types.h intern/include/render_result.h - intern/include/rendercore.h - intern/include/renderdatabase.h intern/include/renderpipeline.h - intern/include/shadbuf.h - intern/include/shading.h - intern/include/sss.h - intern/include/strand.h - intern/include/sunsky.h intern/include/texture.h - intern/include/texture_ocean.h - intern/include/volume_precache.h - intern/include/volumetric.h - intern/include/voxeldata.h intern/include/zbuf.h - intern/raytrace/bvh.h - intern/raytrace/rayobject_hint.h - intern/raytrace/rayobject_internal.h - intern/raytrace/rayobject_rtbuild.h - intern/raytrace/reorganize.h - intern/raytrace/svbvh.h - intern/raytrace/vbvh.h ) if(WITH_PYTHON) @@ -148,10 +95,6 @@ if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) endif() -if(WITH_GAMEENGINE) - add_definitions(-DWITH_GAMEENGINE) -endif() - if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() diff --git a/source/blender/render/extern/include/RE_bake.h b/source/blender/render/extern/include/RE_bake.h index ad4d7485acc..e7f446f07a7 100644 --- a/source/blender/render/extern/include/RE_bake.h +++ b/source/blender/render/extern/include/RE_bake.h @@ -35,6 +35,7 @@ struct ImBuf; struct Render; struct Mesh; +struct Depsgraph; typedef struct BakeImage { struct Image *image; @@ -71,14 +72,11 @@ typedef struct BakeHighPolyData { bool RE_bake_has_engine(struct Render *re); bool RE_bake_engine( - struct Render *re, struct Object *object, const int object_id, const BakePixel pixel_array[], + struct Render *re, struct Depsgraph *depsgraph, struct Object *object, const int object_id, const BakePixel pixel_array[], const size_t num_pixels, const int depth, const eScenePassType pass_type, const int pass_filter, float result[]); /* bake.c */ int RE_pass_depth(const eScenePassType pass_type); -bool RE_bake_internal( - struct Render *re, struct Object *object, const BakePixel pixel_array[], - const size_t num_pixels, const int depth, const eScenePassType pass_type, float result[]); bool RE_bake_pixels_populate_from_objects( struct Mesh *me_low, BakePixel pixel_array_from[], BakePixel pixel_array_to[], diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index cb27ccdbecf..2de355b92a5 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -39,6 +39,10 @@ struct bNode; struct bNodeTree; +struct BakePixel; +struct Depsgraph; +struct IDProperty; +struct Main; struct Object; struct Render; struct RenderData; @@ -48,13 +52,13 @@ struct RenderLayer; struct RenderResult; struct ReportList; struct Scene; -struct BakePixel; +struct ViewLayer; /* External Engine */ /* RenderEngineType.flag */ #define RE_INTERNAL 1 -#define RE_GAME 2 +/* #define RE_FLAG_DEPRECATED 2 */ #define RE_USE_PREVIEW 4 #define RE_USE_POSTPROCESS 8 #define RE_USE_SHADING_NODES 16 @@ -88,15 +92,20 @@ typedef struct RenderEngineType { char name[64]; int flag; - 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 int pass_filter, const int object_id, const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result); + void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Depsgraph *depsgraph); + void (*render)(struct RenderEngine *engine, struct Depsgraph *depsgraph); + void (*bake)(struct RenderEngine *engine, struct Depsgraph *depsgraph, + struct Object *object, const int pass_type, + const int pass_filter, const int object_id, const struct BakePixel *pixel_array, const int num_pixels, + const int depth, void *result); void (*view_update)(struct RenderEngine *engine, const struct bContext *context); void (*view_draw)(struct RenderEngine *engine, const struct bContext *context); void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node); - void (*update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl); + void (*update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer); + + struct DrawEngineType *draw_engine; /* RNA integration */ ExtensionRNA ext; @@ -121,6 +130,9 @@ typedef struct RenderEngine { struct ReportList *reports; + /* Depsgraph */ + struct Depsgraph *depsgraph; + /* for blender internal only */ int update_flag; int job_update_flag; @@ -163,19 +175,23 @@ bool RE_engine_is_external(struct Render *re); void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe); -void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl, +void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer, const char *name, int channels, const char *chanid, int type); /* Engine Types */ void RE_engines_init(void); void RE_engines_exit(void); +void RE_engines_register(RenderEngineType *render_type); + +bool RE_engine_is_opengl(RenderEngineType *render_type); RenderEngineType *RE_engines_find(const char *idname); rcti* RE_engine_get_current_tiles(struct Render *re, int *r_total_tiles, bool *r_needs_free); struct RenderData *RE_engine_get_render_data(struct Render *re); -void RE_bake_engine_set_engine_parameters(struct Render *re, struct Main *bmain, struct Scene *scene); +void RE_bake_engine_set_engine_parameters( + struct Render *re, struct Main *bmain, struct Scene *scene); #endif /* __RE_ENGINE_H__ */ diff --git a/source/blender/render/extern/include/RE_multires_bake.h b/source/blender/render/extern/include/RE_multires_bake.h index d3c04b84981..25a87969b58 100644 --- a/source/blender/render/extern/include/RE_multires_bake.h +++ b/source/blender/render/extern/include/RE_multires_bake.h @@ -43,6 +43,12 @@ typedef struct MultiresBakeRender { short mode; bool use_lores_mesh; /* Use low-resolution mesh when baking displacement maps */ + /* material aligned image array (for per-face bake image) */ + struct { + Image **array; + int len; + } ob_image; + int number_of_rays; /* Number of rays to be cast when doing AO baking */ float bias; /* Bias between object and start ray point when doing AO baking */ diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 71988394881..55638471883 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -34,9 +34,11 @@ #include "DNA_listBase.h" #include "DNA_vec_types.h" +#include "DEG_depsgraph.h" struct bMovieHandle; struct bNodeTree; +struct Depsgraph; struct Image; struct ImageFormatData; struct Main; @@ -46,8 +48,7 @@ struct RenderData; struct RenderResult; struct ReportList; struct Scene; -struct SceneRenderLayer; -struct EnvMap; +struct ViewLayer; struct StampData; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -105,12 +106,8 @@ typedef struct RenderLayer { /* copy of RenderData */ char name[RE_MAXNAME]; - unsigned int lay, lay_zmask, lay_exclude; int layflag, passflag, pass_xor; - struct Material *mat_override; - struct Group *light_override; - /* MULTIVIEW_TODO: acolrect and scolrect are not supported by multiview at the moment. * If they are really required they should be in RenderView instead */ @@ -243,7 +240,7 @@ struct RenderPass *RE_create_gp_pass(struct RenderResult *rr, const char *layern /* obligatory initialize call, disprect is optional */ void RE_InitState(struct Render *re, struct Render *source, struct RenderData *rd, - struct SceneRenderLayer *srl, + struct ListBase *render_layers, struct ViewLayer *single_layer, int winx, int winy, rcti *disprect); void RE_ChangeResolution(struct Render *re, int winx, int winy, rcti *disprect); void RE_ChangeModeFlag(struct Render *re, int flag, bool clear); @@ -252,10 +249,8 @@ void RE_ChangeModeFlag(struct Render *re, int flag, bool clear); 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, const rctf *viewplane, float clipsta, float clipend); void RE_SetOrtho(struct Render *re, const rctf *viewplane, float clipsta, float clipend); -void RE_SetPixelSize(struct Render *re, float pixsize); /* option to set viewmatrix before making dbase */ void RE_SetView(struct Render *re, float mat[4][4]); @@ -265,23 +260,13 @@ void RE_GetView(struct Render *re, float mat[4][4]); void RE_GetViewPlane(struct Render *re, rctf *r_viewplane, rcti *r_disprect); /* make or free the dbase */ -void RE_Database_FromScene( +void RE_Database_CameraOnly( struct Render *re, struct Main *bmain, struct Scene *scene, unsigned int lay, int use_camera_view); -void RE_Database_Preprocess(struct Render *re); -void RE_Database_Free(struct Render *re); - -/* project dbase again, when viewplane/perspective changed */ -void RE_DataBase_ApplyWindow(struct Render *re); -/* rotate scene again, for incremental render */ -void RE_DataBase_IncrementalView(struct Render *re, float viewmat[4][4], int restore); /* set the render threads based on the commandline and autothreads setting */ 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( @@ -291,7 +276,7 @@ bool RE_WriteRenderViewsMovie( /* 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, + struct ViewLayer *single_layer, struct Object *camera_override, unsigned int lay_override, int frame, const bool write_still); void RE_BlenderAnim(struct Render *re, struct Main *bmain, struct Scene *scene, struct Object *camera_override, unsigned int lay_override, int sfra, int efra, int tfra); @@ -316,14 +301,6 @@ bool RE_WriteRenderResult( struct RenderResult *RE_MultilayerConvert( void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty); -extern const float default_envmap_layout[]; -bool RE_WriteEnvmapResult( - struct ReportList *reports, struct Scene *scene, struct EnvMap *env, - const char *relpath, const char imtype, float layout[12]); - -/* do a full sample buffer compo */ -void RE_MergeFullSample(struct Render *re, struct Main *bmain, struct Scene *sce, struct bNodeTree *ntree); - /* display and event callbacks */ void RE_display_init_cb (struct Render *re, void *handle, void (*f)(void *handle, RenderResult *rr)); void RE_display_clear_cb(struct Render *re, void *handle, void (*f)(void *handle, RenderResult *rr)); @@ -334,6 +311,11 @@ void RE_draw_lock_cb (struct Render *re, void *handle, void (*f)(void *handle, void RE_test_break_cb (struct Render *re, void *handle, int (*f)(void *handle)); void RE_current_scene_update_cb(struct Render *re, void *handle, void (*f)(void *handle, struct Scene *scene)); +void RE_gl_context_create(Render *re); +void RE_gl_context_destroy(Render *re); +void *RE_gl_context_get(Render *re); +void *RE_gwn_context_get(Render *re); + /* should move to kernel once... still unsure on how/where */ float RE_filter_value(int type, float x); @@ -346,43 +328,18 @@ struct RenderPass *RE_pass_find_by_name(volatile struct RenderLayer *rl, const c 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 +#define RE_BAKE_NORMALS 0 +#define RE_BAKE_DISPLACEMENT 1 #define RE_BAKE_AO 2 -#define RE_BAKE_NORMALS 3 -#define RE_BAKE_TEXTURE 4 -#define RE_BAKE_DISPLACEMENT 5 -#define RE_BAKE_SHADOW 6 -#define RE_BAKE_SPEC_COLOR 7 -#define RE_BAKE_SPEC_INTENSITY 8 -#define RE_BAKE_MIRROR_COLOR 9 -#define RE_BAKE_MIRROR_INTENSITY 10 -#define RE_BAKE_ALPHA 11 -#define RE_BAKE_EMIT 12 -#define RE_BAKE_DERIVATIVE 13 -#define RE_BAKE_VERTEX_COLORS 14 - -void RE_Database_Baking( - struct Render *re, struct Main *bmain, struct Scene *scene, - unsigned int lay, const int type, struct Object *actob); -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); -bool RE_is_rendering_allowed(struct Scene *scene, struct Object *camera_override, struct ReportList *reports); +bool RE_is_rendering_allowed(struct Scene *scene, struct ViewLayer *single_layer, struct Object *camera_override, struct ReportList *reports); bool RE_allow_render_generic_object(struct Object *ob); -/* RE_updateRenderInstances flag */ -enum { - RE_OBJECT_INSTANCES_UPDATE_VIEW = (1 << 0), - RE_OBJECT_INSTANCES_UPDATE_OBMAT = (1 << 1) -}; -void RE_updateRenderInstances(Render *re, int flag); - /******* defined in render_result.c *********/ bool RE_HasCombinedLayer(RenderResult *res); diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h index 6bd40746773..22a202ee675 100644 --- a/source/blender/render/extern/include/RE_render_ext.h +++ b/source/blender/render/extern/include/RE_render_ext.h @@ -38,9 +38,12 @@ /* called by meshtools */ struct DerivedMesh; +struct Depsgraph; struct ImagePool; struct MTex; struct Scene; +struct ViewLayer; +struct Render; /* render_texture.c */ /* used by particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */ @@ -53,12 +56,6 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen void RE_texture_rng_init(void); void RE_texture_rng_exit(void); -struct Material *RE_sample_material_init(struct Material *orig_mat, struct Scene *scene); -void RE_sample_material_free(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 tri_index, struct DerivedMesh *orcoDm, struct Object *ob); - /* imagetexture.c */ void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4]); @@ -66,23 +63,22 @@ void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, flo struct PointDensity; void RE_point_density_cache( - struct Scene *scene, - struct PointDensity *pd, - const bool use_render_params); + struct Depsgraph *depsgraph, + struct PointDensity *pd); void RE_point_density_minmax( - struct Scene *scene, + struct Depsgraph *depsgraph, struct PointDensity *pd, - const bool use_render_params, float r_min[3], float r_max[3]); void RE_point_density_sample( - struct Scene *scene, + struct Depsgraph *depsgraph, struct PointDensity *pd, const int resolution, - const bool use_render_params, float *values); void RE_point_density_free(struct PointDensity *pd); +void RE_point_density_fix_linking(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 838f7031d14..52d4961352d 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -33,7 +33,7 @@ #define __RE_SHADER_EXT_H__ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* this include is for shading and texture exports */ +/* this include is for texture exports */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* localized texture result data */ @@ -44,150 +44,6 @@ typedef struct TexResult { float *nor; } TexResult; -/* localized shade result data */ -typedef struct ShadeResult { - float combined[4]; - float col[4]; - float alpha, mist, z; - float emit[3]; - float diff[3]; /* diffuse with no ramps, shadow, etc */ - float diffshad[3]; /* diffuse with shadow */ - float spec[3]; /* specular with shadow */ - float shad[4]; /* shad[3] is shadow intensity */ - float ao[3]; - float env[3]; - float indirect[3]; - float refl[3]; - float refr[3]; - float nor[3]; - float winspeed[4]; - float rayhits[4]; -} ShadeResult; - -/* only here for quick copy */ -struct ShadeInputCopy { - - struct Material *mat; - struct VlakRen *vlr; - struct StrandRen *strand; - struct ObjectInstanceRen *obi; - struct ObjectRen *obr; - int facenr; - float facenor[3]; /* copy from face */ - short flippednor; /* is facenor flipped? */ - struct VertRen *v1, *v2, *v3; /* vertices can be in any order for quads... */ - short i1, i2, i3; /* original vertex indices */ - short puno; - short osatex; - float vn[3], vno[3]; /* actual render normal, and a copy to restore it */ - float n1[3], n2[3], n3[3]; /* vertex normals, corrected */ - int mode, mode2; /* base material mode (OR-ed result of entire node tree) */ -}; - -typedef struct ShadeInputUV { - float dxuv[3], dyuv[3], uv[3]; - const char *name; -} ShadeInputUV; - -typedef struct ShadeInputCol { - float col[4]; - const char *name; -} ShadeInputCol; - -/* localized renderloop data */ -typedef struct ShadeInput { - /* copy from face, also to extract tria from quad */ - /* note it mirrors a struct above for quick copy */ - - struct Material *mat; - struct VlakRen *vlr; - struct StrandRen *strand; - struct ObjectInstanceRen *obi; - struct ObjectRen *obr; - int facenr; - float facenor[3]; /* copy from face */ - short flippednor; /* is facenor flipped? */ - struct VertRen *v1, *v2, *v3; /* vertices can be in any order for quads... */ - short i1, i2, i3; /* original vertex indices */ - short puno; - short osatex; - float vn[3], vno[3]; /* actual render normal, and a copy to restore it */ - float n1[3], n2[3], n3[3]; /* vertex normals, corrected */ - int mode, mode2; /* base material mode (OR-ed result of entire node tree) */ - - /* internal face coordinates */ - float u, v, dx_u, dx_v, dy_u, dy_v; - float co[3], view[3], camera_co[3]; - - /* copy from material, keep synced so we can do memcopy */ - /* current size: 23*4 */ - float r, g, b; - float specr, specg, specb; - float mirr, mirg, mirb; - float ambr, ambb, ambg; - - float amb, emit, ang, spectra, ray_mirror; - float alpha, refl, spec, zoffs, add; - float translucency; - /* end direct copy from material */ - - /* individual copies: */ - int har; /* hardness */ - - /* texture coordinates */ - float lo[3], gl[3], ref[3], orn[3], winco[3], vcol[4]; - float refcol[4], displace[3]; - float strandco, tang[3], nmapnorm[3], nmaptang[4], stress, winspeed[4]; - float duplilo[3], dupliuv[3]; - float tangents[8][4]; /* 8 = MAX_MTFACE */ - - ShadeInputUV uv[8]; /* 8 = MAX_MTFACE */ - ShadeInputCol col[8]; /* 8 = MAX_MCOL */ - int totuv, totcol, actuv, actcol; - - /* dx/dy OSA coordinates */ - float dxco[3], dyco[3]; - float dxlo[3], dylo[3], dxgl[3], dygl[3]; - float dxref[3], dyref[3], dxorn[3], dyorn[3]; - float dxno[3], dyno[3], dxview, dyview; - float dxlv[3], dylv[3]; - float dxwin[3], dywin[3]; - float dxrefract[3], dyrefract[3]; - float dxstrand, dystrand; - - /* AO is a pre-process now */ - float ao[3], indirect[3], env[3]; - - int xs, ys; /* pixel to be rendered */ - int mask; /* subsample mask */ - float scanco[3]; /* original scanline coordinate without jitter */ - - int samplenr; /* sample counter, to detect if we should do shadow again */ - int depth; /* 1 or larger on raytrace shading */ - int volume_depth; /* number of intersections through volumes */ - - /* for strand shading, normal at the surface */ - float surfnor[3], surfdist; - - /* from initialize, part or renderlayer */ - bool do_preview; /* for nodes, in previewrender */ - bool do_manage; /* color management flag */ - bool use_world_space_shading; - short thread, sample; /* sample: ShadeSample array index */ - short nodes; /* indicate node shading, temp hack to prevent recursion */ - - unsigned int lay; - int layflag, passflag, combinedflag; - short object_pass_index; - struct Group *light_override; - struct Material *mat_override; - -#ifdef RE_RAYCOUNTER - RayCounter raycounter; -#endif - -} ShadeInput; - typedef struct BakeImBufuserData { float *displacement_buffer; char *mask_buffer; @@ -214,46 +70,6 @@ int multitex_ext(struct Tex *tex, 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 *random, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]); - -float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta); - -/* shaded view and bake */ -struct Render; -struct Image; - -int RE_bake_shade_all_selected(struct Render *re, int type, struct Object *actob, short *do_update, float *progress); -struct Image *RE_bake_shade_get_image(void); -void RE_bake_ibuf_filter(struct ImBuf *ibuf, char *mask, const int filter); -void RE_bake_ibuf_normalize_displacement(struct ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max); -float RE_bake_make_derivative(struct ImBuf *ibuf, float *heights_buffer, const char *mask, - const float height_min, const float height_max, - const float fmult); - -enum { - RE_OBJECT_INSTANCE_MATRIX_OB, - RE_OBJECT_INSTANCE_MATRIX_OBINV, - RE_OBJECT_INSTANCE_MATRIX_LOCALTOVIEW, - RE_OBJECT_INSTANCE_MATRIX_LOCALTOVIEWINV, -}; - -const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4]; - -float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi); -float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi); - -enum { - RE_VIEW_MATRIX, - RE_VIEWINV_MATRIX, -}; - -const float (*RE_render_current_get_matrix(int matrix_id))[4]; - -#define BAKE_RESULT_OK 0 -#define BAKE_RESULT_NO_OBJECTS 1 -#define BAKE_RESULT_FEEDBACK_LOOP 2 + const short thread, short which_output, struct MTex *mtex, struct ImagePool *pool); #endif /* __RE_SHADER_EXT_H__ */ diff --git a/source/blender/render/intern/include/initrender.h b/source/blender/render/intern/include/initrender.h index 0f952baf257..b8732e7cc5c 100644 --- a/source/blender/render/intern/include/initrender.h +++ b/source/blender/render/intern/include/initrender.h @@ -33,16 +33,11 @@ #ifndef __INITRENDER_H__ #define __INITRENDER_H__ - /* Functions */ -void free_sample_tables(Render *re); -void make_sample_tables(Render *re); - -void RE_parts_init(Render *re, bool do_crop); +void RE_parts_init(Render *re); void RE_parts_free(Render *re); void RE_parts_clamp(Render *re); - #endif /* __INITRENDER_H__ */ diff --git a/source/blender/render/intern/include/occlusion.h b/source/blender/render/intern/include/occlusion.h deleted file mode 100644 index 4a70d691436..00000000000 --- a/source/blender/render/intern/include/occlusion.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Brecht Van Lommel. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/occlusion.h - * \ingroup render - */ - - -#ifndef __OCCLUSION_H__ -#define __OCCLUSION_H__ - -struct Render; -struct ShadeInput; -struct RenderPart; -struct ShadeSample; - -void make_occ_tree(struct Render *re); -void free_occ(struct Render *re); -void sample_occ(struct Render *re, struct ShadeInput *shi); - -void cache_occ_samples(struct Render *re, struct RenderPart *pa, struct ShadeSample *ssamp); -void free_occ_samples(struct Render *re, struct RenderPart *pa); - -#endif - diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h deleted file mode 100644 index 4042d183e5f..00000000000 --- a/source/blender/render/intern/include/rayobject.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/rayobject.h - * \ingroup render - */ - - -#ifndef __RAYOBJECT_H__ -#define __RAYOBJECT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -struct Isect; -struct ObjectInstanceRen; -struct RayHint; -struct VlakRen; - -/* RayObject - * Can be a face/triangle, bvh tree, object instance, etc. This is the - * public API used by the renderer, see rayobject_internal.h for the - * internal implementation details. - * */ -typedef struct RayObject RayObject; - -/* Intersection, see rayintersection.h */ - -int RE_rayobject_raycast(RayObject *r, struct Isect *i); - -/* Acceleration Structures */ - -RayObject *RE_rayobject_octree_create(int ocres, int size); -RayObject *RE_rayobject_instance_create(RayObject *target, float transform[4][4], void *ob, void *target_ob); -RayObject *RE_rayobject_empty_create(void); - -RayObject *RE_rayobject_vbvh_create(int size); /* raytrace/rayobject_vbvh.c */ -RayObject *RE_rayobject_svbvh_create(int size); /* raytrace/rayobject_svbvh.c */ -RayObject *RE_rayobject_qbvh_create(int size); /* raytrace/rayobject_qbvh.c */ - -/* Building */ - -void RE_rayobject_add(RayObject *r, RayObject *); -void RE_rayobject_done(RayObject *r); -void RE_rayobject_free(RayObject *r); - -void RE_rayobject_set_control(RayObject *r, void *data, int (*test_break)(void *data)); - -/* RayObject representing faces, all data is locally available instead - * of referring to some external data structure, for possibly faster - * intersection tests. */ - -typedef struct RayFace { - float v1[4], v2[4], v3[4], v4[3]; - int quad; - void *ob; - void *face; -} RayFace; - -#define RE_rayface_isQuad(a) ((a)->quad) - -RayObject *RE_rayface_from_vlak(RayFace *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr); - -RayObject *RE_rayface_from_coords(RayFace *rayface, void *ob, void *face, float *v1, float *v2, float *v3, float *v4); - -/* RayObject representing faces directly from a given VlakRen structure. Thus - * allowing to save memory, but making code triangle intersection dependent on - * render structures. */ - -typedef struct VlakPrimitive { - struct ObjectInstanceRen *ob; - struct VlakRen *face; -} VlakPrimitive; - -RayObject *RE_vlakprimitive_from_vlak(VlakPrimitive *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr); - -/* Bounding Box */ - -/* extend min/max coords so that the rayobject is inside them */ -void RE_rayobject_merge_bb(RayObject *ob, float *min, float *max); - -/* initializes an hint for optimizing raycast where it is know that a ray will pass by the given BB often the origin point */ -void RE_rayobject_hint_bb(RayObject *r, struct RayHint *hint, float min[3], float max[3]); - -/* initializes an hint for optimizing raycast where it is know that a ray will be contained inside the given cone*/ -/* void RE_rayobject_hint_cone(RayObject *r, struct RayHint *hint, float *); */ - -/* Internals */ - -#include "../raytrace/rayobject_internal.h" - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h index 7757e395af4..eebecc53101 100644 --- a/source/blender/render/intern/include/render_result.h +++ b/source/blender/render/intern/include/render_result.h @@ -55,8 +55,6 @@ struct ColorManagedViewSettings; struct RenderResult *render_result_new(struct Render *re, 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, const char *viewname); struct RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty); @@ -117,5 +115,28 @@ void render_result_views_shallowcopy(struct RenderResult *dst, struct RenderResu void render_result_views_shallowdelete(struct RenderResult *rr); bool render_result_has_views(struct RenderResult *rr); +#define FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re_, iter_) \ +{ \ + int nr_; \ + ViewLayer *iter_; \ + for (nr_ = 0, iter_ = (re_)->view_layers.first; \ + iter_ != NULL; \ + iter_ = iter_->next, nr_++) \ + { \ + if ((re_)->r.scemode & R_SINGLE_LAYER) { \ + if (nr_ != re->active_view_layer) { \ + continue; \ + } \ + } \ + else { \ + if ((iter_->flag & VIEW_LAYER_RENDER) == 0) { \ + continue; \ + } \ + } + +#define FOREACH_VIEW_LAYER_TO_RENDER_END \ + } \ +} ((void)0) + #endif /* __RENDER_RESULT_H__ */ diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 4753d65597a..34535fba1e0 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -35,58 +35,19 @@ /* exposed internal in render module only! */ /* ------------------------------------------------------------------------- */ -#include "DNA_color_types.h" -#include "DNA_customdata_types.h" #include "DNA_scene_types.h" -#include "DNA_world_types.h" #include "DNA_object_types.h" -#include "DNA_vec_types.h" #include "BLI_threads.h" #include "BKE_main.h" #include "RE_pipeline.h" -#include "RE_shader_ext.h" /* TexResult, ShadeResult, ShadeInput */ -#include "sunsky.h" -#include "BLI_sys_types.h" // for intptr_t support - -struct EvaluationContext; struct Object; -struct MemArena; -struct VertTableNode; -struct VlakTableNode; -struct GHash; -struct ObjectInstanceRen; -struct RayObject; -struct RayFace; struct RenderEngine; struct ReportList; struct Main; -struct ImagePool; - -#define TABLEINITSIZE 1024 - -typedef struct SampleTables { - float centLut[16]; - float *fmask1[9], *fmask2[9]; - char cmask[256], *centmask; - -} SampleTables; - -typedef struct QMCSampler { - struct QMCSampler *next, *prev; - int type; - int tot; - int used; - double *samp2d; - double offs[BLENDER_MAX_THREADS][2]; -} QMCSampler; - -// #define SAMP_TYPE_JITTERED 0 // UNUSED -#define SAMP_TYPE_HALTON 1 -#define SAMP_TYPE_HAMMERSLEY 2 /* this is handed over to threaded hiding/passes/shading engine */ typedef struct RenderPart { @@ -95,24 +56,10 @@ typedef struct RenderPart { RenderResult *result; /* result of part rendering */ ListBase fullresult; /* optional full sample buffers */ - int *recto; /* object table for objects */ - int *rectp; /* polygon index table */ - int *rectz; /* zbuffer */ - int *rectmask; /* negative zmask */ - intptr_t *rectdaps; /* delta acum buffer for pixel structs */ - int *rectbacko; /* object table for backside sss */ - int *rectbackp; /* polygon index table for backside sss */ - int *rectbackz; /* zbuffer for backside sss */ - intptr_t *rectall; /* buffer for all faces for sss */ - rcti disprect; /* part coordinates within total picture */ int rectx, recty; /* the size */ int nr; /* nr is partnr */ - short crop, status; /* crop is amount of pixels we crop, for filter */ - short sample; /* sample can be used by zbuffers */ - short thread; /* thread id */ - - char *clipflag; /* clipflags for part zbuffering */ + short status; } RenderPart; enum { @@ -129,10 +76,7 @@ struct Render { int slot; /* state settings */ - short flag, osa, ok, result_ok; - - /* due to performance issues, getting initialized from color management settings once on Render initialization */ - bool scene_color_manage; + short flag, ok, result_ok; /* result of rendering */ RenderResult *result; @@ -150,8 +94,6 @@ struct Render { * without border & crop. convert to long before multiplying together to avoid overflow. */ rcti disprect; /* part within winx winy */ rctf viewplane; /* mapped on winx winy */ - float viewdx, viewdy; /* size of 1 pixel */ - float clipcrop; /* 2 pixel boundary to prevent clip when filter used */ /* final picture width and height (within disprect) */ int rectx, recty; @@ -160,14 +102,7 @@ struct Render { * partx*xparts can be larger than rectx, in that case last part is smaller */ int partx, party; - /* values for viewing */ - float ycor; /* (scene->xasp / scene->yasp), multiplied with 'winy' */ - - float panophi, panosi, panoco, panodxp, panodxv; - - /* Matrices */ - float grvec[3]; /* for world */ - float imat[3][3]; /* copy of viewinv */ + /* Camera transform, only used by Freestyle. */ float viewmat[4][4], viewinv[4][4]; float viewmat_orig[4][4]; /* for incremental render */ float winmat[4][4]; @@ -176,21 +111,12 @@ struct Render { float clipsta; float clipend; - /* samples */ - SampleTables *samples; - float jit[32][2]; - float mblur_jit[32][2]; - ListBase *qmcsamplers; - int num_qmc_samplers; - - /* shadow counter, detect shadow-reuse for shaders */ - int shadowsamplenr[BLENDER_MAX_THREADS]; - /* main, scene, and its full copy of renderdata and world */ struct Main *main; Scene *scene; RenderData r; - World wrld; + ListBase view_layers; + int active_view_layer; struct Object *camera_override; unsigned int lay, layer_override; @@ -200,56 +126,11 @@ struct Render { /* render engine */ struct RenderEngine *engine; - /* octree tables and variables for raytrace */ - struct RayObject *raytree; - struct RayFace *rayfaces; - struct VlakPrimitive *rayprimitives; - float maxdist; /* needed for keeping an incorrect behavior of SUN and HEMI lights (avoid breaking old scenes) */ - - /* occlusion tree */ - void *occlusiontree; - ListBase strandsurface; - - /* use this instead of R.r.cfra */ - float mblur_offs, field_offs; - - /* render database */ - int totvlak, totvert, tothalo, totstrand, totlamp; - struct HaloRen **sortedhalos; - - ListBase lights; /* GroupObject pointers */ - ListBase lampren; /* storage, for free */ - - ListBase objecttable; - - struct ObjectInstanceRen *objectinstance; - ListBase instancetable; - int totinstance; - - struct Image *bakebuf; - - struct GHash *orco_hash; - - struct GHash *sss_hash; - ListBase *sss_points; - struct Material *sss_mat; - - ListBase customdata_names; - - struct Object *excludeob; - ListBase render_volumes_inside; - ListBase volumes; - #ifdef WITH_FREESTYLE struct Main *freestyle_bmain; ListBase freestyle_renders; #endif - /* arena for allocating data for use during render, for - * example dynamic TFaces to go in the VlakRen structure. - */ - struct MemArena *memArena; - /* callbacks */ void (*display_init)(void *handle, RenderResult *rr); void *dih; @@ -274,415 +155,18 @@ struct Render { struct ReportList *reports; - struct ImagePool *pool; - struct EvaluationContext *eval_ctx; - void **movie_ctx_arr; char viewname[MAX_NAME]; -}; - -/* ------------------------------------------------------------------------- */ - -struct ISBData; - -typedef struct DeepSample { - int z; - float v; -} DeepSample; - -typedef struct ShadSampleBuf { - struct ShadSampleBuf *next, *prev; - intptr_t *zbuf; - char *cbuf; - DeepSample **deepbuf; - int *totbuf; -} ShadSampleBuf; - -typedef struct ShadBuf { - /* regular shadowbuffer */ - short samp, shadhalostep, totbuf; - float persmat[4][4]; - float viewmat[4][4]; - float winmat[4][4]; - float *jit, *weight; - float d, clipend, pixsize, soft, compressthresh; - int co[3]; - int size, bias; - ListBase buffers; - - /* irregular shadowbufer, result stored per thread */ - struct ISBData *isb_result[BLENDER_MAX_THREADS]; -} ShadBuf; - -/* ------------------------------------------------------------------------- */ - -typedef struct ObjectRen { - struct ObjectRen *next, *prev; - struct Object *ob, *par; - struct Scene *sce; - int index, psysindex, flag, lay; - - float boundbox[2][3]; - - int totvert, totvlak, totstrand, tothalo; - int vertnodeslen, vlaknodeslen, strandnodeslen, blohalen; - struct VertTableNode *vertnodes; - struct VlakTableNode *vlaknodes; - struct StrandTableNode *strandnodes; - struct HaloRen **bloha; - struct StrandBuffer *strandbuf; - - char (*mtface)[MAX_CUSTOMDATA_LAYER_NAME]; - char (*mcol)[MAX_CUSTOMDATA_LAYER_NAME]; - int actmtface, actmcol, bakemtface; - - short tangent_mask; /* which tangent layer should be calculated */ - - float obmat[4][4]; /* only used in convertblender.c, for instancing */ - - /* used on makeraytree */ - struct RayObject *raytree; - struct RayFace *rayfaces; - struct VlakPrimitive *rayprimitives; - struct ObjectInstanceRen *rayobi; - -} ObjectRen; - -typedef struct ObjectInstanceRen { - struct ObjectInstanceRen *next, *prev; - - ObjectRen *obr; - Object *ob, *par; - int index, psysindex, lay; - - float mat[4][4], imat[4][4]; - float nmat[3][3]; /* nmat is inverse mat tranposed */ - - float obmat[4][4], obinvmat[4][4]; - float localtoviewmat[4][4], localtoviewinvmat[4][4]; - - short flag; - float dupliorco[3], dupliuv[2]; - float (*duplitexmat)[4]; - - struct VolumePrecache *volume_precache; - - float *vectors; /* (RE_WINSPEED_ELEMS * VertRen.index) */ - int totvector; - - /* used on makeraytree */ - 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]; - - unsigned int random_id; -} ObjectInstanceRen; - -/* ------------------------------------------------------------------------- */ - -typedef struct VertRen { - float co[3]; - float n[3]; - float *orco; - unsigned int flag; /* in use for clipping zbuffer parts, temp setting stuff in convertblender.c - * only an 'int' because of alignment, could be a char too */ - float accum; /* accum for radio weighting, and for strand texco static particles */ - int index; /* index allows extending vertren with any property */ -} VertRen; - -/* ------------------------------------------------------------------------- */ - -struct halosort { - struct HaloRen *har; - int z; + /* TODO replace by a whole draw manager. */ + void *gl_context; + void *gwn_context; }; -/* ------------------------------------------------------------------------- */ -struct Material; -struct ImagePool; - -typedef struct RadFace { - float unshot[3], totrad[3]; - float norm[3], cent[3], area; - int flag; -} RadFace; - -typedef struct VlakRen { - struct VertRen *v1, *v2, *v3, *v4; /* keep in order for ** addressing */ - float n[3]; - struct Material *mat; - char puno; - char flag, ec; -#ifdef WITH_FREESTYLE - char freestyle_edge_mark; - char freestyle_face_mark; -#endif - int index; -} VlakRen; - -typedef struct HaloRen { - short miny, maxy; - float alfa, xs, ys, rad, radsq, sin, cos, co[3], no[3]; - float hard, b, g, r; - int zs, zd; - int zBufDist; /* depth in the z-buffer coordinate system */ - char starpoints, type, add, tex; - char linec, ringc, seed; - short flarec; /* used to be a char. why ?*/ - float hasize; - int pixels; - unsigned int lay; - struct Material *mat; - struct ImagePool *pool; - bool skip_load_image, texnode_preview; -} HaloRen; - -/* ------------------------------------------------------------------------- */ - -typedef struct StrandVert { - float co[3]; - float strandco; -} StrandVert; - -typedef struct StrandSurface { - struct StrandSurface *next, *prev; - ObjectRen obr; - int (*face)[4]; - float (*co)[3]; - /* for occlusion caching */ - float (*ao)[3]; - float (*env)[3]; - float (*indirect)[3]; - /* for speedvectors */ - float (*prevco)[3], (*nextco)[3]; - int totvert, totface; -} StrandSurface; - -typedef struct StrandBound { - int start, end; - float boundbox[2][3]; -} StrandBound; - -typedef struct StrandBuffer { - struct StrandBuffer *next, *prev; - struct StrandVert *vert; - struct StrandBound *bound; - int totvert, totbound; - - struct ObjectRen *obr; - struct Material *ma; - struct StrandSurface *surface; - unsigned int lay; - int overrideuv; - int flag, maxdepth; - float adaptcos, minwidth, widthfade; - - float maxwidth; /* for cliptest of strands in blender unit */ - - float winmat[4][4]; - int winx, winy; -} StrandBuffer; - -typedef struct StrandRen { - StrandVert *vert; - StrandBuffer *buffer; - int totvert, flag; - int clip, index; - float orco[3]; -} StrandRen; - -/* ------------------------------------------------------------------------- */ - -typedef struct VolumeOb { - struct VolumeOb *next, *prev; - struct Material *ma; - struct ObjectRen *obr; -} VolumeOb; - -typedef struct MatInside { - struct MatInside *next, *prev; - struct Material *ma; - struct ObjectInstanceRen *obi; -} MatInside; - -typedef struct VolPrecachePart { - struct VolPrecachePart *next, *prev; - struct RayObject *tree; - struct ShadeInput *shi; - struct ObjectInstanceRen *obi; - float viewmat[4][4]; - int num; - int minx, maxx; - int miny, maxy; - int minz, maxz; - int res[3]; - float bbmin[3]; - float voxel[3]; - struct Render *re; -} VolPrecachePart; - -typedef struct VolumePrecache { - int res[3]; - float *bbmin, *bbmax; - float *data_r; - float *data_g; - float *data_b; -} VolumePrecache; - -/* ------------------------------------------------------------------------- */ - -struct LampRen; -struct MTex; - -/** - * For each lamp in a scene, a LampRen is created. It determines the - * properties of a lightsource. - */ - -typedef struct LampShadowSubSample { - int samplenr; - float shadfac[4]; /* rgba shadow */ -} LampShadowSubSample; - -typedef struct LampShadowSample { - LampShadowSubSample s[16]; /* MAX OSA */ -} LampShadowSample; - -typedef struct LampRen { - struct LampRen *next, *prev; - - float xs, ys, dist; - float co[3]; - short type; - int mode; - float r, g, b, k; - float shdwr, shdwg, shdwb; - float energy, haint; - int lay; - float spotsi, spotbl; - float vec[3]; - float xsp, ysp, distkw, inpr; - float halokw, halo; - - short falloff_type; - float ld1, ld2; - float coeff_const, coeff_lin, coeff_quad; - struct CurveMapping *curfalloff; - - /* copied from Lamp, to decouple more rendering stuff */ - /** Size of the shadowbuffer */ - short bufsize; - /** Number of samples for the shadows */ - short samp; - /** Softness factor for shadow */ - float soft; - /** amount of subsample buffers and type of filter for sampling */ - short buffers, filtertype; - /** shadow buffer type (regular, irregular) */ - short buftype; - /** autoclip */ - short bufflag; - /** shadow plus halo: detail level */ - short shadhalostep; - /** Near clip of the lamp */ - float clipsta; - /** Far clip of the lamp */ - float clipend; - /** A small depth offset to prevent self-shadowing. */ - float bias; - /* Compression threshold for deep shadow maps */ - float compressthresh; - - short ray_samp, ray_sampy, ray_sampz, ray_samp_method, ray_samp_type, area_shape, ray_totsamp; - short xold[BLENDER_MAX_THREADS], yold[BLENDER_MAX_THREADS]; /* last jitter table for area lights */ - float area_size, area_sizey, area_sizez; - float adapt_thresh; - - /* sun/sky */ - struct SunSky *sunsky; - - struct ShadBuf *shb; - float *jitter; - - float imat[3][3]; - float spottexfac; - float sh_invcampos[3], sh_zfac; /* sh_= spothalo */ - - float lampmat[4][4]; /* worls space lamp matrix, used for scene rotation */ - - float mat[3][3]; /* 3x3 part from lampmat x viewmat */ - float area[8][3], areasize; - - /* passes & node shader support: all shadow info for a pixel */ - LampShadowSample *shadsamp; - - /* ray optim */ - struct RayObject *last_hit[BLENDER_MAX_THREADS]; - - struct MTex *mtex[MAX_MTEX]; - - /* threading */ - int thread_assigned; - int thread_ready; -} LampRen; - /* **************** defines ********************* */ -/* R.r.mode flag is same as for renderdata */ - /* R.flag */ -#define R_ZTRA 1 -#define R_HALO 2 -#define R_SEC_FIELD 4 -#define R_LAMPHALO 8 -#define R_NEED_TANGENT 16 -#define R_BAKE_TRACE 32 -#define R_BAKING 64 -#define R_ANIMATION 128 -#define R_NEED_VCOL 256 - -/* vlakren->flag (vlak = face in dutch) char!!! */ -#define R_SMOOTH 1 -#define R_HIDDEN 2 -/* strand flag, means special handling */ -#define R_STRAND 4 -#define R_FULL_OSA 8 -#define R_FACE_SPLIT 16 -/* Tells render to divide face other way. */ -#define R_DIVIDE_24 32 -/* vertex normals are tangent or view-corrected vector, for hair strands */ -#define R_TANGENT 64 -#define R_TRACEBLE 128 - -/* vlakren->freestyle_edge_mark */ -#ifdef WITH_FREESTYLE -# define R_EDGE_V1V2 1 -# define R_EDGE_V2V3 2 -# define R_EDGE_V3V4 4 -# define R_EDGE_V3V1 4 -# define R_EDGE_V4V1 8 -#endif - -/* strandbuffer->flag */ -#define R_STRAND_BSPLINE 1 -#define R_STRAND_B_UNITS 2 - -/* objectren->flag */ -#define R_INSTANCEABLE 1 - -/* objectinstance->flag */ -#define R_DUPLI_TRANSFORMED 1 -#define R_ENV_TRANSFORMED 2 -#define R_TRANSFORMED (1|2) +#define R_ANIMATION 1 #endif /* __RENDER_TYPES_H__ */ diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h deleted file mode 100644 index d0b0d695224..00000000000 --- a/source/blender/render/intern/include/renderdatabase.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2006 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/renderdatabase.h - * \ingroup render - */ - - -#ifndef __RENDERDATABASE_H__ -#define __RENDERDATABASE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -struct Object; -struct VlakRen; -struct VertRen; -struct HaloRen; -struct Main; -struct Material; -struct Render; -struct MCol; -struct MTFace; -struct CustomData; -struct StrandBuffer; -struct StrandRen; -struct ObjectInstanceRen; -struct RadFace; -struct Isect; - -#define RE_QUAD_MASK 0x7FFFFFF -#define RE_QUAD_OFFS 0x8000000 - -/* render allocates totvert/256 of these nodes, for lookup and quick alloc */ -typedef struct VertTableNode { - struct VertRen *vert; - float *rad; - float *strand; - float *tangent; - float *stress; - float *winspeed; - /* Index of vertex in source mesh (before modifiers). */ - int *origindex; -} VertTableNode; - -typedef struct VlakTableNode { - struct VlakRen *vlak; - struct MTFace *mtface; - struct MCol *mcol; - /* Index of mpoly in source mesh (before tessellation). */ - int *origindex; - int totmtface, totmcol; - float *surfnor; - float *tangent_arrays[MAX_MTFACE]; - struct RadFace **radface; -} VlakTableNode; - -typedef struct StrandTableNode { - struct StrandRen *strand; - float *winspeed; - float *surfnor; - float *simplify; - int *face; - struct MCol *mcol; - float *uv; - int totuv, totmcol; -} StrandTableNode; - -/* renderdatabase.c */ -void free_renderdata_tables(struct Render *re); -void free_renderdata_vertnodes(struct VertTableNode *vertnodes); -void free_renderdata_vlaknodes(struct VlakTableNode *vlaknodes); - -void project_renderdata(struct Render *re, void (*projectfunc)(const float *, float mat[4][4], float *), bool do_pano, float xoffs, bool do_buckets); -int clip_render_object(float boundbox[2][3], float bounds[4], float mat[4][4]); - -/* functions are not exported... so wrong names */ - -struct VlakRen *RE_findOrAddVlak(struct ObjectRen *obr, int nr); -struct VertRen *RE_findOrAddVert(struct ObjectRen *obr, int nr); -struct StrandRen *RE_findOrAddStrand(struct ObjectRen *obr, int nr); -struct HaloRen *RE_findOrAddHalo(struct ObjectRen *obr, int nr); -struct HaloRen *RE_inithalo(struct Render *re, struct ObjectRen *obr, struct Material *ma, - const float vec[3], const float vec1[3], - const float *orco, float hasize, float vectsize, int seed); -struct HaloRen *RE_inithalo_particle(struct Render *re, struct ObjectRen *obr, struct DerivedMesh *dm, struct Material *ma, - 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]); -struct StrandBuffer *RE_addStrandBuffer(struct ObjectRen *obr, int totvert); - -struct ObjectRen *RE_addRenderObject(struct Render *re, struct Object *ob, struct Object *par, int index, int psysindex, int lay); -struct ObjectInstanceRen *RE_addRenderInstance( - struct Render *re, struct ObjectRen *obr, struct Object *ob, struct Object *par, - int index, int psysindex, float mat[4][4], int lay, const struct DupliObject *dob); -void RE_makeRenderInstances(struct Render *re); -void RE_updateRenderInstance(Render *re, ObjectInstanceRen *obi, int flag); - -void RE_instance_rotate_ray_start(struct ObjectInstanceRen *obi, struct Isect *is); -void RE_instance_rotate_ray_dir(struct ObjectInstanceRen *obi, struct Isect *is); -void RE_instance_rotate_ray(struct ObjectInstanceRen *obi, struct Isect *is); -void RE_instance_rotate_ray_restore(struct ObjectInstanceRen *obi, struct Isect *is); - -float *RE_vertren_get_stress(struct ObjectRen *obr, struct VertRen *ver, int verify); -float *RE_vertren_get_rad(struct ObjectRen *obr, struct VertRen *ver, int verify); -float *RE_vertren_get_strand(struct ObjectRen *obr, struct VertRen *ver, int verify); -float *RE_vertren_get_tangent(struct ObjectRen *obr, struct VertRen *ver, int verify); -float *RE_vertren_get_winspeed(struct ObjectInstanceRen *obi, struct VertRen *ver, int verify); -int *RE_vertren_get_origindex(struct ObjectRen *obr, VertRen *ver, int verify); - -struct MTFace *RE_vlakren_get_tface(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify); -struct MCol *RE_vlakren_get_mcol(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify); -int *RE_vlakren_get_origindex(struct ObjectRen *obr, VlakRen *vlak, int verify); -float *RE_vlakren_get_surfnor(struct ObjectRen *obr, VlakRen *ren, int verify); -float *RE_vlakren_get_nmap_tangent(ObjectRen *obr, VlakRen *vlak, int index, bool verify); -RadFace **RE_vlakren_get_radface(struct ObjectRen *obr, VlakRen *ren, int verify); -void RE_vlakren_get_normal(struct Render *re, struct ObjectInstanceRen *obi, struct VlakRen *vlr, float *nor); - -float *RE_strandren_get_surfnor(struct ObjectRen *obr, struct StrandRen *strand, int verify); -float *RE_strandren_get_uv(struct ObjectRen *obr, struct StrandRen *strand, int n, char **name, int verify); -struct MCol *RE_strandren_get_mcol(struct ObjectRen *obr, struct StrandRen *strand, int n, char **name, int verify); -float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand, int verify); -int *RE_strandren_get_face(struct ObjectRen *obr, struct StrandRen *strand, int verify); -float *RE_strandren_get_winspeed(struct ObjectInstanceRen *obi, struct StrandRen *strand, int verify); - -struct VertRen *RE_vertren_copy(struct ObjectRen *obr, struct VertRen *ver); -struct VlakRen *RE_vlakren_copy(struct ObjectRen *obr, struct VlakRen *vlr); - -void RE_set_customdata_names(struct ObjectRen *obr, struct CustomData *data); - -void area_lamp_vectors(struct LampRen *lar); - - -/* haloren->type: flags */ -#define HA_ONLYSKY 1 -#define HA_VECT 2 -#define HA_XALPHA 4 -#define HA_FLARECIRC 8 - -/* convertblender.c */ -void init_render_world(Render *re); -void RE_Database_FromScene_Vectors(Render *re, struct Main *bmain, struct Scene *sce, unsigned int lay); - -#ifdef __cplusplus -} -#endif - -#endif /* __RENDERDATABASE_H__ */ - diff --git a/source/blender/render/intern/include/renderpipeline.h b/source/blender/render/intern/include/renderpipeline.h index 3208288328b..7a409d2dc1c 100644 --- a/source/blender/render/intern/include/renderpipeline.h +++ b/source/blender/render/intern/include/renderpipeline.h @@ -33,14 +33,14 @@ #ifndef __RENDERPIPELINE_H__ #define __RENDERPIPELINE_H__ +struct ListBase; struct Render; struct RenderData; struct RenderLayer; struct RenderResult; struct RenderLayer *render_get_active_layer(struct Render *re, struct RenderResult *rr); -float panorama_pixel_rot(struct Render *re); -void render_update_anim_renderdata(struct Render *re, struct RenderData *rd); +void render_update_anim_renderdata(struct Render *re, struct RenderData *rd, struct ListBase *render_layers); void render_copy_renderdata(struct RenderData *to, struct RenderData *from); #endif /* __RENDERPIPELINE_H__ */ diff --git a/source/blender/render/intern/include/shadbuf.h b/source/blender/render/intern/include/shadbuf.h deleted file mode 100644 index ddf5de8d974..00000000000 --- a/source/blender/render/intern/include/shadbuf.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef __SHADBUF_H__ -#define __SHADBUF_H__ - -/** \file blender/render/intern/include/shadbuf.h - * \ingroup render - */ - -#include "render_types.h" - - -/** - * Calculates shadowbuffers for a vector of shadow-giving lamps - * \param lar The vector of lamps - */ -void makeshadowbuf(struct Render *re, LampRen *lar); -void freeshadowbuf(struct LampRen *lar); - -void threaded_makeshadowbufs(struct Render *re); - -/** - * Determines the shadow factor for a face and lamp. There is some - * communication with global variables here. - * \return The shadow factors: 1.0 for no shadow, 0.0 for complete - * shadow. - * \param shb The shadowbuffer to find the shadow factor in. - * \param inp The inproduct between viewvector and ? - * - */ -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 \a lar, between \a p1 and \a p2. (Which CS?) - */ -float shadow_halo(LampRen *lar, const float p1[3], const float p2[3]); - -/** - * Irregular shadowbuffer - */ - -struct MemArena; -struct APixstr; - -void ISB_create(RenderPart *pa, struct APixstr *apixbuf); -void ISB_free(RenderPart *pa); -float ISB_getshadow(ShadeInput *shi, ShadBuf *shb); - -/* data structures have to be accessible both in camview(x, y) as in lampview(x, y) */ -/* since they're created per tile rendered, speed goes over memory requirements */ - - -/* buffer samples, allocated in camera buffer and pointed to in lampbuffer nodes */ -typedef struct ISBSample { - float zco[3]; /* coordinate in lampview projection */ - short *shadfac; /* initialized zero = full lighted */ - int obi; /* object for face lookup */ - int facenr; /* index in faces list */ -} ISBSample; - -/* transparent version of buffer sample */ -typedef struct ISBSampleA { - float zco[3]; /* coordinate in lampview projection */ - short *shadfac; /* NULL = full lighted */ - int obi; /* object for face lookup */ - int facenr; /* index in faces list */ - struct ISBSampleA *next; /* in end, we want the first items to align with ISBSample */ -} ISBSampleA; - -/* used for transparent storage only */ -typedef struct ISBShadfacA { - struct ISBShadfacA *next; - int obi; - int facenr; - float shadfac; -} ISBShadfacA; - -/* What needs to be stored to evaluate shadow, for each thread in ShadBuf */ -typedef struct ISBData { - short *shadfacs; /* simple storage for solid only */ - ISBShadfacA **shadfaca; - struct MemArena *memarena; - int minx, miny, rectx, recty; /* copy from part disprect */ -} ISBData; - -#endif /* __SHADBUF_H__ */ - diff --git a/source/blender/render/intern/include/sss.h b/source/blender/render/intern/include/sss.h deleted file mode 100644 index c8f759cfe4e..00000000000 --- a/source/blender/render/intern/include/sss.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2007 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/sss.h - * \ingroup render - */ - - -#ifndef __SSS_H__ -#define __SSS_H__ - -/* Generic multiple scattering API */ - -struct ScatterSettings; -typedef struct ScatterSettings ScatterSettings; - -struct ScatterTree; -typedef struct ScatterTree ScatterTree; - -ScatterSettings *scatter_settings_new(float refl, float radius, float ior, - float reflfac, float frontweight, float backweight); -void scatter_settings_free(ScatterSettings *ss); - -ScatterTree *scatter_tree_new(ScatterSettings *ss[3], float scale, float error, - float (*co)[3], float (*color)[3], float *area, int totpoint); -void scatter_tree_build(ScatterTree *tree); -void scatter_tree_sample(ScatterTree *tree, const float co[3], float color[3]); -void scatter_tree_free(ScatterTree *tree); - -/* Internal renderer API */ - -struct Render; -struct Material; - -void make_sss_tree(struct Render *re); -void sss_add_points(Render *re, float (*co)[3], float (*color)[3], float *area, int totpoint); -void free_sss(struct Render *re); - -int sample_sss(struct Render *re, struct Material *mat, const float co[3], float color[3]); -int sss_pass_done(struct Render *re, struct Material *mat); - -#endif /*__SSS_H__*/ - diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h index dfb491f46b0..71000e38960 100644 --- a/source/blender/render/intern/include/texture.h +++ b/source/blender/render/intern/include/texture.h @@ -63,29 +63,12 @@ } \ } \ -struct HaloRen; -struct ShadeInput; struct TexResult; struct Tex; struct Image; struct ImBuf; struct ImagePool; -/* texture.h */ - -void do_halo_tex(struct HaloRen *har, float xn, float yn, float col_r[4]); -void do_sky_tex( - const float rco[3], const float view[3], const float lo[3], const float dxyview[2], - float hor[3], float zen[3], float *blend, int skyflag, short thread); -void do_material_tex(struct ShadeInput *shi, struct Render *re); -void do_lamp_tex(LampRen *la, const float lavec[3], struct ShadeInput *shi, float col_r[3], int effect); -void do_volume_tex(struct ShadeInput *shi, const float xyz[3], int mapto_flag, float col_r[3], float *val, struct Render *re); - -void init_render_textures(Render *re); -void end_render_textures(Render *re); - -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, const bool skip_load_image); diff --git a/source/blender/render/intern/include/volume_precache.h b/source/blender/render/intern/include/volume_precache.h deleted file mode 100644 index 9aa280d8276..00000000000 --- a/source/blender/render/intern/include/volume_precache.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Matt Ebb. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/volume_precache.h - * \ingroup render - */ - - -void global_bounds_obi(Render *re, ObjectInstanceRen *obi, float bbmin[3], float bbmax[3]); -int point_inside_volume_objectinstance(Render *re, ObjectInstanceRen *obi, const float co[3]); - -void volume_precache(Render *re); -void free_volume_precache(Render *re); - -#define VOL_MS_TIMESTEP 0.1f diff --git a/source/blender/render/intern/include/volumetric.h b/source/blender/render/intern/include/volumetric.h deleted file mode 100644 index 3805478fed0..00000000000 --- a/source/blender/render/intern/include/volumetric.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Matt Ebb. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/volumetric.h - * \ingroup render - */ - - -struct Isect; -struct ShadeInput; -struct ShadeResult; - -float vol_get_density(struct ShadeInput *shi, const float co[3]); -void vol_get_scattering(ShadeInput *shi, float scatter_col[3], const float co[3], const float view[3]); - -void shade_volume_outside(ShadeInput *shi, ShadeResult *shr); -void shade_volume_inside(ShadeInput *shi, ShadeResult *shr); -void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct Isect *last_is); - -#define VOL_IS_BACKFACE 1 -#define VOL_IS_SAMEMATERIAL 2 - -#define VOL_BOUNDS_DEPTH 0 -#define VOL_BOUNDS_SS 1 - -#define VOL_SHADE_OUTSIDE 0 -#define VOL_SHADE_INSIDE 1 diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h index 95c78e6d614..0654a4f8df6 100644 --- a/source/blender/render/intern/include/zbuf.h +++ b/source/blender/render/intern/include/zbuf.h @@ -33,57 +33,6 @@ #ifndef __ZBUF_H__ #define __ZBUF_H__ -struct RenderPart; -struct RenderLayer; -struct LampRen; -struct ListBase; -struct ZSpan; -struct APixstrand; -struct APixstr; -struct StrandShadeCache; - -void fillrect(int *rect, int x, int y, int val); - -/** - * Converts a world coordinate into a homogeneous coordinate in view - * coordinates. - */ -void projectvert(const float v1[3], float winmat[4][4], float adr[4]); -void projectverto(const float v1[3], float winmat[4][4], float adr[4]); -int testclip(const float v[3]); - -void zbuffer_shadow(struct Render *re, float winmat[4][4], struct LampRen *lar, int *rectz, int size, float jitx, float jity); -void zbuffer_abuf_shadow(struct Render *re, struct LampRen *lar, float winmat[4][4], struct APixstr *APixbuf, struct APixstrand *apixbuf, struct ListBase *apsmbase, int size, int samples, float (*jit)[2]); -void zbuffer_solid(struct RenderPart *pa, struct RenderLayer *rl, void (*fillfunc)(struct RenderPart *, struct ZSpan *, int, void *), void *data); - -unsigned short *zbuffer_transp_shade(struct RenderPart *pa, struct RenderLayer *rl, float *pass, struct ListBase *psmlist); -void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void *, int, int, int, int, int)); -int zbuffer_strands_abuf(struct Render *re, struct RenderPart *pa, struct APixstrand *apixbuf, struct ListBase *apsmbase, unsigned int lay, int negzmask, float winmat[4][4], int winx, int winy, int sample, float (*jit)[2], float clipcrop, int shadow, struct StrandShadeCache *cache); - -typedef struct APixstr { - unsigned short mask[4]; /* jitter mask */ - int z[4]; /* distance */ - int p[4]; /* index */ - int obi[4]; /* object instance */ - short shadfac[4]; /* optimize storage for irregular shadow */ - struct APixstr *next; -} APixstr; - -typedef struct APixstrand { - unsigned short mask[4]; /* jitter mask */ - int z[4]; /* distance */ - int p[4]; /* index */ - int obi[4]; /* object instance */ - int seg[4]; /* for strands, segment number */ - float u[4], v[4]; /* for strands, u,v coordinate in segment */ - struct APixstrand *next; -} APixstrand; - -typedef struct APixstrMain { - struct APixstrMain *next, *prev; - void *ps; -} APixstrMain; - /* span fill in method, is also used to localize data for zbuffering */ typedef struct ZSpan { int rectx, recty; /* range for clipping */ @@ -91,61 +40,13 @@ typedef struct ZSpan { int miny1, maxy1, miny2, maxy2; /* actual filled in range */ const float *minp1, *maxp1, *minp2, *maxp2; /* vertex pointers detect min/max range in */ float *span1, *span2; - - float zmulx, zmuly, zofsx, zofsy; /* transform from hoco to zbuf co */ - - int *rectz, *arectz; /* zbuffers, arectz is for transparent */ - int *rectz1; /* secondary z buffer for shadowbuffer (2nd closest z) */ - int *rectp; /* polygon index buffer */ - int *recto; /* object buffer */ - int *rectmask; /* negative zmask buffer */ - APixstr *apixbuf, *curpstr; /* apixbuf for transparent */ - APixstrand *curpstrand; /* same for strands */ - struct ListBase *apsmbase; - - int polygon_offset; /* offset in Z */ - float shad_alpha; /* copy from material, used by irregular shadbuf */ - int mask, apsmcounter; /* in use by apixbuf */ - int apstrandmcounter; - - float clipcrop; /* for shadow, was in R global before */ - - void *sss_handle; /* used by sss */ - void (*sss_func)(void *, int, int, int, int, int); - - void (*zbuffunc)(struct ZSpan *, int, int, const float *, const float *, const float *, const float *); - void (*zbuflinefunc)(struct ZSpan *, int, int, const float *, const float *); - } ZSpan; -/* exported to shadbuf.c */ -void zbufclip4(struct ZSpan *zspan, int obi, int zvlnr, - const float f1[4], const float f2[4], const float f3[4], const float f4[4], - const int c1, const int c2, const int c3, const int c4); +void zbuf_alloc_span(struct ZSpan *zspan, int rectx, int recty); void zbuf_free_span(struct ZSpan *zspan); -void freepsA(struct ListBase *lb); -/* to rendercore.c */ void zspan_scanconvert(struct ZSpan *zpan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float) ); -/* exported to edge render... */ -void zbufclip(struct ZSpan *zspan, int obi, int zvlnr, - const float f1[4], const float f2[4], const float f3[4], - const int c1, const int c2, const int c3); -void zbuf_alloc_span(struct ZSpan *zspan, int rectx, int recty, float clipcrop); -void zbufclipwire(struct ZSpan *zspan, int obi, int zvlnr, int ec, - const float ho1[4], const float ho2[4], const float ho3[4], const float ho4[4], - const int c1, const int c2, const int c3, const int c4); - -/* exported to shadeinput.c */ -void zbuf_make_winmat(Render *re, float winmat[4][4]); -void zbuf_render_project(float winmat[4][4], const float co[3], float ho[4]); - -/* should not really be exposed, bad! */ -void hoco_to_zco(ZSpan *zspan, float zco[3], const float hoco[4]); -void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) ); -void zbufsinglewire(ZSpan *zspan, int obi, int zvlnr, const float ho1[4], const float ho2[4]); - #endif diff --git a/source/blender/render/intern/raytrace/rayobject_empty.cpp b/source/blender/render/intern/raytrace/rayobject_empty.cpp deleted file mode 100644 index 6382e6f524c..00000000000 --- a/source/blender/render/intern/raytrace/rayobject_empty.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 1990-1998 NeoGeo BV. - * All rights reserved. - * - * Contributors: 2004/2005 Blender Foundation, full recode - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/rayobject_empty.cpp - * \ingroup render - */ - - -#include "MEM_guardedalloc.h" - -#include "rayobject.h" - -#include "BLI_utildefines.h" - -/* - * Empty raytree - */ - -static int RE_rayobject_empty_intersect(RayObject *UNUSED(o), Isect *UNUSED(is)) -{ - return 0; -} - -static void RE_rayobject_empty_free(RayObject *UNUSED(o)) -{ -} - -static void RE_rayobject_empty_bb(RayObject *UNUSED(o), float *UNUSED(min), float *UNUSED(max)) -{ - return; -} - -static float RE_rayobject_empty_cost(RayObject *UNUSED(o)) -{ - return 0.0; -} - -static void RE_rayobject_empty_hint_bb(RayObject *UNUSED(o), RayHint *UNUSED(hint), - float *UNUSED(min), float *UNUSED(max)) -{} - -static RayObjectAPI empty_api = -{ - RE_rayobject_empty_intersect, - NULL, //static void RE_rayobject_instance_add(RayObject *o, RayObject *ob); - NULL, //static void RE_rayobject_instance_done(RayObject *o); - RE_rayobject_empty_free, - RE_rayobject_empty_bb, - RE_rayobject_empty_cost, - RE_rayobject_empty_hint_bb -}; - -static RayObject empty_raytree = { &empty_api, {NULL, NULL} }; - -RayObject *RE_rayobject_empty_create() -{ - return RE_rayobject_unalignRayAPI( &empty_raytree ); -} - diff --git a/source/blender/render/intern/raytrace/rayobject_internal.h b/source/blender/render/intern/raytrace/rayobject_internal.h deleted file mode 100644 index dbc78b317c6..00000000000 --- a/source/blender/render/intern/raytrace/rayobject_internal.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef __RAYOBJECT_INTERNAL_H__ -#define __RAYOBJECT_INTERNAL_H__ - -/** \file blender/render/intern/raytrace/rayobject_internal.h - * \ingroup render - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* RayObjectControl - * - * This class is intended as a place holder for control, configuration of the - * rayobject like: - * - stop building (TODO maybe when porting build to threads this could be - * implemented with some thread_cancel function) - * - max number of threads and threads callback to use during build - * ... - */ - -typedef int (*RE_rayobjectcontrol_test_break_callback)(void *data); - -typedef struct RayObjectControl { - void *data; - RE_rayobjectcontrol_test_break_callback test_break; -} RayObjectControl; - -/* Returns true if for some reason a heavy processing function should stop - * (eg.: user asked to stop during a tree a build) - */ - -int RE_rayobjectcontrol_test_break(RayObjectControl *c); - -/* RayObject - * - * A ray object is everything where we can cast rays like: - * * a face/triangle - * * an octree - * * a bvh tree - * * an octree of bvh's - * * a bvh of bvh's - * - * - * All types of RayObjects can be created by implementing the - * callbacks of the RayObject. - * - * Due to high computing time evolved with casting on faces - * there is a special type of RayObject (named RayFace) - * which won't use callbacks like other generic nodes. - * - * In order to allow a mixture of RayFace+RayObjects, - * all RayObjects must be 4byte aligned, allowing us to use the - * 2 least significant bits (with the mask 0x03) to define the - * type of RayObject. - * - * This leads to 4 possible types of RayObject: - * - * addr&3 - type of object - * 0 Self (reserved for each structure) - * 1 RayFace (tri/quad primitive) - * 2 RayObject (generic with API callbacks) - * 3 VlakPrimitive - * (vlak primitive - to be used when we have a vlak describing the data - * eg.: on render code) - * - * 0 means it's reserved and has it own meaning inside each ray acceleration structure - * (this way each structure can use the align offset to determine if a node represents a - * RayObject primitive, which can be used to save memory) - */ - -/* used to test the type of ray object */ -#define RE_rayobject_isAligned(o) ((((intptr_t)o)&3) == 0) -#define RE_rayobject_isRayFace(o) ((((intptr_t)o)&3) == 1) -#define RE_rayobject_isRayAPI(o) ((((intptr_t)o)&3) == 2) -#define RE_rayobject_isVlakPrimitive(o) ((((intptr_t)o)&3) == 3) - -/* used to align a given ray object */ -#define RE_rayobject_align(o) ((RayObject *)(((intptr_t)o)&(~3))) - -/* used to unalign a given ray object */ -#define RE_rayobject_unalignRayFace(o) ((RayObject *)(((intptr_t)o)|1)) -#define RE_rayobject_unalignRayAPI(o) ((RayObject *)(((intptr_t)o)|2)) -#define RE_rayobject_unalignVlakPrimitive(o) ((RayObject *)(((intptr_t)o)|3)) - -/* - * This rayobject represents a generic object. With it's own callbacks for raytrace operations. - * It's suitable to implement things like LOD. - */ - -struct RayObject { - struct RayObjectAPI *api; - struct RayObjectControl control; -}; - -typedef int (*RE_rayobject_raycast_callback)(RayObject *, struct Isect *); -typedef void (*RE_rayobject_add_callback)(RayObject *raytree, RayObject *rayobject); -typedef void (*RE_rayobject_done_callback)(RayObject *); -typedef void (*RE_rayobject_free_callback)(RayObject *); -typedef void (*RE_rayobject_merge_bb_callback)(RayObject *, float min[3], float max[3]); -typedef float (*RE_rayobject_cost_callback)(RayObject *); -typedef void (*RE_rayobject_hint_bb_callback)(RayObject *, struct RayHint *, float min[3], float max[3]); - -typedef struct RayObjectAPI { - RE_rayobject_raycast_callback raycast; - RE_rayobject_add_callback add; - RE_rayobject_done_callback done; - RE_rayobject_free_callback free; - RE_rayobject_merge_bb_callback bb; - RE_rayobject_cost_callback cost; - RE_rayobject_hint_bb_callback hint_bb; -} RayObjectAPI; - -/* - * Returns the expected cost of raycast on this node, primitives have a cost of 1 - */ -float RE_rayobject_cost(RayObject *r); - -/* - * This function differs from RE_rayobject_raycast - * RE_rayobject_intersect does NOT perform last-hit optimization - * So this is probably a function to call inside raytrace structures - */ -int RE_rayobject_intersect(RayObject *r, struct Isect *i); - -#ifdef __cplusplus -} -#endif - -#endif /* __RAYOBJECT_INTERNAL_H__ */ diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c index 8b25c1fe962..57846bc7443 100644 --- a/source/blender/render/intern/source/bake_api.c +++ b/source/blender/render/intern/source/bake_api.c @@ -84,19 +84,11 @@ /* local include */ #include "render_types.h" -#include "shading.h" #include "zbuf.h" /* Remove when Cycles moves from MFace to MLoopTri */ #define USE_MFACE_WORKAROUND -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* 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; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - - typedef struct BakeDataZSpan { BakePixel *pixel_array; int primitive_id; @@ -263,6 +255,36 @@ static void calc_point_from_barycentric_extrusion( copy_v3_v3(r_dir, dir); } +static void barycentric_differentials_from_position( + const float co[3], const float v1[3], const float v2[3], const float v3[3], + const float dxco[3], const float dyco[3], const float facenor[3], const bool differentials, + float *u, float *v, float *dx_u, float *dx_v, float *dy_u, float *dy_v) +{ + /* find most stable axis to project */ + int axis1, axis2; + axis_dominant_v3(&axis1, &axis2, facenor); + + /* compute u,v and derivatives */ + float t00 = v3[axis1] - v1[axis1]; + float t01 = v3[axis2] - v1[axis2]; + float t10 = v3[axis1] - v2[axis1]; + float t11 = v3[axis2] - v2[axis2]; + + float detsh = (t00 * t11 - t10 * t01); + detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f; + t00 *= detsh; t01 *= detsh; + t10 *= detsh; t11 *= detsh; + + *u = (v3[axis1] - co[axis1]) * t11 - (v3[axis2] - co[axis2]) * t10; + *v = (v3[axis2] - co[axis2]) * t00 - (v3[axis1] - co[axis1]) * t01; + if (differentials) { + *dx_u = dxco[axis1] * t11 - dxco[axis2] * t10; + *dx_v = dxco[axis2] * t00 - dxco[axis1] * t01; + *dy_u = dyco[axis1] * t11 - dyco[axis2] * t10; + *dy_v = dyco[axis2] * t00 - dyco[axis1] * t01; + } +} + /** * This function populates pixel_array and returns TRUE if things are correct */ @@ -665,7 +687,7 @@ void RE_bake_pixels_populate( } for (i = 0; i < bake_images->size; i++) { - zbuf_alloc_span(&bd.zspan[i], bake_images->data[i].width, bake_images->data[i].height, R.clipcrop); + zbuf_alloc_span(&bd.zspan[i], bake_images->data[i].width, bake_images->data[i].height); } looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__); @@ -958,36 +980,6 @@ void RE_bake_ibuf_clear(Image *image, const bool is_tangent) /* ************************************************************* */ -/** - * not the real UV, but the internal per-face UV instead - * I'm using it to test if everything is correct */ -static bool bake_uv(const BakePixel pixel_array[], const size_t num_pixels, const int depth, float result[]) -{ - size_t i; - - for (i=0; i < num_pixels; i++) { - size_t offset = i * depth; - copy_v2_v2(&result[offset], pixel_array[i].uv); - } - - return true; -} - -bool RE_bake_internal( - Render *UNUSED(re), Object *UNUSED(object), const BakePixel pixel_array[], - const size_t num_pixels, const int depth, const eScenePassType pass_type, float result[]) -{ - switch (pass_type) { - case SCE_PASS_UV: - { - return bake_uv(pixel_array, num_pixels, depth, result); - } - default: - break; - } - return false; -} - int RE_pass_depth(const eScenePassType pass_type) { /* IMB_buffer_byte_from_float assumes 4 channels diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index b99ab611458..6e4336f80ea 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -41,12 +41,20 @@ #include "BLI_string.h" #include "BLI_utildefines.h" +#include "DNA_object_types.h" + #include "BKE_camera.h" #include "BKE_global.h" #include "BKE_colortools.h" +#include "BKE_layer.h" +#include "BKE_node.h" #include "BKE_report.h" #include "BKE_scene.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_debug.h" +#include "DEG_depsgraph_query.h" + #include "RNA_access.h" #ifdef WITH_PYTHON @@ -57,46 +65,28 @@ #include "RE_pipeline.h" #include "RE_bake.h" +#include "DRW_engine.h" + #include "initrender.h" #include "renderpipeline.h" #include "render_types.h" #include "render_result.h" -#include "rendercore.h" /* Render Engine Types */ -static RenderEngineType internal_render_type = { - NULL, NULL, - "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL, - NULL, NULL, NULL, NULL, NULL, NULL, render_internal_update_passes, - {NULL, NULL, NULL} -}; - -#ifdef WITH_GAMEENGINE - -static RenderEngineType internal_game_type = { - NULL, NULL, - "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - {NULL, NULL, NULL} -}; - -#endif - ListBase R_engines = {NULL, NULL}; void RE_engines_init(void) { - BLI_addtail(&R_engines, &internal_render_type); -#ifdef WITH_GAMEENGINE - BLI_addtail(&R_engines, &internal_game_type); -#endif + DRW_engines_register(); } void RE_engines_exit(void) { RenderEngineType *type, *next; + DRW_engines_free(); + for (type = R_engines.first; type; type = next) { next = type->next; @@ -111,21 +101,35 @@ void RE_engines_exit(void) } } +void RE_engines_register(RenderEngineType *render_type) +{ + if (render_type->draw_engine) { + DRW_engine_register(render_type->draw_engine); + } + BLI_addtail(&R_engines, render_type); +} + RenderEngineType *RE_engines_find(const char *idname) { RenderEngineType *type; type = BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname)); if (!type) - type = &internal_render_type; + type = BLI_findstring(&R_engines, "BLENDER_EEVEE", offsetof(RenderEngineType, idname)); return type; } bool RE_engine_is_external(Render *re) { - RenderEngineType *type = RE_engines_find(re->r.engine); - return (type && type->render); + return (re->engine && re->engine->type && re->engine->type->render); +} + +bool RE_engine_is_opengl(RenderEngineType *render_type) +{ + /* TODO refine? Can we have ogl render engine without ogl render pipeline? */ + return (render_type->draw_engine != NULL) && + DRW_engine_render_support(render_type->draw_engine); } /* Create, Free */ @@ -183,7 +187,8 @@ 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, const char *viewname) +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; @@ -413,7 +418,8 @@ float RE_engine_get_camera_shift_x(RenderEngine *engine, Object *camera, int use return BKE_camera_multiview_shift_x(re ? &re->r : NULL, camera, re->viewname); } -void RE_engine_get_camera_model_matrix(RenderEngine *engine, Object *camera, int use_spherical_stereo, float *r_modelmat) +void RE_engine_get_camera_model_matrix( + RenderEngine *engine, Object *camera, int use_spherical_stereo, float *r_modelmat) { Render *re = engine->re; @@ -469,13 +475,6 @@ rcti* RE_engine_get_current_tiles(Render *re, int *r_total_tiles, bool *r_needs_ } tiles[total_tiles] = pa->disprect; - if (pa->crop) { - tiles[total_tiles].xmin += pa->crop; - tiles[total_tiles].ymin += pa->crop; - tiles[total_tiles].xmax -= pa->crop; - tiles[total_tiles].ymax -= pa->crop; - } - total_tiles++; } } @@ -489,6 +488,49 @@ RenderData *RE_engine_get_render_data(Render *re) return &re->r; } +/* Depsgraph */ +static void engine_depsgraph_init(RenderEngine *engine, ViewLayer *view_layer) +{ + Main *bmain = engine->re->main; + Scene *scene = engine->re->scene; + + engine->depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER); + DEG_debug_name_set(engine->depsgraph, "RENDER"); + + BKE_scene_graph_update_for_newframe(engine->depsgraph, bmain); +} + +static void engine_depsgraph_free(RenderEngine *engine) +{ + DEG_graph_free(engine->depsgraph); + + engine->depsgraph = NULL; +} + +void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe) +{ + if(!engine->depsgraph) { + return; + } + +#ifdef WITH_PYTHON + BPy_BEGIN_ALLOW_THREADS; +#endif + + Render *re = engine->re; + double cfra = (double)frame + (double)subframe; + + CLAMP(cfra, MINAFRAME, MAXFRAME); + BKE_scene_frame_set(re->scene, cfra); + BKE_scene_graph_update_for_newframe(engine->depsgraph, re->main); + + BKE_scene_camera_switch_update(re->scene); + +#ifdef WITH_PYTHON + BPy_END_ALLOW_THREADS; +#endif +} + /* Bake */ void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Scene *scene) { @@ -504,7 +546,7 @@ bool RE_bake_has_engine(Render *re) } bool RE_bake_engine( - Render *re, Object *object, + Render *re, Depsgraph *depsgraph, Object *object, const int object_id, const BakePixel pixel_array[], const size_t num_pixels, const int depth, const eScenePassType pass_type, const int pass_filter, @@ -535,16 +577,30 @@ bool RE_bake_engine( engine->resolution_x = re->winx; engine->resolution_y = re->winy; - RE_parts_init(re, false); + RE_parts_init(re); engine->tile_x = re->r.tilex; engine->tile_y = re->r.tiley; - /* update is only called so we create the engine.session */ - if (type->update) - type->update(engine, re->main, re->scene); - - if (type->bake) - type->bake(engine, re->scene, object, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result); + if (type->bake) { + engine->depsgraph = depsgraph; + + /* update is only called so we create the engine.session */ + if (type->update) + type->update(engine, re->main, engine->depsgraph); + + type->bake(engine, + engine->depsgraph, + object, + pass_type, + pass_filter, + object_id, + pixel_array, + num_pixels, + depth, + result); + + engine->depsgraph = NULL; + } engine->tile_x = 0; engine->tile_y = 0; @@ -567,42 +623,8 @@ bool RE_bake_engine( return true; } -void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe) -{ - Render *re = engine->re; - Scene *scene = re->scene; - double cfra = (double)frame + (double)subframe; - - CLAMP(cfra, MINAFRAME, MAXFRAME); - BKE_scene_frame_set(scene, cfra); - -#ifdef WITH_PYTHON - BPy_BEGIN_ALLOW_THREADS; -#endif - - /* It's possible that here we're including layers which were never visible before. */ - BKE_scene_update_for_newframe_ex(re->eval_ctx, re->main, scene, (1 << 20) - 1, true); - -#ifdef WITH_PYTHON - BPy_END_ALLOW_THREADS; -#endif - - BKE_scene_camera_switch_update(scene); -} - /* Render */ -static bool render_layer_exclude_animated(Scene *scene, SceneRenderLayer *srl) -{ - PointerRNA ptr; - PropertyRNA *prop; - - RNA_pointer_create(&scene->id, &RNA_SceneRenderLayer, srl, &ptr); - prop = RNA_struct_find_property(&ptr, "layers_exclude"); - - return RNA_property_animated(&ptr, prop); -} - int RE_engine_render(Render *re, int do_all) { RenderEngineType *type = RE_engines_find(re->r.engine); @@ -627,41 +649,7 @@ int RE_engine_render(Render *re, int do_all) /* update animation here so any render layer animation is applied before * creating the render result */ if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) { - unsigned int lay = re->lay; - - /* don't update layers excluded on all render layers */ - if (type->flag & RE_USE_EXCLUDE_LAYERS) { - SceneRenderLayer *srl; - unsigned int non_excluded_lay = 0; - - if (re->r.scemode & R_SINGLE_LAYER) { - srl = BLI_findlink(&re->r.layers, re->r.actlay); - if (srl) { - non_excluded_lay |= ~(srl->lay_exclude & ~srl->lay_zmask); - - /* in this case we must update all because animation for - * the scene has not been updated yet, and so may not be - * up to date until after BKE_scene_update_for_newframe */ - if (render_layer_exclude_animated(re->scene, srl)) - non_excluded_lay |= ~0; - } - } - else { - for (srl = re->r.layers.first; srl; srl = srl->next) { - if (!(srl->layflag & SCE_LAY_DISABLE)) { - non_excluded_lay |= ~(srl->lay_exclude & ~srl->lay_zmask); - - if (render_layer_exclude_animated(re->scene, srl)) - non_excluded_lay |= ~0; - } - } - } - - lay &= non_excluded_lay; - } - - BKE_scene_update_for_newframe_ex(re->eval_ctx, re->main, re->scene, lay, true); - render_update_anim_renderdata(re, &re->scene->r); + render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers); } /* create render result */ @@ -719,23 +707,42 @@ int RE_engine_render(Render *re, int do_all) engine->resolution_x = re->winx; engine->resolution_y = re->winy; - RE_parts_init(re, false); + RE_parts_init(re); engine->tile_x = re->partx; engine->tile_y = re->party; if (re->result->do_exr_tile) render_result_exr_file_begin(re); - if (type->update) - type->update(engine, re->main, re->scene); - /* Clear UI drawing locks. */ if (re->draw_lock) { re->draw_lock(re->dlh, 0); } - if (type->render) - type->render(engine, re->scene); + if (type->render) { + FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re, view_layer_iter) + { + if (re->draw_lock) { + re->draw_lock(re->dlh, 1); + } + + ViewLayer *view_layer = BLI_findstring(&re->scene->view_layers, view_layer_iter->name, offsetof(ViewLayer, name)); + engine_depsgraph_init(engine, view_layer); + + if (type->update) { + type->update(engine, re->main, engine->depsgraph); + } + + if (re->draw_lock) { + re->draw_lock(re->dlh, 0); + } + + type->render(engine, engine->depsgraph); + + engine_depsgraph_free(engine); + } + FOREACH_VIEW_LAYER_TO_RENDER_END; + } engine->tile_x = 0; engine->tile_y = 0; @@ -778,12 +785,12 @@ int RE_engine_render(Render *re, int do_all) return 1; } -void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl, +void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer, const char *name, int UNUSED(channels), const char *UNUSED(chanid), int type) { /* The channel information is currently not used, but is part of the API in case it's needed in the future. */ - if (!(scene && srl && engine)) { + if (!(scene && view_layer && engine)) { return; } @@ -793,7 +800,7 @@ void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, s Scene *sce; for (sce = G.main->scene.first; sce; sce = sce->id.next) { if (sce->nodetree) { - ntreeCompositRegisterPass(sce->nodetree, scene, srl, name, type); + ntreeCompositRegisterPass(sce->nodetree, scene, view_layer, name, type); } } } diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index 1f1e900ba04..1e9ad79e599 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -53,16 +53,11 @@ #include "BKE_image.h" #include "RE_render_ext.h" +#include "RE_shader_ext.h" #include "render_types.h" #include "texture.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 void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend); /* *********** IMAGEWRAPPING ****************** */ @@ -211,11 +206,6 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul } } - /* warning, no return before setting back! */ - if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { - ibuf->rect+= (ibuf->x*ibuf->y); - } - /* keep this before interpolation [#29761] */ if (ima) { if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) { @@ -243,10 +233,6 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul ibuf_get_color(&texres->tr, ibuf, x, y); } - if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { - ibuf->rect-= (ibuf->x*ibuf->y); - } - if (texres->nor) { if (tex->imaflag & TEX_NORMALMAP) { /* qdn: normal from color @@ -979,17 +965,6 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex fy = texvec[1]; } - if (ibuf->flags & IB_fields) { - if (R.r.mode & R_FIELDS) { /* field render */ - if (R.flag & R_SEC_FIELD) { /* correction for 2nd field */ - /* fac1= 0.5/( (float)ibuf->y ); */ - /* fy-= fac1; */ - } - else /* first field */ - fy += 0.5f/( (float)ibuf->y ); - } - } - /* pixel coordinates */ minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]); maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]); @@ -1129,10 +1104,6 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex intpol = tex->imaflag & TEX_INTERPOL; - /* warning no return! */ - if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields)) - ibuf->rect += ibuf->x*ibuf->y; - /* struct common data */ copy_v2_v2(AFD.dxt, dxt); copy_v2_v2(AFD.dyt, dyt); @@ -1311,9 +1282,6 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex texres->tin = texres->ta; if (tex->flag & TEX_NEGALPHA) texres->ta = 1.f - texres->ta; - if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields)) - ibuf->rect -= ibuf->x*ibuf->y; - if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) { /* normal from color */ /* The invert of the red channel is to make * the normal map compliant with the outside world. @@ -1411,18 +1379,6 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const fy= texvec[1]; } - if (ibuf->flags & IB_fields) { - if (R.r.mode & R_FIELDS) { /* field render */ - if (R.flag & R_SEC_FIELD) { /* correction for 2nd field */ - /* fac1= 0.5/( (float)ibuf->y ); */ - /* fy-= fac1; */ - } - else { /* first field */ - fy+= 0.5f/( (float)ibuf->y ); - } - } - } - /* pixel coordinates */ minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]); @@ -1580,11 +1536,6 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const } } - /* warning no return! */ - if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { - ibuf->rect+= (ibuf->x*ibuf->y); - } - /* choice: */ if (tex->imaflag & TEX_MIPMAP) { ImBuf *previbuf, *curibuf; @@ -1731,10 +1682,6 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const if (tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta; - if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { - ibuf->rect-= (ibuf->x*ibuf->y); - } - if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) { /* qdn: normal from color * The invert of the red channel is to make @@ -1772,16 +1719,10 @@ void image_sample(Image *ima, float fx, float fy, float dx, float dy, float resu return; } - if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) - ibuf->rect+= (ibuf->x*ibuf->y); - texres.talpha = true; /* boxsample expects to be initialized */ boxsample(ibuf, fx, fy, fx + dx, fy + dy, &texres, 0, 1); copy_v4_v4(result, &texres.tr); - if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) - ibuf->rect-= (ibuf->x*ibuf->y); - ima->flag|= IMA_USED_FOR_RENDER; BKE_image_pool_release_ibuf(ima, ibuf, pool); diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index 34e47a00c7a..9611a8a7452 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -38,13 +38,9 @@ #include "BLI_math.h" #include "BLI_blenlib.h" -#include "BLI_jitter_2d.h" #include "BLI_utildefines.h" #include "DNA_camera_types.h" -#include "DNA_image_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" #include "BKE_camera.h" @@ -56,31 +52,6 @@ #include "initrender.h" -/* ********************** */ - -static void init_render_jit(Render *re) -{ - static float jit[32][2]; /* simple caching */ - static float mblur_jit[32][2]; /* simple caching */ - static int lastjit = 0; - static int last_mblur_jit = 0; - - if (lastjit != re->r.osa || last_mblur_jit != re->r.mblur_samples) { - memset(jit, 0, sizeof(jit)); - BLI_jitter_init(jit, re->r.osa); - - memset(mblur_jit, 0, sizeof(mblur_jit)); - BLI_jitter_init(mblur_jit, re->r.mblur_samples); - } - - lastjit = re->r.osa; - memcpy(re->jit, jit, sizeof(jit)); - - last_mblur_jit = re->r.mblur_samples; - memcpy(re->mblur_jit, mblur_jit, sizeof(mblur_jit)); -} - - /* ****************** MASKS and LUTS **************** */ static float filt_quadratic(float x) @@ -171,256 +142,6 @@ float RE_filter_value(int type, float x) return 0.0f; } -static float calc_weight(Render *re, float *weight, int i, int j) -{ - float x, y, dist, totw = 0.0; - int a; - - for (a = 0; a < re->osa; a++) { - x = re->jit[a][0] + i; - y = re->jit[a][1] + j; - dist = sqrtf(x * x + y * y); - - weight[a] = 0.0; - - /* Weighting choices */ - switch (re->r.filtertype) { - case R_FILTER_BOX: - if (i == 0 && j == 0) weight[a] = 1.0; - break; - - case R_FILTER_TENT: - if (dist < re->r.gauss) - weight[a] = re->r.gauss - dist; - break; - - case R_FILTER_GAUSS: - x = dist * re->r.gauss; - weight[a] = (1.0f / expf(x * x) - 1.0f / expf(re->r.gauss * re->r.gauss * 2.25f)); - break; - - case R_FILTER_MITCH: - weight[a] = filt_mitchell(dist * re->r.gauss); - break; - - case R_FILTER_QUAD: - weight[a] = filt_quadratic(dist * re->r.gauss); - break; - - case R_FILTER_CUBIC: - weight[a] = filt_cubic(dist * re->r.gauss); - break; - - case R_FILTER_CATROM: - weight[a] = filt_catrom(dist * re->r.gauss); - break; - - } - - totw += weight[a]; - - } - return totw; -} - -void free_sample_tables(Render *re) -{ - int a; - - if (re->samples) { - for (a = 0; a < 9; a++) { - MEM_freeN(re->samples->fmask1[a]); - MEM_freeN(re->samples->fmask2[a]); - } - - MEM_freeN(re->samples->centmask); - MEM_freeN(re->samples); - re->samples = NULL; - } -} - -/* based on settings in render, it makes the lookup tables */ -void make_sample_tables(Render *re) -{ - static int firsttime = 1; - SampleTables *st; - float flweight[32]; - float weight[32], totw, val, *fpx1, *fpx2, *fpy1, *fpy2, *m3, *m4; - int i, j, a, centmasksize; - - /* optimization tables, only once */ - if (firsttime) { - firsttime = 0; - } - - free_sample_tables(re); - - init_render_jit(re); /* needed for mblur too */ - - if (re->osa == 0) { - /* just prevents cpu cycles for larger render and copying */ - re->r.filtertype = 0; - return; - } - - st = re->samples = MEM_callocN(sizeof(SampleTables), "sample tables"); - - for (a = 0; a < 9; a++) { - st->fmask1[a] = MEM_callocN(256 * sizeof(float), "initfilt"); - st->fmask2[a] = MEM_callocN(256 * sizeof(float), "initfilt"); - } - for (a = 0; a < 256; a++) { - st->cmask[a] = 0; - if (a & 1) st->cmask[a]++; - if (a & 2) st->cmask[a]++; - if (a & 4) st->cmask[a]++; - if (a & 8) st->cmask[a]++; - if (a & 16) st->cmask[a]++; - if (a & 32) st->cmask[a]++; - if (a & 64) st->cmask[a]++; - if (a & 128) st->cmask[a]++; - } - - centmasksize = (1 << re->osa); - st->centmask = MEM_mallocN(centmasksize, "Initfilt3"); - - for (a = 0; a < 16; a++) { - st->centLut[a] = -0.45f + ((float)a) / 16.0f; - } - - /* calculate totw */ - totw = 0.0; - for (j = -1; j < 2; j++) { - for (i = -1; i < 2; i++) { - totw += calc_weight(re, weight, i, j); - } - } - - for (j = -1; j < 2; j++) { - for (i = -1; i < 2; i++) { - /* calculate using jit, with offset the weights */ - - memset(weight, 0, sizeof(weight)); - calc_weight(re, weight, i, j); - - for (a = 0; a < 16; a++) flweight[a] = weight[a] * (1.0f / totw); - - m3 = st->fmask1[3 * (j + 1) + i + 1]; - m4 = st->fmask2[3 * (j + 1) + i + 1]; - - for (a = 0; a < 256; a++) { - if (a & 1) { - m3[a] += flweight[0]; - m4[a] += flweight[8]; - } - if (a & 2) { - m3[a] += flweight[1]; - m4[a] += flweight[9]; - } - if (a & 4) { - m3[a] += flweight[2]; - m4[a] += flweight[10]; - } - if (a & 8) { - m3[a] += flweight[3]; - m4[a] += flweight[11]; - } - if (a & 16) { - m3[a] += flweight[4]; - m4[a] += flweight[12]; - } - if (a & 32) { - m3[a] += flweight[5]; - m4[a] += flweight[13]; - } - if (a & 64) { - m3[a] += flweight[6]; - m4[a] += flweight[14]; - } - if (a & 128) { - m3[a] += flweight[7]; - m4[a] += flweight[15]; - } - } - } - } - - /* centmask: the correct subpixel offset per mask */ - - fpx1 = MEM_mallocN(256 * sizeof(float), "initgauss4"); - fpx2 = MEM_mallocN(256 * sizeof(float), "initgauss4"); - fpy1 = MEM_mallocN(256 * sizeof(float), "initgauss4"); - fpy2 = MEM_mallocN(256 * sizeof(float), "initgauss4"); - for (a = 0; a < 256; a++) { - fpx1[a] = fpx2[a] = 0.0; - fpy1[a] = fpy2[a] = 0.0; - if (a & 1) { - fpx1[a] += re->jit[0][0]; - fpy1[a] += re->jit[0][1]; - fpx2[a] += re->jit[8][0]; - fpy2[a] += re->jit[8][1]; - } - if (a & 2) { - fpx1[a] += re->jit[1][0]; - fpy1[a] += re->jit[1][1]; - fpx2[a] += re->jit[9][0]; - fpy2[a] += re->jit[9][1]; - } - if (a & 4) { - fpx1[a] += re->jit[2][0]; - fpy1[a] += re->jit[2][1]; - fpx2[a] += re->jit[10][0]; - fpy2[a] += re->jit[10][1]; - } - if (a & 8) { - fpx1[a] += re->jit[3][0]; - fpy1[a] += re->jit[3][1]; - fpx2[a] += re->jit[11][0]; - fpy2[a] += re->jit[11][1]; - } - if (a & 16) { - fpx1[a] += re->jit[4][0]; - fpy1[a] += re->jit[4][1]; - fpx2[a] += re->jit[12][0]; - fpy2[a] += re->jit[12][1]; - } - if (a & 32) { - fpx1[a] += re->jit[5][0]; - fpy1[a] += re->jit[5][1]; - fpx2[a] += re->jit[13][0]; - fpy2[a] += re->jit[13][1]; - } - if (a & 64) { - fpx1[a] += re->jit[6][0]; - fpy1[a] += re->jit[6][1]; - fpx2[a] += re->jit[14][0]; - fpy2[a] += re->jit[14][1]; - } - if (a & 128) { - fpx1[a] += re->jit[7][0]; - fpy1[a] += re->jit[7][1]; - fpx2[a] += re->jit[15][0]; - fpy2[a] += re->jit[15][1]; - } - } - - for (a = centmasksize - 1; a > 0; a--) { - val = st->cmask[a & 255] + st->cmask[a >> 8]; - i = 8 + (15.9f * (fpy1[a & 255] + fpy2[a >> 8]) / val); - CLAMP(i, 0, 15); - j = 8 + (15.9f * (fpx1[a & 255] + fpx2[a >> 8]) / val); - CLAMP(j, 0, 15); - i = j + (i << 4); - st->centmask[a] = i; - } - - MEM_freeN(fpx1); - MEM_freeN(fpx2); - MEM_freeN(fpy1); - MEM_freeN(fpy2); -} - - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ struct Object *RE_GetCamera(Render *re) { @@ -435,37 +156,11 @@ static void re_camera_params_get(Render *re, CameraParams *params, Object *cam_o re->clipsta = params->clipsta; re->clipend = params->clipend; - re->ycor = params->ycor; - re->viewdx = params->viewdx; - re->viewdy = params->viewdy; re->viewplane = params->viewplane; BKE_camera_object_mode(&re->r, cam_ob); } -void RE_SetEnvmapCamera(Render *re, Object *cam_ob, float viewscale, float clipsta, float clipend) -{ - CameraParams params; - - /* setup parameters */ - BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, cam_ob); - - params.lens = 16.0f * viewscale; - params.sensor_x = 32.0f; - params.sensor_y = 32.0f; - params.sensor_fit = CAMERA_SENSOR_FIT_AUTO; - params.clipsta = clipsta; - params.clipend = clipend; - - /* compute matrix, viewplane, .. */ - BKE_camera_params_compute_viewplane(¶ms, re->winx, re->winy, 1.0f, 1.0f); - BKE_camera_params_compute_matrix(¶ms); - - /* extract results */ - re_camera_params_get(re, ¶ms, cam_ob); -} - void RE_SetOverrideCamera(Render *re, Object *camera) { re->camera_override = camera; @@ -487,10 +182,6 @@ void RE_SetCamera(Render *re, Object *cam_ob) BKE_camera_params_from_object(¶ms, cam_ob); re_camera_params_stereo3d(re, ¶ms, cam_ob); - params.use_fields = (re->r.mode & R_FIELDS); - params.field_second = (re->flag & R_SEC_FIELD); - params.field_odd = (re->r.mode & R_ODDFIELD); - /* compute matrix, viewplane, .. */ BKE_camera_params_compute_viewplane(¶ms, re->winx, re->winy, re->r.xasp, re->r.yasp); BKE_camera_params_compute_matrix(¶ms); @@ -499,12 +190,6 @@ void RE_SetCamera(Render *re, Object *cam_ob) re_camera_params_get(re, ¶ms, cam_ob); } -void RE_SetPixelSize(Render *re, float pixsize) -{ - re->viewdx = pixsize; - re->viewdy = re->ycor * pixsize; -} - void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[4][4]) { re->r.cfra = frame; @@ -522,13 +207,6 @@ void RE_GetCameraModelMatrix(Render *re, struct Object *camera, float r_mat[4][4 void RE_parts_free(Render *re) { - RenderPart *part = re->parts.first; - - while (part) { - if (part->rectp) MEM_freeN(part->rectp); - if (part->rectz) MEM_freeN(part->rectz); - part = part->next; - } BLI_freelistN(&re->parts); } @@ -539,7 +217,7 @@ void RE_parts_clamp(Render *re) re->party = max_ii(1, min_ii(re->r.tiley, re->recty)); } -void RE_parts_init(Render *re, bool do_crop) +void RE_parts_init(Render *re) { int nr, xd, yd, partx, party, xparts, yparts; int xminb, xmaxb, yminb, ymaxb; @@ -565,10 +243,6 @@ void RE_parts_init(Render *re, bool do_crop) xparts = (re->rectx + partx - 1) / partx; yparts = (re->recty + party - 1) / party; - /* calculate rotation factor of 1 pixel */ - if (re->r.mode & R_PANORAMA) - re->panophi = panorama_pixel_rot(re); - for (nr = 0; nr < xparts * yparts; nr++) { rcti disprect; int rectx, recty; @@ -601,16 +275,6 @@ void RE_parts_init(Render *re, bool do_crop) if (rectx > 0 && recty > 0) { RenderPart *pa = MEM_callocN(sizeof(RenderPart), "new part"); - /* Non-box filters need 2 pixels extra to work */ - if (do_crop && (re->r.filtertype || (re->r.mode & R_EDGE))) { - pa->crop = 2; - disprect.xmin -= pa->crop; - disprect.ymin -= pa->crop; - disprect.xmax += pa->crop; - disprect.ymax += pa->crop; - rectx += 2 * pa->crop; - recty += 2 * pa->crop; - } pa->disprect = disprect; pa->rectx = rectx; pa->recty = recty; diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c index 6f66f6d3520..d506028e306 100644 --- a/source/blender/render/intern/source/multires_bake.c +++ b/source/blender/render/intern/source/multires_bake.c @@ -36,20 +36,23 @@ #include "DNA_object_types.h" #include "DNA_mesh_types.h" +#include "DNA_scene_types.h" #include "BLI_math.h" #include "BLI_listbase.h" #include "BLI_threads.h" #include "BKE_ccg.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_multires.h" #include "BKE_modifier.h" #include "BKE_subsurf.h" +#include "DEG_depsgraph.h" + #include "RE_multires_bake.h" #include "RE_pipeline.h" #include "RE_shader_ext.h" @@ -57,10 +60,6 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" -#include "rayintersection.h" -#include "rayobject.h" -#include "rendercore.h" - typedef void (*MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *thread_data, void *bake_data, ImBuf *ibuf, const int face_index, const int lvl, const float st[2], float tangmat[3][3], const int x, const int y); @@ -78,7 +77,6 @@ typedef struct { MLoop *mloop; MLoopUV *mloopuv; const MLoopTri *mlooptri; - MTexPoly *mtpoly; float *pvtangent; const float *precomputed_normals; int w, h; @@ -89,6 +87,8 @@ typedef struct { void *bake_data; ImBuf *ibuf; MPassKnownData pass_data; + /* material aligned UV array */ + Image **image_array; } MResolvePixelData; typedef void (*MFlushPixel)(const MResolvePixelData *data, const int x, const int y); @@ -112,19 +112,6 @@ typedef struct { const int *orig_index_mp_to_orig; } MNormalBakeData; -typedef struct { - int number_of_rays; - float bias; - - unsigned short *permutation_table_1; - unsigned short *permutation_table_2; - - RayObject *raytree; - RayFace *rayfaces; - - const int *orig_index_mp_to_orig; -} MAOBakeData; - static void multiresbake_get_normal(const MResolvePixelData *data, float norm[],const int tri_num, const int vert_index) { const int poly_index = data->mlooptri[tri_num].poly; @@ -373,13 +360,15 @@ static void *do_multires_bake_thread(void *data_v) 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; + const MPoly *mp = &data->mpoly[lt->poly]; + const short mat_nr = mp->mat_nr; + const MLoopUV *mloopuv = data->mloopuv; if (multiresbake_test_break(bkr)) break; - if (mtpoly->tpage != handle->image) + Image *tri_image = mat_nr < bkr->ob_image.len ? bkr->ob_image.array[mat_nr] : NULL; + if (tri_image != handle->image) continue; data->tri_index = tri_index; @@ -445,7 +434,6 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t 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; @@ -489,7 +477,6 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t handle->data.mvert = mvert; 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 */ @@ -881,6 +868,8 @@ static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, } } +/* TODO: restore ambient occlusion baking support, using BLI BVH? */ +#if 0 /* **************** Ambient Occlusion Baker **************** */ // must be a power of two @@ -1173,35 +1162,101 @@ static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void rrgb[3] = 255; } } +#endif + +/* ******$***************** Post processing ************************* */ + +static void bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter) +{ + /* must check before filtering */ + const bool is_new_alpha = (ibuf->planes != R_IMF_PLANES_RGBA) && BKE_imbuf_alpha_test(ibuf); + + /* Margin */ + if (filter) { + IMB_filter_extend(ibuf, mask, filter); + } + + /* if the bake results in new alpha then change the image setting */ + if (is_new_alpha) { + ibuf->planes = R_IMF_PLANES_RGBA; + } + else { + if (filter && ibuf->planes != R_IMF_PLANES_RGBA) { + /* clear alpha added by filtering */ + IMB_rectfill_alpha(ibuf, 1.0f); + } + } +} + +static void bake_ibuf_normalize_displacement(ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max) +{ + int i; + const float *current_displacement = displacement; + const char *current_mask = mask; + float max_distance; + + max_distance = max_ff(fabsf(displacement_min), fabsf(displacement_max)); + + for (i = 0; i < ibuf->x * ibuf->y; i++) { + if (*current_mask == FILTER_MASK_USED) { + float normalized_displacement; + + if (max_distance > 1e-5f) + normalized_displacement = (*current_displacement + max_distance) / (max_distance * 2); + else + normalized_displacement = 0.5f; + + if (ibuf->rect_float) { + /* currently baking happens to RGBA only */ + float *fp = ibuf->rect_float + i * 4; + fp[0] = fp[1] = fp[2] = normalized_displacement; + fp[3] = 1.0f; + } + + if (ibuf->rect) { + unsigned char *cp = (unsigned char *) (ibuf->rect + i); + cp[0] = cp[1] = cp[2] = unit_float_to_uchar_clamp(normalized_displacement); + cp[3] = 255; + } + } + + current_displacement++; + current_mask++; + } +} /* **************** Common functions public API relates on **************** */ static void count_images(MultiresBakeRender *bkr) { - int a, totpoly; - DerivedMesh *dm = bkr->lores_dm; - MTexPoly *mtexpoly = CustomData_get_layer(&dm->polyData, CD_MTEXPOLY); - BLI_listbase_clear(&bkr->image); bkr->tot_image = 0; - totpoly = dm->getNumPolys(dm); - - for (a = 0; a < totpoly; a++) - mtexpoly[a].tpage->id.tag &= ~LIB_TAG_DOIT; + for (int i = 0; i < bkr->ob_image.len; i++) { + Image *ima = bkr->ob_image.array[i]; + if (ima) { + ima->id.tag &= ~LIB_TAG_DOIT; + } + } - for (a = 0; a < totpoly; a++) { - Image *ima = mtexpoly[a].tpage; - if ((ima->id.tag & LIB_TAG_DOIT) == 0) { - LinkData *data = BLI_genericNodeN(ima); - BLI_addtail(&bkr->image, data); - bkr->tot_image++; - ima->id.tag |= LIB_TAG_DOIT; + for (int i = 0; i < bkr->ob_image.len; i++) { + Image *ima = bkr->ob_image.array[i]; + if (ima) { + if ((ima->id.tag & LIB_TAG_DOIT) == 0) { + LinkData *data = BLI_genericNodeN(ima); + BLI_addtail(&bkr->image, data); + bkr->tot_image++; + ima->id.tag |= LIB_TAG_DOIT; + } } } - for (a = 0; a < totpoly; a++) - mtexpoly[a].tpage->id.tag &= ~LIB_TAG_DOIT; + for (int i = 0; i < bkr->ob_image.len; i++) { + Image *ima = bkr->ob_image.array[i]; + if (ima) { + ima->id.tag &= ~LIB_TAG_DOIT; + } + } } static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result) @@ -1222,12 +1277,14 @@ static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result) do_multires_bake(bkr, ima, true, apply_tangmat_callback, init_normal_data, free_normal_data, result); break; case RE_BAKE_DISPLACEMENT: - case RE_BAKE_DERIVATIVE: do_multires_bake(bkr, ima, false, apply_heights_callback, init_heights_data, free_heights_data, result); break; +/* TODO: restore ambient occlusion baking support. */ +#if 0 case RE_BAKE_AO: do_multires_bake(bkr, ima, false, apply_ao_callback, init_ao_data, free_ao_data, result); break; +#endif } } @@ -1240,7 +1297,7 @@ static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result) static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result) { LinkData *link; - bool use_displacement_buffer = ELEM(bkr->mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE); + bool use_displacement_buffer = bkr->mode == RE_BAKE_DISPLACEMENT; for (link = bkr->image.first; link; link = link->next) { Image *ima = (Image *)link->data; @@ -1251,17 +1308,11 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result) continue; if (use_displacement_buffer) { - if (bkr->mode == RE_BAKE_DERIVATIVE) { - RE_bake_make_derivative(ibuf, userdata->displacement_buffer, userdata->mask_buffer, - result->height_min, result->height_max, bkr->user_scale); - } - else { - RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, - result->height_min, result->height_max); - } + bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, + result->height_min, result->height_max); } - RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter); + bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter); ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID; @@ -1283,7 +1334,7 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result) } BKE_image_release_ibuf(ima, ibuf, NULL); - DAG_id_tag_update(&ima->id, 0); + DEG_id_tag_update(&ima->id, 0); } } diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 707f126b202..0ca9aa41056 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -64,9 +64,9 @@ #include "BKE_animsys.h" /* <------ should this be here?, needed for sequencer update */ #include "BKE_camera.h" #include "BKE_colortools.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_remap.h" #include "BKE_main.h" @@ -80,6 +80,10 @@ #include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */ #include "BKE_object.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" + #include "PIL_time.h" #include "IMB_colormanagement.h" #include "IMB_imbuf.h" @@ -88,6 +92,10 @@ #include "RE_engine.h" #include "RE_pipeline.h" +#include "RE_render_ext.h" + +#include "../../../windowmanager/WM_api.h" /* XXX */ +#include "../../../intern/gawain/gawain/gwn_context.h" #ifdef WITH_FREESTYLE # include "FRS_freestyle.h" @@ -96,14 +104,10 @@ #include "DEG_depsgraph.h" /* internal */ +#include "initrender.h" +#include "renderpipeline.h" #include "render_result.h" #include "render_types.h" -#include "renderpipeline.h" -#include "renderdatabase.h" -#include "rendercore.h" -#include "initrender.h" -#include "pixelblending.h" -#include "zbuf.h" /* render flow * @@ -138,19 +142,10 @@ static struct { ListBase renderlist; } RenderGlobal = {{NULL, NULL}}; -/* hardcopy of current render, used while rendering for speed */ -Render R; - /* ********* alloc and free ******** */ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const int totvideos, const char *name_override); -static volatile int g_break = 0; -static int thread_break(void *UNUSED(arg)) -{ - return g_break; -} - /* default callbacks, set in each new render */ static void result_nothing(void *UNUSED(arg), RenderResult *UNUSED(rr)) {} static void result_rcti_nothing(void *UNUSED(arg), RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect)) {} @@ -270,11 +265,11 @@ RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, bool RenderLayer *render_get_active_layer(Render *re, RenderResult *rr) { - SceneRenderLayer *srl = BLI_findlink(&re->r.layers, re->r.actlay); + ViewLayer *view_layer = BLI_findlink(&re->view_layers, re->active_view_layer); - if (srl) { + if (view_layer) { RenderLayer *rl = BLI_findstring(&rr->layers, - srl->name, + view_layer->name, offsetof(RenderLayer, name)); if (rl) { @@ -285,23 +280,15 @@ RenderLayer *render_get_active_layer(Render *re, RenderResult *rr) return rr->layers.first; } -static int render_scene_needs_vector(Render *re) +static bool render_scene_has_layers_to_render(Scene *scene, ViewLayer *single_layer) { - SceneRenderLayer *srl; - - for (srl = re->r.layers.first; srl; srl = srl->next) - if (!(srl->layflag & SCE_LAY_DISABLE)) - if (srl->passflag & SCE_PASS_VECTOR) - return 1; - - return 0; -} + if (single_layer) { + return true; + } -static bool render_scene_has_layers_to_render(Scene *scene) -{ - SceneRenderLayer *srl; - for (srl = scene->r.layers.first; srl; srl = srl->next) { - if (!(srl->layflag & SCE_LAY_DISABLE)) { + ViewLayer *view_layer; + for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + if (view_layer->flag & VIEW_LAYER_RENDER) { return true; } } @@ -517,14 +504,10 @@ Render *RE_NewRender(const char *name) BLI_strncpy(re->name, name, RE_MAXNAME); BLI_rw_mutex_init(&re->resultmutex); BLI_rw_mutex_init(&re->partsmutex); - re->eval_ctx = DEG_evaluation_context_new(DAG_EVAL_RENDER); } RE_InitRenderCB(re); - /* init some variables */ - re->ycor = 1.0f; - return re; } @@ -586,7 +569,7 @@ void RE_FreeRender(Render *re) BLI_rw_mutex_end(&re->resultmutex); BLI_rw_mutex_end(&re->partsmutex); - BLI_freelistN(&re->r.layers); + BLI_freelistN(&re->view_layers); BLI_freelistN(&re->r.views); curvemapping_free_data(&re->r.mblur_shutter_curve); @@ -595,14 +578,10 @@ void RE_FreeRender(Render *re) re->main = NULL; re->scene = NULL; - RE_Database_Free(re); /* view render can still have full database */ - free_sample_tables(re); - render_result_free(re->result); render_result_free(re->pushedresult); BLI_remlink(&RenderGlobal.renderlist, re); - MEM_freeN(re->eval_ctx); MEM_freeN(re); } @@ -667,14 +646,8 @@ 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; + /* not supported by any current renderer */ + scemode &= ~R_FULL_SAMPLE; #ifdef WITH_OPENEXR if (scemode & R_FULL_SAMPLE) @@ -694,7 +667,7 @@ static void re_init_resolution(Render *re, Render *source, re->winy = winy; if (source && (source->r.mode & R_BORDER)) { /* eeh, doesn't seem original bordered disprect is storing anywhere - * after insertion on black happening in do_render_fields_blur_3d(), + * after insertion on black happening in do_render(), * so for now simply re-calculate disprect using border from source * renderer (sergey) */ @@ -723,20 +696,15 @@ static void re_init_resolution(Render *re, Render *source, re->rectx = winx; re->recty = winy; } - - /* we clip faces with a minimum of 2 pixel boundary outside of image border. see zbuf.c */ - re->clipcrop = 1.0f + 2.0f / (float)(re->winx > re->winy ? re->winy : re->winx); } void render_copy_renderdata(RenderData *to, RenderData *from) { - BLI_freelistN(&to->layers); BLI_freelistN(&to->views); curvemapping_free_data(&to->mblur_shutter_curve); *to = *from; - BLI_duplicatelist(&to->layers, &from->layers); BLI_duplicatelist(&to->views, &from->views); curvemapping_copy_data(&to->mblur_shutter_curve, &from->mblur_shutter_curve); } @@ -744,7 +712,7 @@ void render_copy_renderdata(RenderData *to, RenderData *from) /* what doesn't change during entire render sequence */ /* disprect is optional, if NULL it assumes full window render */ void RE_InitState(Render *re, Render *source, RenderData *rd, - SceneRenderLayer *srl, + ListBase *render_layers, ViewLayer *single_layer, int winx, int winy, rcti *disprect) { bool had_freestyle = (re->r.mode & R_EDGE_FRS) != 0; @@ -755,6 +723,9 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, /* copy render data and render layers for thread safety */ render_copy_renderdata(&re->r, rd); + BLI_freelistN(&re->view_layers); + BLI_duplicatelist(&re->view_layers, render_layers); + re->active_view_layer = 0; if (source) { /* reuse border flags from source renderer */ @@ -786,34 +757,14 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, re->r.scemode = check_mode_full_sample(&re->r); - /* fullsample wants uniform osa levels */ - if (source && (re->r.scemode & R_FULL_SAMPLE)) { - /* but, if source has no full sample we disable it */ - if ((source->r.scemode & R_FULL_SAMPLE) == 0) - re->r.scemode &= ~R_FULL_SAMPLE; - else - re->r.osa = re->osa = source->osa; - } - else { - /* check state variables, osa? */ - if (re->r.mode & (R_OSA)) { - re->osa = re->r.osa; - if (re->osa > 16) re->osa = 16; - } - else re->osa = 0; - } - - if (srl) { - int index = BLI_findindex(&rd->layers, srl); + if (single_layer) { + int index = BLI_findindex(render_layers, single_layer); if (index != -1) { - re->r.actlay = index; + re->active_view_layer = index; re->r.scemode |= R_SINGLE_LAYER; } } - /* always call, checks for gamma, gamma tables and jitter too */ - make_sample_tables(re); - /* if preview render, we try to keep old result */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); @@ -824,12 +775,12 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, re->result = NULL; } else if (re->result) { - SceneRenderLayer *actsrl = BLI_findlink(&re->r.layers, re->r.actlay); + ViewLayer *active_render_layer = BLI_findlink(&re->view_layers, re->active_view_layer); RenderLayer *rl; bool have_layer = false; for (rl = re->result->layers.first; rl; rl = rl->next) - if (STREQ(rl->name, actsrl->name)) + if (STREQ(rl->name, active_render_layer->name)) have_layer = true; if (re->result->rectx == re->rectx && re->result->recty == re->recty && @@ -855,19 +806,18 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, render_result_view_new(re->result, ""); } - if (re->r.scemode & R_VIEWPORT_PREVIEW) - re->eval_ctx->mode = DAG_EVAL_PREVIEW; - else - re->eval_ctx->mode = DAG_EVAL_RENDER; + eEvaluationMode mode = (re->r.scemode & R_VIEWPORT_PREVIEW) ? DAG_EVAL_PREVIEW : DAG_EVAL_RENDER; + /* This mode should have been set in the Depsgraph immediately when it was created. */ + (void)mode; /* ensure renderdatabase can use part settings correct */ RE_parts_clamp(re); BLI_rw_mutex_unlock(&re->resultmutex); - re->mblur_offs = re->field_offs = 0.f; - RE_init_threadcount(re); + + RE_point_density_fix_linking(); } /* This function is only called by view3d rendering, which doesn't support @@ -954,13 +904,12 @@ void RE_ChangeModeFlag(Render *re, int flag, bool clear) /* update some variables that can be animated, and otherwise wouldn't be due to * RenderData getting copied once at the start of animation render */ -void render_update_anim_renderdata(Render *re, RenderData *rd) +void render_update_anim_renderdata(Render *re, RenderData *rd, ListBase *render_layers) { /* filter */ re->r.gauss = rd->gauss; /* motion blur */ - re->r.mblur_samples = rd->mblur_samples; re->r.blurfac = rd->blurfac; /* freestyle */ @@ -968,8 +917,8 @@ void render_update_anim_renderdata(Render *re, RenderData *rd) re->r.unit_line_thickness = rd->unit_line_thickness; /* render layers */ - BLI_freelistN(&re->r.layers); - BLI_duplicatelist(&re->r.layers, &rd->layers); + BLI_freelistN(&re->view_layers); + BLI_duplicatelist(&re->view_layers, render_layers); /* render views */ BLI_freelistN(&re->r.views); @@ -1074,447 +1023,53 @@ void RE_test_break_cb(Render *re, void *handle, int (*f)(void *handle)) re->tbh = handle; } +/* ********* GL Context ******** */ -/* ********* add object data (later) ******** */ - -/* object is considered fully prepared on correct time etc */ -/* includes lights */ -#if 0 -void RE_AddObject(Render *UNUSED(re), Object *UNUSED(ob)) -{ - -} -#endif - -/* *************************************** */ - -static int render_display_update_enabled(Render *re) -{ - /* don't show preprocess for previewrender sss */ - if (re->sss_points) - return !(re->r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW)); - else - return 1; -} - -/* the main thread call, renders an entire part */ -static void *do_part_thread(void *pa_v) -{ - RenderPart *pa = pa_v; - - pa->status = PART_STATUS_IN_PROGRESS; - - /* need to return nicely all parts on esc */ - 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, R.viewname); - else - 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. - * - * TODO(sergey): This actually duplicates logic with external engine, so - * worth looking into more generic solution. - */ - pa->result->do_exr_tile = R.result->do_exr_tile; - - if (R.sss_points) - zbufshade_sss_tile(pa); - else if (R.osa) - zbufshadeDA_tile(pa); - else - zbufshade_tile(pa); - - /* we do actually write pixels, but don't allocate/deallocate anything, - * so it is safe with other threads reading at the same time */ - BLI_rw_mutex_lock(&R.resultmutex, THREAD_LOCK_READ); - - /* merge too on break! */ - if (R.result->do_exr_tile) { - 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 */ - if (R.test_break(R.tbh) && (R.r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))) { - /* pass */ - } - else { - render_result_merge(R.result, pa->result); - } - } - - BLI_rw_mutex_unlock(&R.resultmutex); - } - - pa->status = PART_STATUS_MERGED; - - return NULL; -} - -/* calculus for how much 1 pixel rendered should rotate the 3d geometry */ -/* is not that simple, needs to be corrected for errors of larger viewplane sizes */ -/* called in initrender.c, RE_parts_init() and convertblender.c, for speedvectors */ -float panorama_pixel_rot(Render *re) -{ - float psize, phi, xfac; - float borderfac = (float)BLI_rcti_size_x(&re->disprect) / (float)re->winx; - int xparts = (re->rectx + re->partx - 1) / re->partx; - - /* size of 1 pixel mapped to viewplane coords */ - psize = BLI_rctf_size_x(&re->viewplane) / (float)re->winx; - /* angle of a pixel */ - phi = atan(psize / re->clipsta); - - /* correction factor for viewplane shifting, first calculate how much the viewplane angle is */ - xfac = borderfac * BLI_rctf_size_x(&re->viewplane) / (float)xparts; - xfac = atan(0.5f * xfac / re->clipsta); - /* and how much the same viewplane angle is wrapped */ - psize = 0.5f * phi * ((float)re->partx); - - /* the ratio applied to final per-pixel angle */ - phi *= xfac / psize; - - return phi; -} - -/* for panorama, we render per Y slice, and update - * camera parameters when we go the next slice */ -static bool find_next_pano_slice(Render *re, int *slice, int *minx, rctf *viewplane) +void RE_gl_context_create(Render *re) { - RenderPart *pa, *best = NULL; - bool found = false; - - *minx = re->winx; - - if (!(re->r.mode & R_PANORAMA)) { - /* for regular render, just one 'slice' */ - found = (*slice == 0); - (*slice)++; - return found; - } - - /* most left part of the non-rendering parts */ - for (pa = re->parts.first; pa; pa = pa->next) { - if (pa->status == PART_STATUS_NONE && pa->nr == 0) { - if (pa->disprect.xmin < *minx) { - found = true; - best = pa; - *minx = pa->disprect.xmin; - } - } - } - - if (best) { - float phi = panorama_pixel_rot(re); - - R.panodxp = (re->winx - (best->disprect.xmin + best->disprect.xmax) ) / 2; - R.panodxv = (BLI_rctf_size_x(viewplane) * R.panodxp) / (float)(re->winx); - - /* shift viewplane */ - R.viewplane.xmin = viewplane->xmin + R.panodxv; - R.viewplane.xmax = viewplane->xmax + R.panodxv; - RE_SetWindow(re, &R.viewplane, R.clipsta, R.clipend); - copy_m4_m4(R.winmat, re->winmat); - - /* rotate database according to part coordinates */ - project_renderdata(re, projectverto, 1, -R.panodxp * phi, 1); - R.panosi = sinf(R.panodxp * phi); - R.panoco = cosf(R.panodxp * phi); - } - - (*slice)++; - - return found; -} - -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; + /* Needs to be created in the main ogl thread. */ + re->gl_context = WM_opengl_context_create(); } -static int sort_and_queue_parts(Render *re, int minx, ThreadQueue *workqueue) +void RE_gl_context_destroy(Render *re) { - RenderPart *pa; - - /* long long int's needed because of overflow [#24414] */ - long long int centx = re->winx / 2, centy = re->winy / 2, tot = 1; - int totsort = 0; - - /* find center of rendered parts, image center counts for 1 too */ - for (pa = re->parts.first; pa; pa = pa->next) { - if (pa->status >= PART_STATUS_RENDERED) { - centx += BLI_rcti_cent_x(&pa->disprect); - 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++; - } - } + /* Needs to be called from the thread which used the ogl context for rendering. */ + if (re->gwn_context) { + GWN_context_active_set(re->gwn_context); + GWN_context_discard(re->gwn_context); + re->gwn_context = NULL; } - centx /= tot; - centy /= tot; - - 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; + if (re->gl_context) { + WM_opengl_context_dispose(re->gl_context); + re->gl_context = NULL; } - - return 0; } -static void print_part_stats(Render *re, RenderPart *pa) +void *RE_gl_context_get(Render *re) { - char str[64]; - - BLI_snprintf(str, sizeof(str), IFACE_("%s, Part %d-%d"), re->scene->id.name + 2, pa->nr, re->i.totpart); - re->i.infostr = str; - re->stats_draw(re->sdh, &re->i); - re->i.infostr = NULL; + return re->gl_context; } -typedef struct RenderThread { - ThreadQueue *workqueue; - ThreadQueue *donequeue; - - int number; - - void (*display_update)(void *handle, RenderResult *rr, volatile rcti *rect); - void *duh; -} RenderThread; - -static void *do_render_thread(void *thread_v) +void *RE_gwn_context_get(Render *re) { - RenderThread *thread = thread_v; - RenderPart *pa; - - while ((pa = BLI_thread_queue_pop(thread->workqueue))) { - pa->thread = thread->number; - do_part_thread(pa); - - if (thread->display_update) { - thread->display_update(thread->duh, pa->result, NULL); - } - - BLI_thread_queue_push(thread->donequeue, pa); - - if (R.test_break(R.tbh)) - break; + if (re->gwn_context == NULL) { + re->gwn_context = GWN_context_create(); } - - return NULL; + return re->gwn_context; } -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); - } -} +/* ********* add object data (later) ******** */ -static void main_render_result_new(Render *re) +/* object is considered fully prepared on correct time etc */ +/* includes lights */ +#if 0 +void RE_AddObject(Render *UNUSED(re), Object *UNUSED(ob)) { - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - - /* first step; free the entire render result, make new, and/or prepare exr buffer saving */ - if (re->result == NULL || !(re->r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))) { - 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, 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, 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, RR_ALL_VIEWS); - } - BLI_rw_mutex_unlock(&re->resultmutex); - - if (re->result) { - if (re->result->do_exr_tile) { - render_result_exr_file_begin(re); - } - } } +#endif -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); - - /* assuming no new data gets added to dbase... */ - R = *re; - - /* set threadsafe break */ - R.test_break = thread_break; - - /* create and fill work queue */ - workqueue = BLI_thread_queue_init(); - donequeue = BLI_thread_queue_init(); - - /* for panorama we loop over slices */ - while (find_next_pano_slice(re, &slice, &minx, &viewplane)) { - /* gather parts into queue */ - totpart = sort_and_queue_parts(re, minx, workqueue); - - BLI_thread_queue_nowait(workqueue); - - /* start all threads */ - BLI_threadpool_init(&threads, do_render_thread, re->r.threads); - - for (a = 0; a < re->r.threads; a++) { - thread[a].workqueue = workqueue; - thread[a].donequeue = donequeue; - thread[a].number = a; - - if (render_display_update_enabled(re)) { - thread[a].display_update = re->display_update; - thread[a].duh = re->duh; - } - else { - thread[a].display_update = NULL; - thread[a].duh = NULL; - } - - BLI_threadpool_insert(&threads, &thread[a]); - } - - /* wait for results to come back */ - lastdraw = PIL_check_seconds_timer(); - - while (1) { - elapsed = PIL_check_seconds_timer() - lastdraw; - wait = (redrawtime - elapsed)*1000; - - /* handle finished part */ - if ((pa=BLI_thread_queue_pop_timeout(donequeue, wait))) { - if (pa->result) { - print_part_stats(re, pa); - - render_result_free_list(&pa->fullresult, pa->result); - pa->result = NULL; - re->i.partsdone++; - re->progress(re->prh, re->i.partsdone / (float)re->i.totpart); - } - - totpart--; - } - - /* check for render cancel */ - if ((g_break=re->test_break(re->tbh))) - break; - - /* or done with parts */ - if (totpart == 0) - break; - - /* redraw in progress parts */ - elapsed = PIL_check_seconds_timer() - lastdraw; - if (elapsed > redrawtime) { - if (render_display_update_enabled(re)) - for (pa = re->parts.first; pa; pa = pa->next) - if ((pa->status == PART_STATUS_IN_PROGRESS) && pa->nr && pa->result) - re->display_update(re->duh, pa->result, &pa->result->renrect); - - lastdraw = PIL_check_seconds_timer(); - } - } - - BLI_threadpool_end(&threads); - - if ((g_break=re->test_break(re->tbh))) - break; - } - - if (g_break) { - /* review the done queue and handle all the render parts, - * so no unfreed render result are lurking around - */ - BLI_thread_queue_nowait(donequeue); - while ((pa = BLI_thread_queue_pop(donequeue))) { - if (pa->result) { - render_result_free_list(&pa->fullresult, pa->result); - pa->result = NULL; - } - } - } - - 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_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); @@ -1522,349 +1077,13 @@ static void add_freestyle(Render *re, int render); static void free_all_freestyle_renders(void); #endif -/* 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; - re->stats_draw(re->sdh, &re->i); - -#ifdef WITH_FREESTYLE - /* 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; - re->stats_draw(re->sdh, &re->i); - } - } -#endif - -} /* ************ This part uses API, for rendering Blender scenes ********** */ static void do_render_3d(Render *re) { - RenderView *rv; - re->current_scene_update(re->suh, re->scene); - - /* try external */ - if (RE_engine_render(re, 0)) - return; - - /* internal */ - RE_parts_clamp(re); - - /* add motion blur and fields offset to frames */ - const int cfra_backup = re->scene->r.cfra; - const float subframe_backup = re->scene->r.subframe; - - BKE_scene_frame_set( - re->scene, (double)re->scene->r.cfra + (double)re->scene->r.subframe + - (double)re->mblur_offs + (double)re->field_offs); - - /* init main render result */ - main_render_result_new(re); - if (re->result == NULL) { - BKE_report(re->reports, RPT_ERROR, "Failed allocate render result, out of memory"); - G.is_break = true; - return; - } - -#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); - - 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); -#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); - } - - main_render_result_end(re); - - re->scene->r.cfra = cfra_backup; - re->scene->r.subframe = subframe_backup; -} - -/* called by blur loop, accumulate RGBA key alpha */ -static void addblur_rect_key(RenderResult *rr, float *rectf, float *rectf1, float blurfac) -{ - float mfac = 1.0f - blurfac; - int a, b, stride = 4 * rr->rectx; - int len = stride * sizeof(float); - - for (a = 0; a < rr->recty; a++) { - if (blurfac == 1.0f) { - memcpy(rectf, rectf1, len); - } - else { - float *rf = rectf, *rf1 = rectf1; - - for (b = rr->rectx; b > 0; b--, rf += 4, rf1 += 4) { - if (rf1[3] < 0.01f) - rf[3] = mfac * rf[3]; - else if (rf[3] < 0.01f) { - rf[0] = rf1[0]; - rf[1] = rf1[1]; - rf[2] = rf1[2]; - rf[3] = blurfac * rf1[3]; - } - else { - rf[0] = mfac * rf[0] + blurfac * rf1[0]; - rf[1] = mfac * rf[1] + blurfac * rf1[1]; - rf[2] = mfac * rf[2] + blurfac * rf1[2]; - rf[3] = mfac * rf[3] + blurfac * rf1[3]; - } - } - } - rectf += stride; - rectf1 += stride; - } -} - -/* called by blur loop, accumulate renderlayers */ -static void addblur_rect(RenderResult *rr, float *rectf, float *rectf1, float blurfac, int channels) -{ - float mfac = 1.0f - blurfac; - int a, b, stride = channels * rr->rectx; - int len = stride * sizeof(float); - - for (a = 0; a < rr->recty; a++) { - if (blurfac == 1.0f) { - memcpy(rectf, rectf1, len); - } - else { - float *rf = rectf, *rf1 = rectf1; - - for (b = rr->rectx * channels; b > 0; b--, rf++, rf1++) { - rf[0] = mfac * rf[0] + blurfac * rf1[0]; - } - } - rectf += stride; - rectf1 += stride; - } -} - - -/* called by blur loop, accumulate renderlayers */ -static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float blurfac, bool key_alpha) -{ - RenderLayer *rl, *rl1; - RenderPass *rpass, *rpass1; - - rl1 = brr->layers.first; - for (rl = rr->layers.first; rl && rl1; rl = rl->next, rl1 = rl1->next) { - /* passes are allocated in sync */ - rpass1 = rl1->passes.first; - for (rpass = rl->passes.first; rpass && rpass1; rpass = rpass->next, rpass1 = rpass1->next) { - if (STREQ(rpass->name, RE_PASSNAME_COMBINED) && key_alpha) - addblur_rect_key(rr, rpass->rect, rpass1->rect, blurfac); - else - addblur_rect(rr, rpass->rect, rpass1->rect, blurfac, rpass->channels); - } - } -} - -/* main blur loop, can be called by fields too */ -static void do_render_blur_3d(Render *re) -{ - RenderResult *rres; - float blurfac; - int blur = re->r.mblur_samples; - - /* create accumulation render result */ - rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); - - /* do the blur steps */ - while (blur--) { - re->mblur_offs = re->r.blurfac * ((float)(re->r.mblur_samples - blur)) / (float)re->r.mblur_samples; - - re->i.curblur = re->r.mblur_samples - blur; /* stats */ - - do_render_3d(re); - - blurfac = 1.0f / (float)(re->r.mblur_samples - blur); - - merge_renderresult_blur(rres, re->result, blurfac, false); - if (re->test_break(re->tbh)) break; - } - - /* swap results */ - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - render_result_free(re->result); - re->result = rres; - BLI_rw_mutex_unlock(&re->resultmutex); - - re->mblur_offs = 0.0f; - re->i.curblur = 0; /* stats */ - - /* make sure motion blur changes get reset to current frame */ - if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))==0) { - BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, re->lay); - } - - /* 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); -} - - -/* function assumes rectf1 and rectf2 to be half size of rectf */ -static void interleave_rect(RenderResult *rr, float *rectf, float *rectf1, float *rectf2, int channels) -{ - int a, stride = channels * rr->rectx; - int len = stride * sizeof(float); - - for (a = 0; a < rr->recty; a += 2) { - memcpy(rectf, rectf1, len); - rectf += stride; - rectf1 += stride; - memcpy(rectf, rectf2, len); - rectf += stride; - rectf2 += stride; - } -} - -/* merge render results of 2 fields */ -static void merge_renderresult_fields(RenderResult *rr, RenderResult *rr1, RenderResult *rr2) -{ - RenderLayer *rl, *rl1, *rl2; - RenderPass *rpass, *rpass1, *rpass2; - - rl1 = rr1->layers.first; - rl2 = rr2->layers.first; - for (rl = rr->layers.first; rl && rl1 && rl2; rl = rl->next, rl1 = rl1->next, rl2 = rl2->next) { - - /* passes are allocated in sync */ - rpass1 = rl1->passes.first; - rpass2 = rl2->passes.first; - for (rpass = rl->passes.first; - rpass && rpass1 && rpass2; - rpass = rpass->next, rpass1 = rpass1->next, rpass2 = rpass2->next) - { - interleave_rect(rr, rpass->rect, rpass1->rect, rpass2->rect, rpass->channels); - } - } -} - - -/* interleaves 2 frames */ -static void do_render_fields_3d(Render *re) -{ - Object *camera = RE_GetCamera(re); - RenderResult *rr1, *rr2 = NULL; - - /* no render result was created, we can safely halve render y */ - re->winy /= 2; - re->recty /= 2; - re->disprect.ymin /= 2; - re->disprect.ymax /= 2; - - re->i.curfield = 1; /* stats */ - - /* first field, we have to call camera routine for correct aspect and subpixel offset */ - RE_SetCamera(re, camera); - if (re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE) == 0) - do_render_blur_3d(re); - else - do_render_3d(re); - - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - rr1 = re->result; - re->result = NULL; - BLI_rw_mutex_unlock(&re->resultmutex); - - /* second field */ - if (!re->test_break(re->tbh)) { - - re->i.curfield = 2; /* stats */ - - re->flag |= R_SEC_FIELD; - if ((re->r.mode & R_FIELDSTILL) == 0) { - re->field_offs = 0.5f; - } - RE_SetCamera(re, camera); - if (re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE) == 0) - do_render_blur_3d(re); - else - do_render_3d(re); - re->flag &= ~R_SEC_FIELD; - - re->field_offs = 0.0f; - - rr2 = re->result; - } - - /* allocate original height new buffers */ - re->winy *= 2; - re->recty *= 2; - re->disprect.ymin *= 2; - 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, RR_ALL_VIEWS); - - if (rr2) { - if (re->r.mode & R_ODDFIELD) - merge_renderresult_fields(re->result, rr2, rr1); - else - merge_renderresult_fields(re->result, rr1, rr2); - - render_result_free(rr2); - } - - render_result_free(rr1); - - re->i.curfield = 0; /* stats */ - - /* weak... the display callback wants an active renderlayer pointer... */ - re->result->renlay = render_get_active_layer(re, re->result); - - BLI_rw_mutex_unlock(&re->resultmutex); - - re->display_update(re->duh, re->result, NULL); + RE_engine_render(re, 0); } /* make sure disprect is not affected by the render border */ @@ -1927,7 +1146,7 @@ static void render_result_uncrop(Render *re) } /* main render routine, no compositing */ -static void do_render_fields_blur_3d(Render *re) +static void do_render(Render *re) { Object *camera = RE_GetCamera(re); /* also check for camera here */ @@ -1940,12 +1159,7 @@ static void do_render_fields_blur_3d(Render *re) /* now use renderdata and camera to set viewplane */ RE_SetCamera(re, camera); - if (re->r.mode & R_FIELDS) - do_render_fields_3d(re); - else if (re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE) == 0) - do_render_blur_3d(re); - else - do_render_3d(re); + do_render_3d(re); /* when border render, check if we have to insert it in black */ render_result_uncrop(re); @@ -1971,7 +1185,7 @@ static void render_scene(Render *re, Scene *sce, int cfra) } /* initial setup */ - RE_InitState(resc, re, &sce->r, NULL, winx, winy, &re->disprect); + RE_InitState(resc, re, &sce->r, &sce->view_layers, NULL, winx, winy, &re->disprect); /* We still want to use 'rendercache' setting from org (main) scene... */ resc->r.scemode = (resc->r.scemode & ~R_EXR_CACHE_FILE) | (re->r.scemode & R_EXR_CACHE_FILE); @@ -1980,7 +1194,6 @@ static void render_scene(Render *re, Scene *sce, int cfra) resc->main = re->main; resc->scene = sce; resc->lay = sce->lay; - resc->scene_color_manage = BKE_scene_check_color_management_enabled(sce); /* ensure scene has depsgraph, base flags etc OK */ BKE_scene_set_background(re->main, sce); @@ -1995,7 +1208,7 @@ static void render_scene(Render *re, Scene *sce, int cfra) resc->current_scene_update = re->current_scene_update; resc->suh = re->suh; - do_render_fields_blur_3d(resc); + do_render(resc); } /* helper call to detect if this scene needs a render, or if there's a any render layer to render */ @@ -2060,15 +1273,15 @@ bool RE_allow_render_generic_object(Object *ob) #ifdef DEPSGRAPH_WORKAROUND_HACK static void tag_dependend_object_for_render(Scene *scene, Object *object); -static void tag_dependend_group_for_render(Scene *scene, Group *group) +static void tag_dependend_group_for_render(Scene *scene, Collection *collection) { - if (group->id.tag & LIB_TAG_DOIT) { + if (collection->id.tag & LIB_TAG_DOIT) { return; } - group->id.tag |= LIB_TAG_DOIT; + collection->id.tag |= LIB_TAG_DOIT; - for (GroupObject *go = group->gobject.first; go != NULL; go = go->next) { - Object *object = go->ob; + for (CollectionObject *cob = collection->gobject.first; cob != NULL; cob = cob->next) { + Object *object = cob->ob; tag_dependend_object_for_render(scene, object); } } @@ -2081,7 +1294,7 @@ static void tag_dependend_object_for_render(Scene *scene, Object *object) VirtualModifierData virtualModifierData; if (object->particlesystem.first) { - DAG_id_tag_update(&object->id, OB_RECALC_DATA); + DEG_id_tag_update(&object->id, OB_RECALC_DATA); } for (md = modifiers_getVirtualModifierList(object, &virtualModifierData); @@ -2095,22 +1308,22 @@ static void tag_dependend_object_for_render(Scene *scene, Object *object) if (md->type == eModifierType_Boolean) { BooleanModifierData *bmd = (BooleanModifierData *)md; if (bmd->object && bmd->object->type == OB_MESH) { - DAG_id_tag_update(&bmd->object->id, OB_RECALC_DATA); + DEG_id_tag_update(&bmd->object->id, OB_RECALC_DATA); } } else if (md->type == eModifierType_Array) { ArrayModifierData *amd = (ArrayModifierData *)md; if (amd->start_cap && amd->start_cap->type == OB_MESH) { - DAG_id_tag_update(&amd->start_cap->id, OB_RECALC_DATA); + DEG_id_tag_update(&amd->start_cap->id, OB_RECALC_DATA); } if (amd->end_cap && amd->end_cap->type == OB_MESH) { - DAG_id_tag_update(&amd->end_cap->id, OB_RECALC_DATA); + DEG_id_tag_update(&amd->end_cap->id, OB_RECALC_DATA); } } else if (md->type == eModifierType_Shrinkwrap) { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md; if (smd->target && smd->target->type == OB_MESH) { - DAG_id_tag_update(&smd->target->id, OB_RECALC_DATA); + DEG_id_tag_update(&smd->target->id, OB_RECALC_DATA); } } else if (md->type == eModifierType_ParticleSystem) { @@ -2120,17 +1333,17 @@ static void tag_dependend_object_for_render(Scene *scene, Object *object) switch (part->ren_as) { case PART_DRAW_OB: if (part->dup_ob != NULL) { - DAG_id_tag_update(&part->dup_ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&part->dup_ob->id, OB_RECALC_DATA); } break; case PART_DRAW_GR: if (part->dup_group != NULL) { - for (GroupObject *go = part->dup_group->gobject.first; - go != NULL; - go = go->next) + FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(part->dup_group, base) { - DAG_id_tag_update(&go->ob->id, OB_RECALC_DATA); + Object *ob = base->object; + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } + FOREACH_COLLECTION_BASE_RECURSIVE_END } break; } @@ -2143,18 +1356,14 @@ static void tag_dependend_object_for_render(Scene *scene, Object *object) } } -static void tag_dependend_objects_for_render(Main *bmain, Scene *scene, int renderlay) +static void tag_dependend_objects_for_render(Main *bmain, Scene *scene) { - Scene *sce_iter; - Base *base; BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false); - for (SETLOOPER(scene, sce_iter, base)) { - Object *object = base->object; - if ((base->lay & renderlay) == 0) { - continue; - } + FOREACH_OBJECT_RENDERABLE_BEGIN(scene, object) + { tag_dependend_object_for_render(scene, object); } + FOREACH_OBJECT_RENDERABLE_END; } #endif @@ -2162,14 +1371,11 @@ static void tag_scenes_for_render(Render *re) { bNode *node; Scene *sce; -#ifdef DEPSGRAPH_WORKAROUND_HACK - int renderlay = re->lay; -#endif for (sce = re->main->scene.first; sce; sce = sce->id.next) { sce->id.tag &= ~LIB_TAG_DOIT; #ifdef DEPSGRAPH_WORKAROUND_HACK - tag_dependend_objects_for_render(re->main, sce, renderlay); + tag_dependend_objects_for_render(re->main, sce); #endif } @@ -2178,7 +1384,7 @@ static void tag_scenes_for_render(Render *re) for (sce = re->freestyle_bmain->scene.first; sce; sce = sce->id.next) { sce->id.tag &= ~LIB_TAG_DOIT; #ifdef DEPSGRAPH_WORKAROUND_HACK - tag_dependend_objects_for_render(re->freestyle_bmain, sce, renderlay); + tag_dependend_objects_for_render(re->freestyle_bmain, sce); #endif } } @@ -2187,7 +1393,7 @@ static void tag_scenes_for_render(Render *re) if (RE_GetCamera(re) && composite_needs_render(re->scene, 1)) { re->scene->id.tag |= LIB_TAG_DOIT; #ifdef DEPSGRAPH_WORKAROUND_HACK - tag_dependend_objects_for_render(re->main, re->scene, renderlay); + tag_dependend_objects_for_render(re->main, re->scene); #endif } @@ -2216,11 +1422,11 @@ static void tag_scenes_for_render(Render *re) if (node->id != (ID *)re->scene) { if ((node->id->tag & LIB_TAG_DOIT) == 0) { Scene *scene = (Scene *) node->id; - if (render_scene_has_layers_to_render(scene)) { + if (render_scene_has_layers_to_render(scene, NULL)) { node->flag |= NODE_TEST; node->id->tag |= LIB_TAG_DOIT; #ifdef DEPSGRAPH_WORKAROUND_HACK - tag_dependend_objects_for_render(re->main, scene, renderlay); + tag_dependend_objects_for_render(re->main, scene); #endif } } @@ -2242,6 +1448,10 @@ static void ntree_render_scenes(Render *re) tag_scenes_for_render(re); +#ifdef DEPSGRAPH_WORKAROUND_GROUP_HACK + tag_collections_for_render(re); +#endif + /* now foreach render-result node tagged we do a full render */ /* results are stored in a way compisitor will find it */ for (node = re->scene->nodetree->nodes.first; node; node = node->next) { @@ -2266,12 +1476,14 @@ static void ntree_render_scenes(Render *re) } /* bad call... need to think over proper method still */ -static void render_composit_stats(void *UNUSED(arg), const char *str) +static void render_composit_stats(void *arg, const char *str) { + Render *re = (Render*)arg; + RenderStats i; - memcpy(&i, &R.i, sizeof(i)); + memcpy(&i, &re->i, sizeof(i)); i.infostr = str; - R.stats_draw(R.sdh, &i); + re->stats_draw(re->sdh, &i); } #ifdef WITH_FREESTYLE @@ -2295,66 +1507,27 @@ static void init_freestyle(Render *re) /* invokes Freestyle stroke rendering */ static void add_freestyle(Render *re, int render) { - SceneRenderLayer *srl, *actsrl; + ViewLayer *view_layer, *active_view_layer; LinkData *link; Render *r; - const bool do_link = (re->r.mode & R_MBLUR) == 0 || re->i.curblur == re->r.mblur_samples; - actsrl = BLI_findlink(&re->r.layers, re->r.actlay); + active_view_layer = BLI_findlink(&re->view_layers, re->active_view_layer); FRS_begin_stroke_rendering(re); - for (srl = (SceneRenderLayer *)re->r.layers.first; srl; srl = srl->next) { - if (do_link) { - link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render"); - BLI_addtail(&re->freestyle_renders, link); - } - if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl) + for (view_layer = (ViewLayer *)re->view_layers.first; view_layer; view_layer = view_layer->next) { + link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render"); + BLI_addtail(&re->freestyle_renders, link); + + if ((re->r.scemode & R_SINGLE_LAYER) && view_layer != active_view_layer) continue; - if (FRS_is_freestyle_enabled(srl)) { - r = FRS_do_stroke_rendering(re, srl, render); - if (do_link) - link->data = (void *)r; + if (FRS_is_freestyle_enabled(view_layer)) { + r = FRS_do_stroke_rendering(re, view_layer, render); + link->data = (void *)r; } } FRS_end_stroke_rendering(re); - - /* restore the global R value (invalidated by nested execution of the internal renderer) */ - R = *re; -} - -/* merges the results of Freestyle stroke rendering into a given render result */ -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 (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; - - 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; - } - } } /* releases temporary scenes and renders for Freestyle stroke rendering */ @@ -2390,229 +1563,8 @@ static void free_all_freestyle_renders(void) } #endif -/* 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; - rcti filter_mask = re->disprect; - float *rectf, filt[3][3]; - int x, y, sample; - int nr, numviews; - - /* interaction callbacks */ - if (ntree) { - ntree->stats_draw = render_composit_stats; - ntree->test_break = re->test_break; - ntree->progress = re->progress; - ntree->sdh = re->sdh; - ntree->tbh = re->tbh; - ntree->prh = re->prh; - } - - /* filtmask needs it */ - R = *re; - - /* 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->result->rectx * re->result->recty * sizeof(float) * 4, "fullsample rgba"); - BLI_addtail(rectfs, rv); - } - - for (sample = 0; sample < re->r.osa; sample++) { - Scene *sce; - Render *re1; - RenderResult rres; - int mask; - - /* enable full sample print */ - R.i.curfsa = sample + 1; - - /* set all involved renders on the samplebuffers (first was done by render itself, but needs tagged) */ - /* also function below assumes this */ - - tag_scenes_for_render(re); - for (sce = re->main->scene.first; sce; sce = sce->id.next) { - if (sce->id.tag & LIB_TAG_DOIT) { - re1 = RE_GetSceneRender(sce); - - if (re1 && (re1->r.scemode & R_FULL_SAMPLE)) { - if (sample) { - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - render_result_exr_file_read_sample(re1, sample); -#ifdef WITH_FREESTYLE - if (re1->r.mode & R_EDGE_FRS) - composite_freestyle_renders(re1, sample); -#endif - BLI_rw_mutex_unlock(&re->resultmutex); - render_result_uncrop(re1); - } - ntreeCompositTagRender(re1->scene); /* ensure node gets exec to put buffers on stack */ - } - } - } - - /* composite */ - if (ntree) { - ntreeCompositTagRender(re->scene); - ntreeCompositTagAnimated(ntree); - - 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); - } - } - - 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->result->recty; y++) { - float *rf = rectf + 4 * y * re->result->rectx; - float *col = rres.rectf + 4 * y * re->result->rectx; - - for (x = 0; x < re->result->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->result->rectx, x, y, &filter_mask); - } - } - - 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_SetActiveRenderView(re, rv->name); - re->display_update(re->duh, re->result, NULL); - } - } - } - - 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->result->recty; y++) { - float *rf = rectf + 4 * y * re->result->rectx; - - for (x = 0; x < re->result->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 */ - if (ntree) { - ntree->stats_draw = NULL; - ntree->test_break = NULL; - ntree->progress = NULL; - ntree->tbh = ntree->sdh = ntree->prh = NULL; - } - - /* disable full sample print */ - R.i.curfsa = 0; - - /* garbage collection */ - while (rectfs->first) { - rv = rectfs->first; - BLI_remlink(rectfs, rv); - MEM_freeN(rv); - } - MEM_freeN(rectfs); -} - -/* called externally, via compositor */ -void RE_MergeFullSample(Render *re, Main *bmain, Scene *sce, bNodeTree *ntree) -{ - Scene *scene; - bNode *node; - - /* default start situation */ - G.is_break = false; - - re->main = bmain; - re->scene = sce; - re->scene_color_manage = BKE_scene_check_color_management_enabled(sce); - - /* first call RE_ReadRenderResult on every renderlayer scene. this creates Render structs */ - - /* tag scenes unread */ - for (scene = re->main->scene.first; scene; scene = scene->id.next) - scene->id.tag |= LIB_TAG_DOIT; - -#ifdef WITH_FREESTYLE - if (re->freestyle_bmain) { - for (scene = re->freestyle_bmain->scene.first; scene; scene = scene->id.next) - scene->id.tag &= ~LIB_TAG_DOIT; - } -#endif - - for (node = ntree->nodes.first; node; node = node->next) { - if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0) { - Scene *nodescene = (Scene *)node->id; - - if (nodescene == NULL) nodescene = sce; - if (nodescene->id.tag & LIB_TAG_DOIT) { - nodescene->r.mode |= R_OSA; /* render struct needs tables */ - RE_ReadRenderResult(sce, nodescene); - nodescene->id.tag &= ~LIB_TAG_DOIT; - } - } - } - - /* own render result should be read/allocated */ - if (re->scene->id.tag & LIB_TAG_DOIT) { - RE_ReadRenderResult(re->scene, re->scene); - re->scene->id.tag &= ~LIB_TAG_DOIT; - } - - /* and now we can draw (result is there) */ - re->display_init(re->dih, re->result); - re->display_clear(re->dch, re->result); - -#ifdef WITH_FREESTYLE - if (re->r.mode & R_EDGE_FRS) { - init_freestyle(re); - add_freestyle(re, 0); - } -#endif - - do_merge_fullsample(re, ntree); - -#ifdef WITH_FREESTYLE - free_all_freestyle_renders(); -#endif -} - /* returns fully composited render-result on given time step (in RenderData) */ -static void do_render_composite_fields_blur_3d(Render *re) +static void do_render_composite(Render *re) { bNodeTree *ntree = re->scene->nodetree; int update_newframe = 0; @@ -2628,7 +1580,7 @@ static void do_render_composite_fields_blur_3d(Render *re) * 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); + do_render(re); } else { re->i.cfra = re->r.cfra; @@ -2671,26 +1623,17 @@ static void do_render_composite_fields_blur_3d(Render *re) ntree->stats_draw = render_composit_stats; ntree->test_break = re->test_break; ntree->progress = re->progress; - ntree->sdh = re->sdh; + ntree->sdh = re; ntree->tbh = re->tbh; ntree->prh = re->prh; - /* 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); + if (update_newframe) { + /* If we have consistent depsgraph now would be a time to update them. */ + } - if (re->r.scemode & R_FULL_SAMPLE) - do_merge_fullsample(re, ntree); - else { - 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); - } + 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; @@ -2699,14 +1642,17 @@ static void do_render_composite_fields_blur_3d(Render *re) ntree->tbh = ntree->sdh = ntree->prh = NULL; } } - else if (re->r.scemode & R_FULL_SAMPLE) - do_merge_fullsample(re, NULL); } #ifdef WITH_FREESTYLE free_all_freestyle_renders(); #endif +#ifdef DEPSGRAPH_WORKAROUND_GROUP_HACK + /* Restore their visibility based on the viewport visibility flags. */ + tag_collections_for_render(re); +#endif + /* weak... the display callback wants an active renderlayer pointer... */ if (re->result != NULL) { re->result->renlay = render_get_active_layer(re, re->result); @@ -2769,7 +1715,12 @@ static void do_render_seq(Render *re) if (recurs_depth == 0) { /* otherwise sequencer animation isn't updated */ - BKE_animsys_evaluate_all_animation(re->main, re->scene, (float)cfra); // XXX, was BKE_scene_frame_get(re->scene) + /* TODO(sergey): Currently depsgraph is only used to check whether it is an active + * edit window or not to deal with unkeyed changes. We don't have depsgraph here yet, + * but we also dont' deal with unkeyed changes. But still nice to get proper depsgraph + * within tjhe render pipeline, somehow. + */ + BKE_animsys_evaluate_all_animation(re->main, NULL, re->scene, (float)cfra); // XXX, was BKE_scene_frame_get(re->scene) } recurs_depth++; @@ -2788,9 +1739,14 @@ static void do_render_seq(Render *re) tot_views = BKE_scene_multiview_num_views_get(&re->r); ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * tot_views, "Sequencer Views ImBufs"); + /* TODO(sergey): Currently depsgraph is only used to check whether it is an active + * edit window or not to deal with unkeyed changes. We don't have depsgraph here yet, + * but we also dont' deal with unkeyed changes. But still nice to get proper depsgraph + * within tjhe render pipeline, somehow. + */ BKE_sequencer_new_render_data( - re->eval_ctx, re->main, re->scene, - re_x, re_y, 100, + re->main, NULL, re->scene, + re_x, re_y, 100, true, &context); /* the renderresult gets destroyed during the rendering, so we first collect all ibufs @@ -2866,7 +1822,7 @@ static void do_render_seq(Render *re) /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* main loop: doing sequence + fields + blur + 3d render + compositing */ +/* main loop: doing sequence + 3d render + compositing */ static void do_render_all_options(Render *re) { Object *camera; @@ -2896,12 +1852,7 @@ static void do_render_all_options(Render *re) re->display_update(re->duh, re->result, NULL); } else { - re->pool = BKE_image_pool_new(); - - do_render_composite_fields_blur_3d(re); - - BKE_image_pool_free(re->pool); - re->pool = NULL; + do_render_composite(re); } re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime; @@ -2923,20 +1874,6 @@ static void do_render_all_options(Render *re) } } -bool RE_force_single_renderlayer(Scene *scene) -{ - int scemode = check_mode_full_sample(&scene->r); - if (scemode & R_SINGLE_LAYER) { - SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay); - /* force layer to be enabled */ - if (srl->layflag & SCE_LAY_DISABLE) { - srl->layflag &= ~SCE_LAY_DISABLE; - return true; - } - } - return false; -} - static bool check_valid_compositing_camera(Scene *scene, Object *camera_override) { if (scene->r.scemode & R_DOCOMP && scene->use_nodes) { @@ -2946,7 +1883,7 @@ static bool check_valid_compositing_camera(Scene *scene, Object *camera_override if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0) { Scene *sce = node->id ? (Scene *)node->id : scene; if (sce->camera == NULL) { - sce->camera = BKE_scene_camera_find(sce); + sce->camera = BKE_view_layer_camera_find(BKE_view_layer_default_render(sce)); } if (sce->camera == NULL) { /* all render layers nodes need camera */ @@ -3004,7 +1941,7 @@ static int check_valid_camera(Scene *scene, Object *camera_override, ReportList const char *err_msg = "No camera found in scene \"%s\""; if (camera_override == NULL && scene->camera == NULL) - scene->camera = BKE_scene_camera_find(scene); + scene->camera = BKE_view_layer_camera_find(BKE_view_layer_default_render(scene)); if (!check_valid_camera_multiview(scene, scene->camera, reports)) return false; @@ -3019,7 +1956,9 @@ static int check_valid_camera(Scene *scene, Object *camera_override, ReportList (seq->scene != NULL)) { if (!seq->scene_camera) { - if (!seq->scene->camera && !BKE_scene_camera_find(seq->scene)) { + if (!seq->scene->camera && + !BKE_view_layer_camera_find(BKE_view_layer_default_render(seq->scene))) + { /* camera could be unneeded due to composite nodes */ Object *override = (seq->scene == scene) ? camera_override : NULL; @@ -3070,7 +2009,7 @@ static int check_composite_output(Scene *scene) return node_tree_has_composite_output(scene->nodetree); } -bool RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *reports) +bool RE_is_rendering_allowed(Scene *scene, ViewLayer *single_layer, Object *camera_override, ReportList *reports) { int scemode = check_mode_full_sample(&scene->r); @@ -3092,13 +2031,6 @@ bool RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList * BKE_report(reports, RPT_ERROR, "Cannot save render buffers, check the temp default path"); return 0; } - - /* no fullsample and edge */ - if ((scemode & R_FULL_SAMPLE) && (scene->r.mode & R_EDGE)) { - BKE_report(reports, RPT_ERROR, "Full sample does not support edge enhance"); - return 0; - } - } if (scemode & R_DOCOMP) { @@ -3145,15 +2077,6 @@ bool RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList * #endif } -#ifdef WITH_FREESTYLE - if (scene->r.mode & R_EDGE_FRS) { - if (scene->r.mode & R_FIELDS) { - BKE_report(reports, RPT_ERROR, "Fields not supported in Freestyle"); - return false; - } - } -#endif - if (RE_seq_render_active(scene, &scene->r)) { if (scene->r.mode & R_BORDER) { BKE_report(reports, RPT_ERROR, "Border rendering is not supported by sequencer"); @@ -3162,7 +2085,7 @@ bool RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList * } /* layer flag tests */ - if (!render_scene_has_layers_to_render(scene)) { + if (!render_scene_has_layers_to_render(scene, single_layer)) { BKE_report(reports, RPT_ERROR, "All render layers are disabled"); return 0; } @@ -3172,26 +2095,21 @@ bool RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList * static void validate_render_settings(Render *re) { - if (re->r.scemode & (R_EXR_TILE_FILE | R_FULL_SAMPLE)) { - /* no osa + fullsample won't work... */ - if (re->r.osa == 0) - re->r.scemode &= ~R_FULL_SAMPLE; - } - if (RE_engine_is_external(re)) { /* not supported yet */ re->r.scemode &= ~(R_FULL_SAMPLE); - re->r.mode &= ~(R_FIELDS | R_MBLUR); } } -static void update_physics_cache(Render *re, Scene *scene, int UNUSED(anim_init)) +static void update_physics_cache(Render *re, Scene *scene, ViewLayer *view_layer, int UNUSED(anim_init)) { PTCacheBaker baker; memset(&baker, 0, sizeof(baker)); baker.main = re->main; baker.scene = scene; + baker.view_layer = view_layer; + baker.depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); baker.bake = 0; baker.render = 1; baker.anim_init = 1; @@ -3211,8 +2129,9 @@ const char *RE_GetActiveRenderView(Render *re) } /* 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) +static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, Scene *scene, + ViewLayer *single_layer, Object *camera_override, unsigned int lay_override, + int anim, int anim_init) { int winx, winy; rcti disprect; @@ -3240,7 +2159,6 @@ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, re->main = bmain; re->scene = scene; - re->scene_color_manage = BKE_scene_check_color_management_enabled(scene); re->camera_override = camera_override; re->lay = lay_override ? lay_override : scene->lay; re->layer_override = lay_override; @@ -3249,7 +2167,7 @@ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, /* not too nice, but it survives anim-border render */ if (anim) { - render_update_anim_renderdata(re, &scene->r); + render_update_anim_renderdata(re, &scene->r, &scene->view_layers); re->disprect = disprect; return 1; } @@ -3257,6 +2175,11 @@ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, /* check all scenes involved */ tag_scenes_for_render(re); +#ifdef DEPSGRAPH_WORKAROUND_GROUP_HACK + /* Update collection collections visibility. */ + tag_collections_for_render(re); +#endif + /* * Disabled completely for now, * can be later set as render profile option @@ -3264,16 +2187,17 @@ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, */ if (0) { /* make sure dynamics are up to date */ - update_physics_cache(re, scene, anim_init); + ViewLayer *view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene); + update_physics_cache(re, scene, view_layer, anim_init); } - if (srl || scene->r.scemode & R_SINGLE_LAYER) { + if (single_layer || scene->r.scemode & R_SINGLE_LAYER) { BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); render_result_single_layer_begin(re); BLI_rw_mutex_unlock(&re->resultmutex); } - RE_InitState(re, NULL, &scene->r, srl, winx, winy, &disprect); + RE_InitState(re, NULL, &scene->r, &scene->view_layers, single_layer, winx, winy, &disprect); if (!re->ok) /* if an error was printed, abort */ return 0; @@ -3294,7 +2218,7 @@ void RE_SetReports(Render *re, ReportList *reports) } /* general Blender frame render call */ -void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, Object *camera_override, +void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, ViewLayer *single_layer, Object *camera_override, unsigned int lay_override, int frame, const bool write_still) { BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT); @@ -3304,7 +2228,9 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr scene->r.cfra = frame; - if (render_initialize_from_main(re, &scene->r, bmain, scene, srl, camera_override, lay_override, 0, 0)) { + if (render_initialize_from_main(re, &scene->r, bmain, scene, single_layer, + camera_override, lay_override, 0, 0)) + { MEM_reset_peak_memory(); BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE); @@ -3335,6 +2261,9 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr BLI_callback_exec(re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE); + /* Destroy the opengl context in the correct thread. */ + RE_gl_context_destroy(re); + /* UGLY WARNING */ G.is_rendering = false; } @@ -3345,7 +2274,7 @@ void RE_RenderFreestyleStrokes(Render *re, Main *bmain, Scene *scene, int render re->result_ok= 0; if (render_initialize_from_main(re, &scene->r, bmain, scene, NULL, NULL, scene->lay, 0, 0)) { if (render) - do_render_fields_blur_3d(re); + do_render_3d(re); } re->result_ok = 1; } @@ -3359,10 +2288,29 @@ void RE_RenderFreestyleExternal(Render *re) for (rv = re->result->views.first; rv; rv = rv->next) { RE_SetActiveRenderView(re, rv->name); - RE_Database_FromScene(re, re->main, re->scene, re->lay, 1); - RE_Database_Preprocess(re); + + /* scene needs to be set to get camera */ + Object *camera = RE_GetCamera(re); + + /* if no camera, viewmat should have been set! */ + if (camera) { + /* called before but need to call again in case of lens animation from the + * above call to BKE_scene_graph_update_for_newframe, fixes bug. [#22702]. + * following calls don't depend on 'RE_SetCamera' */ + float mat[4][4]; + + RE_SetCamera(re, camera); + RE_GetCameraModelMatrix(re, camera, mat); + invert_m4(mat); + RE_SetView(re, mat); + + /* force correct matrix for scaled cameras */ + DEG_id_tag_update_ex(re->main, &camera->id, OB_RECALC_OB); + } + + printf("add freestyle\n"); + add_freestyle(re, 1); - RE_Database_Free(re); } } } @@ -3642,15 +2590,6 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri if (!render_initialize_from_main(re, &rd, bmain, scene, NULL, camera_override, lay_override, 0, 1)) return; - /* 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 - */ - 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; - } - if (is_movie) { size_t width, height; int i; @@ -3725,26 +2664,20 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri { float ctime = BKE_scene_frame_get(scene); AnimData *adt = BKE_animdata_from_id(&scene->id); - BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, ADT_RECALC_ALL); + /* TODO(sergey): Currently depsgraph is only used to check whether it is an active + * edit window or not to deal with unkeyed changes. We don't have depsgraph here yet, + * but we also dont' deal with unkeyed changes. But still nice to get proper depsgraph + * within tjhe render pipeline, somehow. + */ + BKE_animsys_evaluate_animdata(NULL, scene, &scene->id, adt, ctime, ADT_RECALC_ALL); } /* only border now, todo: camera lens. (ton) */ - render_initialize_from_main(re, &rd, bmain, scene, NULL, camera_override, lay_override, 1, 0); + render_initialize_from_main(re, &rd, bmain, scene, + NULL, camera_override, lay_override, 1, 0); if (nfra != scene->r.cfra) { - /* - * Skip this frame, but update for physics and particles system. - * From convertblender.c: - * in localview, lamps are using normal layers, objects only local bits. - */ - unsigned int updatelay; - - if (re->lay & 0xFF000000) - updatelay = re->lay & 0xFF000000; - else - updatelay = re->lay; - - BKE_scene_update_for_newframe(re->eval_ctx, bmain, scene, updatelay); + /* Skip this frame, but could update for physics and particles system. */ continue; } else @@ -3886,6 +2819,9 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri BLI_callback_exec(re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE); BKE_sound_reset_scene_specs(scene); + /* Destroy the opengl context in the correct thread. */ + RE_gl_context_destroy(re); + /* UGLY WARNING */ G.is_rendering = false; } @@ -3898,22 +2834,16 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce) winx = (sce->r.size * sce->r.xsch) / 100; winy = (sce->r.size * sce->r.ysch) / 100; - RE_InitState(re, NULL, &sce->r, NULL, winx, winy, NULL); - - re->pool = BKE_image_pool_new(); + RE_InitState(re, NULL, &sce->r, &sce->view_layers, NULL, winx, winy, NULL); re->main = bmain; re->scene = sce; - re->scene_color_manage = BKE_scene_check_color_management_enabled(sce); re->lay = sce->lay; camera = RE_GetCamera(re); RE_SetCamera(re, camera); do_render_3d(re); - - BKE_image_pool_free(re->pool); - re->pool = NULL; } /* note; repeated win/disprect calc... solve that nicer, also in compo */ @@ -3951,9 +2881,8 @@ bool RE_ReadRenderResult(Scene *scene, Scene *scenode) re = RE_GetSceneRender(scene); if (re == NULL) re = RE_NewSceneRender(scene); - RE_InitState(re, NULL, &scene->r, NULL, winx, winy, &disprect); + RE_InitState(re, NULL, &scene->r, &scene->view_layers, NULL, winx, winy, &disprect); re->scene = scene; - re->scene_color_manage = BKE_scene_check_color_management_enabled(scene); BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); success = render_result_exr_file_cache_read(re); @@ -4030,67 +2959,6 @@ void RE_result_load_from_file(RenderResult *result, ReportList *reports, const c } } -const float default_envmap_layout[] = { 0, 0, 1, 0, 2, 0, 0, 1, 1, 1, 2, 1 }; - -bool RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env, const char *relpath, const char imtype, float layout[12]) -{ - ImageFormatData imf; - ImBuf *ibuf = NULL; - int ok; - int dx; - int maxX = 0, maxY = 0, i = 0; - char filepath[FILE_MAX]; - - if (env->cube[1] == NULL) { - BKE_report(reports, RPT_ERROR, "There is no generated environment map available to save"); - return 0; - } - - imf = scene->r.im_format; - imf.imtype = imtype; - - dx = env->cube[1]->x; - - if (env->type == ENV_CUBE) { - for (i = 0; i < 12; i += 2) { - maxX = max_ii(maxX, (int)layout[i] + 1); - maxY = max_ii(maxY, (int)layout[i + 1] + 1); - } - - ibuf = IMB_allocImBuf(maxX * dx, maxY * dx, 24, IB_rectfloat); - - for (i = 0; i < 12; i += 2) - if (layout[i] > -1 && layout[i + 1] > -1) - IMB_rectcpy(ibuf, env->cube[i / 2], layout[i] * dx, layout[i + 1] * dx, 0, 0, dx, dx); - } - else if (env->type == ENV_PLANE) { - ibuf = IMB_allocImBuf(dx, dx, 24, IB_rectfloat); - IMB_rectcpy(ibuf, env->cube[1], 0, 0, 0, 0, dx, dx); - } - else { - BKE_report(reports, RPT_ERROR, "Invalid environment map type"); - return 0; - } - - IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, &scene->display_settings, &imf); - - /* to save, we first get absolute path */ - BLI_strncpy(filepath, relpath, sizeof(filepath)); - BLI_path_abs(filepath, BKE_main_blendfile_path_from_global()); - - ok = BKE_imbuf_write(ibuf, filepath, &imf); - - IMB_freeImBuf(ibuf); - - if (ok) { - return true; - } - else { - BKE_report(reports, RPT_ERROR, "Error writing environment map"); - return false; - } -} - /* Used in the interface to decide whether to show layers or passes. */ bool RE_layers_have_name(struct RenderResult *rr) { @@ -4184,7 +3052,6 @@ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const cha rl = MEM_callocN(sizeof(RenderLayer), layername); BLI_addtail(&rr->layers, rl); BLI_strncpy(rl->name, layername, sizeof(rl->name)); - rl->lay = 0; rl->layflag = SCE_LAY_SOLID; rl->passflag = SCE_PASS_COMBINED; rl->rectx = rr->rectx; diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index 635bfc58425..c025a1fdef7 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -43,6 +43,7 @@ #include "BLT_translation.h" +#include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_particle_types.h" @@ -50,7 +51,6 @@ #include "BKE_colorband.h" #include "BKE_deform.h" -#include "BKE_DerivedMesh.h" #include "BKE_lattice.h" #include "BKE_main.h" #include "BKE_object.h" @@ -58,17 +58,14 @@ #include "BKE_scene.h" #include "BKE_colortools.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + #include "render_types.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; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#include "RE_shader_ext.h" static ThreadMutex sample_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -77,15 +74,13 @@ 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) || + if ((pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) || (pd->color_source == TEX_PD_COLOR_PARTVEL) || (pd->color_source == TEX_PD_COLOR_PARTSPEED)) { pd_bitflag |= POINT_DATA_VEL; } - if ((pd->noise_influence == TEX_PD_NOISE_AGE) || - (pd->color_source == TEX_PD_COLOR_PARTAGE) || + if ((pd->color_source == TEX_PD_COLOR_PARTAGE) || (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE)) { pd_bitflag |= POINT_DATA_LIFE; @@ -167,16 +162,11 @@ static void alloc_point_data(PointDensity *pd) } } -static void pointdensity_cache_psys(Scene *scene, +static void pointdensity_cache_psys(Depsgraph *depsgraph, Scene *scene, PointDensity *pd, Object *ob, - ParticleSystem *psys, - float viewmat[4][4], - float winmat[4][4], - int winx, int winy, - const bool use_render_params) + ParticleSystem *psys) { - DerivedMesh *dm; ParticleKey state; ParticleCacheKey *cache; ParticleSimulationData sim = {NULL}; @@ -187,35 +177,15 @@ static void pointdensity_cache_psys(Scene *scene, int data_used; float *data_vel, *data_life; float partco[3]; - - /* init everything */ - if (!psys || !ob || !pd) { - return; - } + const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); data_used = point_data_used(pd); - /* Just to create a valid rendering context for particles */ - if (use_render_params) { - psys_render_set(ob, psys, viewmat, winmat, winx, winy, 0); - } - - if (use_render_params) { - dm = mesh_create_derived_render(scene, - ob, - CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); - } - else { - dm = mesh_get_derived_final(scene, - ob, - CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); - } - if (!psys_check_enabled(ob, psys, use_render_params)) { - psys_render_restore(ob, psys); return; } + sim.depsgraph = depsgraph; sim.scene = scene; sim.ob = ob; sim.psys = psys; @@ -298,33 +268,28 @@ static void pointdensity_cache_psys(Scene *scene, } 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; } - - if (use_render_params) { - psys_render_restore(ob, psys); - } } -static void pointdensity_cache_vertex_color(PointDensity *pd, Object *UNUSED(ob), DerivedMesh *dm, float *data_color) +static void pointdensity_cache_vertex_color(PointDensity *pd, Object *UNUSED(ob), Mesh *mesh, float *data_color) { - const MLoop *mloop = dm->getLoopArray(dm); - const int totloop = dm->getNumLoops(dm); + const MLoop *mloop = mesh->mloop; + const int totloop = mesh->totloop; const MLoopCol *mcol; char layername[MAX_CUSTOMDATA_LAYER_NAME]; int i; BLI_assert(data_color); - if (!CustomData_has_layer(&dm->loopData, CD_MLOOPCOL)) + if (!CustomData_has_layer(&mesh->ldata, CD_MLOOPCOL)) return; - CustomData_validate_layer_name(&dm->loopData, CD_MLOOPCOL, pd->vertex_attribute_name, layername); - mcol = CustomData_get_layer_named(&dm->loopData, CD_MLOOPCOL, layername); + CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPCOL, pd->vertex_attribute_name, layername); + mcol = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPCOL, layername); if (!mcol) return; @@ -357,16 +322,16 @@ static void pointdensity_cache_vertex_color(PointDensity *pd, Object *UNUSED(ob) MEM_freeN(mcorners); } -static void pointdensity_cache_vertex_weight(PointDensity *pd, Object *ob, DerivedMesh *dm, float *data_color) +static void pointdensity_cache_vertex_weight(PointDensity *pd, Object *ob, Mesh *mesh, float *data_color) { - const int totvert = dm->getNumVerts(dm); + const int totvert = mesh->totvert; const MDeformVert *mdef, *dv; int mdef_index; int i; BLI_assert(data_color); - mdef = CustomData_get_layer(&dm->vertData, CD_MDEFORMVERT); + mdef = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT); if (!mdef) return; mdef_index = defgroup_name_index(ob, pd->vertex_attribute_name); @@ -388,9 +353,9 @@ static void pointdensity_cache_vertex_weight(PointDensity *pd, Object *ob, Deriv } } -static void pointdensity_cache_vertex_normal(PointDensity *pd, Object *UNUSED(ob), DerivedMesh *dm, float *data_color) +static void pointdensity_cache_vertex_normal(PointDensity *pd, Object *UNUSED(ob), Mesh *mesh, float *data_color) { - MVert *mvert = dm->getVertArray(dm), *mv; + MVert *mvert = mesh->mvert, *mv; int i; BLI_assert(data_color); @@ -400,16 +365,14 @@ static void pointdensity_cache_vertex_normal(PointDensity *pd, Object *UNUSED(ob } } -static void pointdensity_cache_object(Scene *scene, - PointDensity *pd, - Object *ob, - const bool use_render_params) +static void pointdensity_cache_object(PointDensity *pd, + Object *ob) { float *data_color; int i; - DerivedMesh *dm; CustomDataMask mask = CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL; MVert *mvert = NULL, *mv; + Mesh *mesh = ob->data; switch (pd->ob_color_source) { case TEX_PD_COLOR_VERTCOL: @@ -420,15 +383,8 @@ static void pointdensity_cache_object(Scene *scene, break; } - if (use_render_params) { - dm = mesh_create_derived_render(scene, ob, mask); - } - else { - dm = mesh_get_derived_final(scene, ob, mask); - } - - mvert = dm->getVertArray(dm); /* local object space */ - pd->totpoints = dm->getNumVerts(dm); + mvert = mesh->mvert; /* local object space */ + pd->totpoints = mesh->totvert; if (pd->totpoints == 0) { return; } @@ -460,27 +416,22 @@ static void pointdensity_cache_object(Scene *scene, switch (pd->ob_color_source) { case TEX_PD_COLOR_VERTCOL: - pointdensity_cache_vertex_color(pd, ob, dm, data_color); + pointdensity_cache_vertex_color(pd, ob, mesh, data_color); break; case TEX_PD_COLOR_VERTWEIGHT: - pointdensity_cache_vertex_weight(pd, ob, dm, data_color); + pointdensity_cache_vertex_weight(pd, ob, mesh, data_color); break; case TEX_PD_COLOR_VERTNOR: - pointdensity_cache_vertex_normal(pd, ob, dm, data_color); + pointdensity_cache_vertex_normal(pd, ob, mesh, data_color); break; } BLI_bvhtree_balance(pd->point_tree); - dm->release(dm); - } -static void cache_pointdensity_ex(Scene *scene, - PointDensity *pd, - float viewmat[4][4], - float winmat[4][4], - int winx, int winy, - const bool use_render_params) +static void cache_pointdensity(Depsgraph *depsgraph, + Scene *scene, + PointDensity *pd) { if (pd == NULL) { return; @@ -504,31 +455,20 @@ static void cache_pointdensity_ex(Scene *scene, return; } - pointdensity_cache_psys(scene, + pointdensity_cache_psys(depsgraph, + scene, pd, ob, - psys, - viewmat, winmat, - winx, winy, - use_render_params); + psys); } else if (pd->source == TEX_PD_OBJECT) { Object *ob = pd->object; if (ob && ob->type == OB_MESH) - pointdensity_cache_object(scene, pd, ob, use_render_params); + pointdensity_cache_object(pd, ob); } } -void cache_pointdensity(Render *re, PointDensity *pd) -{ - cache_pointdensity_ex(re->scene, - pd, - re->viewmat, re->winmat, - re->winx, re->winy, - true); -} - -void free_pointdensity(PointDensity *pd) +static void free_pointdensity(PointDensity *pd) { if (pd == NULL) { return; @@ -546,41 +486,6 @@ void free_pointdensity(PointDensity *pd) pd->totpoints = 0; } -void make_pointdensities(Render *re) -{ - Tex *tex; - - 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 != 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); -} - -void free_pointdensities(Render *re) -{ - Tex *tex; - - if (re->scene->r.scemode & R_BUTS_PREVIEW) - return; - - for (tex = re->main->tex.first; tex != NULL; tex = tex->id.next) { - if (tex->id.us && tex->type == TEX_POINTDENSITY) { - free_pointdensity(tex->pd); - } - } -} - typedef struct PointDensityRangeData { float *density; float squared_radius; @@ -691,16 +596,13 @@ static int pointdensity(PointDensity *pd, { int retval = TEX_INT; PointDensityRangeData pdr; - float density = 0.0f, age = 0.0f, time = 0.0f; + float density = 0.0f, age = 0.0f; float vec[3] = {0.0f, 0.0f, 0.0f}, col[3] = {0.0f, 0.0f, 0.0f}, co[3]; float turb, noise_fac; int num = 0; texres->tin = 0.0f; - if ((!pd) || (!pd->point_tree)) - return 0; - init_pointdensityrangedata(pd, &pdr, &density, vec, &age, col, (pd->flag & TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : NULL), pd->falloff_speed_scale * 0.001f); @@ -725,21 +627,8 @@ static int pointdensity(PointDensity *pd, } 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); - } - 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_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 */ @@ -771,9 +660,9 @@ static int pointdensity(PointDensity *pd, return retval; } -static int pointdensity_color(PointDensity *pd, TexResult *texres, float age, const float vec[3], const float col[3]) +static void pointdensity_color(PointDensity *pd, TexResult *texres, float age, const float vec[3], const float col[3]) { - int retval = TEX_RGB; + texres->tr = texres->tg = texres->tb = texres->ta = 1.0f; if (pd->source == TEX_PD_PSYS) { float rgba[4]; @@ -810,8 +699,6 @@ static int pointdensity_color(PointDensity *pd, TexResult *texres, float age, co break; case TEX_PD_COLOR_CONSTANT: default: - texres->tr = texres->tg = texres->tb = texres->ta = 1.0f; - retval = TEX_INT; break; } } @@ -842,33 +729,9 @@ static int pointdensity_color(PointDensity *pd, TexResult *texres, float age, co break; case TEX_PD_COLOR_CONSTANT: default: - texres->tr = texres->tg = texres->tb = texres->ta = 1.0f; - retval = TEX_INT; break; } } - - 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}; - float col[3] = {0.0f, 0.0f, 0.0f}; - int retval = pointdensity(pd, texvec, texres, vec, &age, col); - - retval |= pointdensity_color(pd, texres, age, vec, col); - 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) @@ -876,11 +739,11 @@ static void sample_dummy_point_density(int resolution, float *values) memset(values, 0, sizeof(float) * 4 * resolution * resolution * resolution); } -static void particle_system_minmax(Scene *scene, +static void particle_system_minmax(Depsgraph *depsgraph, + Scene *scene, Object *object, ParticleSystem *psys, float radius, - const bool use_render_params, float min[3], float max[3]) { const float size[3] = {radius, radius, radius}; @@ -899,10 +762,8 @@ static void particle_system_minmax(Scene *scene, } unit_m4(mat); - if (use_render_params) { - psys_render_set(object, psys, mat, mat, 1, 1, 0); - } + sim.depsgraph = depsgraph; sim.scene = scene; sim.ob = object; sim.psys = psys; @@ -930,31 +791,26 @@ static void particle_system_minmax(Scene *scene, end_latt_deform(psys->lattice_deform_data); psys->lattice_deform_data = NULL; } - - if (use_render_params) { - psys_render_restore(object, psys); - } } void RE_point_density_cache( - Scene *scene, - PointDensity *pd, - const bool use_render_params) + struct Depsgraph *depsgraph, + PointDensity *pd) { - float mat[4][4]; + Scene *scene = DEG_get_evaluated_scene(depsgraph); + /* 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, use_render_params); + cache_pointdensity(depsgraph, scene, pd); BLI_mutex_unlock(&sample_mutex); } void RE_point_density_minmax( - struct Scene *scene, + struct Depsgraph *depsgraph, struct PointDensity *pd, - const bool use_render_params, float r_min[3], float r_max[3]) { + Scene *scene = DEG_get_evaluated_scene(depsgraph); Object *object = pd->object; if (object == NULL) { zero_v3(r_min); @@ -963,6 +819,7 @@ void RE_point_density_minmax( } if (pd->source == TEX_PD_PSYS) { ParticleSystem *psys; + if (pd->psys == 0) { zero_v3(r_min); zero_v3(r_max); @@ -974,11 +831,12 @@ void RE_point_density_minmax( zero_v3(r_max); return; } - particle_system_minmax(scene, + + particle_system_minmax(depsgraph, + scene, object, psys, pd->radius, - use_render_params, r_min, r_max); } else { @@ -1020,6 +878,10 @@ static void point_density_sample_func( PointDensity *pd = data->pd; float *values = data->values; + if (!pd || !pd->point_tree) { + return; + } + size_t z = (size_t)iter; for (size_t y = 0; y < resolution; ++y) { for (size_t x = 0; x < resolution; ++x) { @@ -1046,10 +908,9 @@ static void point_density_sample_func( * NOTE 2: Frees point density structure after sampling. */ void RE_point_density_sample( - Scene *scene, + Depsgraph *depsgraph, PointDensity *pd, const int resolution, - const bool use_render_params, float *values) { Object *object = pd->object; @@ -1065,9 +926,8 @@ void RE_point_density_sample( } BLI_mutex_lock(&sample_mutex); - RE_point_density_minmax(scene, + RE_point_density_minmax(depsgraph, pd, - use_render_params, min, max); BLI_mutex_unlock(&sample_mutex); @@ -1099,3 +959,8 @@ void RE_point_density_free(struct PointDensity *pd) { free_pointdensity(pd); } + +void RE_point_density_fix_linking(void) +{ +} + diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index d9e83b209b8..e0cacdf4b8f 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -266,9 +266,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf RenderResult *rr; RenderLayer *rl; RenderView *rv; - SceneRenderLayer *srl; int rectx, recty; - int nr; rectx = BLI_rcti_size_x(partrct); recty = BLI_rcti_size_y(partrct); @@ -296,33 +294,21 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf 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 (!STREQ(srl->name, layername)) - continue; - - if (re->r.scemode & R_SINGLE_LAYER) { - if (nr != re->r.actlay) - continue; - } - else { - if (srl->layflag & SCE_LAY_DISABLE) + FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re, view_layer) + { + if (layername && layername[0]) { + if (!STREQ(view_layer->name, layername)) { continue; + } } rl = MEM_callocN(sizeof(RenderLayer), "new render layer"); BLI_addtail(&rr->layers, rl); - BLI_strncpy(rl->name, srl->name, sizeof(rl->name)); - rl->lay = srl->lay; - rl->lay_zmask = srl->lay_zmask; - rl->lay_exclude = srl->lay_exclude; - rl->layflag = srl->layflag; - rl->passflag = srl->passflag; /* for debugging: srl->passflag | SCE_PASS_RAYHITS; */ - rl->pass_xor = srl->pass_xor; - rl->light_override = srl->light_override; - rl->mat_override = srl->mat_override; + BLI_strncpy(rl->name, view_layer->name, sizeof(rl->name)); + rl->layflag = view_layer->layflag; + rl->passflag = view_layer->passflag; /* for debugging: view_layer->passflag | SCE_PASS_RAYHITS; */ + rl->pass_xor = view_layer->pass_xor; rl->rectx = rectx; rl->recty = recty; @@ -357,70 +343,72 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf /* a renderlayer should always have a Combined pass*/ render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA"); - if (srl->passflag & SCE_PASS_Z) + if (view_layer->passflag & SCE_PASS_Z) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_Z, view, "Z"); - if (srl->passflag & SCE_PASS_VECTOR) + if (view_layer->passflag & SCE_PASS_VECTOR) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_VECTOR, view, "XYZW"); - if (srl->passflag & SCE_PASS_NORMAL) + if (view_layer->passflag & SCE_PASS_NORMAL) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_NORMAL, view, "XYZ"); - if (srl->passflag & SCE_PASS_UV) + if (view_layer->passflag & SCE_PASS_UV) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA"); - if (srl->passflag & SCE_PASS_RGBA) + if (view_layer->passflag & SCE_PASS_RGBA) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RGBA, view, "RGBA"); - if (srl->passflag & SCE_PASS_EMIT) + if (view_layer->passflag & SCE_PASS_EMIT) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_EMIT, view, "RGB"); - if (srl->passflag & SCE_PASS_DIFFUSE) + if (view_layer->passflag & SCE_PASS_DIFFUSE) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE, view, "RGB"); - if (srl->passflag & SCE_PASS_SPEC) + if (view_layer->passflag & SCE_PASS_SPEC) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SPEC, view, "RGB"); - if (srl->passflag & SCE_PASS_AO) + if (view_layer->passflag & SCE_PASS_AO) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_AO, view, "RGB"); - if (srl->passflag & SCE_PASS_ENVIRONMENT) + if (view_layer->passflag & SCE_PASS_ENVIRONMENT) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_ENVIRONMENT, view, "RGB"); - if (srl->passflag & SCE_PASS_INDIRECT) + if (view_layer->passflag & SCE_PASS_INDIRECT) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_INDIRECT, view, "RGB"); - if (srl->passflag & SCE_PASS_SHADOW) + if (view_layer->passflag & SCE_PASS_SHADOW) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SHADOW, view, "RGB"); - if (srl->passflag & SCE_PASS_REFLECT) + if (view_layer->passflag & SCE_PASS_REFLECT) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_REFLECT, view, "RGB"); - if (srl->passflag & SCE_PASS_REFRACT) + if (view_layer->passflag & SCE_PASS_REFRACT) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_REFRACT, view, "RGB"); - if (srl->passflag & SCE_PASS_INDEXOB) + if (view_layer->passflag & SCE_PASS_INDEXOB) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXOB, view, "X"); - if (srl->passflag & SCE_PASS_INDEXMA) + if (view_layer->passflag & SCE_PASS_INDEXMA) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXMA, view, "X"); - if (srl->passflag & SCE_PASS_MIST) + if (view_layer->passflag & SCE_PASS_MIST) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_MIST, view, "Z"); if (rl->passflag & SCE_PASS_RAYHITS) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RAYHITS, view, "RGB"); - if (srl->passflag & SCE_PASS_DIFFUSE_DIRECT) + if (view_layer->passflag & SCE_PASS_DIFFUSE_DIRECT) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_DIRECT, view, "RGB"); - if (srl->passflag & SCE_PASS_DIFFUSE_INDIRECT) + if (view_layer->passflag & SCE_PASS_DIFFUSE_INDIRECT) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_INDIRECT, view, "RGB"); - if (srl->passflag & SCE_PASS_DIFFUSE_COLOR) + if (view_layer->passflag & SCE_PASS_DIFFUSE_COLOR) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_COLOR, view, "RGB"); - if (srl->passflag & SCE_PASS_GLOSSY_DIRECT) + if (view_layer->passflag & SCE_PASS_GLOSSY_DIRECT) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_DIRECT, view, "RGB"); - if (srl->passflag & SCE_PASS_GLOSSY_INDIRECT) + if (view_layer->passflag & SCE_PASS_GLOSSY_INDIRECT) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_INDIRECT, view, "RGB"); - if (srl->passflag & SCE_PASS_GLOSSY_COLOR) + if (view_layer->passflag & SCE_PASS_GLOSSY_COLOR) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_COLOR, view, "RGB"); - if (srl->passflag & SCE_PASS_TRANSM_DIRECT) + if (view_layer->passflag & SCE_PASS_TRANSM_DIRECT) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_DIRECT, view, "RGB"); - if (srl->passflag & SCE_PASS_TRANSM_INDIRECT) + if (view_layer->passflag & SCE_PASS_TRANSM_INDIRECT) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_INDIRECT, view, "RGB"); - if (srl->passflag & SCE_PASS_TRANSM_COLOR) + if (view_layer->passflag & SCE_PASS_TRANSM_COLOR) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_COLOR, view, "RGB"); - if (srl->passflag & SCE_PASS_SUBSURFACE_DIRECT) + if (view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_DIRECT, view, "RGB"); - if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT) + if (view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_INDIRECT, view, "RGB"); - if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR) + if (view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB"); #undef RENDER_LAYER_ADD_PASS_SAFE } } - /* sss, previewrender and envmap don't do layers, so we make a default one */ + FOREACH_VIEW_LAYER_TO_RENDER_END; + + /* previewrender doesn't do layers, so we make a default one */ if (BLI_listbase_is_empty(&rr->layers) && !(layername && layername[0])) { rl = MEM_callocN(sizeof(RenderLayer), "new render layer"); BLI_addtail(&rr->layers, rl); @@ -449,11 +437,10 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf } /* note, this has to be in sync with scene.c */ - rl->lay = (1 << 20) - 1; rl->layflag = 0x7FFF; /* solid ztra halo strand */ rl->passflag = SCE_PASS_COMBINED; - re->r.actlay = 0; + re->active_view_layer = 0; } /* border render; calculate offset for use in compositor. compo is centralized coords */ @@ -518,23 +505,6 @@ void render_result_add_pass(RenderResult *rr, const char *name, int channels, co } } -/* allocate osa new results for samples */ -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, viewname); - - for (a = 0; a < re->osa; a++) { - RenderResult *rr = render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS, viewname); - BLI_addtail(lb, rr); - rr->sample_nr = a; - } - - return lb->first; -} - static int passtype_from_name(const char *name) { const char delim[] = {'.', '\0'}; @@ -994,7 +964,7 @@ void render_result_single_layer_begin(Render *re) /* if scemode is R_SINGLE_LAYER, at end of rendering, merge the both render results */ void render_result_single_layer_end(Render *re) { - SceneRenderLayer *srl; + ViewLayer *view_layer; RenderLayer *rlpush; RenderLayer *rl; int nr; @@ -1015,12 +985,12 @@ void render_result_single_layer_end(Render *re) BLI_remlink(&re->result->layers, rl); /* reconstruct render result layers */ - for (nr = 0, srl = re->r.layers.first; srl; srl = srl->next, nr++) { - if (nr == re->r.actlay) { + for (nr = 0, view_layer = re->view_layers.first; view_layer; view_layer = view_layer->next, nr++) { + if (nr == re->active_view_layer) { BLI_addtail(&re->result->layers, rl); } else { - rlpush = RE_GetRenderLayer(re->pushedresult, srl->name); + rlpush = RE_GetRenderLayer(re->pushedresult, view_layer->name); if (rlpush) { BLI_remlink(&re->pushedresult->layers, rlpush); BLI_addtail(&re->result->layers, rlpush); @@ -1103,8 +1073,8 @@ void render_result_save_empty_result_tiles(Render *re) for (rl = rr->layers.first; rl; rl = rl->next) { for (pa = re->parts.first; pa; pa = pa->next) { if (pa->status != PART_STATUS_MERGED) { - int party = pa->disprect.ymin - re->disprect.ymin + pa->crop; - int partx = pa->disprect.xmin - re->disprect.xmin + pa->crop; + int party = pa->disprect.ymin - re->disprect.ymin; + int partx = pa->disprect.xmin - re->disprect.xmin; IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, re->viewname, true); } } diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 8450098d733..99da5b3ca01 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -65,23 +65,11 @@ #include "MEM_guardedalloc.h" -#include "envmap.h" -#include "pointdensity.h" -#include "voxeldata.h" #include "render_types.h" -#include "shading.h" #include "texture.h" -#include "texture_ocean.h" - -#include "renderdatabase.h" /* needed for UV */ #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; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#include "RE_shader_ext.h" static RNG_THREAD_ARRAY *random_tex_array; @@ -97,63 +85,6 @@ void RE_texture_rng_exit(void) } -static void init_render_texture(Render *re, Tex *tex) -{ - /* imap test */ - if (tex->ima && BKE_image_is_animated(tex->ima)) { - BKE_image_user_frame_calc(&tex->iuser, re ? re->r.cfra : 0, re ? re->flag & R_SEC_FIELD:0); - } - - else if (tex->type==TEX_ENVMAP) { - /* just in case */ - tex->imaflag |= TEX_INTERPOL | TEX_MIPMAP; - tex->extend= TEX_CLIP; - - if (tex->env) { - if (tex->env->type==ENV_PLANE) - tex->extend= TEX_EXTEND; - - /* only free envmap when rendermode was set to render envmaps, for previewrender */ - if (G.is_rendering && re) { - if (re->r.mode & R_ENVMAP) - if (tex->env->stype==ENV_ANIM) - BKE_texture_envmap_free_data(tex->env); - } - } - } - - if (tex->nodetree && tex->use_nodes) { - ntreeTexBeginExecTree(tex->nodetree); /* has internal flag to detect it only does it once */ - } -} - -/* ------------------------------------------------------------------------- */ - -void init_render_textures(Render *re) -{ - Tex *tex; - - tex= re->main->tex.first; - while (tex) { - if (tex->id.us) init_render_texture(re, tex); - tex= tex->id.next; - } -} - -static void end_render_texture(Tex *tex) -{ - if (tex && tex->use_nodes && tex->nodetree && tex->nodetree->execdata) - ntreeTexEndExecTree(tex->nodetree->execdata); -} - -void end_render_textures(Render *re) -{ - Tex *tex; - for (tex= re->main->tex.first; tex; tex= tex->id.next) - if (tex->id.us) - end_render_texture(tex); -} - /* ------------------------------------------------------------------------- */ @@ -755,7 +686,6 @@ static int cubemap_glob(const float n[3], float x, float y, float z, float *adr1 else { copy_v3_v3(nor, n); } - mul_mat3_m4_v3(R.viewinv, nor); x1 = fabsf(nor[0]); y1 = fabsf(nor[1]); @@ -781,115 +711,20 @@ static int cubemap_glob(const float n[3], float x, float y, float z, float *adr1 /* ------------------------------------------------------------------------- */ -/* mtex argument only for projection switches */ -static int cubemap( - const MTex *mtex, VlakRen *vlr, const float n[3], float x, float y, float z, float *adr1, float *adr2) -{ - int proj[4]={0, ME_PROJXY, ME_PROJXZ, ME_PROJYZ}, ret= 0; - - if (vlr) { - int index; - - /* Mesh vertices have such flags, for others we calculate it once based on orco */ - if ((vlr->puno & (ME_PROJXY|ME_PROJXZ|ME_PROJYZ))==0) { - /* test for v1, vlr can be faked for baking */ - if (vlr->v1 && vlr->v1->orco) { - float nor[3]; - normal_tri_v3(nor, vlr->v1->orco, vlr->v2->orco, vlr->v3->orco); - - if (fabsf(nor[0]) < fabsf(nor[2]) && fabsf(nor[1]) < fabsf(nor[2])) vlr->puno |= ME_PROJXY; - else if (fabsf(nor[0]) < fabsf(nor[1]) && fabsf(nor[2]) < fabsf(nor[1])) vlr->puno |= ME_PROJXZ; - else vlr->puno |= ME_PROJYZ; - } - else return cubemap_glob(n, x, y, z, adr1, adr2); - } - - if (mtex) { - /* the mtex->proj{xyz} have type char. maybe this should be wider? */ - /* casting to int ensures that the index type is right. */ - index = (int) mtex->projx; - proj[index]= ME_PROJXY; - - index = (int) mtex->projy; - proj[index]= ME_PROJXZ; - - index = (int) mtex->projz; - proj[index]= ME_PROJYZ; - } - - if (vlr->puno & proj[1]) { - *adr1 = (x + 1.0f) / 2.0f; - *adr2 = (y + 1.0f) / 2.0f; - } - else if (vlr->puno & proj[2]) { - *adr1 = (x + 1.0f) / 2.0f; - *adr2 = (z + 1.0f) / 2.0f; - ret= 1; - } - else { - *adr1 = (y + 1.0f) / 2.0f; - *adr2 = (z + 1.0f) / 2.0f; - ret= 2; - } - } - else { - return cubemap_glob(n, x, y, z, adr1, adr2); - } - - return ret; -} - -/* ------------------------------------------------------------------------- */ - -static int cubemap_ob(Object *ob, const float n[3], float x, float y, float z, float *adr1, float *adr2) -{ - float x1, y1, z1, nor[3]; - int ret; - - if (n==NULL) return 0; - - copy_v3_v3(nor, n); - if (ob) mul_mat3_m4_v3(ob->imat, nor); - - x1 = fabsf(nor[0]); - y1 = fabsf(nor[1]); - z1 = fabsf(nor[2]); - - if (z1>=x1 && z1>=y1) { - *adr1 = (x + 1.0f) / 2.0f; - *adr2 = (y + 1.0f) / 2.0f; - ret= 0; - } - else if (y1>=x1 && y1>=z1) { - *adr1 = (x + 1.0f) / 2.0f; - *adr2 = (z + 1.0f) / 2.0f; - ret= 1; - } - else { - *adr1 = (y + 1.0f) / 2.0f; - *adr2 = (z + 1.0f) / 2.0f; - ret= 2; - } - return ret; -} - /* ------------------------------------------------------------------------- */ static void do_2d_mapping( - const MTex *mtex, float texvec[3], VlakRen *vlr, const float n[3], float dxt[3], float dyt[3]) + const MTex *mtex, float texvec[3], const float n[3], float dxt[3], float dyt[3]) { Tex *tex; - Object *ob= NULL; float fx, fy, fac1, area[8]; - int ok, proj, areaflag= 0, wrap, texco; + int ok, proj, areaflag= 0, wrap; /* mtex variables localized, only cubemap doesn't cooperate yet... */ wrap= mtex->mapping; tex= mtex->tex; - ob= mtex->object; - texco= mtex->texco; - if (R.osa==0) { + if (!(dxt && dyt)) { if (wrap==MTEX_FLAT) { fx = (texvec[0] + 1.0f) / 2.0f; @@ -898,9 +733,7 @@ static void do_2d_mapping( else if (wrap == MTEX_TUBE) map_to_tube( &fx, &fy, texvec[0], texvec[1], texvec[2]); else if (wrap == MTEX_SPHERE) map_to_sphere(&fx, &fy, texvec[0], texvec[1], texvec[2]); else { - if (texco == TEXCO_OBJECT) cubemap_ob(ob, n, texvec[0], texvec[1], texvec[2], &fx, &fy); - else if (texco == TEXCO_GLOB) cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy); - else cubemap(mtex, vlr, n, texvec[0], texvec[1], texvec[2], &fx, &fy); + cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy); } /* repeat */ @@ -996,9 +829,7 @@ static void do_2d_mapping( } else { - if (texco==TEXCO_OBJECT) proj = cubemap_ob(ob, n, texvec[0], texvec[1], texvec[2], &fx, &fy); - else if (texco==TEXCO_GLOB) proj = cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy); - else proj = cubemap(mtex, vlr, n, texvec[0], texvec[1], texvec[2], &fx, &fy); + proj = cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy); if (proj==1) { SWAP(float, dxt[1], dxt[2]); @@ -1124,8 +955,9 @@ static int multitex(Tex *tex, texres->talpha = false; /* is set when image texture returns alpha (considered premul) */ if (use_nodes && tex->use_nodes && tex->nodetree) { + const float cfra = 1.0f; /* This was only set for Blender Internal render before. */ retval = ntreeTexExecTree(tex->nodetree, texres, texvec, dxt, dyt, osatex, thread, - tex, which_output, R.r.cfra, texnode_preview, NULL, NULL); + tex, which_output, cfra, texnode_preview, NULL); } else { switch (tex->type) { @@ -1160,9 +992,6 @@ static int multitex(Tex *tex, BKE_image_tag_time(tex->ima); } break; - case TEX_ENVMAP: - retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres, pool, skip_load_image); - break; case TEX_MUSGRAVE: /* newnoise: musgrave types */ @@ -1205,15 +1034,6 @@ static int multitex(Tex *tex, retval = mg_distNoiseTex(tex, tmpvec, texres); break; - case TEX_POINTDENSITY: - retval = pointdensitytex(tex, texvec, texres); - break; - case TEX_VOXELDATA: - retval = voxeldatatex(tex, texvec, texres); - break; - case TEX_OCEAN: - retval = ocean_texture(tex, texvec, texres); - break; } } @@ -1238,7 +1058,6 @@ static int multitex_nodes_intern(Tex *tex, TexResult *texres, const short thread, short which_output, - ShadeInput *shi, MTex *mtex, struct ImagePool *pool, const bool scene_color_manage, @@ -1259,7 +1078,7 @@ static int multitex_nodes_intern(Tex *tex, if (mtex) { /* we have mtex, use it for 2d mapping images only */ - do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt); + do_2d_mapping(mtex, texvec, NULL, dxt, dyt); rgbnor = multitex(tex, texvec, dxt, dyt, @@ -1272,7 +1091,7 @@ static int multitex_nodes_intern(Tex *tex, texnode_preview, use_nodes); - if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) { + if (mtex->mapto & (MAP_COL)) { ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool); /* don't linearize float buffers, assumed to be linear */ @@ -1307,7 +1126,7 @@ static int multitex_nodes_intern(Tex *tex, zero_v3(dyt_l); } - do_2d_mapping(&localmtex, texvec_l, NULL, NULL, dxt_l, dyt_l); + do_2d_mapping(&localmtex, texvec_l, NULL, dxt_l, dyt_l); rgbnor = multitex(tex, texvec_l, dxt_l, dyt_l, @@ -1357,41 +1176,15 @@ static int multitex_nodes_intern(Tex *tex, * Use it from render pipeline only! */ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, - const short thread, short which_output, ShadeInput *shi, MTex *mtex, struct ImagePool *pool) + const short thread, short which_output, 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, - (R.r.scemode & R_NO_IMAGE_LOAD) != 0, - (R.r.scemode & R_TEXNODE_PREVIEW) != 0, + thread, which_output, mtex, pool, true, + false, + false, true); } -/* 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, const bool skip_load_image) -{ - Tex *tex = mtex->tex; - /* TODO(sergey): Texture preview should become an argument? */ - if (tex->use_nodes && tex->nodetree) { - /* stupid exception here .. but we have to pass shi and mtex to - * textures nodes for 2d mapping and color management for images */ - return ntreeTexExecTree(tex->nodetree, texres, texvec, dxt, dyt, shi->osatex, shi->thread, - 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, - skip_load_image, - (R.r.scemode & R_TEXNODE_PREVIEW) != 0, - true); - } -} - /* Warning, if the texres's values are not declared zero, check the return value to be sure * the color values are set before using the r/g/b values, otherwise you may use uninitialized values - Campbell * @@ -1414,7 +1207,7 @@ int multitex_ext(Tex *tex, texres, thread, 0, - NULL, NULL, + NULL, pool, scene_color_manage, skip_load_image, @@ -1435,7 +1228,7 @@ int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct Image texres, 0, 0, - NULL, NULL, + NULL, pool, scene_color_manage, skip_load_image, @@ -1652,1949 +1445,6 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen return in; } -static void texco_mapping(ShadeInput *shi, Tex *tex, MTex *mtex, - const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3]) -{ - /* new: first swap coords, then map, then trans/scale */ - if (tex->type == TEX_IMAGE) { - /* placement */ - texvec[0] = mtex->projx ? co[mtex->projx - 1] : 0.f; - texvec[1] = mtex->projy ? co[mtex->projy - 1] : 0.f; - texvec[2] = mtex->projz ? co[mtex->projz - 1] : 0.f; - - if (shi->osatex) { - if (mtex->projx) { - dxt[0] = dx[mtex->projx - 1]; - dyt[0] = dy[mtex->projx - 1]; - } - else dxt[0] = dyt[0] = 0.f; - if (mtex->projy) { - dxt[1] = dx[mtex->projy - 1]; - dyt[1] = dy[mtex->projy - 1]; - } - else dxt[1] = dyt[1] = 0.f; - if (mtex->projz) { - dxt[2] = dx[mtex->projz - 1]; - dyt[2] = dy[mtex->projz - 1]; - } - else dxt[2] = dyt[2] = 0.f; - } - do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt); - - /* translate and scale */ - texvec[0] = mtex->size[0]*(texvec[0] - 0.5f) + mtex->ofs[0] + 0.5f; - texvec[1] = mtex->size[1]*(texvec[1] - 0.5f) + mtex->ofs[1] + 0.5f; - if (shi->osatex) { - dxt[0] = mtex->size[0] * dxt[0]; - dxt[1] = mtex->size[1] * dxt[1]; - dyt[0] = mtex->size[0] * dyt[0]; - dyt[1] = mtex->size[1] * dyt[1]; - } - - /* problem: repeat-mirror is not a 'repeat' but 'extend' in imagetexture.c */ - /* TXF: bug was here, only modify texvec when repeat mode set, old code affected other modes too. - * New texfilters solve mirroring differently so that it also works correctly when - * textures are scaled (sizeXYZ) as well as repeated. See also modification in do_2d_mapping(). - * (since currently only done in osa mode, results will look incorrect without osa TODO) */ - if (tex->extend == TEX_REPEAT && (tex->flag & TEX_REPEAT_XMIR)) { - if (tex->texfilter == TXF_BOX) - texvec[0] -= floorf(texvec[0]); /* this line equivalent to old code, same below */ - else if (texvec[0] < 0.f || texvec[0] > 1.f) { - const float tx = 0.5f*texvec[0]; - texvec[0] = 2.f*(tx - floorf(tx)); - if (texvec[0] > 1.f) texvec[0] = 2.f - texvec[0]; - } - } - if (tex->extend == TEX_REPEAT && (tex->flag & TEX_REPEAT_YMIR)) { - if (tex->texfilter == TXF_BOX) - texvec[1] -= floorf(texvec[1]); - else if (texvec[1] < 0.f || texvec[1] > 1.f) { - const float ty = 0.5f*texvec[1]; - texvec[1] = 2.f*(ty - floorf(ty)); - if (texvec[1] > 1.f) texvec[1] = 2.f - texvec[1]; - } - } - - } - else { /* procedural */ - /* placement */ - texvec[0] = mtex->size[0]*(mtex->projx ? (co[mtex->projx - 1] + mtex->ofs[0]) : mtex->ofs[0]); - texvec[1] = mtex->size[1]*(mtex->projy ? (co[mtex->projy - 1] + mtex->ofs[1]) : mtex->ofs[1]); - texvec[2] = mtex->size[2]*(mtex->projz ? (co[mtex->projz - 1] + mtex->ofs[2]) : mtex->ofs[2]); - - if (shi->osatex) { - if (mtex->projx) { - dxt[0] = mtex->size[0]*dx[mtex->projx - 1]; - dyt[0] = mtex->size[0]*dy[mtex->projx - 1]; - } - else dxt[0] = dyt[0] = 0.f; - if (mtex->projy) { - dxt[1] = mtex->size[1]*dx[mtex->projy - 1]; - dyt[1] = mtex->size[1]*dy[mtex->projy - 1]; - } - else dxt[1] = dyt[1] = 0.f; - if (mtex->projz) { - dxt[2] = mtex->size[2]*dx[mtex->projz - 1]; - dyt[2] = mtex->size[2]*dy[mtex->projz - 1]; - } - else dxt[2]= dyt[2] = 0.f; - } - - if (mtex->tex->type == TEX_ENVMAP) { - EnvMap *env = tex->env; - if (!env->object) { - // env->object is a view point for envmap rendering - // if it's not set, return the result depending on the world_space_shading flag - if (BKE_scene_use_world_space_shading(R.scene)) { - mul_mat3_m4_v3(R.viewinv, texvec); - if (shi->osatex) { - mul_mat3_m4_v3(R.viewinv, dxt); - mul_mat3_m4_v3(R.viewinv, dyt); - } - } - } - } - } -} - -/* Bump code from 2.5 development cycle, has a number of bugs, but here for compatibility */ - -typedef struct CompatibleBump { - float nu[3], nv[3], nn[3]; - float dudnu, dudnv, dvdnu, dvdnv; - bool nunvdone; -} CompatibleBump; - -static void compatible_bump_init(CompatibleBump *compat_bump) -{ - memset(compat_bump, 0, sizeof(*compat_bump)); - - compat_bump->dudnu = 1.0f; - compat_bump->dvdnv = 1.0f; -} - -static void compatible_bump_uv_derivs(CompatibleBump *compat_bump, ShadeInput *shi, MTex *mtex, int i) -{ - /* uvmapping only, calculation of normal tangent u/v partial derivatives - * (should not be here, dudnu, dudnv, dvdnu & dvdnv should probably be part of ShadeInputUV struct, - * nu/nv in ShadeInput and this calculation should then move to shadeinput.c, - * shade_input_set_shade_texco() func.) */ - - /* NOTE: test for shi->obr->ob here, - * since vlr/obr/obi can be 'fake' when called from fastshade(), another reason to move it.. */ - - /* NOTE: shi->v1 is NULL when called from displace_render_vert, - * assigning verts in this case is not trivial because the shi quad face side is not know. */ - if ((mtex->texflag & MTEX_COMPAT_BUMP) && shi->obr && shi->obr->ob && shi->v1) { - if (mtex->mapto & (MAP_NORM|MAP_WARP) && !((mtex->tex->type==TEX_IMAGE) && (mtex->tex->imaflag & TEX_NORMALMAP))) { - MTFace* tf = RE_vlakren_get_tface(shi->obr, shi->vlr, i, NULL, 0); - int j1 = shi->i1, j2 = shi->i2, j3 = shi->i3; - - vlr_set_uv_indices(shi->vlr, &j1, &j2, &j3); - - /* compute ortho basis around normal */ - if (!compat_bump->nunvdone) { - /* render normal is negated */ - compat_bump->nn[0] = -shi->vn[0]; - compat_bump->nn[1] = -shi->vn[1]; - compat_bump->nn[2] = -shi->vn[2]; - ortho_basis_v3v3_v3(compat_bump->nu, compat_bump->nv, compat_bump->nn); - compat_bump->nunvdone = true; - } - - if (tf) { - const float *uv1 = tf->uv[j1], *uv2 = tf->uv[j2], *uv3 = tf->uv[j3]; - const float an[3] = {fabsf(compat_bump->nn[0]), fabsf(compat_bump->nn[1]), fabsf(compat_bump->nn[2])}; - const int a1 = (an[0] > an[1] && an[0] > an[2]) ? 1 : 0; - const int a2 = (an[2] > an[0] && an[2] > an[1]) ? 1 : 2; - const float dp1_a1 = shi->v1->co[a1] - shi->v3->co[a1]; - const float dp1_a2 = shi->v1->co[a2] - shi->v3->co[a2]; - const float dp2_a1 = shi->v2->co[a1] - shi->v3->co[a1]; - const float dp2_a2 = shi->v2->co[a2] - shi->v3->co[a2]; - const float du1 = uv1[0] - uv3[0], du2 = uv2[0] - uv3[0]; - const float dv1 = uv1[1] - uv3[1], dv2 = uv2[1] - uv3[1]; - const float dpdu_a1 = dv2*dp1_a1 - dv1*dp2_a1; - const float dpdu_a2 = dv2*dp1_a2 - dv1*dp2_a2; - const float dpdv_a1 = du1*dp2_a1 - du2*dp1_a1; - const float dpdv_a2 = du1*dp2_a2 - du2*dp1_a2; - float d = dpdu_a1*dpdv_a2 - dpdv_a1*dpdu_a2; - float uvd = du1*dv2 - dv1*du2; - - if (uvd == 0.f) uvd = 1e-5f; - if (d == 0.f) d = 1e-5f; - d = uvd / d; - - compat_bump->dudnu = (dpdv_a2*compat_bump->nu[a1] - dpdv_a1*compat_bump->nu[a2])*d; - compat_bump->dvdnu = (dpdu_a1*compat_bump->nu[a2] - dpdu_a2*compat_bump->nu[a1])*d; - compat_bump->dudnv = (dpdv_a2*compat_bump->nv[a1] - dpdv_a1*compat_bump->nv[a2])*d; - compat_bump->dvdnv = (dpdu_a1*compat_bump->nv[a2] - dpdu_a2*compat_bump->nv[a1])*d; - } - } - } -} - -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, 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; - const int fromrgb = ((tex->type == TEX_IMAGE) || ((tex->flag & TEX_COLORBAND)!=0)); - const float bf = -0.04f*Tnor*mtex->norfac; - int rgbnor; - /* disable internal bump eval */ - float *nvec = texres->nor; - texres->nor = NULL; - /* du & dv estimates, constant value defaults */ - du = dv = 0.01f; - - /* compute ortho basis around normal */ - if (!compat_bump->nunvdone) { - /* render normal is negated */ - negate_v3_v3(compat_bump->nn, shi->vn); - ortho_basis_v3v3_v3(compat_bump->nu, compat_bump->nv, compat_bump->nn); - compat_bump->nunvdone = true; - } - - /* two methods, either constant based on main image resolution, - * (which also works without osa, though of course not always good (or even very bad) results), - * or based on tex derivative max values (osa only). Not sure which is best... */ - - if (!shi->osatex && (tex->type == TEX_IMAGE) && tex->ima) { - /* in case we have no proper derivatives, fall back to - * computing du/dv it based on image size */ - ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool); - if (ibuf) { - du = 1.f/(float)ibuf->x; - dv = 1.f/(float)ibuf->y; - } - BKE_image_pool_release_ibuf(tex->ima, ibuf, pool); - } - else if (shi->osatex) { - /* we have derivatives, can compute proper du/dv */ - if (tex->type == TEX_IMAGE) { /* 2d image, use u & v max. of dx/dy 2d vecs */ - const float adx[2] = {fabsf(dx[0]), fabsf(dx[1])}; - const float ady[2] = {fabsf(dy[0]), fabsf(dy[1])}; - du = MAX2(adx[0], ady[0]); - dv = MAX2(adx[1], ady[1]); - } - else { /* 3d procedural, estimate from all dx/dy elems */ - const float adx[3] = {fabsf(dx[0]), fabsf(dx[1]), fabsf(dx[2])}; - const float ady[3] = {fabsf(dy[0]), fabsf(dy[1]), fabsf(dy[2])}; - du = max_fff(adx[0], adx[1], adx[2]); - dv = max_fff(ady[0], ady[1], ady[2]); - } - } - - /* 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, skip_load_image); - cd = fromrgb ? (texres->tr + texres->tg + texres->tb) / 3.0f : texres->tin; - - if (mtex->texco == TEXCO_UV) { - /* for the uv case, use the same value for both du/dv, - * since individually scaling the normal derivatives makes them useless... */ - du = min_ff(du, dv); - idu = (du < 1e-5f) ? bf : (bf/du); - - /* +u val */ - tco[0] = co[0] + compat_bump->dudnu*du; - 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, skip_load_image); - ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin)); - - /* +v val */ - tco[0] = co[0] + compat_bump->dudnv*du; - 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, skip_load_image); - vd = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin)); - } - else { - float tu[3], tv[3]; - - copy_v3_v3(tu, compat_bump->nu); - copy_v3_v3(tv, compat_bump->nv); - - idu = (du < 1e-5f) ? bf : (bf/du); - idv = (dv < 1e-5f) ? bf : (bf/dv); - - if ((mtex->texco == TEXCO_ORCO) && shi->obr && shi->obr->ob) { - mul_mat3_m4_v3(shi->obr->ob->imat_ren, tu); - mul_mat3_m4_v3(shi->obr->ob->imat_ren, tv); - normalize_v3(tu); - normalize_v3(tv); - } - else if (mtex->texco == TEXCO_GLOB) { - mul_mat3_m4_v3(R.viewinv, tu); - mul_mat3_m4_v3(R.viewinv, tv); - } - else if (mtex->texco == TEXCO_OBJECT && mtex->object) { - mul_mat3_m4_v3(mtex->object->imat_ren, tu); - mul_mat3_m4_v3(mtex->object->imat_ren, tv); - normalize_v3(tu); - normalize_v3(tv); - } - - /* +u val */ - tco[0] = co[0] + tu[0]*du; - 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, skip_load_image); - ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin)); - - /* +v val */ - tco[0] = co[0] + tv[0]*dv; - 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, skip_load_image); - vd = idv*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin)); - } - - /* bumped normal */ - compat_bump->nu[0] += ud*compat_bump->nn[0]; - compat_bump->nu[1] += ud*compat_bump->nn[1]; - compat_bump->nu[2] += ud*compat_bump->nn[2]; - compat_bump->nv[0] += vd*compat_bump->nn[0]; - compat_bump->nv[1] += vd*compat_bump->nn[1]; - compat_bump->nv[2] += vd*compat_bump->nn[2]; - cross_v3_v3v3(nvec, compat_bump->nu, compat_bump->nv); - - nvec[0] = -nvec[0]; - nvec[1] = -nvec[1]; - nvec[2] = -nvec[2]; - texres->nor = nvec; - - rgbnor |= TEX_NOR; - return rgbnor; -} - -/* Improved bump code from later in 2.5 development cycle */ - -typedef struct NTapBump { - int init_done; - int iPrevBumpSpace; /* 0: uninitialized, 1: objectspace, 2: texturespace, 4: viewspace */ - /* bumpmapping */ - float vNorg[3]; /* backup copy of shi->vn */ - float vNacc[3]; /* original surface normal minus the surface gradient of every bump map which is encountered */ - float vR1[3], vR2[3]; /* cross products (sigma_y, original_normal), (original_normal, sigma_x) */ - float sgn_det; /* sign of the determinant of the matrix {sigma_x, sigma_y, original_normal} */ - float fPrevMagnitude; /* copy of previous magnitude, used for multiple bumps in different spaces */ -} NTapBump; - -static void ntap_bump_init(NTapBump *ntap_bump) -{ - memset(ntap_bump, 0, sizeof(*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, - const bool skip_load_image) -{ - TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */ - - const int fromrgb = ((tex->type == TEX_IMAGE) || ((tex->flag & TEX_COLORBAND)!=0)); - - /* The negate on Hscale is done because the - * normal in the renderer points inward which corresponds - * to inverting the bump map. The normals are generated - * this way in calc_vertexnormals(). Should this ever change - * this negate must be removed. */ - float Hscale = -Tnor*mtex->norfac; - - int dimx=512, dimy=512; - const int imag_tspace_dimension_x = 1024; /* only used for texture space variant */ - float aspect = 1.0f; - - /* 2 channels for 2D texture and 3 for 3D textures. */ - const int nr_channels = (mtex->texco == TEXCO_UV)? 2 : 3; - int c, rgbnor, iBumpSpace; - float dHdx, dHdy; - int found_deriv_map = (tex->type==TEX_IMAGE) && (tex->imaflag & TEX_DERIVATIVEMAP); - - /* disable internal bump eval in sampler, save pointer */ - float *nvec = texres->nor; - texres->nor = NULL; - - if (found_deriv_map==0) { - if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) { - if (tex->ima) - Hscale *= 13.0f; /* appears to be a sensible default value */ - } - else - Hscale *= 0.1f; /* factor 0.1 proved to look like the previous bump code */ - } - - if ( !ntap_bump->init_done ) { - copy_v3_v3(ntap_bump->vNacc, shi->vn); - copy_v3_v3(ntap_bump->vNorg, shi->vn); - ntap_bump->fPrevMagnitude = 1.0f; - ntap_bump->iPrevBumpSpace = 0; - - ntap_bump->init_done = true; - } - - /* resolve image dimensions */ - if (found_deriv_map || (mtex->texflag&MTEX_BUMP_TEXTURESPACE)!=0) { - ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool); - if (ibuf) { - dimx = ibuf->x; - dimy = ibuf->y; - aspect = ((float) dimy) / dimx; - } - BKE_image_pool_release_ibuf(tex->ima, ibuf, pool); - } - - if (found_deriv_map) { - float dBdu, dBdv, auto_bump = 1.0f; - float s = 1; /* negate this if flipped texture coordinate */ - texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); - rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool, skip_load_image); - - if (shi->obr->ob->derivedFinal) { - auto_bump = shi->obr->ob->derivedFinal->auto_bump_scale; - } - - { - float fVirtDim = sqrtf(fabsf((float) (dimx*dimy)*mtex->size[0]*mtex->size[1])); - auto_bump /= MAX2(fVirtDim, FLT_EPSILON); - } - - /* this variant using a derivative map is described here - * http://mmikkelsen3d.blogspot.com/2011/07/derivative-maps.html */ - dBdu = auto_bump*Hscale*dimx*(2*texres->tr-1); - dBdv = auto_bump*Hscale*dimy*(2*texres->tg-1); - - dHdx = dBdu*dxt[0] + s * dBdv*dxt[1]; - dHdy = dBdu*dyt[0] + s * dBdv*dyt[1]; - } - else if (!(mtex->texflag & MTEX_5TAP_BUMP)) { - /* compute height derivatives with respect to output image pixel coordinates x and y */ - float STll[3], STlr[3], STul[3]; - float Hll, Hlr, Hul; - - texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); - - for (c=0; c<nr_channels; c++) { - /* dx contains the derivatives (du/dx, dv/dx) - * dy contains the derivatives (du/dy, dv/dy) */ - STll[c] = texvec[c]; - STlr[c] = texvec[c]+dxt[c]; - STul[c] = texvec[c]+dyt[c]; - } - - /* clear unused derivatives */ - for (c=nr_channels; c<3; c++) { - STll[c] = 0.0f; - STlr[c] = 0.0f; - STul[c] = 0.0f; - } - - /* use texres for the center sample, set rgbnor */ - 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, skip_load_image); - Hlr = (fromrgb) ? IMB_colormanagement_get_luminance(&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); - } - else { - /* same as above, but doing 5 taps, increasing quality at cost of speed */ - float STc[3], STl[3], STr[3], STd[3], STu[3]; - float /* Hc, */ /* UNUSED */ Hl, Hr, Hd, Hu; - - texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); - - for (c=0; c<nr_channels; c++) { - STc[c] = texvec[c]; - STl[c] = texvec[c] - 0.5f*dxt[c]; - STr[c] = texvec[c] + 0.5f*dxt[c]; - STd[c] = texvec[c] - 0.5f*dyt[c]; - STu[c] = texvec[c] + 0.5f*dyt[c]; - } - - /* clear unused derivatives */ - for (c=nr_channels; c<3; c++) { - STc[c] = 0.0f; - STl[c] = 0.0f; - STr[c] = 0.0f; - STd[c] = 0.0f; - STu[c] = 0.0f; - } - - /* use texres for the center sample, set rgbnor */ - 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, 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); - } - - /* restore pointer */ - texres->nor = nvec; - - /* replaced newbump with code based on listing 1 and 2 of - * [Mik10] Mikkelsen M. S.: Bump Mapping Unparameterized Surfaces on the GPU. - * -> http://jbit.net/~sparky/sfgrad_bump/mm_sfgrad_bump.pdf */ - - if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) - iBumpSpace = 1; - else if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) - iBumpSpace = 2; - else - iBumpSpace = 4; /* ViewSpace */ - - if ( ntap_bump->iPrevBumpSpace != iBumpSpace ) { - - /* initialize normal perturbation vectors */ - int xyz; - float fDet, abs_fDet, fMagnitude; - /* object2view and inverted matrix */ - float obj2view[3][3], view2obj[3][3], tmp[4][4]; - /* local copies of derivatives and normal */ - float dPdx[3], dPdy[3], vN[3]; - copy_v3_v3(dPdx, shi->dxco); - copy_v3_v3(dPdy, shi->dyco); - copy_v3_v3(vN, ntap_bump->vNorg); - - if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) { - /* TODO: these calculations happen for every pixel! - * -> move to shi->obi */ - mul_m4_m4m4(tmp, R.viewmat, shi->obr->ob->obmat); - copy_m3_m4(obj2view, tmp); /* use only upper left 3x3 matrix */ - invert_m3_m3(view2obj, obj2view); - - /* generate the surface derivatives in object space */ - mul_m3_v3(view2obj, dPdx); - mul_m3_v3(view2obj, dPdy); - /* generate the unit normal in object space */ - mul_transposed_m3_v3(obj2view, vN); - normalize_v3(vN); - } - - cross_v3_v3v3(ntap_bump->vR1, dPdy, vN); - cross_v3_v3v3(ntap_bump->vR2, vN, dPdx); - fDet = dot_v3v3(dPdx, ntap_bump->vR1); - ntap_bump->sgn_det = (fDet < 0)? -1.0f: 1.0f; - abs_fDet = ntap_bump->sgn_det * fDet; - - if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) { - if (tex->ima) { - /* crazy hack solution that gives results similar to normal mapping - part 1 */ - normalize_v3(ntap_bump->vR1); - normalize_v3(ntap_bump->vR2); - abs_fDet = 1.0f; - } - } - - fMagnitude = abs_fDet; - if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) { - /* pre do transform of texres->nor by the inverse transposed of obj2view */ - mul_transposed_m3_v3(view2obj, vN); - mul_transposed_m3_v3(view2obj, ntap_bump->vR1); - mul_transposed_m3_v3(view2obj, ntap_bump->vR2); - - fMagnitude *= len_v3(vN); - } - - if (ntap_bump->fPrevMagnitude > 0.0f) - for (xyz=0; xyz<3; xyz++) - ntap_bump->vNacc[xyz] *= fMagnitude / ntap_bump->fPrevMagnitude; - - ntap_bump->fPrevMagnitude = fMagnitude; - ntap_bump->iPrevBumpSpace = iBumpSpace; - } - - if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) { - if (tex->ima) { - /* crazy hack solution that gives results similar to normal mapping - part 2 */ - float vec[2]; - const float imag_tspace_dimension_y = aspect*imag_tspace_dimension_x; - - vec[0] = imag_tspace_dimension_x*dxt[0]; - vec[1] = imag_tspace_dimension_y*dxt[1]; - dHdx *= 1.0f/len_v2(vec); - vec[0] = imag_tspace_dimension_x*dyt[0]; - vec[1] = imag_tspace_dimension_y*dyt[1]; - dHdy *= 1.0f/len_v2(vec); - } - } - - /* subtract the surface gradient from vNacc */ - for (c=0; c<3; c++) { - float vSurfGrad_compi = ntap_bump->sgn_det * (dHdx * ntap_bump->vR1[c] + dHdy * ntap_bump->vR2[c]); - ntap_bump->vNacc[c] -= vSurfGrad_compi; - texres->nor[c] = ntap_bump->vNacc[c]; /* copy */ - } - - rgbnor |= TEX_NOR; - return rgbnor; -} - -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; - Tex *tex; - TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; - float *co = NULL, *dx = NULL, *dy = NULL; - float fact, facm, factt, facmm, stencilTin=1.0; - float texvec[3], dxt[3], dyt[3], tempvec[3], norvec[3], warpvec[3]={0.0f, 0.0f, 0.0f}, Tnor=1.0; - int tex_nr, rgbnor= 0; - bool warp_done = false, use_compat_bump = false, use_ntap_bump = false; - bool found_nmapping = false, found_deriv_map = false; - bool iFirstTimeNMap = true; - - compatible_bump_init(&compat_bump); - ntap_bump_init(&ntap_bump); - - if (re->r.scemode & R_NO_TEX) return; - /* here: test flag if there's a tex (todo) */ - - for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) { - - /* separate tex switching */ - if (shi->mat->septex & (1<<tex_nr)) continue; - - if (shi->mat->mtex[tex_nr]) { - mtex= shi->mat->mtex[tex_nr]; - - tex= mtex->tex; - if (tex == NULL) continue; - - found_deriv_map = (tex->type==TEX_IMAGE) && (tex->imaflag & TEX_DERIVATIVEMAP); - use_compat_bump= (mtex->texflag & MTEX_COMPAT_BUMP) != 0; - use_ntap_bump = ((mtex->texflag & (MTEX_3TAP_BUMP|MTEX_5TAP_BUMP|MTEX_BICUBIC_BUMP))!=0 || found_deriv_map!=0) ? true : false; - - /* XXX texture node trees don't work for this yet */ - if (tex->nodetree && tex->use_nodes) { - use_compat_bump = false; - use_ntap_bump = false; - } - - /* case displacement mapping */ - if (shi->osatex == 0 && use_ntap_bump) { - use_ntap_bump = false; - use_compat_bump = true; - } - - /* case ocean */ - if (tex->type == TEX_OCEAN) { - use_ntap_bump = false; - use_compat_bump = false; - } - - /* which coords */ - if (mtex->texco==TEXCO_ORCO) { - if (mtex->texflag & MTEX_DUPLI_MAPTO) { - co= shi->duplilo; dx= dxt; dy= dyt; - dxt[0]= dxt[1]= dxt[2]= 0.0f; - dyt[0]= dyt[1]= dyt[2]= 0.0f; - } - else { - co= shi->lo; dx= shi->dxlo; dy= shi->dylo; - } - } - else if (mtex->texco==TEXCO_OBJECT) { - Object *ob= mtex->object; - if (ob) { - co= tempvec; - dx= dxt; - dy= dyt; - copy_v3_v3(tempvec, shi->co); - if (mtex->texflag & MTEX_OB_DUPLI_ORIG) - if (shi->obi && shi->obi->duplitexmat) - mul_m4_v3(shi->obi->duplitexmat, tempvec); - mul_m4_v3(ob->imat_ren, tempvec); - if (shi->osatex) { - copy_v3_v3(dxt, shi->dxco); - copy_v3_v3(dyt, shi->dyco); - mul_mat3_m4_v3(ob->imat_ren, dxt); - mul_mat3_m4_v3(ob->imat_ren, dyt); - } - } - else { - /* if object doesn't exist, do not use orcos (not initialized) */ - co= shi->co; - dx= shi->dxco; dy= shi->dyco; - } - } - else if (mtex->texco==TEXCO_REFL) { - calc_R_ref(shi); - co= shi->ref; dx= shi->dxref; dy= shi->dyref; - } - else if (mtex->texco==TEXCO_NORM) { - co= shi->orn; dx= shi->dxno; dy= shi->dyno; - } - else if (mtex->texco==TEXCO_TANGENT) { - co= shi->tang; dx= shi->dxno; dy= shi->dyno; - } - else if (mtex->texco==TEXCO_GLOB) { - co= shi->gl; dx= shi->dxgl; dy= shi->dygl; - } - else if (mtex->texco==TEXCO_UV) { - if (mtex->texflag & MTEX_DUPLI_MAPTO) { - co= shi->dupliuv; dx= dxt; dy= dyt; - dxt[0]= dxt[1]= dxt[2]= 0.0f; - dyt[0]= dyt[1]= dyt[2]= 0.0f; - } - else { - ShadeInputUV *suv= &shi->uv[shi->actuv]; - int i = shi->actuv; - - if (mtex->uvname[0] != 0) { - for (i = 0; i < shi->totuv; i++) { - if (STREQ(shi->uv[i].name, mtex->uvname)) { - suv= &shi->uv[i]; - break; - } - } - } - - co= suv->uv; - dx= suv->dxuv; - dy= suv->dyuv; - - compatible_bump_uv_derivs(&compat_bump, shi, mtex, i); - } - } - else if (mtex->texco==TEXCO_WINDOW) { - co= shi->winco; dx= shi->dxwin; dy= shi->dywin; - } - else if (mtex->texco==TEXCO_STRAND) { - co= tempvec; dx= dxt; dy= dyt; - co[0]= shi->strandco; - co[1]= co[2]= 0.0f; - dx[0]= shi->dxstrand; - dx[1]= dx[2]= 0.0f; - dy[0]= shi->dystrand; - dy[1]= dy[2]= 0.0f; - } - else if (mtex->texco==TEXCO_STRESS) { - co= tempvec; dx= dxt; dy= dyt; - co[0]= shi->stress; - co[1]= co[2]= 0.0f; - dx[0]= 0.0f; - dx[1]= dx[2]= 0.0f; - dy[0]= 0.0f; - dy[1]= dy[2]= 0.0f; - } - else { - continue; /* can happen when texco defines disappear and it renders old files */ - } - - /* the pointer defines if bumping happens */ - if (mtex->mapto & (MAP_NORM|MAP_WARP)) { - texres.nor= norvec; - norvec[0]= norvec[1]= norvec[2]= 0.0; - } - else texres.nor= NULL; - - if (warp_done) { - add_v3_v3v3(tempvec, co, warpvec); - co= tempvec; - } - - /* XXX texture node trees don't work for this yet */ - if (texres.nor && !((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP))) { - if (use_compat_bump) { - rgbnor = compatible_bump_compute(&compat_bump, shi, mtex, tex, - &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt, - 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, 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, 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, skip_load_image); - } - - /* texture output */ - - if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - rgbnor -= TEX_RGB; - } - if (mtex->texflag & MTEX_NEGATIVE) { - if (rgbnor & TEX_RGB) { - texres.tr= 1.0f-texres.tr; - texres.tg= 1.0f-texres.tg; - texres.tb= 1.0f-texres.tb; - } - texres.tin= 1.0f-texres.tin; - } - if (mtex->texflag & MTEX_STENCIL) { - if (rgbnor & TEX_RGB) { - fact= texres.ta; - texres.ta*= stencilTin; - stencilTin*= fact; - } - else { - fact= texres.tin; - texres.tin*= stencilTin; - stencilTin*= fact; - } - } - else { - Tnor*= stencilTin; - } - - if (texres.nor) { - if ((rgbnor & TEX_NOR)==0) { - /* make our own normal */ - if (rgbnor & TEX_RGB) { - copy_v3_v3(texres.nor, &texres.tr); - } - else { - float co_nor= 0.5f * cosf(texres.tin - 0.5f); - float si = 0.5f * sinf(texres.tin - 0.5f); - float f1, f2; - - f1= shi->vn[0]; - f2= shi->vn[1]; - texres.nor[0]= f1*co_nor+f2*si; - f1= shi->vn[1]; - f2= shi->vn[2]; - texres.nor[1]= f1*co_nor+f2*si; - texres.nor[2]= f2*co_nor-f1*si; - } - } - /* warping, local space */ - if (mtex->mapto & MAP_WARP) { - float *warpnor= texres.nor, warpnor_[3]; - - if (use_ntap_bump) { - copy_v3_v3(warpnor_, texres.nor); - warpnor= warpnor_; - normalize_v3(warpnor_); - } - warpvec[0]= mtex->warpfac*warpnor[0]; - warpvec[1]= mtex->warpfac*warpnor[1]; - warpvec[2]= mtex->warpfac*warpnor[2]; - warp_done = true; - } -#if 0 - if (mtex->texflag & MTEX_VIEWSPACE) { - /* rotate to global coords */ - if (mtex->texco==TEXCO_ORCO || mtex->texco==TEXCO_UV) { - if (shi->vlr && shi->obr && shi->obr->ob) { - float len= normalize_v3(texres.nor); - /* can be optimized... (ton) */ - mul_mat3_m4_v3(shi->obr->ob->obmat, texres.nor); - mul_mat3_m4_v3(re->viewmat, texres.nor); - normalize_v3_length(texres.nor, len); - } - } - } -#endif - } - - /* mapping */ - if (mtex->mapto & (MAP_COL | MAP_COLSPEC | MAP_COLMIR)) { - float tcol[3]; - - /* stencil maps on the texture control slider, not texture intensity value */ - copy_v3_v3(tcol, &texres.tr); - - if ((rgbnor & TEX_RGB) == 0) { - copy_v3_v3(tcol, &mtex->r); - } - else if (mtex->mapto & MAP_ALPHA) { - texres.tin = stencilTin; - } - else { - texres.tin = texres.ta; - } - - /* inverse gamma correction */ - if (tex->type==TEX_IMAGE) { - Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, re->pool); - - /* don't linearize float buffers, assumed to be linear */ - if (ibuf != NULL && - ibuf->rect_float == NULL && - (rgbnor & TEX_RGB) && - R.scene_color_manage) - { - IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace); - } - - 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); - } - if (mtex->mapto & MAP_COLSPEC) { - float colspecfac= mtex->colspecfac*stencilTin; - texture_rgb_blend(&shi->specr, tcol, &shi->specr, texres.tin, colspecfac, mtex->blendtype); - } - if (mtex->mapto & MAP_COLMIR) { - float mirrfac= mtex->mirrfac*stencilTin; - - /* exception for envmap only */ - if (tex->type==TEX_ENVMAP && mtex->blendtype==MTEX_BLEND) { - fact= texres.tin*mirrfac; - facm= 1.0f- fact; - shi->refcol[0]= fact + facm*shi->refcol[0]; - shi->refcol[1]= fact*tcol[0] + facm*shi->refcol[1]; - shi->refcol[2]= fact*tcol[1] + facm*shi->refcol[2]; - shi->refcol[3]= fact*tcol[2] + facm*shi->refcol[3]; - } - else { - texture_rgb_blend(&shi->mirr, tcol, &shi->mirr, texres.tin, mirrfac, mtex->blendtype); - } - } - } - if ( (mtex->mapto & MAP_NORM) ) { - if (texres.nor) { - float norfac= mtex->norfac; - - /* we need to code blending modes for normals too once.. now 1 exception hardcoded */ - - if ((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP)) { - - found_nmapping = 1; - - /* qdn: for normalmaps, to invert the normalmap vector, - * it is better to negate x & y instead of subtracting the vector as was done before */ - if (norfac < 0.0f) { - texres.nor[0] = -texres.nor[0]; - texres.nor[1] = -texres.nor[1]; - } - fact = Tnor*fabsf(norfac); - if (fact>1.f) fact = 1.f; - facm = 1.f-fact; - if (mtex->normapspace == MTEX_NSPACE_TANGENT) { - /* qdn: tangent space */ - float B[3], tv[3]; - const float *no = iFirstTimeNMap ? shi->nmapnorm : shi->vn; - iFirstTimeNMap = false; - cross_v3_v3v3(B, no, shi->nmaptang); /* bitangent */ - mul_v3_fl(B, shi->nmaptang[3]); - /* transform norvec from tangent space to object surface in camera space */ - tv[0] = texres.nor[0]*shi->nmaptang[0] + texres.nor[1]*B[0] + texres.nor[2]*no[0]; - tv[1] = texres.nor[0]*shi->nmaptang[1] + texres.nor[1]*B[1] + texres.nor[2]*no[1]; - tv[2] = texres.nor[0]*shi->nmaptang[2] + texres.nor[1]*B[2] + texres.nor[2]*no[2]; - shi->vn[0]= facm*no[0] + fact*tv[0]; - shi->vn[1]= facm*no[1] + fact*tv[1]; - shi->vn[2]= facm*no[2] + fact*tv[2]; - } - else { - float nor[3]; - - copy_v3_v3(nor, texres.nor); - - if (mtex->normapspace == MTEX_NSPACE_CAMERA) { - /* pass */ - } - else if (mtex->normapspace == MTEX_NSPACE_WORLD) { - mul_mat3_m4_v3(re->viewmat, nor); - } - else if (mtex->normapspace == MTEX_NSPACE_OBJECT) { - if (shi->obr && shi->obr->ob) - mul_mat3_m4_v3(shi->obr->ob->obmat, nor); - mul_mat3_m4_v3(re->viewmat, nor); - } - - normalize_v3(nor); - - /* qdn: worldspace */ - shi->vn[0]= facm*shi->vn[0] + fact*nor[0]; - shi->vn[1]= facm*shi->vn[1] + fact*nor[1]; - shi->vn[2]= facm*shi->vn[2] + fact*nor[2]; - } - } - else { - /* XXX texture node trees don't work for this yet */ - if (use_compat_bump || use_ntap_bump) { - shi->vn[0] = texres.nor[0]; - shi->vn[1] = texres.nor[1]; - shi->vn[2] = texres.nor[2]; - } - else { - float nor[3], dot; - - if (shi->mat->mode & MA_TANGENT_V) { - shi->tang[0]+= Tnor*norfac*texres.nor[0]; - shi->tang[1]+= Tnor*norfac*texres.nor[1]; - shi->tang[2]+= Tnor*norfac*texres.nor[2]; - } - - /* prevent bump to become negative normal */ - nor[0]= Tnor*norfac*texres.nor[0]; - nor[1]= Tnor*norfac*texres.nor[1]; - nor[2]= Tnor*norfac*texres.nor[2]; - - dot= 0.5f + 0.5f * dot_v3v3(nor, shi->vn); - - shi->vn[0]+= dot*nor[0]; - shi->vn[1]+= dot*nor[1]; - shi->vn[2]+= dot*nor[2]; - } - } - normalize_v3(shi->vn); - - /* this makes sure the bump is passed on to the next texture */ - shi->orn[0]= -shi->vn[0]; - shi->orn[1]= -shi->vn[1]; - shi->orn[2]= -shi->vn[2]; - } - } - - if ( mtex->mapto & MAP_DISPLACE ) { - /* Now that most textures offer both Nor and Intensity, allow */ - /* both to work, and let user select with slider. */ - if (texres.nor) { - float norfac= mtex->norfac; - - shi->displace[0]+= 0.2f*Tnor*norfac*texres.nor[0]; - shi->displace[1]+= 0.2f*Tnor*norfac*texres.nor[1]; - shi->displace[2]+= 0.2f*Tnor*norfac*texres.nor[2]; - } - - if (rgbnor & TEX_RGB) { - texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - } - - factt= (0.5f-texres.tin)*mtex->dispfac*stencilTin; facmm= 1.0f-factt; - - if (mtex->blendtype==MTEX_BLEND) { - shi->displace[0]= factt*shi->vn[0] + facmm*shi->displace[0]; - shi->displace[1]= factt*shi->vn[1] + facmm*shi->displace[1]; - shi->displace[2]= factt*shi->vn[2] + facmm*shi->displace[2]; - } - else if (mtex->blendtype==MTEX_MUL) { - shi->displace[0]*= factt*shi->vn[0]; - shi->displace[1]*= factt*shi->vn[1]; - shi->displace[2]*= factt*shi->vn[2]; - } - else { /* add or sub */ - if (mtex->blendtype==MTEX_SUB) factt= -factt; - shi->displace[0]+= factt*shi->vn[0]; - shi->displace[1]+= factt*shi->vn[1]; - shi->displace[2]+= factt*shi->vn[2]; - } - } - - if (mtex->mapto & MAP_VARS) { - /* stencil maps on the texture control slider, not texture intensity value */ - - if (rgbnor & TEX_RGB) { - if (texres.talpha) texres.tin = texres.ta; - else texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - } - - if (mtex->mapto & MAP_REF) { - float difffac= mtex->difffac*stencilTin; - - shi->refl= texture_value_blend(mtex->def_var, shi->refl, texres.tin, difffac, mtex->blendtype); - if (shi->refl<0.0f) shi->refl= 0.0f; - } - if (mtex->mapto & MAP_SPEC) { - float specfac= mtex->specfac*stencilTin; - - shi->spec= texture_value_blend(mtex->def_var, shi->spec, texres.tin, specfac, mtex->blendtype); - if (shi->spec<0.0f) shi->spec= 0.0f; - } - if (mtex->mapto & MAP_EMIT) { - float emitfac= mtex->emitfac*stencilTin; - - shi->emit= texture_value_blend(mtex->def_var, shi->emit, texres.tin, emitfac, mtex->blendtype); - if (shi->emit<0.0f) shi->emit= 0.0f; - } - if (mtex->mapto & MAP_ALPHA) { - float alphafac= mtex->alphafac*stencilTin; - - shi->alpha= texture_value_blend(mtex->def_var, shi->alpha, texres.tin, alphafac, mtex->blendtype); - if (shi->alpha<0.0f) shi->alpha= 0.0f; - else if (shi->alpha>1.0f) shi->alpha= 1.0f; - } - if (mtex->mapto & MAP_HAR) { - float har; /* have to map to 0-1 */ - float hardfac= mtex->hardfac*stencilTin; - - har= ((float)shi->har)/128.0f; - har= 128.0f*texture_value_blend(mtex->def_var, har, texres.tin, hardfac, mtex->blendtype); - - if (har<1.0f) shi->har= 1; - else if (har>511) shi->har= 511; - else shi->har= (int)har; - } - if (mtex->mapto & MAP_RAYMIRR) { - float raymirrfac= mtex->raymirrfac*stencilTin; - - shi->ray_mirror= texture_value_blend(mtex->def_var, shi->ray_mirror, texres.tin, raymirrfac, mtex->blendtype); - if (shi->ray_mirror<0.0f) shi->ray_mirror= 0.0f; - else if (shi->ray_mirror>1.0f) shi->ray_mirror= 1.0f; - } - if (mtex->mapto & MAP_TRANSLU) { - float translfac= mtex->translfac*stencilTin; - - shi->translucency= texture_value_blend(mtex->def_var, shi->translucency, texres.tin, translfac, mtex->blendtype); - if (shi->translucency<0.0f) shi->translucency= 0.0f; - else if (shi->translucency>1.0f) shi->translucency= 1.0f; - } - if (mtex->mapto & MAP_AMB) { - float ambfac= mtex->ambfac*stencilTin; - - shi->amb= texture_value_blend(mtex->def_var, shi->amb, texres.tin, ambfac, mtex->blendtype); - if (shi->amb<0.0f) shi->amb= 0.0f; - else if (shi->amb>1.0f) shi->amb= 1.0f; - - shi->ambr= shi->amb*re->wrld.ambr; - shi->ambg= shi->amb*re->wrld.ambg; - shi->ambb= shi->amb*re->wrld.ambb; - } - } - } - } - if ((use_compat_bump || use_ntap_bump || found_nmapping) && (shi->mat->mode & MA_TANGENT_V) != 0) { - const float fnegdot = -dot_v3v3(shi->vn, shi->tang); - /* apply Gram-Schmidt projection */ - madd_v3_v3fl(shi->tang, shi->vn, fnegdot); - normalize_v3(shi->tang); - } -} - - -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; - const bool texnode_preview = (re->r.scemode & R_TEXNODE_PREVIEW) != 0; - MTex *mtex; - Tex *tex; - TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; - int tex_nr, rgbnor= 0; - float co[3], texvec[3]; - float fact, stencilTin=1.0; - - if (re->r.scemode & R_NO_TEX) return; - /* here: test flag if there's a tex (todo) */ - - for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) { - /* separate tex switching */ - if (shi->mat->septex & (1<<tex_nr)) continue; - - if (shi->mat->mtex[tex_nr]) { - mtex= shi->mat->mtex[tex_nr]; - tex= mtex->tex; - if (tex == NULL) continue; - - /* only process if this texture is mapped - * to one that we're interested in */ - if (!(mtex->mapto & mapto_flag)) continue; - - /* which coords */ - if (mtex->texco==TEXCO_OBJECT) { - Object *ob= mtex->object; - if (ob) { - copy_v3_v3(co, xyz); - if (mtex->texflag & MTEX_OB_DUPLI_ORIG) { - if (shi->obi && shi->obi->duplitexmat) - mul_m4_v3(shi->obi->duplitexmat, co); - } - mul_m4_v3(ob->imat_ren, co); - - if (mtex->texflag & MTEX_MAPTO_BOUNDS && ob->bb) { - /* use bb vec[0] as min and bb vec[6] as max */ - co[0] = (co[0] - ob->bb->vec[0][0]) / (ob->bb->vec[6][0]-ob->bb->vec[0][0]) * 2.0f - 1.0f; - co[1] = (co[1] - ob->bb->vec[0][1]) / (ob->bb->vec[6][1]-ob->bb->vec[0][1]) * 2.0f - 1.0f; - co[2] = (co[2] - ob->bb->vec[0][2]) / (ob->bb->vec[6][2]-ob->bb->vec[0][2]) * 2.0f - 1.0f; - } - } - } - /* not really orco, but 'local' */ - else if (mtex->texco==TEXCO_ORCO) { - - if (mtex->texflag & MTEX_DUPLI_MAPTO) { - copy_v3_v3(co, shi->duplilo); - } - else { - Object *ob= shi->obi->ob; - copy_v3_v3(co, xyz); - mul_m4_v3(ob->imat_ren, co); - - if (mtex->texflag & MTEX_MAPTO_BOUNDS && ob->bb) { - /* use bb vec[0] as min and bb vec[6] as max */ - co[0] = (co[0] - ob->bb->vec[0][0]) / (ob->bb->vec[6][0]-ob->bb->vec[0][0]) * 2.0f - 1.0f; - co[1] = (co[1] - ob->bb->vec[0][1]) / (ob->bb->vec[6][1]-ob->bb->vec[0][1]) * 2.0f - 1.0f; - co[2] = (co[2] - ob->bb->vec[0][2]) / (ob->bb->vec[6][2]-ob->bb->vec[0][2]) * 2.0f - 1.0f; - } - } - } - else if (mtex->texco==TEXCO_GLOB) { - copy_v3_v3(co, xyz); - mul_m4_v3(re->viewinv, co); - } - else { - continue; /* can happen when texco defines disappear and it renders old files */ - } - - texres.nor= NULL; - - if (tex->type == TEX_IMAGE) { - continue; /* not supported yet */ - //do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); - } - else { - /* placement */ - if (mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]); - else texvec[0]= mtex->size[0]*(mtex->ofs[0]); - - if (mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]); - else texvec[1]= mtex->size[1]*(mtex->ofs[1]); - - if (mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]); - else texvec[2]= mtex->size[2]*(mtex->ofs[2]); - } - - rgbnor = multitex(tex, - texvec, - NULL, NULL, - 0, - &texres, - shi->thread, - mtex->which_output, - re->pool, - skip_load_image, - texnode_preview, - true); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */ - - /* texture output */ - - if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - rgbnor -= TEX_RGB; - } - if (mtex->texflag & MTEX_NEGATIVE) { - if (rgbnor & TEX_RGB) { - texres.tr= 1.0f-texres.tr; - texres.tg= 1.0f-texres.tg; - texres.tb= 1.0f-texres.tb; - } - texres.tin= 1.0f-texres.tin; - } - if (mtex->texflag & MTEX_STENCIL) { - if (rgbnor & TEX_RGB) { - fact= texres.ta; - texres.ta*= stencilTin; - stencilTin*= fact; - } - else { - fact= texres.tin; - texres.tin*= stencilTin; - stencilTin*= fact; - } - } - - - if ((mapto_flag & (MAP_EMISSION_COL+MAP_TRANSMISSION_COL+MAP_REFLECTION_COL)) && (mtex->mapto & (MAP_EMISSION_COL+MAP_TRANSMISSION_COL+MAP_REFLECTION_COL))) { - float tcol[3]; - - /* stencil maps on the texture control slider, not texture intensity value */ - - if ((rgbnor & TEX_RGB) == 0) { - copy_v3_v3(tcol, &mtex->r); - } - else if (mtex->mapto & MAP_DENSITY) { - copy_v3_v3(tcol, &texres.tr); - if (texres.talpha) { - texres.tin = stencilTin; - } - } - else { - copy_v3_v3(tcol, &texres.tr); - if (texres.talpha) { - texres.tin= texres.ta; - } - } - - /* used for emit */ - if ((mapto_flag & MAP_EMISSION_COL) && (mtex->mapto & MAP_EMISSION_COL)) { - float colemitfac= mtex->colemitfac*stencilTin; - texture_rgb_blend(col_r, tcol, col_r, texres.tin, colemitfac, mtex->blendtype); - } - - if ((mapto_flag & MAP_REFLECTION_COL) && (mtex->mapto & MAP_REFLECTION_COL)) { - float colreflfac= mtex->colreflfac*stencilTin; - texture_rgb_blend(col_r, tcol, col_r, texres.tin, colreflfac, mtex->blendtype); - } - - if ((mapto_flag & MAP_TRANSMISSION_COL) && (mtex->mapto & MAP_TRANSMISSION_COL)) { - float coltransfac= mtex->coltransfac*stencilTin; - texture_rgb_blend(col_r, tcol, col_r, texres.tin, coltransfac, mtex->blendtype); - } - } - - if ((mapto_flag & MAP_VARS) && (mtex->mapto & MAP_VARS)) { - /* stencil maps on the texture control slider, not texture intensity value */ - - /* convert RGB to intensity if intensity info isn't provided */ - if (rgbnor & TEX_RGB) { - if (texres.talpha) texres.tin = texres.ta; - else texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - } - - if ((mapto_flag & MAP_EMISSION) && (mtex->mapto & MAP_EMISSION)) { - float emitfac= mtex->emitfac*stencilTin; - - *val = texture_value_blend(mtex->def_var, *val, texres.tin, emitfac, mtex->blendtype); - if (*val<0.0f) *val= 0.0f; - } - if ((mapto_flag & MAP_DENSITY) && (mtex->mapto & MAP_DENSITY)) { - float densfac= mtex->densfac*stencilTin; - - *val = texture_value_blend(mtex->def_var, *val, texres.tin, densfac, mtex->blendtype); - CLAMP(*val, 0.0f, 1.0f); - } - if ((mapto_flag & MAP_SCATTERING) && (mtex->mapto & MAP_SCATTERING)) { - float scatterfac= mtex->scatterfac*stencilTin; - - *val = texture_value_blend(mtex->def_var, *val, texres.tin, scatterfac, mtex->blendtype); - CLAMP(*val, 0.0f, 1.0f); - } - if ((mapto_flag & MAP_REFLECTION) && (mtex->mapto & MAP_REFLECTION)) { - float reflfac= mtex->reflfac*stencilTin; - - *val = texture_value_blend(mtex->def_var, *val, texres.tin, reflfac, mtex->blendtype); - CLAMP(*val, 0.0f, 1.0f); - } - } - } - } -} - - -/* ------------------------------------------------------------------------- */ - -void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4]) -{ - const bool skip_load_image = har->skip_load_image; - const bool texnode_preview = har->texnode_preview; - 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; - int rgb, osatex; - - if (R.r.scemode & R_NO_TEX) return; - - mtex= har->mat->mtex[0]; - if (har->mat->septex & (1<<0)) return; - if (mtex->tex==NULL) return; - - /* no normal mapping */ - texres.nor= NULL; - - texvec[0]= xn/har->rad; - texvec[1]= yn/har->rad; - texvec[2]= 0.0; - - osatex= (har->mat->texco & TEXCO_OSA); - - /* placement */ - if (mtex->projx) texvec[0]= mtex->size[0]*(texvec[mtex->projx-1]+mtex->ofs[0]); - else texvec[0]= mtex->size[0]*(mtex->ofs[0]); - - if (mtex->projy) texvec[1]= mtex->size[1]*(texvec[mtex->projy-1]+mtex->ofs[1]); - else texvec[1]= mtex->size[1]*(mtex->ofs[1]); - - if (mtex->projz) texvec[2]= mtex->size[2]*(texvec[mtex->projz-1]+mtex->ofs[2]); - else texvec[2]= mtex->size[2]*(mtex->ofs[2]); - - if (osatex) { - - dx= 1.0f/har->rad; - - if (mtex->projx) { - dxt[0]= mtex->size[0]*dx; - dyt[0]= mtex->size[0]*dx; - } - else dxt[0]= dyt[0]= 0.0; - - if (mtex->projy) { - dxt[1]= mtex->size[1]*dx; - dyt[1]= mtex->size[1]*dx; - } - else dxt[1]= dyt[1]= 0.0; - - if (mtex->projz) { - dxt[2]= 0.0; - dyt[2]= 0.0; - } - else dxt[2]= dyt[2]= 0.0; - - } - - 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, - skip_load_image, - texnode_preview, - true); - - /* texture output */ - if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - rgb= 0; - } - if (mtex->texflag & MTEX_NEGATIVE) { - if (rgb) { - texres.tr= 1.0f-texres.tr; - texres.tg= 1.0f-texres.tg; - texres.tb= 1.0f-texres.tb; - } - else texres.tin= 1.0f-texres.tin; - } - - /* mapping */ - if (mtex->mapto & MAP_COL) { - - if (rgb==0) { - texres.tr= mtex->r; - texres.tg= mtex->g; - texres.tb= mtex->b; - } - else if (mtex->mapto & MAP_ALPHA) { - texres.tin= 1.0; - } - else texres.tin= texres.ta; - - /* inverse gamma correction */ - if (mtex->tex->type==TEX_IMAGE) { - Image *ima = mtex->tex->ima; - ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &mtex->tex->iuser, har->pool); - - /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) - IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace); - - BKE_image_pool_release_ibuf(ima, ibuf, har->pool); - } - - fact= texres.tin*mtex->colfac; - facm= 1.0f-fact; - - if (mtex->blendtype==MTEX_MUL) { - facm= 1.0f-mtex->colfac; - } - - if (mtex->blendtype==MTEX_SUB) fact= -fact; - - if (mtex->blendtype==MTEX_BLEND) { - col_r[0]= (fact*texres.tr + facm*har->r); - col_r[1]= (fact*texres.tg + facm*har->g); - col_r[2]= (fact*texres.tb + facm*har->b); - } - else if (mtex->blendtype==MTEX_MUL) { - col_r[0]= (facm+fact*texres.tr)*har->r; - col_r[1]= (facm+fact*texres.tg)*har->g; - col_r[2]= (facm+fact*texres.tb)*har->b; - } - else { - col_r[0]= (fact*texres.tr + har->r); - col_r[1]= (fact*texres.tg + har->g); - col_r[2]= (fact*texres.tb + har->b); - - CLAMP(col_r[0], 0.0f, 1.0f); - CLAMP(col_r[1], 0.0f, 1.0f); - CLAMP(col_r[2], 0.0f, 1.0f); - } - } - if (mtex->mapto & MAP_ALPHA) { - if (rgb) { - if (texres.talpha) { - texres.tin = texres.ta; - } - else { - texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - } - } - - col_r[3]*= texres.tin; - } -} - -/* ------------------------------------------------------------------------- */ - -/* hor and zen are RGB vectors, blend is 1 float, should all be initialized */ -void do_sky_tex( - const float rco[3], const float view[3], const 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; - const bool texnode_preview = (R.r.scemode & R_TEXNODE_PREVIEW) != 0; - MTex *mtex; - Tex *tex; - TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; - float fact, stencilTin=1.0; - float tempvec[3], texvec[3], dxt[3], dyt[3]; - int tex_nr, rgb= 0; - - if (R.r.scemode & R_NO_TEX) return; - /* todo: add flag to test if there's a tex */ - texres.nor= NULL; - - for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) { - if (R.wrld.mtex[tex_nr]) { - const float *co; - - mtex= R.wrld.mtex[tex_nr]; - - tex= mtex->tex; - if (tex == NULL) continue; - /* if (mtex->mapto==0) continue; */ - - /* which coords */ - co= lo; - - /* dxt dyt just from 1 value */ - if (dxyview) { - dxt[0]= dxt[1]= dxt[2]= dxyview[0]; - dyt[0]= dyt[1]= dyt[2]= dxyview[1]; - } - else { - dxt[0]= dxt[1]= dxt[2]= 0.0; - dyt[0]= dyt[1]= dyt[2]= 0.0; - } - - /* Grab the mapping settings for this texture */ - 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 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; - tempvec[1]= lo[1]*fact; - tempvec[2]= 0.0; - } - else { - /* this value has no angle, the vector is directly along the view. - * avoid divide by zero and use a dummy value. */ - tempvec[0]= 1.0f; - tempvec[1]= 0.0; - tempvec[2]= 0.0; - } - co= tempvec; - break; - - case TEXCO_H_SPHEREMAP: - case TEXCO_H_TUBEMAP: - if (skyflag & WO_ZENUP) { - if (mtex->texco==TEXCO_H_TUBEMAP) map_to_tube( tempvec, tempvec+1, lo[0], lo[2], lo[1]); - else map_to_sphere(tempvec, tempvec+1, lo[0], lo[2], lo[1]); - /* tube/spheremap maps for outside view, not inside */ - tempvec[0]= 1.0f-tempvec[0]; - /* only top half */ - tempvec[1]= 2.0f*tempvec[1]-1.0f; - tempvec[2]= 0.0; - /* and correction for do_2d_mapping */ - tempvec[0]= 2.0f*tempvec[0]-1.0f; - tempvec[1]= 2.0f*tempvec[1]-1.0f; - co= tempvec; - } - else { - /* potentially dangerous... check with multitex! */ - continue; - } - break; - case TEXCO_EQUIRECTMAP: - tempvec[0]= -atan2f(lo[2], lo[0]) / (float)M_PI; - tempvec[1]= atan2f(lo[1], hypot(lo[0], lo[2])) / (float)M_PI_2; - tempvec[2]= 0.0f; - co= tempvec; - break; - case TEXCO_OBJECT: - if (mtex->object) { - copy_v3_v3(tempvec, lo); - mul_m4_v3(mtex->object->imat_ren, tempvec); - co= tempvec; - } - break; - - case TEXCO_GLOB: - if (rco) { - copy_v3_v3(tempvec, rco); - mul_m4_v3(R.viewinv, tempvec); - co= tempvec; - } - else - co= lo; - -// copy_v3_v3(shi->dxgl, shi->dxco); -// mul_m3_v3(R.imat, shi->dxco); -// copy_v3_v3(shi->dygl, shi->dyco); -// mul_m3_v3(R.imat, shi->dyco); - break; - case TEXCO_VIEW: - co = view; - break; - } - - /* placement */ - if (mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]); - else texvec[0]= mtex->size[0]*(mtex->ofs[0]); - - if (mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]); - else texvec[1]= mtex->size[1]*(mtex->ofs[1]); - - if (mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]); - else texvec[2]= mtex->size[2]*(mtex->ofs[2]); - - /* texture */ - if (tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); - - rgb = multitex(mtex->tex, - texvec, - dxt, dyt, - R.osa, - &texres, - thread, - mtex->which_output, - R.pool, - skip_load_image, - texnode_preview, - true); - - /* texture output */ - if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - rgb= 0; - } - if (mtex->texflag & MTEX_NEGATIVE) { - if (rgb) { - texres.tr= 1.0f-texres.tr; - texres.tg= 1.0f-texres.tg; - texres.tb= 1.0f-texres.tb; - } - else texres.tin= 1.0f-texres.tin; - } - if (mtex->texflag & MTEX_STENCIL) { - if (rgb) { - fact= texres.ta; - texres.ta*= stencilTin; - stencilTin*= fact; - } - else { - fact= texres.tin; - texres.tin*= stencilTin; - stencilTin*= fact; - } - } - else { - if (rgb) texres.ta *= stencilTin; - else texres.tin*= stencilTin; - } - - /* color mapping */ - if (mtex->mapto & (WOMAP_HORIZ+WOMAP_ZENUP+WOMAP_ZENDOWN)) { - float tcol[3]; - - if (rgb==0) { - texres.tr= mtex->r; - texres.tg= mtex->g; - texres.tb= mtex->b; - } - else texres.tin= texres.ta; - - tcol[0]= texres.tr; tcol[1]= texres.tg; tcol[2]= texres.tb; - - /* inverse gamma correction */ - if (tex->type==TEX_IMAGE) { - Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, R.pool); - - /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) - IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace); - - BKE_image_pool_release_ibuf(ima, ibuf, R.pool); - } - - if (mtex->mapto & WOMAP_HORIZ) { - texture_rgb_blend(hor, tcol, hor, texres.tin, mtex->colfac, mtex->blendtype); - } - if (mtex->mapto & (WOMAP_ZENUP+WOMAP_ZENDOWN)) { - float zenfac = 0.0f; - - if (R.wrld.skytype & WO_SKYREAL) { - if ((skyflag & WO_ZENUP)) { - if (mtex->mapto & WOMAP_ZENUP) zenfac= mtex->zenupfac; - } - else if (mtex->mapto & WOMAP_ZENDOWN) zenfac= mtex->zendownfac; - } - else { - if (mtex->mapto & WOMAP_ZENUP) zenfac= mtex->zenupfac; - else if (mtex->mapto & WOMAP_ZENDOWN) zenfac= mtex->zendownfac; - } - - if (zenfac != 0.0f) - texture_rgb_blend(zen, tcol, zen, texres.tin, zenfac, mtex->blendtype); - } - } - if (mtex->mapto & WOMAP_BLEND) { - if (rgb) texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - - *blend= texture_value_blend(mtex->def_var, *blend, texres.tin, mtex->blendfac, mtex->blendtype); - } - } - } -} - -/* ------------------------------------------------------------------------- */ -/* col_r supposed to be initialized with la->r,g,b */ - -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; - const bool texnode_preview = (R.r.scemode & R_TEXNODE_PREVIEW) != 0; - Object *ob; - MTex *mtex; - Tex *tex; - TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; - float *co = NULL, *dx = NULL, *dy = NULL, fact, stencilTin=1.0; - float texvec[3], dxt[3], dyt[3], tempvec[3]; - int i, tex_nr, rgb= 0; - - if (R.r.scemode & R_NO_TEX) return; - tex_nr= 0; - - for (; tex_nr<MAX_MTEX; tex_nr++) { - - if (la->mtex[tex_nr]) { - mtex= la->mtex[tex_nr]; - - tex= mtex->tex; - if (tex==NULL) continue; - texres.nor= NULL; - - /* which coords */ - if (mtex->texco==TEXCO_OBJECT) { - ob= mtex->object; - if (ob) { - co= tempvec; - dx= dxt; - dy= dyt; - copy_v3_v3(tempvec, shi->co); - mul_m4_v3(ob->imat_ren, tempvec); - if (shi->osatex) { - copy_v3_v3(dxt, shi->dxco); - copy_v3_v3(dyt, shi->dyco); - mul_mat3_m4_v3(ob->imat_ren, dxt); - mul_mat3_m4_v3(ob->imat_ren, dyt); - } - } - else { - co= shi->co; - dx= shi->dxco; dy= shi->dyco; - } - } - else if (mtex->texco==TEXCO_GLOB) { - co= shi->gl; dx= shi->dxco; dy= shi->dyco; - copy_v3_v3(shi->gl, shi->co); - mul_m4_v3(R.viewinv, shi->gl); - } - else if (mtex->texco==TEXCO_VIEW) { - - copy_v3_v3(tempvec, lavec); - mul_m3_v3(la->imat, tempvec); - - if (la->type==LA_SPOT) { - tempvec[0]*= la->spottexfac; - tempvec[1]*= la->spottexfac; - /* project from 3d to 2d */ - tempvec[0] /= -tempvec[2]; - tempvec[1] /= -tempvec[2]; - } - co= tempvec; - - dx= dxt; dy= dyt; - if (shi->osatex) { - copy_v3_v3(dxt, shi->dxlv); - copy_v3_v3(dyt, shi->dylv); - /* need some matrix conversion here? la->imat is a [3][3] matrix!!! **/ - mul_m3_v3(la->imat, dxt); - mul_m3_v3(la->imat, dyt); - - mul_v3_fl(dxt, la->spottexfac); - mul_v3_fl(dyt, la->spottexfac); - } - } - - - /* placement */ - if (mtex->projx && co) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]); - else texvec[0]= mtex->size[0]*(mtex->ofs[0]); - - if (mtex->projy && co) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]); - else texvec[1]= mtex->size[1]*(mtex->ofs[1]); - - if (mtex->projz && co) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]); - else texvec[2]= mtex->size[2]*(mtex->ofs[2]); - - if (shi->osatex) { - if (!dx) { - for (i=0;i<2;i++) { - dxt[i] = dyt[i] = 0.0; - } - } - else { - if (mtex->projx) { - dxt[0]= mtex->size[0]*dx[mtex->projx-1]; - dyt[0]= mtex->size[0]*dy[mtex->projx-1]; - } - else { - dxt[0]= 0.0; - dyt[0]= 0.0; - } - if (mtex->projy) { - dxt[1]= mtex->size[1]*dx[mtex->projy-1]; - dyt[1]= mtex->size[1]*dy[mtex->projy-1]; - } - else { - dxt[1]= 0.0; - dyt[1]= 0.0; - } - if (mtex->projz) { - dxt[2]= mtex->size[2]*dx[mtex->projz-1]; - dyt[2]= mtex->size[2]*dy[mtex->projz-1]; - } - else { - dxt[2]= 0.0; - dyt[2]= 0.0; - } - } - } - - /* texture */ - if (tex->type==TEX_IMAGE) { - 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, - skip_load_image, - texnode_preview, - true); - - /* texture output */ - if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { - texres.tin = IMB_colormanagement_get_luminance(&texres.tr); - rgb= 0; - } - if (mtex->texflag & MTEX_NEGATIVE) { - if (rgb) { - texres.tr= 1.0f-texres.tr; - texres.tg= 1.0f-texres.tg; - texres.tb= 1.0f-texres.tb; - } - else texres.tin= 1.0f-texres.tin; - } - if (mtex->texflag & MTEX_STENCIL) { - if (rgb) { - fact= texres.ta; - texres.ta*= stencilTin; - stencilTin*= fact; - } - else { - fact= texres.tin; - texres.tin*= stencilTin; - stencilTin*= fact; - } - } - else { - if (rgb) texres.ta*= stencilTin; - else texres.tin*= stencilTin; - } - - /* mapping */ - if (((mtex->mapto & LAMAP_COL) && (effect & LA_TEXTURE))||((mtex->mapto & LAMAP_SHAD) && (effect & LA_SHAD_TEX))) { - float col[3]; - - if (rgb==0) { - texres.tr= mtex->r; - texres.tg= mtex->g; - texres.tb= mtex->b; - } - else if (mtex->mapto & MAP_ALPHA) { - texres.tin= stencilTin; - } - else texres.tin= texres.ta; - - /* inverse gamma correction */ - if (tex->type==TEX_IMAGE) { - Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, R.pool); - - /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) - IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace); - - BKE_image_pool_release_ibuf(ima, ibuf, R.pool); - } - - /* lamp colors were premultiplied with this */ - col[0]= texres.tr*la->energy; - col[1]= texres.tg*la->energy; - col[2]= texres.tb*la->energy; - - 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); - } - } - } -} - /* ------------------------------------------------------------------------- */ int externtex(const MTex *mtex, @@ -3626,7 +1476,7 @@ int externtex(const MTex *mtex, /* texture */ if (tex->type==TEX_IMAGE) { - do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); + do_2d_mapping(mtex, texvec, NULL, dxt, dyt); } rgb = multitex(tex, @@ -3658,327 +1508,3 @@ int externtex(const MTex *mtex, return (rgb != 0); } - -/* ------------------------------------------------------------------------- */ - -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; - Tex *tex; - float texvec[3], dx[2], dy[2]; - ShadeInputUV *suv= &shi->uv[shi->actuv]; - int a; - - if (R.r.scemode & R_NO_TEX) return; - - if (firsttime) { - BLI_thread_lock(LOCK_IMAGE); - if (firsttime) { - const int num_threads = BLI_system_thread_count(); - for (a = 0; a < num_threads; a++) { - memset(&imatex[a], 0, sizeof(Tex)); - BKE_texture_default(&imatex[a]); - imatex[a].type= TEX_IMAGE; - } - - firsttime= 0; - } - BLI_thread_unlock(LOCK_IMAGE); - } - - tex= &imatex[shi->thread]; - tex->iuser.ok= ima->ok; - tex->ima = ima; - - texvec[0]= 0.5f+0.5f*suv->uv[0]; - texvec[1]= 0.5f+0.5f*suv->uv[1]; - texvec[2] = 0.0f; /* initalize it because imagewrap looks at it. */ - if (shi->osatex) { - dx[0]= 0.5f*suv->dxuv[0]; - dx[1]= 0.5f*suv->dxuv[1]; - dy[0]= 0.5f*suv->dyuv[0]; - dy[1]= 0.5f*suv->dyuv[1]; - } - - texr.nor= NULL; - - 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; - shi->vcol[2]*= texr.tb; - shi->vcol[3]*= texr.ta; -} - -/* A modified part of shadeinput.c -> shade_input_set_uv() - * Used for sampling UV mapped texture color */ -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; - int axis1, axis2; - - /* find most stable axis to project */ - axis_dominant_v3(&axis1, &axis2, normal); - - /* compute u,v and derivatives */ - t00= v3[axis1]-v1[axis1]; t01= v3[axis2]-v1[axis2]; - t10= v3[axis1]-v2[axis1]; t11= v3[axis2]-v2[axis2]; - - detsh= 1.0f/(t00*t11-t10*t01); - t00*= detsh; t01*=detsh; - t10*=detsh; t11*=detsh; - - 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(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. */ -Material *RE_sample_material_init(Material *orig_mat, Scene *scene) -{ - Tex *tex = NULL; - Material *mat; - int tex_nr; - - if (!orig_mat) return NULL; - - /* copy material */ - mat = BKE_material_localize(orig_mat); - - /* update material anims */ - BKE_animsys_evaluate_animdata(scene, &mat->id, mat->adt, BKE_scene_frame_get(scene), ADT_RECALC_ANIM); - - /* strip material copy from unsupported flags */ - for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) { - - if (mat->mtex[tex_nr]) { - MTex *mtex = mat->mtex[tex_nr]; - - /* just in case make all non-used mtexes empty*/ - Tex *cur_tex = mtex->tex; - mtex->tex = NULL; - - if (mat->septex & (1<<tex_nr) || !cur_tex) continue; - - /* only keep compatible texflags */ - mtex->texflag = mtex->texflag & (MTEX_RGBTOINT | MTEX_STENCIL | MTEX_NEGATIVE | MTEX_ALPHAMIX); - - /* depending of material type, strip non-compatible mapping modes */ - if (mat->material_type == MA_TYPE_SURFACE) { - if (!ELEM(mtex->texco, TEXCO_ORCO, TEXCO_OBJECT, TEXCO_GLOB, TEXCO_UV)) { - /* ignore this texture */ - mtex->texco = 0; - continue; - } - /* strip all mapto flags except color and alpha */ - mtex->mapto = (mtex->mapto & MAP_COL) | (mtex->mapto & MAP_ALPHA); - } - else if (mat->material_type == MA_TYPE_VOLUME) { - if (!ELEM(mtex->texco, TEXCO_OBJECT, TEXCO_ORCO, TEXCO_GLOB)) { - /* ignore */ - mtex->texco = 0; - continue; - } - /* strip all mapto flags except color and alpha */ - mtex->mapto = mtex->mapto & (MAP_TRANSMISSION_COL | MAP_REFLECTION_COL | MAP_DENSITY); - } - - /* if mapped to an object, calculate inverse matrices */ - if (mtex->texco==TEXCO_OBJECT) { - Object *ob= mtex->object; - if (ob) { - invert_m4_m4(ob->imat, ob->obmat); - copy_m4_m4(ob->imat_ren, ob->imat); - } - } - - /* copy texture */ - 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); - - /* update texture cache if required */ - if (tex->type==TEX_VOXELDATA) { - cache_voxeldata(tex, (int)scene->r.cfra); - } - if (tex->type==TEX_POINTDENSITY) { - /* set dummy values for render and do cache */ - Render dummy_re = {NULL}; - dummy_re.scene = scene; - unit_m4(dummy_re.viewinv); - unit_m4(dummy_re.viewmat); - unit_m4(dummy_re.winmat); - dummy_re.winx = dummy_re.winy = 128; - cache_pointdensity(&dummy_re, tex->pd); - } - - /* update image sequences and movies */ - if (tex->ima && BKE_image_is_animated(tex->ima)) { - BKE_image_user_check_frame_calc(&tex->iuser, (int)scene->r.cfra, 0); - } - } - } - return mat; -} - -/* free all duplicate data allocated by RE_sample_material_init() */ -void RE_sample_material_free(Material *mat) -{ - int tex_nr; - - /* free textures */ - for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) { - if (mat->septex & (1<<tex_nr)) continue; - if (mat->mtex[tex_nr]) { - MTex *mtex= mat->mtex[tex_nr]; - - if (mtex->tex) { - /* don't update user counts as we are freeing a duplicate */ - BKE_texture_free(mtex->tex); - MEM_freeN(mtex->tex); - mtex->tex = NULL; - } - } - } - - /* don't update user counts as we are freeing a duplicate */ - BKE_material_free(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 - * 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 tri_index, DerivedMesh *orcoDm, Object *ob) -{ - int v1, v2, v3; - MVert *mvert; - MLoop *mloop; - const MLoopTri *mlooptri; - float normal[3]; - ShadeInput shi = {NULL}; - Render re = {NULL}; - - /* Get face data */ - mvert = orcoDm->getVertArray(orcoDm); - mloop = orcoDm->getLoopArray(orcoDm); - mlooptri = orcoDm->getLoopTriArray(orcoDm); - - 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 */ - shi.mat = mat; - - /* fill shadeinput data depending on material type */ - if (mat->material_type == MA_TYPE_SURFACE) { - /* global coordinates */ - copy_v3_v3(shi.gl, surface_co); - /* object space coordinates */ - copy_v3_v3(shi.co, surface_co); - mul_m4_v3(ob->imat, shi.co); - /* orco coordinates */ - { - float uv[2]; - float l; - /* Get generated UV */ - 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 */ - shi.lo[0]= l*mvert[v3].co[0]-uv[0]*mvert[v1].co[0]-uv[1]*mvert[v2].co[0]; - shi.lo[1]= l*mvert[v3].co[1]-uv[0]*mvert[v1].co[1]-uv[1]*mvert[v2].co[1]; - shi.lo[2]= l*mvert[v3].co[2]-uv[0]*mvert[v1].co[2]-uv[1]*mvert[v2].co[2]; - } - /* uv coordinates */ - { - 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; - - /* 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(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 = 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->loopData, CD_MLOOPUV) - layer_index; - shi.totuv = layers; - } - - /* apply initial values from material */ - shi.r = mat->r; - shi.g = mat->g; - shi.b = mat->b; - shi.alpha = mat->alpha; - - /* do texture */ - do_material_tex(&shi, &re); - - /* apply result */ - color[0] = shi.r; - color[1] = shi.g; - color[2] = shi.b; - *alpha = shi.alpha; - } - else if (mat->material_type == MA_TYPE_VOLUME) { - ObjectInstanceRen obi = {NULL}; - obi.ob = ob; - shi.obi = &obi; - unit_m4(re.viewinv); - copy_v3_v3(color, mat->vol.reflection_col); - *alpha = mat->vol.density; - - /* do texture */ - do_volume_tex(&shi, volume_co, (MAP_TRANSMISSION_COL | MAP_REFLECTION_COL | MAP_DENSITY), - color, alpha, &re); - } -} - -/* eof */ diff --git a/source/blender/render/intern/source/texture_ocean.c b/source/blender/render/intern/source/texture_ocean.c deleted file mode 100644 index a932123243d..00000000000 --- a/source/blender/render/intern/source/texture_ocean.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributors: Matt Ebb - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/texture_ocean.c - * \ingroup bke - */ - -#include <stddef.h> - -#include "BLI_math.h" -#include "BLI_utildefines.h" - -#include "DNA_modifier_types.h" -#include "DNA_object_types.h" -#include "DNA_texture_types.h" - -#include "BKE_global.h" /* XXX */ - -#include "BKE_modifier.h" -#include "BKE_ocean.h" - -#include "render_types.h" -#include "RE_shader_ext.h" - -#include "texture.h" - -#include "texture_ocean.h" /* own include */ - - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* 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; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - - -/* ***** actual texture sampling ***** */ -int ocean_texture(Tex *tex, const float texvec[2], TexResult *texres) -{ - OceanTex *ot = tex->ot; - ModifierData *md; - OceanModifierData *omd; - - texres->tin = 0.0f; - - if ( !(ot) || - !(ot->object) || - !(md = (ModifierData *)modifiers_findByType(ot->object, eModifierType_Ocean)) || - !(omd = (OceanModifierData *)md)->ocean) - { - return 0; - } - else { - const bool do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS) != 0; - int cfra = R.r.cfra; - int retval = TEX_INT; - - OceanResult ocr; - const float u = 0.5f + 0.5f * texvec[0]; - const float v = 0.5f + 0.5f * texvec[1]; - - if (omd->oceancache && omd->cached == true) { - - CLAMP(cfra, omd->bakestart, omd->bakeend); - cfra -= omd->bakestart; /* shift to 0 based */ - - BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v); - - } - else { /* non-cached */ - - if (G.is_rendering) - BKE_ocean_eval_uv_catrom(omd->ocean, &ocr, u, v); - else - BKE_ocean_eval_uv(omd->ocean, &ocr, u, v); - - ocr.foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage); - } - - switch (ot->output) { - case TEX_OCN_DISPLACEMENT: - /* XYZ displacement */ - texres->tr = 0.5f + 0.5f * ocr.disp[0]; - texres->tg = 0.5f + 0.5f * ocr.disp[2]; - texres->tb = 0.5f + 0.5f * ocr.disp[1]; - - texres->tr = MAX2(0.0f, texres->tr); - texres->tg = MAX2(0.0f, texres->tg); - texres->tb = MAX2(0.0f, texres->tb); - - BRICONTRGB; - - retval = TEX_RGB; - break; - - case TEX_OCN_EMINUS: - /* -ve eigenvectors ? */ - texres->tr = ocr.Eminus[0]; - texres->tg = ocr.Eminus[2]; - texres->tb = ocr.Eminus[1]; - retval = TEX_RGB; - break; - - case TEX_OCN_EPLUS: - /* -ve eigenvectors ? */ - texres->tr = ocr.Eplus[0]; - texres->tg = ocr.Eplus[2]; - texres->tb = ocr.Eplus[1]; - retval = TEX_RGB; - break; - - case TEX_OCN_JPLUS: - texres->tin = ocr.Jplus; - retval = TEX_INT; - break; - - case TEX_OCN_FOAM: - - texres->tin = ocr.foam; - - BRICONT; - - retval = TEX_INT; - break; - } - - /* if normals needed */ - - if (texres->nor && do_normals) { - normalize_v3_v3(texres->nor, ocr.normal); - retval |= TEX_NOR; - } - - texres->ta = 1.0f; - - return retval; - } -} diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 6c11dee5dde..436ee590f5c 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -34,40 +34,11 @@ /* Common includes */ /*---------------------------------------------------------------------------*/ -#include <math.h> -#include <float.h> -#include <stdlib.h> -#include <limits.h> #include <string.h> -#include "BLI_math.h" -#include "BLI_blenlib.h" -#include "BLI_jitter_2d.h" -#include "BLI_threads.h" -#include "BLI_utildefines.h" - #include "MEM_guardedalloc.h" -#include "DNA_lamp_types.h" -#include "DNA_node_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_material_types.h" - -#include "BKE_global.h" -#include "BKE_material.h" - - -#include "RE_render_ext.h" - -/* local includes */ -#include "pixelblending.h" -#include "render_result.h" -#include "render_types.h" -#include "renderdatabase.h" -#include "rendercore.h" -#include "shadbuf.h" -#include "shading.h" -#include "strand.h" +#include "BLI_math_base.h" /* own includes */ #include "zbuf.h" @@ -77,17 +48,10 @@ # pragma GCC diagnostic ignored "-Wdouble-promotion" #endif -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* 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; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - - /* ****************** Spans ******************************* */ /* each zbuffer has coordinates transformed to local rect coordinates, so we can simply clip */ -void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty, float clipcrop) +void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty) { memset(zspan, 0, sizeof(ZSpan)); @@ -96,8 +60,6 @@ void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty, float clipcrop) zspan->span1= MEM_mallocN(recty*sizeof(float), "zspan"); zspan->span2= MEM_mallocN(recty*sizeof(float), "zspan"); - - zspan->clipcrop= clipcrop; } void zbuf_free_span(ZSpan *zspan) @@ -200,1312 +162,6 @@ static void zbuf_add_to_span(ZSpan *zspan, const float v1[2], const float v2[2]) /* Functions */ /*-----------------------------------------------------------*/ -void fillrect(int *rect, int x, int y, int val) -{ - int len, *drect; - - len= x*y; - drect= rect; - while (len>0) { - len--; - *drect= val; - drect++; - } -} - -/* based on Liang&Barsky, for clipping of pyramidical volume */ -static short cliptestf(float a, float b, float c, float d, float *u1, float *u2) -{ - float p= a + b, q= c + d, r; - - if (p<0.0f) { - if (q<p) return 0; - else if (q<0.0f) { - r= q/p; - if (r>*u2) return 0; - else if (r>*u1) *u1=r; - } - } - else { - if (p>0.0f) { - if (q<0.0f) return 0; - else if (q<p) { - r= q/p; - if (r<*u1) return 0; - else if (r<*u2) *u2=r; - } - } - else if (q<0.0f) return 0; - } - return 1; -} - -int testclip(const float v[4]) -{ - float abs4; /* WATCH IT: this function should do the same as cliptestf, otherwise troubles in zbufclip()*/ - short c=0; - - /* if we set clip flags, the clipping should be at least larger than epsilon. - * prevents issues with vertices lying exact on borders */ - abs4= fabsf(v[3]) + FLT_EPSILON; - - if ( v[0] < -abs4) c+=1; - else if ( v[0] > abs4) c+=2; - - if ( v[1] > abs4) c+=4; - else if ( v[1] < -abs4) c+=8; - - if (v[2] < -abs4) c+=16; /* this used to be " if (v[2]<0) ", see clippz() */ - else if (v[2]> abs4) c+= 32; - - return c; -} - - - -/* ************* ACCUMULATION ZBUF ************ */ - - -static APixstr *addpsmainA(ListBase *lb) -{ - APixstrMain *psm; - - psm= MEM_mallocN(sizeof(APixstrMain), "addpsmainA"); - BLI_addtail(lb, psm); - psm->ps= MEM_callocN(4096*sizeof(APixstr), "pixstr"); - - return psm->ps; -} - -void freepsA(ListBase *lb) -{ - APixstrMain *psm, *psmnext; - - for (psm= lb->first; psm; psm= psmnext) { - psmnext= psm->next; - if (psm->ps) - MEM_freeN(psm->ps); - MEM_freeN(psm); - } -} - -static APixstr *addpsA(ZSpan *zspan) -{ - /* make new PS */ - if (zspan->apsmcounter==0) { - zspan->curpstr= addpsmainA(zspan->apsmbase); - zspan->apsmcounter= 4095; - } - else { - zspan->curpstr++; - zspan->apsmcounter--; - } - return zspan->curpstr; -} - -static void zbuffillAc4(ZSpan *zspan, int obi, int zvlnr, - const float *v1, const float *v2, const float *v3, const float *v4) -{ - APixstr *ap, *apofs, *apn; - double zxd, zyd, zy0, zverg; - float x0, y0, z0; - float x1, y1, z1, x2, y2, z2, xx1; - const float *span1, *span2; - int *rz, *rm, x, y; - int sn1, sn2, rectx, *rectzofs, *rectmaskofs, my0, my2, mask; - - /* init */ - zbuf_init_span(zspan); - - /* set spans */ - zbuf_add_to_span(zspan, v1, v2); - zbuf_add_to_span(zspan, v2, v3); - if (v4) { - zbuf_add_to_span(zspan, v3, v4); - zbuf_add_to_span(zspan, v4, v1); - } - else - zbuf_add_to_span(zspan, v3, v1); - - /* clipped */ - if (zspan->minp2==NULL || zspan->maxp2==NULL) return; - - my0 = max_ii(zspan->miny1, zspan->miny2); - my2 = min_ii(zspan->maxy1, zspan->maxy2); - - if (my2<my0) return; - - /* ZBUF DX DY, in floats still */ - x1= v1[0]- v2[0]; - x2= v2[0]- v3[0]; - y1= v1[1]- v2[1]; - y2= v2[1]- v3[1]; - z1= v1[2]- v2[2]; - z2= v2[2]- v3[2]; - x0= y1*z2-z1*y2; - y0= z1*x2-x1*z2; - z0= x1*y2-y1*x2; - - if (z0==0.0f) return; - - xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2]; - - zxd= -(double)x0/(double)z0; - zyd= -(double)y0/(double)z0; - zy0= ((double)my2)*zyd + (double)xx1; - - /* start-offset in rect */ - rectx= zspan->rectx; - rectzofs= (int *)(zspan->arectz+rectx*(my2)); - rectmaskofs= (int *)(zspan->rectmask+rectx*(my2)); - apofs= (zspan->apixbuf+ rectx*(my2)); - mask= zspan->mask; - - /* correct span */ - sn1= (my0 + my2)/2; - if (zspan->span1[sn1] < zspan->span2[sn1]) { - span1= zspan->span1+my2; - span2= zspan->span2+my2; - } - else { - span1= zspan->span2+my2; - span2= zspan->span1+my2; - } - - for (y=my2; y>=my0; y--, span1--, span2--) { - - sn1= floor(*span1); - sn2= floor(*span2); - sn1++; - - if (sn2>=rectx) sn2= rectx-1; - if (sn1<0) sn1= 0; - - if (sn2>=sn1) { - int intzverg; - - zverg= (double)sn1*zxd + zy0; - rz= rectzofs+sn1; - rm= rectmaskofs+sn1; - ap= apofs+sn1; - x= sn2-sn1; - - zverg-= zspan->polygon_offset; - - while (x>=0) { - intzverg = round_db_to_int_clamp(zverg); - - if ( intzverg < *rz) { - if (!zspan->rectmask || intzverg > *rm) { - - apn= ap; - while (apn) { - if (apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= intzverg; apn->mask[0]= mask; break; } - if (apn->p[0]==zvlnr && apn->obi[0]==obi) {apn->mask[0]|= mask; break; } - if (apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= intzverg; apn->mask[1]= mask; break; } - if (apn->p[1]==zvlnr && apn->obi[1]==obi) {apn->mask[1]|= mask; break; } - if (apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= intzverg; apn->mask[2]= mask; break; } - if (apn->p[2]==zvlnr && apn->obi[2]==obi) {apn->mask[2]|= mask; break; } - if (apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= intzverg; apn->mask[3]= mask; break; } - if (apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; } - if (apn->next==NULL) apn->next= addpsA(zspan); - apn= apn->next; - } - } - } - zverg+= zxd; - rz++; - rm++; - ap++; - x--; - } - } - - zy0-=zyd; - rectzofs-= rectx; - rectmaskofs-= rectx; - apofs-= rectx; - } -} - - - -static void zbuflineAc(ZSpan *zspan, int obi, int zvlnr, const float vec1[3], const float vec2[3]) -{ - APixstr *ap, *apn; - const int *rectz, *rectmask; - int start, end, x, y, oldx, oldy, ofs; - int dz, vergz, mask, maxtest=0; - float dx, dy; - float v1[3], v2[3]; - - dx= vec2[0]-vec1[0]; - dy= vec2[1]-vec1[1]; - - mask= zspan->mask; - - if (fabsf(dx) > fabsf(dy)) { - - /* all lines from left to right */ - if (vec1[0]<vec2[0]) { - copy_v3_v3(v1, vec1); - copy_v3_v3(v2, vec2); - } - else { - copy_v3_v3(v2, vec1); - copy_v3_v3(v1, vec2); - dx= -dx; dy= -dy; - } - - start= floor(v1[0]); - end= start+floor(dx); - if (end>=zspan->rectx) end= zspan->rectx-1; - - oldy= floor(v1[1]); - dy/= dx; - - vergz= v1[2]; - vergz-= zspan->polygon_offset; - dz= (v2[2]-v1[2])/dx; - if (vergz>0x50000000 && dz>0) maxtest= 1; /* prevent overflow */ - - rectz= (int *)(zspan->arectz+zspan->rectx*(oldy) +start); - rectmask= (int *)(zspan->rectmask+zspan->rectx*(oldy) +start); - ap= (zspan->apixbuf+ zspan->rectx*(oldy) +start); - - if (dy<0) ofs= -zspan->rectx; - else ofs= zspan->rectx; - - for (x= start; x<=end; x++, rectz++, rectmask++, ap++) { - - y= floor(v1[1]); - if (y!=oldy) { - oldy= y; - rectz+= ofs; - rectmask+= ofs; - ap+= ofs; - } - - if (x>=0 && y>=0 && y<zspan->recty) { - if (vergz<*rectz) { - if (!zspan->rectmask || vergz>*rectmask) { - - apn= ap; - while (apn) { /* loop unrolled */ - if (apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; } - if (apn->p[0]==zvlnr && apn->obi[0]==obi) {apn->mask[0]|= mask; break; } - if (apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; } - if (apn->p[1]==zvlnr && apn->obi[1]==obi) {apn->mask[1]|= mask; break; } - if (apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; } - if (apn->p[2]==zvlnr && apn->obi[2]==obi) {apn->mask[2]|= mask; break; } - if (apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; } - if (apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; } - if (apn->next == NULL) apn->next = addpsA(zspan); - apn= apn->next; - } - } - } - } - - v1[1]+= dy; - if (maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0; - else vergz+= dz; - } - } - else { - - /* all lines from top to bottom */ - if (vec1[1]<vec2[1]) { - copy_v3_v3(v1, vec1); - copy_v3_v3(v2, vec2); - } - else { - copy_v3_v3(v2, vec1); - copy_v3_v3(v1, vec2); - dx= -dx; dy= -dy; - } - - start= floor(v1[1]); - end= start+floor(dy); - - if (start>=zspan->recty || end<0) return; - - if (end>=zspan->recty) end= zspan->recty-1; - - oldx= floor(v1[0]); - dx/= dy; - - vergz= v1[2]; - vergz-= zspan->polygon_offset; - dz= (v2[2]-v1[2])/dy; - if (vergz>0x50000000 && dz>0) maxtest= 1; /* prevent overflow */ - - rectz= (int *)( zspan->arectz+ (start)*zspan->rectx+ oldx ); - rectmask= (int *)( zspan->rectmask+ (start)*zspan->rectx+ oldx ); - ap= (zspan->apixbuf+ zspan->rectx*(start) +oldx); - - if (dx<0) ofs= -1; - else ofs= 1; - - for (y= start; y<=end; y++, rectz+=zspan->rectx, rectmask+=zspan->rectx, ap+=zspan->rectx) { - - x= floor(v1[0]); - if (x!=oldx) { - oldx= x; - rectz+= ofs; - rectmask+= ofs; - ap+= ofs; - } - - if (x>=0 && y>=0 && x<zspan->rectx) { - if (vergz<*rectz) { - if (!zspan->rectmask || vergz>*rectmask) { - - apn= ap; - while (apn) { /* loop unrolled */ - if (apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; } - if (apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; } - if (apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; } - if (apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; } - if (apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; } - if (apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; } - if (apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; } - if (apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; } - if (apn->next == NULL) apn->next = addpsA(zspan); - apn= apn->next; - } - } - } - } - - v1[0]+= dx; - if (maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0; - else vergz+= dz; - } - } -} - -/* ************* NORMAL ZBUFFER ************ */ - -static void zbufline(ZSpan *zspan, int obi, int zvlnr, const float vec1[3], const float vec2[3]) -{ - int *rectz, *rectp, *recto, *rectmask; - int start, end, x, y, oldx, oldy, ofs; - int dz, vergz, maxtest= 0; - float dx, dy; - float v1[3], v2[3]; - - dx= vec2[0]-vec1[0]; - dy= vec2[1]-vec1[1]; - - if (fabsf(dx) > fabsf(dy)) { - - /* all lines from left to right */ - if (vec1[0]<vec2[0]) { - copy_v3_v3(v1, vec1); - copy_v3_v3(v2, vec2); - } - else { - copy_v3_v3(v2, vec1); - copy_v3_v3(v1, vec2); - dx= -dx; dy= -dy; - } - - start= floor(v1[0]); - end= start+floor(dx); - if (end>=zspan->rectx) end= zspan->rectx-1; - - oldy= floor(v1[1]); - dy/= dx; - - vergz= floor(v1[2]); - dz= floor((v2[2]-v1[2])/dx); - if (vergz>0x50000000 && dz>0) maxtest= 1; /* prevent overflow */ - - rectz= zspan->rectz + oldy*zspan->rectx+ start; - rectp= zspan->rectp + oldy*zspan->rectx+ start; - recto= zspan->recto + oldy*zspan->rectx+ start; - rectmask= zspan->rectmask + oldy*zspan->rectx+ start; - - if (dy<0) ofs= -zspan->rectx; - else ofs= zspan->rectx; - - for (x= start; x<=end; x++, rectz++, rectp++, recto++, rectmask++) { - - y= floor(v1[1]); - if (y!=oldy) { - oldy= y; - rectz+= ofs; - rectp+= ofs; - recto+= ofs; - rectmask+= ofs; - } - - if (x>=0 && y>=0 && y<zspan->recty) { - if (vergz<*rectz) { - if (!zspan->rectmask || vergz>*rectmask) { - *recto= obi; - *rectz= vergz; - *rectp= zvlnr; - } - } - } - - v1[1]+= dy; - - if (maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0; - else vergz+= dz; - } - } - else { - /* all lines from top to bottom */ - if (vec1[1]<vec2[1]) { - copy_v3_v3(v1, vec1); - copy_v3_v3(v2, vec2); - } - else { - copy_v3_v3(v2, vec1); - copy_v3_v3(v1, vec2); - dx= -dx; dy= -dy; - } - - start= floor(v1[1]); - end= start+floor(dy); - - if (end>=zspan->recty) end= zspan->recty-1; - - oldx= floor(v1[0]); - dx/= dy; - - vergz= floor(v1[2]); - dz= floor((v2[2]-v1[2])/dy); - if (vergz>0x50000000 && dz>0) maxtest= 1; /* prevent overflow */ - - rectz= zspan->rectz + start*zspan->rectx+ oldx; - rectp= zspan->rectp + start*zspan->rectx+ oldx; - recto= zspan->recto + start*zspan->rectx+ oldx; - rectmask= zspan->rectmask + start*zspan->rectx+ oldx; - - if (dx<0) ofs= -1; - else ofs= 1; - - for (y= start; y<=end; y++, rectz+=zspan->rectx, rectp+=zspan->rectx, recto+=zspan->rectx, rectmask+=zspan->rectx) { - - x= floor(v1[0]); - if (x!=oldx) { - oldx= x; - rectz+= ofs; - rectp+= ofs; - recto+= ofs; - rectmask+= ofs; - } - - if (x>=0 && y>=0 && x<zspan->rectx) { - if (vergz<*rectz) { - if (!zspan->rectmask || vergz>*rectmask) { - *rectz= vergz; - *rectp= zvlnr; - *recto= obi; - } - } - } - - v1[0]+= dx; - if (maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0; - else vergz+= dz; - } - } -} - -static void zbufline_onlyZ(ZSpan *zspan, int UNUSED(obi), int UNUSED(zvlnr), const float vec1[3], const float vec2[3]) -{ - int *rectz, *rectz1= NULL; - int start, end, x, y, oldx, oldy, ofs; - int dz, vergz, maxtest= 0; - float dx, dy; - float v1[3], v2[3]; - - dx= vec2[0]-vec1[0]; - dy= vec2[1]-vec1[1]; - - if (fabsf(dx) > fabsf(dy)) { - - /* all lines from left to right */ - if (vec1[0]<vec2[0]) { - copy_v3_v3(v1, vec1); - copy_v3_v3(v2, vec2); - } - else { - copy_v3_v3(v2, vec1); - copy_v3_v3(v1, vec2); - dx= -dx; dy= -dy; - } - - start= floor(v1[0]); - end= start+floor(dx); - if (end>=zspan->rectx) end= zspan->rectx-1; - - oldy= floor(v1[1]); - dy/= dx; - - vergz= floor(v1[2]); - dz= floor((v2[2]-v1[2])/dx); - if (vergz>0x50000000 && dz>0) maxtest= 1; /* prevent overflow */ - - rectz= zspan->rectz + oldy*zspan->rectx+ start; - if (zspan->rectz1) - rectz1= zspan->rectz1 + oldy*zspan->rectx+ start; - - if (dy<0) ofs= -zspan->rectx; - else ofs= zspan->rectx; - - for (x= start; x<=end; x++, rectz++) { - - y= floor(v1[1]); - if (y!=oldy) { - oldy= y; - rectz+= ofs; - if (rectz1) rectz1+= ofs; - } - - if (x>=0 && y>=0 && y<zspan->recty) { - if (vergz < *rectz) { - if (rectz1) *rectz1= *rectz; - *rectz= vergz; - } - else if (rectz1 && vergz < *rectz1) - *rectz1= vergz; - } - - v1[1]+= dy; - - if (maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0; - else vergz+= dz; - - if (rectz1) rectz1++; - } - } - else { - /* all lines from top to bottom */ - if (vec1[1]<vec2[1]) { - copy_v3_v3(v1, vec1); - copy_v3_v3(v2, vec2); - } - else { - copy_v3_v3(v2, vec1); - copy_v3_v3(v1, vec2); - dx= -dx; dy= -dy; - } - - start= floor(v1[1]); - end= start+floor(dy); - - if (end>=zspan->recty) end= zspan->recty-1; - - oldx= floor(v1[0]); - dx/= dy; - - vergz= floor(v1[2]); - dz= floor((v2[2]-v1[2])/dy); - if (vergz>0x50000000 && dz>0) maxtest= 1; /* prevent overflow */ - - rectz= zspan->rectz + start*zspan->rectx+ oldx; - if (zspan->rectz1) - rectz1= zspan->rectz1 + start*zspan->rectx+ oldx; - - if (dx<0) ofs= -1; - else ofs= 1; - - for (y= start; y<=end; y++, rectz+=zspan->rectx) { - - x= floor(v1[0]); - if (x!=oldx) { - oldx= x; - rectz+= ofs; - if (rectz1) rectz1+= ofs; - } - - if (x>=0 && y>=0 && x<zspan->rectx) { - if (vergz < *rectz) { - if (rectz1) *rectz1= *rectz; - *rectz= vergz; - } - else if (rectz1 && vergz < *rectz1) - *rectz1= vergz; - } - - v1[0]+= dx; - if (maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0; - else vergz+= dz; - - if (rectz1) - rectz1+=zspan->rectx; - } - } -} - - -static int clipline(float v1[4], float v2[4]) /* return 0: do not draw */ -{ - float dz, dw, u1=0.0, u2=1.0; - float dx, dy, v13; - - dz= v2[2]-v1[2]; - dw= v2[3]-v1[3]; - - /* this 1.01 is for clipping x and y just a tinsy larger. that way it is - * filled in with zbufwire correctly when rendering in parts. otherwise - * you see line endings at edges... */ - - if (cliptestf(-dz, -dw, v1[3], v1[2], &u1, &u2)) { - if (cliptestf(dz, -dw, v1[3], -v1[2], &u1, &u2)) { - - dx= v2[0]-v1[0]; - dz= 1.01f*(v2[3]-v1[3]); - v13= 1.01f*v1[3]; - - if (cliptestf(-dx, -dz, v1[0], v13, &u1, &u2)) { - if (cliptestf(dx, -dz, v13, -v1[0], &u1, &u2)) { - - dy= v2[1]-v1[1]; - - if (cliptestf(-dy, -dz, v1[1], v13, &u1, &u2)) { - if (cliptestf(dy, -dz, v13, -v1[1], &u1, &u2)) { - - if (u2<1.0f) { - v2[0]= v1[0]+u2*dx; - v2[1]= v1[1]+u2*dy; - v2[2]= v1[2]+u2*dz; - v2[3]= v1[3]+u2*dw; - } - if (u1>0.0f) { - v1[0]= v1[0]+u1*dx; - v1[1]= v1[1]+u1*dy; - v1[2]= v1[2]+u1*dz; - v1[3]= v1[3]+u1*dw; - } - return 1; - } - } - } - } - } - } - - return 0; -} - -void hoco_to_zco(ZSpan *zspan, float zco[3], const float hoco[4]) -{ - float div; - - div= 1.0f/hoco[3]; - zco[0]= zspan->zmulx*(1.0f+hoco[0]*div) + zspan->zofsx; - zco[1]= zspan->zmuly*(1.0f+hoco[1]*div) + zspan->zofsy; - zco[2]= 0x7FFFFFFF *(hoco[2]*div); -} - -void zbufclipwire(ZSpan *zspan, int obi, int zvlnr, int ec, - const float ho1[4], const float ho2[4], const float ho3[4], const float ho4[4], - const int c1, const int c2, const int c3, const int c4) -{ - float vez[20]; - int and, or; - - /* edgecode: 1= draw */ - if (ec==0) return; - - if (ho4) { - and= (c1 & c2 & c3 & c4); - or= (c1 | c2 | c3 | c4); - } - else { - and= (c1 & c2 & c3); - or= (c1 | c2 | c3); - } - - if (or) { /* not in the middle */ - if (and) { /* out completely */ - return; - } - else { /* clipping */ - - if (ec & ME_V1V2) { - copy_v4_v4(vez, ho1); - copy_v4_v4(vez+4, ho2); - if ( clipline(vez, vez+4)) { - hoco_to_zco(zspan, vez, vez); - hoco_to_zco(zspan, vez+4, vez+4); - zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); - } - } - if (ec & ME_V2V3) { - copy_v4_v4(vez, ho2); - copy_v4_v4(vez+4, ho3); - if ( clipline(vez, vez+4)) { - hoco_to_zco(zspan, vez, vez); - hoco_to_zco(zspan, vez+4, vez+4); - zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); - } - } - if (ho4) { - if (ec & ME_V3V4) { - copy_v4_v4(vez, ho3); - copy_v4_v4(vez+4, ho4); - if ( clipline(vez, vez+4)) { - hoco_to_zco(zspan, vez, vez); - hoco_to_zco(zspan, vez+4, vez+4); - zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); - } - } - if (ec & ME_V4V1) { - copy_v4_v4(vez, ho4); - copy_v4_v4(vez+4, ho1); - if ( clipline(vez, vez+4)) { - hoco_to_zco(zspan, vez, vez); - hoco_to_zco(zspan, vez+4, vez+4); - zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); - } - } - } - else { - if (ec & ME_V3V1) { - copy_v4_v4(vez, ho3); - copy_v4_v4(vez+4, ho1); - if ( clipline(vez, vez+4)) { - hoco_to_zco(zspan, vez, vez); - hoco_to_zco(zspan, vez+4, vez+4); - zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); - } - } - } - - return; - } - } - - hoco_to_zco(zspan, vez, ho1); - hoco_to_zco(zspan, vez+4, ho2); - hoco_to_zco(zspan, vez+8, ho3); - if (ho4) { - hoco_to_zco(zspan, vez+12, ho4); - - if (ec & ME_V3V4) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+8, vez+12); - if (ec & ME_V4V1) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+12, vez); - } - else { - if (ec & ME_V3V1) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+8, vez); - } - - if (ec & ME_V1V2) zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); - if (ec & ME_V2V3) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+4, vez+8); - -} - -void zbufsinglewire(ZSpan *zspan, int obi, int zvlnr, const float ho1[4], const float ho2[4]) -{ - float f1[4], f2[4]; - int c1, c2; - - c1= testclip(ho1); - c2= testclip(ho2); - - if (c1 | c2) { /* not in the middle */ - if (!(c1 & c2)) { /* not out completely */ - copy_v4_v4(f1, ho1); - copy_v4_v4(f2, ho2); - - if (clipline(f1, f2)) { - hoco_to_zco(zspan, f1, f1); - hoco_to_zco(zspan, f2, f2); - zspan->zbuflinefunc(zspan, obi, zvlnr, f1, f2); - } - } - } - else { - hoco_to_zco(zspan, f1, ho1); - hoco_to_zco(zspan, f2, ho2); - - zspan->zbuflinefunc(zspan, obi, zvlnr, f1, f2); - } -} - -/** - * Fill the z buffer, but invert z order, and add the face index to - * the corresponding face buffer. - * - * This is one of the z buffer fill functions called in zbufclip() and - * zbufwireclip(). - * - * \param v1 [4 floats, world coordinates] first vertex - * \param v2 [4 floats, world coordinates] second vertex - * \param v3 [4 floats, world coordinates] third vertex - */ - -/* WATCH IT: zbuffillGLinv4 and zbuffillGL4 are identical except for a 2 lines, - * commented below */ -static void zbuffillGLinv4(ZSpan *zspan, int obi, int zvlnr, - const float *v1, const float *v2, const float *v3, const float *v4) -{ - double zxd, zyd, zy0, zverg; - float x0, y0, z0; - float x1, y1, z1, x2, y2, z2, xx1; - const float *span1, *span2; - int *rectoofs, *ro; - int *rectpofs, *rp; - const int *rectmaskofs, *rm; - int *rz, x, y; - int sn1, sn2, rectx, *rectzofs, my0, my2; - - /* init */ - zbuf_init_span(zspan); - - /* set spans */ - zbuf_add_to_span(zspan, v1, v2); - zbuf_add_to_span(zspan, v2, v3); - if (v4) { - zbuf_add_to_span(zspan, v3, v4); - zbuf_add_to_span(zspan, v4, v1); - } - else - zbuf_add_to_span(zspan, v3, v1); - - /* clipped */ - if (zspan->minp2==NULL || zspan->maxp2==NULL) return; - - 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; - - - /* ZBUF DX DY, in floats still */ - x1= v1[0]- v2[0]; - x2= v2[0]- v3[0]; - y1= v1[1]- v2[1]; - y2= v2[1]- v3[1]; - z1= v1[2]- v2[2]; - z2= v2[2]- v3[2]; - x0= y1*z2-z1*y2; - y0= z1*x2-x1*z2; - z0= x1*y2-y1*x2; - - if (z0==0.0f) return; - - xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2]; - - zxd= -(double)x0/(double)z0; - zyd= -(double)y0/(double)z0; - zy0= ((double)my2)*zyd + (double)xx1; - - /* start-offset in rect */ - rectx= zspan->rectx; - rectzofs= (zspan->rectz+rectx*my2); - rectpofs= (zspan->rectp+rectx*my2); - rectoofs= (zspan->recto+rectx*my2); - rectmaskofs= (zspan->rectmask+rectx*my2); - - /* correct span */ - sn1= (my0 + my2)/2; - if (zspan->span1[sn1] < zspan->span2[sn1]) { - span1= zspan->span1+my2; - span2= zspan->span2+my2; - } - else { - span1= zspan->span2+my2; - span2= zspan->span1+my2; - } - - for (y=my2; y>=my0; y--, span1--, span2--) { - - sn1= floor(*span1); - sn2= floor(*span2); - sn1++; - - if (sn2>=rectx) sn2= rectx-1; - if (sn1<0) sn1= 0; - - if (sn2>=sn1) { - int intzverg; - - zverg= (double)sn1*zxd + zy0; - rz= rectzofs+sn1; - rp= rectpofs+sn1; - ro= rectoofs+sn1; - rm= rectmaskofs+sn1; - x= sn2-sn1; - - while (x>=0) { - intzverg = round_db_to_int_clamp(zverg); - - if ( intzverg > *rz || *rz==0x7FFFFFFF) { /* UNIQUE LINE: see comment above */ - if (!zspan->rectmask || intzverg > *rm) { - *ro= obi; /* UNIQUE LINE: see comment above (order differs) */ - *rz= intzverg; - *rp= zvlnr; - } - } - zverg+= zxd; - rz++; - rp++; - ro++; - rm++; - x--; - } - } - - zy0-=zyd; - rectzofs-= rectx; - rectpofs-= rectx; - rectoofs-= rectx; - rectmaskofs-= rectx; - } -} - -/* uses spanbuffers */ - -/* WATCH IT: zbuffillGLinv4 and zbuffillGL4 are identical except for a 2 lines, - * commented below */ -static void zbuffillGL4(ZSpan *zspan, int obi, int zvlnr, - const float *v1, const float *v2, const float *v3, const float *v4) -{ - double zxd, zyd, zy0, zverg; - float x0, y0, z0; - float x1, y1, z1, x2, y2, z2, xx1; - const float *span1, *span2; - int *rectoofs, *ro; - int *rectpofs, *rp; - const int *rectmaskofs, *rm; - int *rz, x, y; - int sn1, sn2, rectx, *rectzofs, my0, my2; - - /* init */ - zbuf_init_span(zspan); - - /* set spans */ - zbuf_add_to_span(zspan, v1, v2); - zbuf_add_to_span(zspan, v2, v3); - if (v4) { - zbuf_add_to_span(zspan, v3, v4); - zbuf_add_to_span(zspan, v4, v1); - } - else - zbuf_add_to_span(zspan, v3, v1); - - /* clipped */ - if (zspan->minp2==NULL || zspan->maxp2==NULL) return; - - 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; - - - /* ZBUF DX DY, in floats still */ - x1= v1[0]- v2[0]; - x2= v2[0]- v3[0]; - y1= v1[1]- v2[1]; - y2= v2[1]- v3[1]; - z1= v1[2]- v2[2]; - z2= v2[2]- v3[2]; - x0= y1*z2-z1*y2; - y0= z1*x2-x1*z2; - z0= x1*y2-y1*x2; - - if (z0==0.0f) return; - - xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2]; - - zxd= -(double)x0/(double)z0; - zyd= -(double)y0/(double)z0; - zy0= ((double)my2)*zyd + (double)xx1; - - /* start-offset in rect */ - rectx= zspan->rectx; - rectzofs= (zspan->rectz+rectx*my2); - rectpofs= (zspan->rectp+rectx*my2); - rectoofs= (zspan->recto+rectx*my2); - rectmaskofs= (zspan->rectmask+rectx*my2); - - /* correct span */ - sn1= (my0 + my2)/2; - if (zspan->span1[sn1] < zspan->span2[sn1]) { - span1= zspan->span1+my2; - span2= zspan->span2+my2; - } - else { - span1= zspan->span2+my2; - span2= zspan->span1+my2; - } - - for (y=my2; y>=my0; y--, span1--, span2--) { - - sn1= floor(*span1); - sn2= floor(*span2); - sn1++; - - if (sn2>=rectx) sn2= rectx-1; - if (sn1<0) sn1= 0; - - if (sn2>=sn1) { - int intzverg; - - zverg= (double)sn1*zxd + zy0; - rz= rectzofs+sn1; - rp= rectpofs+sn1; - ro= rectoofs+sn1; - rm= rectmaskofs+sn1; - x= sn2-sn1; - - while (x>=0) { - intzverg = round_db_to_int_clamp(zverg); - - if (intzverg < *rz) { /* ONLY UNIQUE LINE: see comment above */ - if (!zspan->rectmask || intzverg > *rm) { - *rz= intzverg; - *rp= zvlnr; - *ro= obi; /* UNIQUE LINE: see comment above (order differs) */ - } - } - zverg+= zxd; - rz++; - rp++; - ro++; - rm++; - x--; - } - } - - zy0-=zyd; - rectzofs-= rectx; - rectpofs-= rectx; - rectoofs-= rectx; - rectmaskofs-= rectx; - } -} - -/** - * Fill the z buffer. The face buffer is not operated on! - * - * This is one of the z buffer fill functions called in zbufclip() and - * zbufwireclip(). - * - * \param v1 [4 floats, world coordinates] first vertex - * \param v2 [4 floats, world coordinates] second vertex - * \param v3 [4 floats, world coordinates] third vertex - */ - -/* now: filling two Z values, the closest and 2nd closest */ -static void zbuffillGL_onlyZ(ZSpan *zspan, int UNUSED(obi), int UNUSED(zvlnr), - const float *v1, const float *v2, const float *v3, const float *v4) -{ - double zxd, zyd, zy0, zverg; - float x0, y0, z0; - float x1, y1, z1, x2, y2, z2, xx1; - const float *span1, *span2; - int *rz, *rz1, x, y; - int sn1, sn2, rectx, *rectzofs, *rectzofs1= NULL, my0, my2; - - /* init */ - zbuf_init_span(zspan); - - /* set spans */ - zbuf_add_to_span(zspan, v1, v2); - zbuf_add_to_span(zspan, v2, v3); - if (v4) { - zbuf_add_to_span(zspan, v3, v4); - zbuf_add_to_span(zspan, v4, v1); - } - else - zbuf_add_to_span(zspan, v3, v1); - - /* clipped */ - if (zspan->minp2==NULL || zspan->maxp2==NULL) return; - - 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; - - - /* ZBUF DX DY, in floats still */ - x1= v1[0]- v2[0]; - x2= v2[0]- v3[0]; - y1= v1[1]- v2[1]; - y2= v2[1]- v3[1]; - z1= v1[2]- v2[2]; - z2= v2[2]- v3[2]; - x0= y1*z2-z1*y2; - y0= z1*x2-x1*z2; - z0= x1*y2-y1*x2; - - if (z0==0.0f) return; - - xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2]; - - zxd= -(double)x0/(double)z0; - zyd= -(double)y0/(double)z0; - zy0= ((double)my2)*zyd + (double)xx1; - - /* start-offset in rect */ - rectx= zspan->rectx; - rectzofs= (zspan->rectz+rectx*my2); - if (zspan->rectz1) - rectzofs1= (zspan->rectz1+rectx*my2); - - /* correct span */ - sn1= (my0 + my2)/2; - if (zspan->span1[sn1] < zspan->span2[sn1]) { - span1= zspan->span1+my2; - span2= zspan->span2+my2; - } - else { - span1= zspan->span2+my2; - span2= zspan->span1+my2; - } - - for (y=my2; y>=my0; y--, span1--, span2--) { - - sn1= floor(*span1); - sn2= floor(*span2); - sn1++; - - if (sn2>=rectx) sn2= rectx-1; - if (sn1<0) sn1= 0; - - if (sn2>=sn1) { - zverg= (double)sn1*zxd + zy0; - rz= rectzofs+sn1; - rz1= rectzofs1+sn1; - x= sn2-sn1; - - while (x>=0) { - int zvergi = round_db_to_int_clamp(zverg); - - /* option: maintain two depth values, closest and 2nd closest */ - if (zvergi < *rz) { - if (rectzofs1) *rz1= *rz; - *rz= zvergi; - } - else if (rectzofs1 && zvergi < *rz1) - *rz1= zvergi; - - zverg+= zxd; - - rz++; - rz1++; - x--; - } - } - - zy0-=zyd; - rectzofs-= rectx; - if (rectzofs1) rectzofs1-= rectx; - } -} - -/* 2d scanconvert for tria, calls func for each x, y coordinate and gives UV barycentrics */ -void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) ) -{ - float x0, y0, x1, y1, x2, y2, z0, z1, z2, z; - float u, v, uxd, uyd, vxd, vyd, uy0, vy0, zxd, zyd, zy0, xx1; - const float *span1, *span2; - int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2; - - /* init */ - zbuf_init_span(zspan); - - /* set spans */ - zbuf_add_to_span(zspan, v1, v2); - zbuf_add_to_span(zspan, v2, v3); - zbuf_add_to_span(zspan, v3, v1); - - /* clipped */ - if (zspan->minp2==NULL || zspan->maxp2==NULL) return; - - 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; - - /* ZBUF DX DY, in floats still */ - x1= v1[0]- v2[0]; - x2= v2[0]- v3[0]; - y1= v1[1]- v2[1]; - y2= v2[1]- v3[1]; - z1= v1[2]- v2[2]; - z2= v2[2]- v3[2]; - - x0= y1*z2-z1*y2; - y0= z1*x2-x1*z2; - z0= x1*y2-y1*x2; - - if (z0==0.0f) return; - - xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2]; - zxd= -(double)x0/(double)z0; - zyd= -(double)y0/(double)z0; - zy0= ((double)my2)*zyd + (double)xx1; - - z1= 1.0f; /* (u1 - u2) */ - z2= 0.0f; /* (u2 - u3) */ - - x0= y1*z2-z1*y2; - y0= z1*x2-x1*z2; - - xx1= (x0*v1[0] + y0*v1[1])/z0 + 1.0f; - uxd= -(double)x0/(double)z0; - uyd= -(double)y0/(double)z0; - uy0= ((double)my2)*uyd + (double)xx1; - - z1= -1.0f; /* (v1 - v2) */ - z2= 1.0f; /* (v2 - v3) */ - - x0= y1*z2-z1*y2; - y0= z1*x2-x1*z2; - - xx1= (x0*v1[0] + y0*v1[1])/z0; - vxd= -(double)x0/(double)z0; - vyd= -(double)y0/(double)z0; - vy0= ((double)my2)*vyd + (double)xx1; - - /* correct span */ - sn1= (my0 + my2)/2; - if (zspan->span1[sn1] < zspan->span2[sn1]) { - span1= zspan->span1+my2; - span2= zspan->span2+my2; - } - else { - span1= zspan->span2+my2; - span2= zspan->span1+my2; - } - - for (y=my2; y>=my0; y--, span1--, span2--) { - - sn1= floor(*span1); - sn2= floor(*span2); - sn1++; - - if (sn2>=rectx) sn2= rectx-1; - if (sn1<0) sn1= 0; - - u= (double)sn1*uxd + uy0; - v= (double)sn1*vxd + vy0; - z= (double)sn1*zxd + zy0; - - for (x= sn1; x<=sn2; x++, u+=uxd, v+=vxd, z+=zxd) - func(handle, x, y, u, v, z); - - uy0 -= uyd; - vy0 -= vyd; - zy0 -= zyd; - } -} - /* scanconvert for strand triangles, calls func for each x, y coordinate and gives UV barycentrics and z */ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float) ) @@ -1585,2154 +241,4 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float * } } - - -/** - * (clip pyramid) - * Sets lambda: flag, and parametrize the clipping of vertices in - * viewspace coordinates. lambda = -1 means no clipping, lambda in [0, 1] means a clipping. - * Note: uses globals. - * \param v1 start coordinate s - * \param v2 target coordinate t - * \param b2 - * \param b3 - * \param a index for coordinate (x, y, or z) - */ - -static void clippyra(float *lambda, float *v1, float *v2, int *b2, int *b3, int a, float clipcrop) -{ - float da, dw, u1=0.0, u2=1.0; - float v13; - - lambda[0]= -1.0; - lambda[1]= -1.0; - - da= v2[a]-v1[a]; - /* prob; we clip slightly larger, osa renders add 2 pixels on edges, should become variable? */ - /* or better; increase r.winx/y size, but thats quite a complex one. do it later */ - if (a==2) { - dw= (v2[3]-v1[3]); - v13= v1[3]; - } - else { - dw= clipcrop*(v2[3]-v1[3]); - v13= clipcrop*v1[3]; - } - /* according the original article by Liang&Barsky, for clipping of - * homogeneous coordinates with viewplane, the value of "0" is used instead of "-w" . - * This differs from the other clipping cases (like left or top) and I considered - * it to be not so 'homogenic'. But later it has proven to be an error, - * who would have thought that of L&B! - */ - - if (cliptestf(-da, -dw, v13, v1[a], &u1, &u2)) { - if (cliptestf(da, -dw, v13, -v1[a], &u1, &u2)) { - *b3=1; - if (u2<1.0f) { - lambda[1]= u2; - *b2=1; - } - else lambda[1]=1.0; /* u2 */ - if (u1>0.0f) { - lambda[0] = u1; - *b2 = 1; - } - else { - lambda[0] = 0.0; - } - } - } -} - -/** - * (make vertex pyramide clip) - * Checks lambda and uses this to make decision about clipping the line - * segment from v1 to v2. lambda is the factor by which the vector is - * cut. ( calculate s + l * ( t - s )). The result is appended to the - * vertex list of this face. - * - * - * \param v1 start coordinate s - * \param v2 target coordinate t - * \param b1 - * \param b2 - * \param clve vertex vector. - */ - -static void makevertpyra(float *vez, float *lambda, float **trias, float *v1, float *v2, int *b1, int *clve) -{ - float l1, l2, *adr; - - l1= lambda[0]; - l2= lambda[1]; - - if (l1!= -1.0f) { - if (l1!= 0.0f) { - adr= vez+4*(*clve); - trias[*b1]=adr; - (*clve)++; - adr[0]= v1[0]+l1*(v2[0]-v1[0]); - adr[1]= v1[1]+l1*(v2[1]-v1[1]); - adr[2]= v1[2]+l1*(v2[2]-v1[2]); - adr[3]= v1[3]+l1*(v2[3]-v1[3]); - } - else trias[*b1]= v1; - - (*b1)++; - } - if (l2!= -1.0f) { - if (l2!= 1.0f) { - adr= vez+4*(*clve); - trias[*b1]=adr; - (*clve)++; - adr[0]= v1[0]+l2*(v2[0]-v1[0]); - adr[1]= v1[1]+l2*(v2[1]-v1[1]); - adr[2]= v1[2]+l2*(v2[2]-v1[2]); - adr[3]= v1[3]+l2*(v2[3]-v1[3]); - (*b1)++; - } - } -} - -/* ------------------------------------------------------------------------- */ - -void projectverto(const float v1[3], float winmat[4][4], float adr[4]) -{ - /* calcs homogenic coord of vertex v1 */ - float x, y, z; - - x = v1[0]; - y = v1[1]; - z = v1[2]; - adr[0] = x * winmat[0][0] + z * winmat[2][0] + winmat[3][0]; - adr[1] = y * winmat[1][1] + z * winmat[2][1] + winmat[3][1]; - adr[2] = z * winmat[2][2] + winmat[3][2]; - adr[3] = z * winmat[2][3] + winmat[3][3]; - - //printf("hoco %f %f %f %f\n", adr[0], adr[1], adr[2], adr[3]); -} - -/* ------------------------------------------------------------------------- */ - -void projectvert(const float v1[3], float winmat[4][4], float adr[4]) -{ - /* calcs homogenic coord of vertex v1 */ - float x, y, z; - - x = v1[0]; - y = v1[1]; - z = v1[2]; - adr[0] = x * winmat[0][0] + y * winmat[1][0] + z * winmat[2][0] + winmat[3][0]; - adr[1] = x * winmat[0][1] + y * winmat[1][1] + z * winmat[2][1] + winmat[3][1]; - adr[2] = x * winmat[0][2] + y * winmat[1][2] + z * winmat[2][2] + winmat[3][2]; - adr[3] = x * winmat[0][3] + y * winmat[1][3] + z * winmat[2][3] + winmat[3][3]; -} - -/* ------------------------------------------------------------------------- */ - -#define ZBUF_PROJECT_CACHE_SIZE 256 - -typedef struct ZbufProjectCache { - int index, clip; - float ho[4]; -} ZbufProjectCache; - -static void zbuf_project_cache_clear(ZbufProjectCache *cache, int size) -{ - int i; - - if (size > ZBUF_PROJECT_CACHE_SIZE) - size= ZBUF_PROJECT_CACHE_SIZE; - - memset(cache, 0, sizeof(ZbufProjectCache)*size); - for (i=0; i<size; i++) - cache[i].index= -1; -} - -static int zbuf_shadow_project(ZbufProjectCache *cache, int index, float winmat[4][4], float *co, float *ho) -{ - int cindex= index & 255; - - if (cache[cindex].index == index) { - copy_v4_v4(ho, cache[cindex].ho); - return cache[cindex].clip; - } - else { - int clipflag; - projectvert(co, winmat, ho); - clipflag= testclip(ho); - - copy_v4_v4(cache[cindex].ho, ho); - cache[cindex].clip= clipflag; - cache[cindex].index= index; - - return clipflag; - } -} - -static void zbuffer_part_bounds(int winx, int winy, RenderPart *pa, float *bounds) -{ - bounds[0]= (2*pa->disprect.xmin - winx-1)/(float)winx; - bounds[1]= (2*pa->disprect.xmax - winx+1)/(float)winx; - bounds[2]= (2*pa->disprect.ymin - winy-1)/(float)winy; - bounds[3]= (2*pa->disprect.ymax - winy+1)/(float)winy; -} - -static int zbuf_part_project(ZbufProjectCache *cache, int index, float winmat[4][4], float *bounds, float *co, float *ho) -{ - float vec[3]; - int cindex= index & 255; - - if (cache[cindex].index == index) { - copy_v4_v4(ho, cache[cindex].ho); - return cache[cindex].clip; - } - else { - float wco; - int clipflag= 0; - copy_v3_v3(vec, co); - projectvert(co, winmat, ho); - - wco= ho[3]; - if (ho[0] < bounds[0]*wco) clipflag |= 1; - else if (ho[0] > bounds[1]*wco) clipflag |= 2; - if (ho[1] > bounds[3]*wco) clipflag |= 4; - else if (ho[1] < bounds[2]*wco) clipflag |= 8; - - copy_v4_v4(cache[cindex].ho, ho); - cache[cindex].clip= clipflag; - cache[cindex].index= index; - - return clipflag; - } -} - -void zbuf_render_project(float winmat[4][4], const float co[3], float ho[4]) -{ - float vec[3]; - - copy_v3_v3(vec, co); - projectvert(vec, winmat, ho); -} - -void zbuf_make_winmat(Render *re, float winmat[4][4]) -{ - if (re->r.mode & R_PANORAMA) { - float panomat[4][4]; - - unit_m4(panomat); - - panomat[0][0]= re->panoco; - panomat[0][2]= re->panosi; - panomat[2][0]= -re->panosi; - panomat[2][2]= re->panoco; - - mul_m4_m4m4(winmat, re->winmat, panomat); - } - else - copy_m4_m4(winmat, re->winmat); -} - -/* do zbuffering and clip, f1 f2 f3 are hocos, c1 c2 c3 are clipping flags */ - -void zbufclip(ZSpan *zspan, int obi, int zvlnr, - const float f1[4], const float f2[4], const float f3[4], - const int c1, const int c2, const int c3) -{ - float *vlzp[32][3], lambda[3][2]; - float vez[400], *trias[40]; - - if (c1 | c2 | c3) { /* not in middle */ - if (c1 & c2 & c3) { /* completely out */ - return; - } - else { /* clipping */ - int arg, v, b, clipflag[3], b1, b2, b3, c4, clve=3, clvlo, clvl=1; - float *fp; - - vez[0]= f1[0]; vez[1]= f1[1]; vez[2]= f1[2]; vez[3]= f1[3]; - vez[4]= f2[0]; vez[5]= f2[1]; vez[6]= f2[2]; vez[7]= f2[3]; - vez[8]= f3[0]; vez[9]= f3[1]; vez[10]= f3[2];vez[11]= f3[3]; - - vlzp[0][0]= vez; - vlzp[0][1]= vez+4; - vlzp[0][2]= vez+8; - - clipflag[0]= ( (c1 & 48) | (c2 & 48) | (c3 & 48) ); - if (clipflag[0]==0) { /* othwerwise it needs to be calculated again, after the first (z) clip */ - clipflag[1]= ( (c1 & 3) | (c2 & 3) | (c3 & 3) ); - clipflag[2]= ( (c1 & 12) | (c2 & 12) | (c3 & 12) ); - } - else clipflag[1]=clipflag[2]= 0; - - for (b=0;b<3;b++) { - - if (clipflag[b]) { - - clvlo= clvl; - - for (v=0; v<clvlo; v++) { - - if (vlzp[v][0]!=NULL) { /* face is still there */ - b2= b3 =0; /* clip flags */ - - if (b==0) arg= 2; - else if (b==1) arg= 0; - else arg= 1; - - clippyra(lambda[0], vlzp[v][0], vlzp[v][1], &b2, &b3, arg, zspan->clipcrop); - clippyra(lambda[1], vlzp[v][1], vlzp[v][2], &b2, &b3, arg, zspan->clipcrop); - clippyra(lambda[2], vlzp[v][2], vlzp[v][0], &b2, &b3, arg, zspan->clipcrop); - - if (b2==0 && b3==1) { - /* completely 'in', but we copy because of last for () loop in this section */; - vlzp[clvl][0]= vlzp[v][0]; - vlzp[clvl][1]= vlzp[v][1]; - vlzp[clvl][2]= vlzp[v][2]; - vlzp[v][0]= NULL; - clvl++; - } - else if (b3==0) { - vlzp[v][0]= NULL; - /* completely 'out' */; - } - else { - b1=0; - makevertpyra(vez, lambda[0], trias, vlzp[v][0], vlzp[v][1], &b1, &clve); - makevertpyra(vez, lambda[1], trias, vlzp[v][1], vlzp[v][2], &b1, &clve); - makevertpyra(vez, lambda[2], trias, vlzp[v][2], vlzp[v][0], &b1, &clve); - - /* after front clip done: now set clip flags */ - if (b==0) { - clipflag[1]= clipflag[2]= 0; - f1= vez; - for (b3=0; b3<clve; b3++) { - c4= testclip(f1); - clipflag[1] |= (c4 & 3); - clipflag[2] |= (c4 & 12); - f1+= 4; - } - } - - vlzp[v][0]= NULL; - if (b1>2) { - for (b3=3; b3<=b1; b3++) { - vlzp[clvl][0]= trias[0]; - vlzp[clvl][1]= trias[b3-2]; - vlzp[clvl][2]= trias[b3-1]; - clvl++; - } - } - } - } - } - } - } - - /* warning, clip overflow, this should never happen! */ - BLI_assert(!(clve > 38 || clvl > 31)); - - /* perspective division */ - fp = vez; - for (b = 0; b < clve; b++) { - hoco_to_zco(zspan, fp, fp); - fp += 4; - } - for (b = 1; b < clvl; b++) { - if (vlzp[b][0]) { - zspan->zbuffunc(zspan, obi, zvlnr, vlzp[b][0], vlzp[b][1], vlzp[b][2], NULL); - } - } - return; - } - } - - /* perspective division: HCS to ZCS */ - hoco_to_zco(zspan, vez, f1); - hoco_to_zco(zspan, vez+4, f2); - hoco_to_zco(zspan, vez+8, f3); - zspan->zbuffunc(zspan, obi, zvlnr, vez, vez+4, vez+8, NULL); -} - -void zbufclip4(ZSpan *zspan, int obi, int zvlnr, - const float f1[4], const float f2[4], const float f3[4], const float f4[4], - const int c1, const int c2, const int c3, const int c4) -{ - float vez[16]; - - if (c1 | c2 | c3 | c4) { /* not in middle */ - if (c1 & c2 & c3 & c4) { /* completely out */ - return; - } - else { /* clipping */ - zbufclip(zspan, obi, zvlnr, f1, f2, f3, c1, c2, c3); - zbufclip(zspan, obi, zvlnr, f1, f3, f4, c1, c3, c4); - } - return; - } - - /* perspective division: HCS to ZCS */ - hoco_to_zco(zspan, vez, f1); - hoco_to_zco(zspan, vez+4, f2); - hoco_to_zco(zspan, vez+8, f3); - hoco_to_zco(zspan, vez+12, f4); - - zspan->zbuffunc(zspan, obi, zvlnr, vez, vez+4, vez+8, vez+12); -} - -/* ************** ZMASK ******************************** */ - -#define EXTEND_PIXEL(a) if (temprectp[a]) { z += rectz[a]; tot++; } (void)0 - -/* changes the zbuffer to be ready for z-masking: applies an extend-filter, and then clears */ -static void zmask_rect(int *rectz, int *rectp, int xs, int ys, int neg) -{ - int len=0, x, y; - int *temprectp; - int row1, row2, row3, *curp, *curz; - - temprectp= MEM_dupallocN(rectp); - - /* extend: if pixel is not filled in, we check surrounding pixels and average z value */ - - for (y=1; y<=ys; y++) { - /* setup row indices */ - row1= (y-2)*xs; - row2= row1 + xs; - row3= row2 + xs; - if (y==1) - row1= row2; - else if (y==ys) - row3= row2; - - curp= rectp + (y-1)*xs; - curz= rectz + (y-1)*xs; - - for (x=0; x<xs; x++, curp++, curz++) { - if (curp[0]==0) { - int tot= 0; - float z= 0.0f; - - EXTEND_PIXEL(row1); - EXTEND_PIXEL(row2); - EXTEND_PIXEL(row3); - EXTEND_PIXEL(row1 + 1); - EXTEND_PIXEL(row3 + 1); - if (x!=xs-1) { - EXTEND_PIXEL(row1 + 2); - EXTEND_PIXEL(row2 + 2); - EXTEND_PIXEL(row3 + 2); - } - if (tot) { - len++; - curz[0]= (int)(z/(float)tot); - curp[0]= -1; /* env */ - } - } - - if (x!=0) { - row1++; row2++; row3++; - } - } - } - - MEM_freeN(temprectp); - - if (neg) { - /* z values for negative are already correct */ - } - else { - /* clear not filled z values */ - for (len= xs*ys -1; len>=0; len--) { - if (rectp[len]==0) { - rectz[len] = -0x7FFFFFFF; - rectp[len]= -1; /* env code */ - } - } - } -} - - -/* ***************** ZBUFFER MAIN ROUTINES **************** */ - -void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart *, ZSpan *, int, void *), void *data) -{ - ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE]; - ZSpan zspans[16], *zspan; /* 16 = RE_MAX_OSA */ - VlakRen *vlr= NULL; - VertRen *v1, *v2, *v3, *v4; - Material *ma = NULL; - ObjectInstanceRen *obi; - ObjectRen *obr; - float obwinmat[4][4], winmat[4][4], bounds[4]; - float ho1[4], ho2[4], ho3[4], ho4[4]={0}; - 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; - 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); - - samples= (R.osa? R.osa: 1); - samples= MIN2(4, samples-pa->sample); - - for (zsample=0; zsample<samples; zsample++) { - zspan= &zspans[zsample]; - - zbuffer_part_bounds(R.winx, R.winy, pa, bounds); - zbuf_alloc_span(zspan, pa->rectx, pa->recty, R.clipcrop); - - /* needed for transform from hoco to zbuffer co */ - zspan->zmulx= ((float)R.winx)/2.0f; - zspan->zmuly= ((float)R.winy)/2.0f; - - if (R.osa) { - zspan->zofsx= -pa->disprect.xmin - R.jit[pa->sample+zsample][0]; - zspan->zofsy= -pa->disprect.ymin - R.jit[pa->sample+zsample][1]; - } - else if (R.i.curblur) { - zspan->zofsx= -pa->disprect.xmin - R.mblur_jit[R.i.curblur-1][0]; - zspan->zofsy= -pa->disprect.ymin - R.mblur_jit[R.i.curblur-1][1]; - } - else { - zspan->zofsx= -pa->disprect.xmin; - zspan->zofsy= -pa->disprect.ymin; - } - /* to center the sample position */ - zspan->zofsx -= 0.5f; - zspan->zofsy -= 0.5f; - - /* the buffers */ - if (zsample == samples-1) { - zspan->rectp= pa->rectp; - zspan->recto= pa->recto; - - if (neg_zmask) - zspan->rectz= pa->rectmask; - else - zspan->rectz= pa->rectz; - } - else { - zspan->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto"); - zspan->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); - zspan->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); - } - - fillrect(zspan->rectz, pa->rectx, pa->recty, 0x7FFFFFFF); - fillrect(zspan->rectp, pa->rectx, pa->recty, 0); - fillrect(zspan->recto, pa->rectx, pa->recty, 0); - } - - /* in case zmask we fill Z for objects in lay_zmask first, then clear Z, and then do normal zbuffering */ - if (rl->layflag & SCE_LAY_ZMASK) - zmaskpass= 1; - - for (; zmaskpass >=0; zmaskpass--) { - ma= NULL; - - /* filling methods */ - for (zsample=0; zsample<samples; zsample++) { - zspan= &zspans[zsample]; - - if (zmaskpass && neg_zmask) - zspan->zbuffunc= zbuffillGLinv4; - else - zspan->zbuffunc= zbuffillGL4; - zspan->zbuflinefunc= zbufline; - } - - /* regular zbuffering loop, does all sample buffers */ - for (i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) { - obr= obi->obr; - - /* continue happens in 2 different ways... zmaskpass only does lay_zmask stuff */ - if (zmaskpass) { - if ((obi->lay & lay_zmask)==0) - continue; - } - else if (!all_z && !(obi->lay & (lay|lay_zmask))) - continue; - - if (obi->flag & R_TRANSFORMED) - mul_m4_m4m4(obwinmat, winmat, obi->mat); - else - copy_m4_m4(obwinmat, winmat); - - if (clip_render_object(obi->obr->boundbox, bounds, obwinmat)) - continue; - - zbuf_project_cache_clear(cache, obr->totvert); - - for (v=0; v<obr->totvlak; v++) { - if ((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak; - else vlr++; - - /* the cases: visible for render, only z values, zmask, nothing */ - if (obi->lay & lay) { - if (vlr->mat!=ma) { - ma= vlr->mat; - nofill= (ma->mode & MA_ONLYCAST) || ((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP)); - env= (ma->mode & MA_ENV); - wire= (ma->material_type == MA_TYPE_WIRE); - - for (zsample=0; zsample<samples; zsample++) { - if (ma->mode & MA_ZINV || (zmaskpass && neg_zmask)) - zspans[zsample].zbuffunc= zbuffillGLinv4; - else - zspans[zsample].zbuffunc= zbuffillGL4; - } - } - } - else if (all_z || (obi->lay & lay_zmask)) { - env= 1; - nofill= 0; - ma= NULL; - } - else { - nofill= 1; - ma= NULL; /* otherwise nofill can hang */ - } - - if (!(vlr->flag & R_HIDDEN) && nofill==0) { - unsigned short partclip; - - v1= vlr->v1; - v2= vlr->v2; - v3= vlr->v3; - v4= vlr->v4; - - c1= zbuf_part_project(cache, v1->index, obwinmat, bounds, v1->co, ho1); - c2= zbuf_part_project(cache, v2->index, obwinmat, bounds, v2->co, ho2); - c3= zbuf_part_project(cache, v3->index, obwinmat, bounds, v3->co, ho3); - - /* partclipping doesn't need viewplane clipping */ - partclip= c1 & c2 & c3; - if (v4) { - c4= zbuf_part_project(cache, v4->index, obwinmat, bounds, v4->co, ho4); - partclip &= c4; - } - - if (partclip==0) { - - if (env) zvlnr= -1; - else zvlnr= v+1; - - c1= testclip(ho1); - c2= testclip(ho2); - c3= testclip(ho3); - if (v4) - c4= testclip(ho4); - - for (zsample=0; zsample<samples; zsample++) { - zspan= &zspans[zsample]; - - if (wire) { - if (v4) - zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4); - else - zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, NULL, c1, c2, c3, 0); - } - else { - /* strands allow to be filled in as quad */ - if (v4 && (vlr->flag & R_STRAND)) { - zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4); - } - else { - zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3); - if (v4) - zbufclip(zspan, i, (env)? zvlnr: zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4); - } - } - } - } - } - } - } - - /* clear all z to close value, so it works as mask for next passes (ztra+strand) */ - if (zmaskpass) { - for (zsample=0; zsample<samples; zsample++) { - zspan= &zspans[zsample]; - - if (neg_zmask) { - zspan->rectmask= zspan->rectz; - if (zsample == samples-1) - zspan->rectz= pa->rectz; - else - zspan->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); - fillrect(zspan->rectz, pa->rectx, pa->recty, 0x7FFFFFFF); - - zmask_rect(zspan->rectmask, zspan->rectp, pa->rectx, pa->recty, 1); - } - else - zmask_rect(zspan->rectz, zspan->rectp, pa->rectx, pa->recty, 0); - } - } - } - - for (zsample=0; zsample<samples; zsample++) { - zspan= &zspans[zsample]; - - if (fillfunc) - fillfunc(pa, zspan, pa->sample+zsample, data); - - if (zsample != samples-1) { - MEM_freeN(zspan->rectz); - MEM_freeN(zspan->rectp); - MEM_freeN(zspan->recto); - if (zspan->rectmask) - MEM_freeN(zspan->rectmask); - } - - zbuf_free_span(zspan); - } -} - -void zbuffer_shadow(Render *re, float winmat[4][4], LampRen *lar, int *rectz, int size, float jitx, float jity) -{ - ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE]; - ZSpan zspan; - ObjectInstanceRen *obi; - ObjectRen *obr; - VlakRen *vlr= NULL; - Material *ma= NULL; - StrandSegment sseg; - StrandRen *strand= NULL; - StrandVert *svert; - StrandBound *sbound; - float obwinmat[4][4], ho1[4], ho2[4], ho3[4], ho4[4]; - int a, b, c, i, c1, c2, c3, c4, ok=1, lay= -1; - - if (lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay; - - /* 1.0f for clipping in clippyra()... bad stuff actually */ - zbuf_alloc_span(&zspan, size, size, 1.0f); - zspan.zmulx= ((float)size)/2.0f; - zspan.zmuly= ((float)size)/2.0f; - /* -0.5f to center the sample position */ - zspan.zofsx= jitx - 0.5f; - zspan.zofsy= jity - 0.5f; - - /* the buffers */ - zspan.rectz= rectz; - fillrect(rectz, size, size, 0x7FFFFFFE); - if (lar->buftype==LA_SHADBUF_HALFWAY) { - zspan.rectz1= MEM_mallocN(size*size*sizeof(int), "seconday z buffer"); - fillrect(zspan.rectz1, size, size, 0x7FFFFFFE); - } - - /* filling methods */ - zspan.zbuflinefunc= zbufline_onlyZ; - zspan.zbuffunc= zbuffillGL_onlyZ; - - for (i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) { - obr= obi->obr; - - if (obr->ob==re->excludeob) - continue; - else if (!(obi->lay & lay)) - continue; - - if (obi->flag & R_TRANSFORMED) - mul_m4_m4m4(obwinmat, winmat, obi->mat); - else - copy_m4_m4(obwinmat, winmat); - - if (clip_render_object(obi->obr->boundbox, NULL, obwinmat)) - continue; - - zbuf_project_cache_clear(cache, obr->totvert); - - /* faces */ - for (a=0; a<obr->totvlak; a++) { - - if ((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; - else vlr++; - - /* note, these conditions are copied in shadowbuf_autoclip() */ - if (vlr->mat!= ma) { - ma= vlr->mat; - ok= 1; - if ((ma->mode2 & MA_CASTSHADOW)==0 || (ma->mode & MA_SHADBUF)==0) ok= 0; - } - - if (ok && (obi->lay & lay) && !(vlr->flag & R_HIDDEN)) { - c1= zbuf_shadow_project(cache, vlr->v1->index, obwinmat, vlr->v1->co, ho1); - c2= zbuf_shadow_project(cache, vlr->v2->index, obwinmat, vlr->v2->co, ho2); - c3= zbuf_shadow_project(cache, vlr->v3->index, obwinmat, vlr->v3->co, ho3); - - if ((ma->material_type == MA_TYPE_WIRE) || (vlr->flag & R_STRAND)) { - if (vlr->v4) { - c4= zbuf_shadow_project(cache, vlr->v4->index, obwinmat, vlr->v4->co, ho4); - zbufclipwire(&zspan, 0, a+1, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4); - } - else - zbufclipwire(&zspan, 0, a+1, vlr->ec, ho1, ho2, ho3, NULL, c1, c2, c3, 0); - } - else { - if (vlr->v4) { - c4= zbuf_shadow_project(cache, vlr->v4->index, obwinmat, vlr->v4->co, ho4); - zbufclip4(&zspan, 0, 0, ho1, ho2, ho3, ho4, c1, c2, c3, c4); - } - else - zbufclip(&zspan, 0, 0, ho1, ho2, ho3, c1, c2, c3); - } - } - - if ((a & 255)==255 && re->test_break(re->tbh)) - break; - } - - /* strands */ - if (obr->strandbuf) { - /* for each bounding box containing a number of strands */ - sbound= obr->strandbuf->bound; - for (c=0; c<obr->strandbuf->totbound; c++, sbound++) { - if (clip_render_object(sbound->boundbox, NULL, obwinmat)) - continue; - - /* for each strand in this bounding box */ - for (a=sbound->start; a<sbound->end; a++) { - strand= RE_findOrAddStrand(obr, a); - - sseg.obi= obi; - sseg.buffer= strand->buffer; - sseg.sqadaptcos= sseg.buffer->adaptcos; - sseg.sqadaptcos *= sseg.sqadaptcos; - sseg.strand= strand; - svert= strand->vert; - - /* note, these conditions are copied in shadowbuf_autoclip() */ - if (sseg.buffer->ma!= ma) { - ma= sseg.buffer->ma; - ok= 1; - if ((ma->mode2 & MA_CASTSHADOW)==0 || (ma->mode & MA_SHADBUF)==0) ok= 0; - } - - if (ok && (sseg.buffer->lay & lay)) { - zbuf_project_cache_clear(cache, strand->totvert); - - for (b=0; b<strand->totvert-1; b++, svert++) { - sseg.v[0]= (b > 0)? (svert-1): svert; - sseg.v[1]= svert; - sseg.v[2]= svert+1; - sseg.v[3]= (b < strand->totvert-2)? svert+2: svert+1; - - c1= zbuf_shadow_project(cache, sseg.v[0]-strand->vert, obwinmat, sseg.v[0]->co, ho1); - c2= zbuf_shadow_project(cache, sseg.v[1]-strand->vert, obwinmat, sseg.v[1]->co, ho2); - c3= zbuf_shadow_project(cache, sseg.v[2]-strand->vert, obwinmat, sseg.v[2]->co, ho3); - c4= zbuf_shadow_project(cache, sseg.v[3]-strand->vert, obwinmat, sseg.v[3]->co, ho4); - - if (!(c1 & c2 & c3 & c4)) - render_strand_segment(re, winmat, NULL, &zspan, 1, &sseg); - } - } - - if ((a & 255)==255 && re->test_break(re->tbh)) - break; - } - } - } - - if (re->test_break(re->tbh)) - break; - } - - /* merge buffers */ - if (lar->buftype==LA_SHADBUF_HALFWAY) { - for (a=size*size -1; a>=0; a--) - rectz[a]= (rectz[a]>>1) + (zspan.rectz1[a]>>1); - - MEM_freeN(zspan.rectz1); - } - - zbuf_free_span(&zspan); -} - -static void zbuffill_sss(ZSpan *zspan, int obi, int zvlnr, - const float *v1, const float *v2, const float *v3, const float *v4) -{ - double zxd, zyd, zy0, z; - float x0, y0, x1, y1, x2, y2, z0, z1, z2, xx1, *span1, *span2; - int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2; - /* init */ - zbuf_init_span(zspan); - - /* set spans */ - zbuf_add_to_span(zspan, v1, v2); - zbuf_add_to_span(zspan, v2, v3); - if (v4) { - zbuf_add_to_span(zspan, v3, v4); - zbuf_add_to_span(zspan, v4, v1); - } - else - zbuf_add_to_span(zspan, v3, v1); - - /* clipped */ - if (zspan->minp2==NULL || zspan->maxp2==NULL) return; - - my0 = max_ii(zspan->miny1, zspan->miny2); - my2 = min_ii(zspan->maxy1, zspan->maxy2); - - if (my2<my0) return; - - /* ZBUF DX DY, in floats still */ - x1= v1[0]- v2[0]; - x2= v2[0]- v3[0]; - y1= v1[1]- v2[1]; - y2= v2[1]- v3[1]; - z1= v1[2]- v2[2]; - z2= v2[2]- v3[2]; - - x0= y1*z2-z1*y2; - y0= z1*x2-x1*z2; - z0= x1*y2-y1*x2; - - if (z0==0.0f) return; - - xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2]; - zxd= -(double)x0/(double)z0; - zyd= -(double)y0/(double)z0; - zy0= ((double)my2)*zyd + (double)xx1; - - /* correct span */ - sn1= (my0 + my2)/2; - if (zspan->span1[sn1] < zspan->span2[sn1]) { - span1= zspan->span1+my2; - span2= zspan->span2+my2; - } - else { - span1= zspan->span2+my2; - span2= zspan->span1+my2; - } - - for (y=my2; y>=my0; y--, span1--, span2--) { - sn1= floor(*span1); - sn2= floor(*span2); - sn1++; - - if (sn2>=rectx) sn2= rectx-1; - if (sn1<0) sn1= 0; - - z= (double)sn1*zxd + zy0; - - for (x= sn1; x<=sn2; x++, z+=zxd) - zspan->sss_func(zspan->sss_handle, obi, zvlnr, x, y, z); - - zy0 -= zyd; - } -} - -void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void *, int, int, int, int, int)) -{ - ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE]; - ZSpan zspan; - ObjectInstanceRen *obi; - ObjectRen *obr; - VlakRen *vlr= NULL; - VertRen *v1, *v2, *v3, *v4; - Material *ma = NULL, *sss_ma = R.sss_mat; - float obwinmat[4][4], winmat[4][4], bounds[4]; - float ho1[4], ho2[4], ho3[4], ho4[4]={0}; - int i, v, zvlnr, c1, c2, c3, c4=0; - short nofill=0, env=0, wire=0; - - zbuf_make_winmat(&R, winmat); - zbuffer_part_bounds(R.winx, R.winy, pa, bounds); - zbuf_alloc_span(&zspan, pa->rectx, pa->recty, R.clipcrop); - - zspan.sss_handle= handle; - zspan.sss_func= func; - - /* needed for transform from hoco to zbuffer co */ - zspan.zmulx= ((float)R.winx)/2.0f; - zspan.zmuly= ((float)R.winy)/2.0f; - - /* -0.5f to center the sample position */ - zspan.zofsx= -pa->disprect.xmin - 0.5f; - zspan.zofsy= -pa->disprect.ymin - 0.5f; - - /* filling methods */ - zspan.zbuffunc= zbuffill_sss; - - /* fill front and back zbuffer */ - if (pa->rectz) { - fillrect(pa->recto, pa->rectx, pa->recty, 0); - fillrect(pa->rectp, pa->rectx, pa->recty, 0); - fillrect(pa->rectz, pa->rectx, pa->recty, 0x7FFFFFFF); - } - if (pa->rectbackz) { - fillrect(pa->rectbacko, pa->rectx, pa->recty, 0); - fillrect(pa->rectbackp, pa->rectx, pa->recty, 0); - fillrect(pa->rectbackz, pa->rectx, pa->recty, -0x7FFFFFFF); - } - - for (i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) { - obr= obi->obr; - - if (!(obi->lay & lay)) - continue; - - if (obi->flag & R_TRANSFORMED) - mul_m4_m4m4(obwinmat, winmat, obi->mat); - else - copy_m4_m4(obwinmat, winmat); - - if (clip_render_object(obi->obr->boundbox, bounds, obwinmat)) - continue; - - zbuf_project_cache_clear(cache, obr->totvert); - - for (v=0; v<obr->totvlak; v++) { - if ((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak; - else vlr++; - - if (material_in_material(vlr->mat, sss_ma)) { - /* three cases, visible for render, only z values and nothing */ - if (obi->lay & lay) { - if (vlr->mat!=ma) { - ma= vlr->mat; - nofill= ma->mode & MA_ONLYCAST; - env= (ma->mode & MA_ENV); - wire= (ma->material_type == MA_TYPE_WIRE); - } - } - else { - nofill= 1; - ma= NULL; /* otherwise nofill can hang */ - } - - if (nofill==0 && wire==0 && env==0) { - unsigned short partclip; - - v1= vlr->v1; - v2= vlr->v2; - v3= vlr->v3; - v4= vlr->v4; - - c1= zbuf_part_project(cache, v1->index, obwinmat, bounds, v1->co, ho1); - c2= zbuf_part_project(cache, v2->index, obwinmat, bounds, v2->co, ho2); - c3= zbuf_part_project(cache, v3->index, obwinmat, bounds, v3->co, ho3); - - /* partclipping doesn't need viewplane clipping */ - partclip= c1 & c2 & c3; - if (v4) { - c4= zbuf_part_project(cache, v4->index, obwinmat, bounds, v4->co, ho4); - partclip &= c4; - } - - if (partclip==0) { - c1= testclip(ho1); - c2= testclip(ho2); - c3= testclip(ho3); - - zvlnr= v+1; - zbufclip(&zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3); - if (v4) { - c4= testclip(ho4); - zbufclip(&zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4); - } - } - } - } - } - } - - zbuf_free_span(&zspan); -} - -/* ******************** ABUF ************************* */ - -/** - * Copy results from the solid face z buffering to the transparent - * buffer. - */ -static void copyto_abufz(RenderPart *pa, int *arectz, int *rectmask, int sample) -{ - PixStr *ps; - int x, y, *rza, *rma; - intptr_t *rd; - - if (R.osa==0) { - if (!pa->rectz) - fillrect(arectz, pa->rectx, pa->recty, 0x7FFFFFFE); - else - memcpy(arectz, pa->rectz, sizeof(int)*pa->rectx*pa->recty); - - if (rectmask && pa->rectmask) - memcpy(rectmask, pa->rectmask, sizeof(int)*pa->rectx*pa->recty); - - return; - } - else if (!pa->rectdaps) { - fillrect(arectz, pa->rectx, pa->recty, 0x7FFFFFFE); - return; - } - - rza= arectz; - rma= rectmask; - rd= pa->rectdaps; - - sample= (1<<sample); - - for (y=0; y<pa->recty; y++) { - for (x=0; x<pa->rectx; x++) { - - *rza= 0x7FFFFFFF; - if (rectmask) *rma= 0x7FFFFFFF; - if (*rd) { - /* when there's a sky pixstruct, fill in sky-Z, otherwise solid Z */ - for (ps= (PixStr *)(*rd); ps; ps= ps->next) { - if (sample & ps->mask) { - *rza= ps->z; - if (rectmask) *rma= ps->maskz; - break; - } - } - } - - rza++; - rma++; - rd++; - } - } -} - - -/* ------------------------------------------------------------------------ */ - -/** - * Do accumulation z buffering. - */ - -static int zbuffer_abuf(Render *re, RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, unsigned int lay, int negzmask, float winmat[4][4], int winx, int winy, int samples, float (*jit)[2], float UNUSED(clipcrop), int shadow) -{ - ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE]; - ZSpan zspans[16], *zspan; /* MAX_OSA */ - Material *ma=NULL; - ObjectInstanceRen *obi; - ObjectRen *obr; - VlakRen *vlr=NULL; - VertRen *v1, *v2, *v3, *v4; - float vec[3], hoco[4], mul, zval, fval; - float obwinmat[4][4], bounds[4], ho1[4], ho2[4], ho3[4], ho4[4]={0}; - int i, v, zvlnr, c1, c2, c3, c4=0, dofill= 0; - int zsample, polygon_offset; - - zbuffer_part_bounds(winx, winy, pa, bounds); - - for (zsample=0; zsample<samples; zsample++) { - zspan= &zspans[zsample]; - - zbuf_alloc_span(zspan, pa->rectx, pa->recty, re->clipcrop); - - /* needed for transform from hoco to zbuffer co */ - zspan->zmulx= ((float)winx)/2.0f; - zspan->zmuly= ((float)winy)/2.0f; - - /* the buffers */ - zspan->arectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "Arectz"); - zspan->apixbuf= APixbuf; - zspan->apsmbase= apsmbase; - - if (negzmask) - zspan->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "Arectmask"); - - /* filling methods */ - zspan->zbuffunc= zbuffillAc4; - zspan->zbuflinefunc= zbuflineAc; - - copyto_abufz(pa, zspan->arectz, zspan->rectmask, zsample); /* init zbuffer */ - zspan->mask= 1<<zsample; - - if (jit) { - zspan->zofsx= -pa->disprect.xmin - jit[zsample][0]; - zspan->zofsy= -pa->disprect.ymin - jit[zsample][1]; - } - else { - zspan->zofsx= -pa->disprect.xmin; - zspan->zofsy= -pa->disprect.ymin; - } - - /* to center the sample position */ - zspan->zofsx -= 0.5f; - zspan->zofsy -= 0.5f; - } - - /* we use this to test if nothing was filled in */ - zvlnr= 0; - - for (i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) { - obr= obi->obr; - - if (!(obi->lay & lay)) - continue; - - if (obi->flag & R_TRANSFORMED) - mul_m4_m4m4(obwinmat, winmat, obi->mat); - else - copy_m4_m4(obwinmat, winmat); - - if (clip_render_object(obi->obr->boundbox, bounds, obwinmat)) - continue; - - zbuf_project_cache_clear(cache, obr->totvert); - - for (v=0; v<obr->totvlak; v++) { - if ((v & 255)==0) - vlr= obr->vlaknodes[v>>8].vlak; - else vlr++; - - if (vlr->mat!=ma) { - ma= vlr->mat; - if (shadow) - dofill= (ma->mode2 & MA_CASTSHADOW) && (ma->mode & MA_SHADBUF); - else - dofill= (((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP)) && !(ma->mode & MA_ONLYCAST)); - } - - if (dofill) { - if (!(vlr->flag & R_HIDDEN) && (obi->lay & lay)) { - unsigned short partclip; - - v1= vlr->v1; - v2= vlr->v2; - v3= vlr->v3; - v4= vlr->v4; - - c1= zbuf_part_project(cache, v1->index, obwinmat, bounds, v1->co, ho1); - c2= zbuf_part_project(cache, v2->index, obwinmat, bounds, v2->co, ho2); - c3= zbuf_part_project(cache, v3->index, obwinmat, bounds, v3->co, ho3); - - /* partclipping doesn't need viewplane clipping */ - partclip= c1 & c2 & c3; - if (v4) { - c4= zbuf_part_project(cache, v4->index, obwinmat, bounds, v4->co, ho4); - partclip &= c4; - } - - if (partclip==0) { - /* a little advantage for transp rendering (a z offset) */ - if (!shadow && ma->zoffs != 0.0f) { - mul= 0x7FFFFFFF; - zval= mul*(1.0f+ho1[2]/ho1[3]); - - copy_v3_v3(vec, v1->co); - /* z is negative, otherwise its being clipped */ - vec[2]-= ma->zoffs; - projectverto(vec, obwinmat, hoco); - fval= mul*(1.0f+hoco[2]/hoco[3]); - - polygon_offset= (int)fabsf(zval - fval); - } - else polygon_offset= 0; - - zvlnr= v+1; - - c1= testclip(ho1); - c2= testclip(ho2); - c3= testclip(ho3); - if (v4) - c4= testclip(ho4); - - for (zsample=0; zsample<samples; zsample++) { - zspan= &zspans[zsample]; - zspan->polygon_offset= polygon_offset; - - if (ma->material_type == MA_TYPE_WIRE) { - if (v4) - zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4); - else - zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, NULL, c1, c2, c3, 0); - } - else { - if (v4 && (vlr->flag & R_STRAND)) { - zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4); - } - else { - zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3); - if (v4) - zbufclip(zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4); - } - } - } - } - if ((v & 255)==255) - if (re->test_break(re->tbh)) - break; - } - } - } - - if (re->test_break(re->tbh)) break; - } - - for (zsample=0; zsample<samples; zsample++) { - zspan= &zspans[zsample]; - MEM_freeN(zspan->arectz); - if (zspan->rectmask) - MEM_freeN(zspan->rectmask); - zbuf_free_span(zspan); - } - - return zvlnr; -} - -static int zbuffer_abuf_render(RenderPart *pa, APixstr *APixbuf, APixstrand *APixbufstrand, ListBase *apsmbase, RenderLayer *rl, StrandShadeCache *sscache) -{ - float winmat[4][4], (*jit)[2]; - int samples, negzmask, doztra= 0; - - samples= (R.osa)? R.osa: 1; - negzmask= ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK)); - - if (R.osa) - jit= R.jit; - else if (R.i.curblur) - jit= &R.mblur_jit[R.i.curblur-1]; - else - jit= NULL; - - zbuf_make_winmat(&R, winmat); - - if (rl->layflag & SCE_LAY_ZTRA) - doztra+= zbuffer_abuf(&R, pa, APixbuf, apsmbase, rl->lay, negzmask, winmat, R.winx, R.winy, samples, jit, R.clipcrop, 0); - if ((rl->layflag & SCE_LAY_STRAND) && APixbufstrand) - doztra+= zbuffer_strands_abuf(&R, pa, APixbufstrand, apsmbase, rl->lay, negzmask, winmat, R.winx, R.winy, samples, jit, R.clipcrop, 0, sscache); - - return doztra; -} - -void zbuffer_abuf_shadow(Render *re, LampRen *lar, float winmat[4][4], APixstr *APixbuf, APixstrand *APixbufstrand, ListBase *apsmbase, int size, int samples, float (*jit)[2]) -{ - RenderPart pa; - int lay= -1; - - if (lar->mode & LA_LAYER) lay= lar->lay; - - memset(&pa, 0, sizeof(RenderPart)); - pa.rectx= size; - pa.recty= size; - pa.disprect.xmin = 0; - pa.disprect.ymin = 0; - pa.disprect.xmax = size; - pa.disprect.ymax = size; - - zbuffer_abuf(re, &pa, APixbuf, apsmbase, lay, 0, winmat, size, size, samples, jit, 1.0f, 1); - if (APixbufstrand) - zbuffer_strands_abuf(re, &pa, APixbufstrand, apsmbase, lay, 0, winmat, size, size, samples, jit, 1.0f, 1, NULL); -} - -/* different rules for speed in transparent pass... */ -/* speed pointer NULL = sky, we clear */ -/* else if either alpha is full or no solid was filled in: copy speed */ -/* else fill in minimum speed */ -static void add_transp_speed(RenderLayer *rl, int offset, float speed[4], float alpha, intptr_t *rdrect) -{ - RenderPass *rpass; - - for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) { - float *fp= rpass->rect + 4*offset; - - if (speed==NULL) { - /* clear */ - if (fp[0]==PASS_VECTOR_MAX) fp[0]= 0.0f; - if (fp[1]==PASS_VECTOR_MAX) fp[1]= 0.0f; - if (fp[2]==PASS_VECTOR_MAX) fp[2]= 0.0f; - if (fp[3]==PASS_VECTOR_MAX) fp[3]= 0.0f; - } - else if (rdrect==NULL || rdrect[offset]==0 || alpha>0.95f) { - copy_v4_v4(fp, speed); - } - else { - /* add minimum speed in pixel */ - if ( (ABS(speed[0]) + ABS(speed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) { - fp[0]= speed[0]; - fp[1]= speed[1]; - } - if ( (ABS(speed[2]) + ABS(speed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) { - fp[2]= speed[2]; - fp[3]= speed[3]; - } - } - break; - } - } -} - -static void add_transp_obindex(RenderLayer *rl, int offset, Object *ob) -{ - RenderPass *rpass; - - for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - if (STREQ(rpass->name, RE_PASSNAME_INDEXOB)) { - float *fp= rpass->rect + offset; - *fp= (float)ob->index; - break; - } - } -} - -static void add_transp_material_index(RenderLayer *rl, int offset, Material *mat) -{ - RenderPass *rpass; - - for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - if (STREQ(rpass->name, RE_PASSNAME_INDEXMA)) { - float *fp= rpass->rect + offset; - *fp= (float)mat->index; - break; - } - } -} - -/* ONLY OSA! merge all shaderesult samples to one */ -/* target should have been cleared */ -static void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) -{ - RenderPass *rpass; - float weight= 1.0f/((float)R.osa); - int delta= sizeof(ShadeResult)/4; - - for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - float *col = NULL; - int pixsize = 3; - - if (STREQ(rpass->name, RE_PASSNAME_RGBA)) { - col = shr->col; - pixsize = 4; - } - else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) { - col = shr->emit; - } - else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) { - col = shr->diff; - } - else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) { - col = shr->spec; - } - else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) { - col = shr->shad; - } - else if (STREQ(rpass->name, RE_PASSNAME_AO)) { - col = shr->ao; - } - else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) { - col = shr->env; - } - else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) { - col = shr->indirect; - } - else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) { - col = shr->refl; - } - else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) { - col = shr->refr; - } - else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) { - col = shr->nor; - } - else if (STREQ(rpass->name, RE_PASSNAME_MIST)) { - col = &shr->mist; - pixsize = 1; - } - else if (STREQ(rpass->name, RE_PASSNAME_Z)) { - col = &shr->z; - pixsize = 1; - } - else if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) { - ShadeResult *shr_t = shr+1; - float *fp = shr->winspeed; /* was initialized */ - int samp; - - /* add minimum speed in pixel */ - for (samp = 1; samp<R.osa; samp++, shr_t++) { - - if (shr_t->combined[3] > 0.0f) { - const float *speed = shr_t->winspeed; - - if ( (ABS(speed[0]) + ABS(speed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) { - fp[0] = speed[0]; - fp[1] = speed[1]; - } - if ( (ABS(speed[2]) + ABS(speed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) { - fp[2] = speed[2]; - fp[3] = speed[3]; - } - } - } - } - - if (col) { - const float *fp= col+delta; - int samp; - - for (samp= 1; samp<R.osa; samp++, fp+=delta) { - col[0]+= fp[0]; - if (pixsize>1) { - col[1]+= fp[1]; - col[2]+= fp[2]; - if (pixsize==4) col[3]+= fp[3]; - } - } - col[0]*= weight; - if (pixsize>1) { - col[1]*= weight; - col[2]*= weight; - if (pixsize==4) col[3]*= weight; - } - } - } - -} - -static void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha) -{ - RenderPass *rpass; - - for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - float *fp, *col= NULL; - int pixsize= 3; - - if (STREQ(rpass->name, RE_PASSNAME_Z)) { - fp = rpass->rect + offset; - if (shr->z < *fp) - *fp = shr->z; - } - else if (STREQ(rpass->name, RE_PASSNAME_RGBA)) { - fp = rpass->rect + 4*offset; - addAlphaOverFloat(fp, shr->col); - } - else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) { - col = shr->emit; - } - else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) { - col = shr->diff; - } - else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) { - col = shr->spec; - } - else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) { - col = shr->shad; - } - else if (STREQ(rpass->name, RE_PASSNAME_AO)) { - col = shr->ao; - } - else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) { - col = shr->env; - } - else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) { - col = shr->indirect; - } - else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) { - col = shr->refl; - } - else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) { - col = shr->refr; - } - else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) { - col = shr->nor; - } - else if (STREQ(rpass->name, RE_PASSNAME_MIST)) { - col = &shr->mist; - pixsize = 1; - } - - if (col) { - fp= rpass->rect + pixsize*offset; - fp[0]= col[0] + (1.0f-alpha)*fp[0]; - if (pixsize==3) { - fp[1]= col[1] + (1.0f-alpha)*fp[1]; - fp[2]= col[2] + (1.0f-alpha)*fp[2]; - } - } - } -} - -typedef struct ZTranspRow { - int obi; - int z; - int p; - int mask; - int segment; - float u, v; -} ZTranspRow; - -static int vergzvlak(const void *a1, const void *a2) -{ - const ZTranspRow *r1 = a1, *r2 = a2; - - if (r1->z < r2->z) return 1; - else if (r1->z > r2->z) return -1; - return 0; -} - -static void shade_strand_samples(StrandShadeCache *cache, ShadeSample *ssamp, int UNUSED(x), int UNUSED(y), ZTranspRow *row, int addpassflag) -{ - StrandSegment sseg; - StrandVert *svert; - ObjectInstanceRen *obi; - ObjectRen *obr; - - obi= R.objectinstance + row->obi; - obr= obi->obr; - - sseg.obi= obi; - sseg.strand= RE_findOrAddStrand(obr, row->p-1); - sseg.buffer= sseg.strand->buffer; - - svert= sseg.strand->vert + row->segment; - sseg.v[0]= (row->segment > 0)? (svert-1): svert; - sseg.v[1]= svert; - sseg.v[2]= svert+1; - sseg.v[3]= (row->segment < sseg.strand->totvert-2)? svert+2: svert+1; - - ssamp->tot= 1; - strand_shade_segment(&R, cache, &sseg, ssamp, row->v, row->u, addpassflag); - ssamp->shi[0].mask= row->mask; -} - -static void unref_strand_samples(StrandShadeCache *cache, ZTranspRow *row, int totface) -{ - StrandVert *svert; - ObjectInstanceRen *obi; - ObjectRen *obr; - StrandRen *strand; - - /* remove references to samples that are not being rendered, but we still - * need to remove them so that the reference count of strand vertex shade - * samples correctly drops to zero */ - while (totface > 0) { - totface--; - - if (row[totface].segment != -1) { - obi= R.objectinstance + row[totface].obi; - obr= obi->obr; - strand= RE_findOrAddStrand(obr, row[totface].p-1); - svert= strand->vert + row[totface].segment; - - strand_shade_unref(cache, obi, svert); - strand_shade_unref(cache, obi, svert+1); - } - } -} - -static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int obi, int facenr, int curmask) -{ - ShadeInput *shi= ssamp->shi; - float xs, ys; - - ssamp->tot= 0; - - shade_input_set_triangle(shi, obi, facenr, 1); - - /* officially should always be true... we have no sky info */ - if (shi->vlr) { - - /* full osa is only set for OSA renders */ - if (shi->vlr->flag & R_FULL_OSA) { - short shi_inc= 0, samp; - - for (samp=0; samp<R.osa; samp++) { - if (curmask & (1<<samp)) { - xs= (float)x + R.jit[samp][0] + 0.5f; /* zbuffer has this inverse corrected, ensures (xs, ys) are inside pixel */ - ys= (float)y + R.jit[samp][1] + 0.5f; - - if (shi_inc) { - shade_input_copy_triangle(shi+1, shi); - shi++; - } - shi->mask= (1<<samp); - shi->samplenr= R.shadowsamplenr[shi->thread]++; - shade_input_set_viewco(shi, x, y, xs, ys, (float)z); - shade_input_set_uv(shi); - if (shi_inc==0) - shade_input_set_normals(shi); - else /* XXX shi->flippednor messes up otherwise */ - shade_input_set_vertex_normals(shi); - - shi_inc= 1; - } - } - } - else { - if (R.osa) { - short b= R.samples->centmask[curmask]; - xs= (float)x + R.samples->centLut[b & 15] + 0.5f; - ys= (float)y + R.samples->centLut[b>>4] + 0.5f; - } - else if (R.i.curblur) { - xs= (float)x + R.mblur_jit[R.i.curblur-1][0] + 0.5f; - ys= (float)y + R.mblur_jit[R.i.curblur-1][1] + 0.5f; - } - else { - xs= (float)x + 0.5f; - ys= (float)y + 0.5f; - } - shi->mask= curmask; - shi->samplenr= R.shadowsamplenr[shi->thread]++; - shade_input_set_viewco(shi, x, y, xs, ys, (float)z); - shade_input_set_uv(shi); - shade_input_set_normals(shi); - } - - /* total sample amount, shi->sample is static set in initialize */ - ssamp->tot= shi->sample+1; - } -} - -static int shade_tra_samples(ShadeSample *ssamp, StrandShadeCache *cache, int x, int y, ZTranspRow *row, int addpassflag) -{ - if (row->segment != -1) { - shade_strand_samples(cache, ssamp, x, y, row, addpassflag); - return 1; - } - - shade_tra_samples_fill(ssamp, x, y, row->z, row->obi, row->p, row->mask); - - if (ssamp->tot) { - ShadeInput *shi= ssamp->shi; - ShadeResult *shr= ssamp->shr; - int samp; - - /* if AO? */ - shade_samples_do_AO(ssamp); - - /* if shade (all shadepinputs have same passflag) */ - if (shi->passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB|SCE_PASS_INDEXMA)) { - for (samp=0; samp<ssamp->tot; samp++, shi++, shr++) { - shade_input_set_shade_texco(shi); - shade_input_do_shade(shi, shr); - - /* include lamphalos for ztra, since halo layer was added already */ - if (R.flag & R_LAMPHALO) - if (shi->layflag & SCE_LAY_HALO) - renderspothalo(shi, shr->combined, shr->combined[3]); - } - } - else if (shi->passflag & SCE_PASS_Z) { - for (samp=0; samp<ssamp->tot; samp++, shi++, shr++) - shr->z= -shi->co[2]; - } - - return 1; - } - return 0; -} - -static int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag) -{ - int a, sample, osa = (R.osa? R.osa: 1), retval = osa; - - for (a=0; a < osa; a++, samp_shr++) { - ShadeInput *shi= ssamp->shi; - ShadeResult *shr= ssamp->shr; - - for (sample=0; sample<ssamp->tot; sample++, shi++, shr++) { - - if (shi->mask & (1<<a)) { - float fac= (1.0f - samp_shr->combined[3])*shr->combined[3]; - - addAlphaUnderFloat(samp_shr->combined, shr->combined); - - samp_shr->z = min_ff(samp_shr->z, shr->z); - - if (addpassflag & SCE_PASS_VECTOR) { - copy_v4_v4(samp_shr->winspeed, shr->winspeed); - } - /* optim... */ - if (addpassflag & ~(SCE_PASS_VECTOR)) { - - if (addpassflag & SCE_PASS_RGBA) - addAlphaUnderFloat(samp_shr->col, shr->col); - - if (addpassflag & SCE_PASS_NORMAL) - madd_v3_v3fl(samp_shr->nor, shr->nor, fac); - - if (addpassflag & SCE_PASS_EMIT) - madd_v3_v3fl(samp_shr->emit, shr->emit, fac); - - if (addpassflag & SCE_PASS_DIFFUSE) - madd_v3_v3fl(samp_shr->diff, shr->diff, fac); - - if (addpassflag & SCE_PASS_SPEC) - madd_v3_v3fl(samp_shr->spec, shr->spec, fac); - - if (addpassflag & SCE_PASS_SHADOW) - madd_v3_v3fl(samp_shr->shad, shr->shad, fac); - - if (addpassflag & SCE_PASS_AO) - madd_v3_v3fl(samp_shr->ao, shr->ao, fac); - - if (addpassflag & SCE_PASS_ENVIRONMENT) - madd_v3_v3fl(samp_shr->env, shr->env, fac); - - if (addpassflag & SCE_PASS_INDIRECT) - madd_v3_v3fl(samp_shr->indirect, shr->indirect, fac); - - if (addpassflag & SCE_PASS_REFLECT) - madd_v3_v3fl(samp_shr->refl, shr->refl, fac); - - if (addpassflag & SCE_PASS_REFRACT) - madd_v3_v3fl(samp_shr->refr, shr->refr, fac); - - if (addpassflag & SCE_PASS_MIST) - samp_shr->mist= samp_shr->mist+fac*shr->mist; - - } - } - } - - if (samp_shr->combined[3]>0.999f) retval--; - } - return retval; -} - -static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf) -{ - /* speed vector exception... if solid render was done, sky pixels are set to zero already */ - /* for all pixels with alpha zero, we re-initialize speed again then */ - float *fp, *col; - int a; - - fp = RE_RenderLayerGetPass(rl, RE_PASSNAME_VECTOR, R.viewname); - if (fp==NULL) return; - col= rectf+3; - - for (a= 4*pa->rectx*pa->recty -4; a>=0; a-=4) { - if (col[a]==0.0f) { - fp[a]= PASS_VECTOR_MAX; - fp[a+1]= PASS_VECTOR_MAX; - fp[a+2]= PASS_VECTOR_MAX; - fp[a+3]= PASS_VECTOR_MAX; - } - } -} - -#define MAX_ZROW 2000 - -/* main render call to do the z-transparent layer */ -/* returns a mask, only if a) transp rendered and b) solid was rendered */ -unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass, ListBase *UNUSED(psmlist)) -{ - RenderResult *rr= pa->result; - ShadeSample ssamp; - APixstr *APixbuf; /* Zbuffer: linked list of face samples */ - APixstrand *APixbufstrand = NULL; - APixstr *ap, *aprect, *apn; - APixstrand *apstrand, *aprectstrand, *apnstrand; - ListBase apsmbase={NULL, NULL}; - ShadeResult samp_shr[16]; /* MAX_OSA */ - ZTranspRow zrow[MAX_ZROW]; - StrandShadeCache *sscache= NULL; - RenderLayer *rlpp[RE_MAX_OSA]; - float sampalpha, alpha, *passrect= pass; - intptr_t *rdrect; - int x, y, crop=0, a, b, totface, totfullsample, totsample, doztra; - int addpassflag, offs= 0, od, osa = (R.osa? R.osa: 1); - unsigned short *ztramask= NULL, filled; - - /* looks nicer for calling code */ - if (R.test_break(R.tbh)) - return NULL; - - if (R.osa > 16) { /* MAX_OSA */ - printf("zbuffer_transp_shade: osa too large\n"); - G.is_break = true; - return NULL; - } - - APixbuf= MEM_callocN(pa->rectx*pa->recty*sizeof(APixstr), "APixbuf"); - if (R.totstrand && (rl->layflag & SCE_LAY_STRAND)) { - APixbufstrand= MEM_callocN(pa->rectx*pa->recty*sizeof(APixstrand), "APixbufstrand"); - sscache= strand_shade_cache_create(); - } - - /* general shader info, passes */ - shade_sample_initialize(&ssamp, pa, rl); - addpassflag= rl->passflag & ~(SCE_PASS_COMBINED); - - if (R.osa) - sampalpha= 1.0f/(float)R.osa; - else - sampalpha= 1.0f; - - /* fill the Apixbuf */ - doztra= zbuffer_abuf_render(pa, APixbuf, APixbufstrand, &apsmbase, rl, sscache); - - if (doztra == 0) { - /* nothing filled in */ - MEM_freeN(APixbuf); - if (APixbufstrand) - MEM_freeN(APixbufstrand); - if (sscache) - strand_shade_cache_free(sscache); - freepsA(&apsmbase); - return NULL; - } - - aprect= APixbuf; - aprectstrand= APixbufstrand; - rdrect= pa->rectdaps; - - /* needed for correct zbuf/index pass */ - totfullsample= get_sample_layers(pa, rl, rlpp); - - /* irregular shadowb buffer creation */ - if (R.r.mode & R_SHADOW) - ISB_create(pa, APixbuf); - - /* masks, to have correct alpha combine */ - if (R.osa && (rl->layflag & SCE_LAY_SOLID) && pa->fullresult.first==NULL) - ztramask= MEM_callocN(pa->rectx*pa->recty*sizeof(short), "ztramask"); - - /* zero alpha pixels get speed vector max again */ - if (addpassflag & SCE_PASS_VECTOR) - if (rl->layflag & SCE_LAY_SOLID) { - float *rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_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; - offs= pa->rectx + 1; - passrect+= 4*offs; - aprect+= offs; - aprectstrand+= offs; - } - - /* init scanline updates */ - rr->renrect.ymin = 0; - rr->renrect.ymax = -pa->crop; - rr->renlay= rl; - - /* render the tile */ - for (y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) { - pass= passrect; - ap= aprect; - apstrand= aprectstrand; - od= offs; - - if (R.test_break(R.tbh)) - break; - - for (x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, ap++, apstrand++, pass+=4, od++) { - - if (ap->p[0]==0 && (!APixbufstrand || apstrand->p[0]==0)) { - if (addpassflag & SCE_PASS_VECTOR) - add_transp_speed(rl, od, NULL, 0.0f, rdrect); - } - else { - /* sort in z */ - totface= 0; - apn= ap; - while (apn) { - for (a=0; a<4; a++) { - if (apn->p[a]) { - zrow[totface].obi= apn->obi[a]; - zrow[totface].z= apn->z[a]; - zrow[totface].p= apn->p[a]; - zrow[totface].mask= apn->mask[a]; - zrow[totface].segment= -1; - totface++; - if (totface>=MAX_ZROW) totface= MAX_ZROW-1; - } - else break; - } - apn= apn->next; - } - - apnstrand= (APixbufstrand)? apstrand: NULL; - while (apnstrand) { - for (a=0; a<4; a++) { - if (apnstrand->p[a]) { - zrow[totface].obi= apnstrand->obi[a]; - zrow[totface].z= apnstrand->z[a]; - zrow[totface].p= apnstrand->p[a]; - zrow[totface].mask= apnstrand->mask[a]; - zrow[totface].segment= apnstrand->seg[a]; - - if (R.osa) { - totsample= 0; - for (b=0; b<R.osa; b++) - if (zrow[totface].mask & (1<<b)) - totsample++; - } - else - totsample= 1; - - zrow[totface].u= apnstrand->u[a]/totsample; - zrow[totface].v= apnstrand->v[a]/totsample; - totface++; - if (totface>=MAX_ZROW) totface= MAX_ZROW-1; - } - } - apnstrand= apnstrand->next; - } - - if (totface==2) { - if (zrow[0].z < zrow[1].z) { - SWAP(ZTranspRow, zrow[0], zrow[1]); - } - - } - else if (totface>2) { - qsort(zrow, totface, sizeof(ZTranspRow), vergzvlak); - } - - /* front face does index pass for transparent, no AA or filters, but yes FSA */ - if (addpassflag & SCE_PASS_INDEXOB) { - ObjectRen *obr= R.objectinstance[zrow[totface-1].obi].obr; - if (obr->ob) { - for (a= 0; a<totfullsample; a++) - add_transp_obindex(rlpp[a], od, obr->ob); - } - } - if (addpassflag & SCE_PASS_INDEXMA) { - ObjectRen *obr = R.objectinstance[zrow[totface-1].obi].obr; - int p = zrow[totface-1].p; - Material *mat = NULL; - - if (zrow[totface-1].segment == -1) { - int facenr = (p - 1) & RE_QUAD_MASK; - VlakRen *vlr = NULL; - - if (facenr >= 0 && facenr < obr->totvlak) - vlr = RE_findOrAddVlak(obr, facenr); - - if (vlr) - mat = vlr->mat; - } - else { - StrandRen *strand = RE_findOrAddStrand(obr, p - 1); - - if (strand) - mat = strand->buffer->ma; - } - - if (mat) { - for (a= 0; a<totfullsample; a++) - add_transp_material_index(rlpp[a], od, mat); - } - } - - /* for each mask-sample we alpha-under colors. then in end it's added using filter */ - memset(samp_shr, 0, sizeof(ShadeResult)*osa); - for (a=0; a<osa; a++) { - samp_shr[a].z= 10e10f; - if (addpassflag & SCE_PASS_VECTOR) { - samp_shr[a].winspeed[0]= PASS_VECTOR_MAX; - samp_shr[a].winspeed[1]= PASS_VECTOR_MAX; - samp_shr[a].winspeed[2]= PASS_VECTOR_MAX; - samp_shr[a].winspeed[3]= PASS_VECTOR_MAX; - } - } - - if (R.osa==0) { - while (totface>0) { - totface--; - - if (shade_tra_samples(&ssamp, sscache, x, y, &zrow[totface], addpassflag)) { - filled= addtosamp_shr(samp_shr, &ssamp, addpassflag); - addAlphaUnderFloat(pass, ssamp.shr[0].combined); - - if (filled == 0) { - if (sscache) - unref_strand_samples(sscache, zrow, totface); - break; - } - } - } - - alpha= samp_shr->combined[3]; - if (alpha!=0.0f) { - add_transp_passes(rl, od, samp_shr, alpha); - if (addpassflag & SCE_PASS_VECTOR) - add_transp_speed(rl, od, samp_shr->winspeed, alpha, rdrect); - } - } - else { - short *sp= (short *)(ztramask+od); - - while (totface>0) { - totface--; - - if (shade_tra_samples(&ssamp, sscache, x, y, &zrow[totface], addpassflag)) { - filled= addtosamp_shr(samp_shr, &ssamp, addpassflag); - - if (ztramask) - *sp |= zrow[totface].mask; - if (filled==0) { - if (sscache) - unref_strand_samples(sscache, zrow, totface); - break; - } - } - } - - /* multisample buffers or filtered mask filling? */ - if (pa->fullresult.first) { - for (a=0; a<R.osa; a++) { - alpha= samp_shr[a].combined[3]; - if (alpha != 0.0f) { - RenderLayer *rl_other = ssamp.rlpp[a]; - - float *rect = RE_RenderLayerGetPass(rl_other , RE_PASSNAME_COMBINED, R.viewname); - addAlphaOverFloat(rect + 4 * od, samp_shr[a].combined); - - add_transp_passes(rl_other , od, &samp_shr[a], alpha); - if (addpassflag & SCE_PASS_VECTOR) - add_transp_speed(rl_other , od, samp_shr[a].winspeed, alpha, rdrect); - } - } - } - else { - alpha= 0.0f; - - /* note; cannot use pass[3] for alpha due to filtermask */ - for (a=0; a<R.osa; a++) { - add_filt_fmask(1<<a, samp_shr[a].combined, pass, rr->rectx); - alpha+= samp_shr[a].combined[3]; - } - - if (addpassflag) { - alpha*= sampalpha; - - /* merge all in one, and then add */ - merge_transp_passes(rl, samp_shr); - add_transp_passes(rl, od, samp_shr, alpha); - - if (addpassflag & SCE_PASS_VECTOR) - add_transp_speed(rl, od, samp_shr[0].winspeed, alpha, rdrect); - } - } - } - } - } - - aprect+= pa->rectx; - aprectstrand+= pa->rectx; - passrect+= 4*pa->rectx; - offs+= pa->rectx; - } - - /* disable scanline updating */ - rr->renlay= NULL; - - MEM_freeN(APixbuf); - if (APixbufstrand) - MEM_freeN(APixbufstrand); - if (sscache) - strand_shade_cache_free(sscache); - freepsA(&apsmbase); - - if (R.r.mode & R_SHADOW) - ISB_free(pa); - - return ztramask; -} - - /* end of zbuf.c */ |