Render API/Cycles: Identify Render Passes by their name instead of a type flag

Previously, every RenderPass would have a bitfield that specified its type. That limits the number of passes to 32, which was reached a while ago.
However, most of the code already supported arbitrary RenderPasses since they were also used to store Multilayer EXR images.
Therefore, this commit completely removes the passflag from RenderPass and changes all code to use the unique pass name for identification.
Since Blender Internal relies on hardcoded passes and to preserve compatibility, 32 pass names are reserved for the old hardcoded passes.

To support these arbitrary passes, the Render Result compositor node now adds dynamic sockets. For compatibility, the old hardcoded sockets are always stored and just hidden when the corresponding pass isn't available.

To use these changes, the Render Engine API now includes a function that allows render engines to add arbitrary passes to the render result. To be able to add options for these passes, addons can now add their own properties to SceneRenderLayers.
To keep the compositor input node updated, render engine plugins have to implement a callback that registers all the passes that will be generated.

From a user perspective, nothing should change with this commit.

Differential Revision: https://developer.blender.org/D2443

Differential Revision: https://developer.blender.org/D2444
This commit is contained in:
Lukas Stockner 2017-05-03 00:21:18 +02:00
parent 6bf4115c13
commit 4cf7fc3b3a
Notes: blender-bot 2023-02-14 08:35:51 +01:00
Referenced by commit 24330f679e, Fix T56875: Auto Render not working after render pass name refactor
Referenced by commit 04800ed434, Fix T52113: Compositor doesnt mix unrendered render layers well
Referenced by issue #70802, Hidden sockets in Compositor don't stay hidden when we duplicate any node or render starts
Referenced by issue #56875, Compositor: Auto Render doesn't work
Referenced by issue #53321, "Z" changed to "depth" breaks consistency in compositing and in Render layers
Referenced by issue #51587, Blender fails to interpret a specific layer in OpenEXR multilayer file
Referenced by issue #51455, Render Layers in compositor from a different scene not working
50 changed files with 1433 additions and 1681 deletions

View File

@ -102,6 +102,9 @@ class CyclesRender(bpy.types.RenderEngine):
else:
self.report({'ERROR'}, "OSL support disabled in this build.")
def update_render_passes(self, scene, srl):
engine.register_passes(self, scene, srl)
def engine_exit():
engine.exit()

View File

@ -205,3 +205,36 @@ def with_network():
def system_info():
import _cycles
return _cycles.system_info()
def register_passes(engine, scene, srl):
engine.register_pass(scene, srl, "Combined", 4, "RGBA", 'COLOR')
if srl.use_pass_z: engine.register_pass(scene, srl, "Depth", 1, "Z", 'VALUE')
if srl.use_pass_mist: engine.register_pass(scene, srl, "Mist", 1, "Z", 'VALUE')
if srl.use_pass_normal: engine.register_pass(scene, srl, "Normal", 3, "XYZ", 'VECTOR')
if srl.use_pass_vector: engine.register_pass(scene, srl, "Vector", 4, "XYZW", 'VECTOR')
if srl.use_pass_uv: engine.register_pass(scene, srl, "UV", 3, "UVA", 'VECTOR')
if srl.use_pass_object_index: engine.register_pass(scene, srl, "IndexOB", 1, "X", 'VALUE')
if srl.use_pass_material_index: engine.register_pass(scene, srl, "IndexMA", 1, "X", 'VALUE')
if srl.use_pass_shadow: engine.register_pass(scene, srl, "Shadow", 3, "RGB", 'COLOR')
if srl.use_pass_ambient_occlusion: engine.register_pass(scene, srl, "AO", 3, "RGB", 'COLOR')
if srl.use_pass_diffuse_direct: engine.register_pass(scene, srl, "DiffDir", 3, "RGB", 'COLOR')
if srl.use_pass_diffuse_indirect: engine.register_pass(scene, srl, "DiffInd", 3, "RGB", 'COLOR')
if srl.use_pass_diffuse_color: engine.register_pass(scene, srl, "DiffCol", 3, "RGB", 'COLOR')
if srl.use_pass_glossy_direct: engine.register_pass(scene, srl, "GlossDir", 3, "RGB", 'COLOR')
if srl.use_pass_glossy_indirect: engine.register_pass(scene, srl, "GlossInd", 3, "RGB", 'COLOR')
if srl.use_pass_glossy_color: engine.register_pass(scene, srl, "GlossCol", 3, "RGB", 'COLOR')
if srl.use_pass_transmission_direct: engine.register_pass(scene, srl, "TransDir", 3, "RGB", 'COLOR')
if srl.use_pass_transmission_indirect: engine.register_pass(scene, srl, "TransInd", 3, "RGB", 'COLOR')
if srl.use_pass_transmission_color: engine.register_pass(scene, srl, "TransCol", 3, "RGB", 'COLOR')
if srl.use_pass_subsurface_direct: engine.register_pass(scene, srl, "SubsurfaceDir", 3, "RGB", 'COLOR')
if srl.use_pass_subsurface_indirect: engine.register_pass(scene, srl, "SubsurfaceInd", 3, "RGB", 'COLOR')
if srl.use_pass_subsurface_color: engine.register_pass(scene, srl, "SubsurfaceCol", 3, "RGB", 'COLOR')
if srl.use_pass_emit: engine.register_pass(scene, srl, "Emit", 3, "RGB", 'COLOR')
if srl.use_pass_environment: engine.register_pass(scene, srl, "Env", 3, "RGB", 'COLOR')
crl = srl.cycles
if crl.pass_debug_bvh_traversed_nodes: engine.register_pass(scene, srl, "Debug BVH Traversed Nodes", 1, "X", 'VALUE')
if crl.pass_debug_bvh_traversed_instances: engine.register_pass(scene, srl, "Debug BVH Traversed Instances", 1, "X", 'VALUE')
if crl.pass_debug_bvh_intersections: engine.register_pass(scene, srl, "Debug BVH Intersections", 1, "X", 'VALUE')
if crl.pass_debug_ray_bounces: engine.register_pass(scene, srl, "Debug Ray Bounces", 1, "X", 'VALUE')

View File

@ -1166,6 +1166,39 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
def unregister(cls):
del bpy.types.Scene.cycles_curves
class CyclesRenderLayerSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
bpy.types.SceneRenderLayer.cycles = PointerProperty(
name="Cycles SceneRenderLayer Settings",
description="Cycles SceneRenderLayer Settings",
type=cls,
)
cls.pass_debug_bvh_traversed_nodes = BoolProperty(
name="Debug BVH Traversed Nodes",
description="Store Debug BVH Traversed Nodes pass",
default=False,
)
cls.pass_debug_bvh_traversed_instances = BoolProperty(
name="Debug BVH Traversed Instances",
description="Store Debug BVH Traversed Instances pass",
default=False,
)
cls.pass_debug_bvh_intersections = BoolProperty(
name="Debug BVH Intersections",
description="Store Debug BVH Intersections",
default=False,
)
cls.pass_debug_ray_bounces = BoolProperty(
name="Debug Ray Bounces",
description="Store Debug Ray Bounces pass",
default=False,
)
@classmethod
def unregister(cls):
del bpy.types.SceneRenderLayer.cycles
class CyclesCurveSettings(bpy.types.PropertyGroup):
@classmethod
@ -1324,6 +1357,7 @@ def register():
bpy.utils.register_class(CyclesCurveSettings)
bpy.utils.register_class(CyclesDeviceSettings)
bpy.utils.register_class(CyclesPreferences)
bpy.utils.register_class(CyclesRenderLayerSettings)
def unregister():
@ -1339,3 +1373,4 @@ def unregister():
bpy.utils.unregister_class(CyclesCurveSettings)
bpy.utils.unregister_class(CyclesDeviceSettings)
bpy.utils.unregister_class(CyclesPreferences)
bpy.utils.unregister_class(CyclesRenderLayerSettings)

View File

@ -476,11 +476,14 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
import _cycles
layout = self.layout
scene = context.scene
rd = scene.render
rl = rd.layers.active
crl = rl.cycles
split = layout.split()
@ -527,8 +530,12 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
col.prop(rl, "use_pass_emit", text="Emission")
col.prop(rl, "use_pass_environment")
if hasattr(rd, "debug_pass_type"):
layout.prop(rd, "debug_pass_type")
if _cycles.with_cycles_debug:
col = layout.column()
col.prop(crl, "pass_debug_bvh_traversed_nodes")
col.prop(crl, "pass_debug_bvh_traversed_instances")
col.prop(crl, "pass_debug_bvh_intersections")
col.prop(crl, "pass_debug_ray_bounces")
class CyclesRender_PT_views(CyclesButtonsPanel, Panel):

View File

@ -811,6 +811,14 @@ void *CCL_python_module_init()
PyModule_AddStringConstant(mod, "osl_version_string", "unknown");
#endif
#ifdef WITH_CYCLES_DEBUG
PyModule_AddObject(mod, "with_cycles_debug", Py_True);
Py_INCREF(Py_True);
#else
PyModule_AddObject(mod, "with_cycles_debug", Py_False);
Py_INCREF(Py_False);
#endif
#ifdef WITH_NETWORK
PyModule_AddObject(mod, "with_network", Py_True);
Py_INCREF(Py_True);

View File

@ -243,90 +243,6 @@ void BlenderSession::free_session()
delete session;
}
static PassType get_pass_type(BL::RenderPass& b_pass)
{
switch(b_pass.type()) {
case BL::RenderPass::type_COMBINED:
return PASS_COMBINED;
case BL::RenderPass::type_Z:
return PASS_DEPTH;
case BL::RenderPass::type_MIST:
return PASS_MIST;
case BL::RenderPass::type_NORMAL:
return PASS_NORMAL;
case BL::RenderPass::type_OBJECT_INDEX:
return PASS_OBJECT_ID;
case BL::RenderPass::type_UV:
return PASS_UV;
case BL::RenderPass::type_VECTOR:
return PASS_MOTION;
case BL::RenderPass::type_MATERIAL_INDEX:
return PASS_MATERIAL_ID;
case BL::RenderPass::type_DIFFUSE_DIRECT:
return PASS_DIFFUSE_DIRECT;
case BL::RenderPass::type_GLOSSY_DIRECT:
return PASS_GLOSSY_DIRECT;
case BL::RenderPass::type_TRANSMISSION_DIRECT:
return PASS_TRANSMISSION_DIRECT;
case BL::RenderPass::type_SUBSURFACE_DIRECT:
return PASS_SUBSURFACE_DIRECT;
case BL::RenderPass::type_DIFFUSE_INDIRECT:
return PASS_DIFFUSE_INDIRECT;
case BL::RenderPass::type_GLOSSY_INDIRECT:
return PASS_GLOSSY_INDIRECT;
case BL::RenderPass::type_TRANSMISSION_INDIRECT:
return PASS_TRANSMISSION_INDIRECT;
case BL::RenderPass::type_SUBSURFACE_INDIRECT:
return PASS_SUBSURFACE_INDIRECT;
case BL::RenderPass::type_DIFFUSE_COLOR:
return PASS_DIFFUSE_COLOR;
case BL::RenderPass::type_GLOSSY_COLOR:
return PASS_GLOSSY_COLOR;
case BL::RenderPass::type_TRANSMISSION_COLOR:
return PASS_TRANSMISSION_COLOR;
case BL::RenderPass::type_SUBSURFACE_COLOR:
return PASS_SUBSURFACE_COLOR;
case BL::RenderPass::type_EMIT:
return PASS_EMISSION;
case BL::RenderPass::type_ENVIRONMENT:
return PASS_BACKGROUND;
case BL::RenderPass::type_AO:
return PASS_AO;
case BL::RenderPass::type_SHADOW:
return PASS_SHADOW;
case BL::RenderPass::type_DIFFUSE:
case BL::RenderPass::type_COLOR:
case BL::RenderPass::type_REFRACTION:
case BL::RenderPass::type_SPECULAR:
case BL::RenderPass::type_REFLECTION:
return PASS_NONE;
#ifdef WITH_CYCLES_DEBUG
case BL::RenderPass::type_DEBUG:
{
switch(b_pass.debug_type()) {
case BL::RenderPass::debug_type_BVH_TRAVERSED_NODES:
return PASS_BVH_TRAVERSED_NODES;
case BL::RenderPass::debug_type_BVH_TRAVERSED_INSTANCES:
return PASS_BVH_TRAVERSED_INSTANCES;
case BL::RenderPass::debug_type_BVH_INTERSECTIONS:
return PASS_BVH_INTERSECTIONS;
case BL::RenderPass::debug_type_RAY_BOUNCES:
return PASS_RAY_BOUNCES;
}
break;
}
#endif
}
return PASS_NONE;
}
static ShaderEvalType get_shader_type(const string& pass_type)
{
const char *shader_type = pass_type.c_str();
@ -483,22 +399,11 @@ void BlenderSession::render()
/* add passes */
array<Pass> passes;
Pass::add(PASS_COMBINED, passes);
if(session_params.device.advanced_shading) {
/* loop over passes */
BL::RenderLayer::passes_iterator b_pass_iter;
for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) {
BL::RenderPass b_pass(*b_pass_iter);
PassType pass_type = get_pass_type(b_pass);
if(pass_type == PASS_MOTION && scene->integrator->motion_blur)
continue;
if(pass_type != PASS_NONE)
Pass::add(pass_type, passes);
}
passes = sync->sync_render_passes(b_rlay, *b_layer_iter);
}
else {
Pass::add(PASS_COMBINED, passes);
}
buffer_params.passes = passes;
@ -753,19 +658,25 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult& b_rr,
BL::RenderPass b_pass(*b_iter);
/* find matching pass type */
PassType pass_type = get_pass_type(b_pass);
PassType pass_type = BlenderSync::get_pass_type(b_pass);
int components = b_pass.channels();
/* copy pixels */
if(!buffers->get_pass_rect(pass_type, exposure, sample, components, &pixels[0]))
bool read = false;
if(pass_type != PASS_NONE) {
/* copy pixels */
read = buffers->get_pass_rect(pass_type, exposure, sample, components, &pixels[0]);
}
if(!read) {
memset(&pixels[0], 0, pixels.size()*sizeof(float));
}
b_pass.rect(&pixels[0]);
}
}
else {
/* copy combined pass */
BL::RenderPass b_combined_pass(b_rlay.passes.find_by_type(BL::RenderPass::type_COMBINED, b_rview_name.c_str()));
BL::RenderPass b_combined_pass(b_rlay.passes.find_by_name("Combined", b_rview_name.c_str()));
if(buffers->get_pass_rect(PASS_COMBINED, exposure, sample, 4, &pixels[0]))
b_combined_pass.rect(&pixels[0]);
}

View File

@ -479,6 +479,94 @@ void BlenderSync::sync_images()
}
}
/* Passes */
PassType BlenderSync::get_pass_type(BL::RenderPass& b_pass)
{
string name = b_pass.name();
#define MAP_PASS(passname, passtype) if(name == passname) return passtype;
/* NOTE: Keep in sync with defined names from DNA_scene_types.h */
MAP_PASS("Combined", PASS_COMBINED);
MAP_PASS("Depth", PASS_DEPTH);
MAP_PASS("Mist", PASS_MIST);
MAP_PASS("Normal", PASS_NORMAL);
MAP_PASS("IndexOB", PASS_OBJECT_ID);
MAP_PASS("UV", PASS_UV);
MAP_PASS("Vector", PASS_MOTION);
MAP_PASS("IndexMA", PASS_MATERIAL_ID);
MAP_PASS("DiffDir", PASS_DIFFUSE_DIRECT);
MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT);
MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT);
MAP_PASS("SubsurfaceDir", PASS_SUBSURFACE_DIRECT);
MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT);
MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT);
MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT);
MAP_PASS("SubsurfaceInd", PASS_SUBSURFACE_INDIRECT);
MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR);
MAP_PASS("GlossCol", PASS_GLOSSY_COLOR);
MAP_PASS("TransCol", PASS_TRANSMISSION_COLOR);
MAP_PASS("SubsurfaceCol", PASS_SUBSURFACE_COLOR);
MAP_PASS("Emit", PASS_EMISSION);
MAP_PASS("Env", PASS_BACKGROUND);
MAP_PASS("AO", PASS_AO);
MAP_PASS("Shadow", PASS_SHADOW);
#ifdef __KERNEL_DEBUG__
MAP_PASS("Debug BVH Traversed Nodes", PASS_BVH_TRAVERSED_NODES);
MAP_PASS("Debug BVH Traversed Instances", PASS_BVH_TRAVERSED_INSTANCES);
MAP_PASS("Debug BVH Intersections", PASS_BVH_INTERSECTIONS);
MAP_PASS("Debug Ray Bounces", PASS_RAY_BOUNCES);
#endif
#undef MAP_PASS
return PASS_NONE;
}
array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
BL::SceneRenderLayer& b_srlay)
{
array<Pass> passes;
Pass::add(PASS_COMBINED, passes);
/* loop over passes */
BL::RenderLayer::passes_iterator b_pass_iter;
for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) {
BL::RenderPass b_pass(*b_pass_iter);
PassType pass_type = get_pass_type(b_pass);
if(pass_type == PASS_MOTION && scene->integrator->motion_blur)
continue;
if(pass_type != PASS_NONE)
Pass::add(pass_type, passes);
}
#ifdef __KERNEL_DEBUG__
PointerRNA crp = RNA_pointer_get(&b_srlay.ptr, "cycles");
if(get_boolean(crp, "pass_debug_bvh_traversed_nodes")) {
b_engine.add_pass("Debug BVH Traversed Nodes", 1, "X", b_srlay.name().c_str());
Pass::add(PASS_BVH_TRAVERSED_NODES, passes);
}
if(get_boolean(crp, "pass_debug_bvh_traversed_instances")) {
b_engine.add_pass("Debug BVH Traversed Instances", 1, "X", b_srlay.name().c_str());
Pass::add(PASS_BVH_TRAVERSED_INSTANCES, passes);
}
if(get_boolean(crp, "pass_debug_bvh_intersections")) {
b_engine.add_pass("Debug BVH Intersections", 1, "X", b_srlay.name().c_str());
Pass::add(PASS_BVH_INTERSECTIONS, passes);
}
if(get_boolean(crp, "pass_debug_ray_bounces")) {
b_engine.add_pass("Debug Ray Bounces", 1, "X", b_srlay.name().c_str());
Pass::add(PASS_RAY_BOUNCES, passes);
}
#endif
return passes;
}
/* Scene Parameters */
SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,

View File

@ -67,6 +67,8 @@ public:
void **python_thread_state,
const char *layer = 0);
void sync_render_layers(BL::SpaceView3D& b_v3d, const char *layer);
array<Pass> sync_render_passes(BL::RenderLayer& b_rlay,
BL::SceneRenderLayer& b_srlay);
void sync_integrator();
void sync_camera(BL::RenderSettings& b_render,
BL::Object& b_override,
@ -93,6 +95,8 @@ public:
Camera *cam,
int width, int height);
static PassType get_pass_type(BL::RenderPass& b_pass);
private:
/* sync */
void sync_lamps(bool update_all);

View File

@ -28,7 +28,7 @@
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 278
#define BLENDER_SUBVERSION 4
#define BLENDER_SUBVERSION 5
/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 6

View File

@ -973,7 +973,8 @@ void ntreeCompositExecTree(struct Scene *scene, struct bNodeTree *ntree, struct
void ntreeCompositTagRender(struct Scene *sce);
int ntreeCompositTagAnimated(struct bNodeTree *ntree);
void ntreeCompositTagGenerators(struct bNodeTree *ntree);
void ntreeCompositForceHidden(struct bNodeTree *ntree);
void ntreeCompositUpdateRLayers(struct bNodeTree *ntree);
void ntreeCompositRegisterPass(struct bNodeTree *ntree, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int type);
void ntreeCompositClearTags(struct bNodeTree *ntree);
struct bNodeSocket *ntreeCompositOutputFileAddSocket(struct bNodeTree *ntree, struct bNode *node,

View File

@ -2739,7 +2739,6 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
}
}
#define PASSTYPE_UNSET -1
/* return renderpass for a given pass index and active view */
/* fallback to available if there are missing passes for active view */
static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const int view, int *r_passindex)
@ -2748,7 +2747,7 @@ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const
RenderPass *rpass;
int rp_index = 0;
int rp_passtype = PASSTYPE_UNSET;
const char *rp_name = "";
for (rpass = rl->passes.first; rpass; rpass = rpass->next, rp_index++) {
if (rp_index == pass) {
@ -2758,12 +2757,12 @@ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const
break;
}
else {
rp_passtype = rpass->passtype;
rp_name = rpass->name;
}
}
/* multiview */
else if ((rp_passtype != PASSTYPE_UNSET) &&
(rpass->passtype == rp_passtype) &&
else if (rp_name[0] &&
STREQ(rpass->name, rp_name) &&
(rpass->view_id == view))
{
rpass_ret = rpass;
@ -2783,7 +2782,6 @@ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const
return rpass_ret;
}
#undef PASSTYPE_UNSET
/* if layer or pass changes, we need an index for the imbufs list */
/* note it is called for rendered results, but it doesnt use the index! */
@ -3753,7 +3751,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
}
for (rpass = rl->passes.first; rpass; rpass = rpass->next)
if (rpass->passtype == SCE_PASS_Z)
if (STREQ(rpass->name, RE_PASSNAME_Z) && rpass->view_id == actview)
rectz = rpass->rect;
}
}

View File

@ -2063,6 +2063,11 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *
BKE_freestyle_config_free(&srl->freestyleConfig);
if (srl->prop) {
IDP_FreeProperty(srl->prop);
MEM_freeN(srl->prop);
}
BLI_remlink(&scene->r.layers, srl);
MEM_freeN(srl);

View File

@ -3109,7 +3109,7 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
else if (ntree->type==NTREE_COMPOSIT) {
if (ELEM(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
direct_link_curvemapping(fd, node->storage);
else if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
else if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
((ImageUser *)node->storage)->ok = 1;
}
else if ( ntree->type==NTREE_TEXTURE) {
@ -6162,6 +6162,11 @@ static void direct_link_scene(FileData *fd, Scene *sce)
link_list(fd, &(sce->r.layers));
link_list(fd, &(sce->r.views));
for (srl = sce->r.layers.first; srl; srl = srl->next) {
srl->prop = newdataadr(fd, srl->prop);
IDP_DirectLinkGroup_OrFree(&srl->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
for (srl = sce->r.layers.first; srl; srl = srl->next) {
link_list(fd, &(srl->freestyleConfig.modules));
}

View File

@ -80,6 +80,7 @@
#include "NOD_common.h"
#include "NOD_socket.h"
#include "NOD_composite.h"
#include "readfile.h"
@ -1559,8 +1560,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
/* To be added to next subversion bump! */
{
if (!MAIN_VERSION_ATLEAST(main, 278, 5)) {
/* Mask primitive adding code was not initializing correctly id_type of its points' parent. */
for (Mask *mask = main->mask.first; mask; mask = mask->id.next) {
for (MaskLayer *mlayer = mask->masklayers.first; mlayer; mlayer = mlayer->next) {
@ -1609,6 +1609,30 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
}
FOREACH_NODETREE(main, ntree, id) {
if (ntree->type == NTREE_COMPOSIT) {
bNode *node;
for (node = ntree->nodes.first; node; node = node->next) {
if (node->type == CMP_NODE_R_LAYERS) {
int pass_index = 0;
const char *sockname;
for (bNodeSocket *sock = node->outputs.first; sock && pass_index < 31; sock = sock->next, pass_index++) {
if (sock->storage == NULL) {
NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
sock->storage = sockdata;
BLI_strncpy(sockdata->pass_name, node_cmp_rlayers_sock_to_pass(pass_index), sizeof(sockdata->pass_name));
if (pass_index == 0) sockname = "Image";
else if (pass_index == 1) sockname = "Alpha";
else sockname = node_cmp_rlayers_sock_to_pass(pass_index);
BLI_strncpy(sock->name, sockname, sizeof(sock->name));
}
}
}
}
}
} FOREACH_NODETREE_END
}
}

View File

@ -1052,7 +1052,7 @@ static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree)
writestruct(wd, DATA, NodeImageMultiFileSocket, 1, sock->storage);
}
}
if (node->type == CMP_NODE_IMAGE) {
if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS)) {
/* write extra socket info */
for (sock = node->outputs.first; sock; sock = sock->next) {
writestruct(wd, DATA, NodeImageLayer, 1, sock->storage);
@ -2710,6 +2710,9 @@ static void write_scene(WriteData *wd, Scene *sce)
for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) {
writestruct(wd, DATA, SceneRenderLayer, 1, srl);
if (srl->prop) {
IDP_WriteProperty(srl->prop, wd);
}
for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc);
}

View File

@ -551,8 +551,4 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
if(WITH_CYCLES AND WITH_CYCLES_DEBUG)
add_definitions(-DWITH_CYCLES_DEBUG)
endif()
blender_add_lib(bf_compositor "${SRC}" "${INC}" "${INC_SYS}")

View File

@ -179,7 +179,8 @@ void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink
/// @note: ignore invalid links
if (!(b_nodelink->flag & NODE_LINK_VALID))
return;
if ((b_nodelink->fromsock->flag & SOCK_UNAVAIL) || (b_nodelink->tosock->flag & SOCK_UNAVAIL))
const int unavail_mask = SOCK_UNAVAIL | SOCK_VIRTUAL;
if ((b_nodelink->fromsock->flag & unavail_mask) || (b_nodelink->tosock->flag & unavail_mask))
return;
/* Note: a DNA input socket can have multiple NodeInput in the compositor tree! (proxies)

View File

@ -95,18 +95,10 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
NodeOperation *operation = NULL;
socket = this->getOutputSocket(index);
bNodeSocket *bnodeSocket = socket->getbNodeSocket();
RenderPass *rpass = (RenderPass *)BLI_findstring(&rl->passes, bnodeSocket->identifier, offsetof(RenderPass, internal_name));
NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage;
RenderPass *rpass = (RenderPass *)BLI_findstring(&rl->passes, storage->pass_name, offsetof(RenderPass, name));
int view = 0;
/* Passes in the file can differ from passes stored in sockets (#36755).
* Look up the correct file pass using the socket identifier instead.
*/
#if 0
NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage;*/
int passindex = storage->pass_index;*/
RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex);
#endif
/* returns the image view to use for the current active view */
if (BLI_listbase_count_ex(&image->rr->views, 2) > 1) {
const int view_image = imageuser->view;
@ -147,7 +139,7 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
if (index == 0 && operation) {
converter.addPreview(operation->getOutputSocket());
}
if (rpass->passtype == SCE_PASS_COMBINED) {
if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
BLI_assert(operation != NULL);
BLI_assert(index < numberOfOutputs - 1);
NodeOutput *outputSocket = this->getOutputSocket(index + 1);

View File

@ -27,76 +27,61 @@
#include "COM_ScaleOperation.h"
#include "COM_SetValueOperation.h"
#ifdef WITH_CYCLES_DEBUG
# include "RE_pipeline.h"
#endif
RenderLayersNode::RenderLayersNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
}
void RenderLayersNode::testSocketLink(NodeConverter &converter, const CompositorContext &context,
int outputSocketNumber, RenderLayersBaseProg *operation) const
NodeOutput *output, RenderLayersProg *operation,
Scene *scene, int layerId, bool is_preview) const
{
NodeOutput *outputSocket = this->getOutputSocket(outputSocketNumber);
Scene *scene = (Scene *)this->getbNode()->id;
short layerId = this->getbNode()->custom1;
operation->setScene(scene);
operation->setLayerId(layerId);
operation->setRenderData(context.getRenderData());
operation->setViewName(context.getViewName());
converter.mapOutputSocket(outputSocket, operation->getOutputSocket());
converter.mapOutputSocket(output, operation->getOutputSocket());
converter.addOperation(operation);
if (outputSocketNumber == 0) /* only for image socket */
if (is_preview) /* only for image socket */
converter.addPreview(operation->getOutputSocket());
}
void RenderLayersNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
testSocketLink(converter, context, 0, new RenderLayersColorProg());
testSocketLink(converter, context, 1, new RenderLayersAlphaProg());
testSocketLink(converter, context, 2, new RenderLayersDepthProg());
testSocketLink(converter, context, 3, new RenderLayersNormalOperation());
testSocketLink(converter, context, 4, new RenderLayersUVOperation());
testSocketLink(converter, context, 5, new RenderLayersSpeedOperation());
testSocketLink(converter, context, 6, new RenderLayersColorOperation());
testSocketLink(converter, context, 7, new RenderLayersDiffuseOperation());
testSocketLink(converter, context, 8, new RenderLayersSpecularOperation());
testSocketLink(converter, context, 9, new RenderLayersShadowOperation());
testSocketLink(converter, context, 10, new RenderLayersAOOperation());
testSocketLink(converter, context, 11, new RenderLayersReflectionOperation());
testSocketLink(converter, context, 12, new RenderLayersRefractionOperation());
testSocketLink(converter, context, 13, new RenderLayersIndirectOperation());
testSocketLink(converter, context, 14, new RenderLayersObjectIndexOperation());
testSocketLink(converter, context, 15, new RenderLayersMaterialIndexOperation());
testSocketLink(converter, context, 16, new RenderLayersMistOperation());
testSocketLink(converter, context, 17, new RenderLayersEmitOperation());
testSocketLink(converter, context, 18, new RenderLayersEnvironmentOperation());
Scene *scene = (Scene *)this->getbNode()->id;
short layerId = this->getbNode()->custom1;
Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL;
int numberOfOutputs = this->getNumberOfOutputSockets();
// cycles passes
testSocketLink(converter, context, 19, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_DIRECT));
testSocketLink(converter, context, 20, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_INDIRECT));
testSocketLink(converter, context, 21, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_COLOR));
testSocketLink(converter, context, 22, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_DIRECT));
testSocketLink(converter, context, 23, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_INDIRECT));
testSocketLink(converter, context, 24, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_COLOR));
testSocketLink(converter, context, 25, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_DIRECT));
testSocketLink(converter, context, 26, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_INDIRECT));
testSocketLink(converter, context, 27, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_COLOR));
testSocketLink(converter, context, 28, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_DIRECT));
testSocketLink(converter, context, 29, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_INDIRECT));
testSocketLink(converter, context, 30, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_COLOR));
#ifdef WITH_CYCLES_DEBUG
{
Scene *scene = (Scene *)this->getbNode()->id;
Render *re = RE_GetRender(scene->id.name);
int debug_pass_type = ((re != NULL) ? RE_debug_pass_type_get(re) : scene->r.debug_pass_type);
testSocketLink(converter, context, 31, new RenderLayersCyclesDebugOperation(SCE_PASS_DEBUG, debug_pass_type));
if (re) {
RenderResult *rr = RE_AcquireResultRead(re);
if (rr) {
SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&scene->r.layers, layerId);
if (srl) {
RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
if (rl) {
for (int i = 0; i < numberOfOutputs; i++) {
NodeOutput *output = this->getOutputSocket(i);
NodeImageLayer *storage = (NodeImageLayer*) output->getbNodeSocket()->storage;
RenderPass *rpass = (RenderPass*) BLI_findstring(&rl->passes, storage->pass_name, offsetof(RenderPass, name));
if (rpass) {
if (STREQ(rpass->name, RE_PASSNAME_COMBINED) && STREQ(output->getbNodeSocket()->name, "Alpha")) {
testSocketLink(converter, context, output, new RenderLayersAlphaProg(rpass->name, COM_DT_VALUE, rpass->channels), scene, layerId, false);
}
else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
testSocketLink(converter, context, output, new RenderLayersDepthProg(rpass->name, COM_DT_VALUE, rpass->channels), scene, layerId, false);
}
else {
DataType type = ((rpass->channels == 4)? COM_DT_COLOR : ((rpass->channels == 3)? COM_DT_VECTOR : COM_DT_VALUE));
testSocketLink(converter, context, output, new RenderLayersProg(rpass->name, type, rpass->channels), scene, layerId, STREQ(output->getbNodeSocket()->name, "Image"));
}
}
}
}
}
}
RE_ReleaseResult(re);
}
#endif
}

View File

@ -33,5 +33,11 @@ public:
RenderLayersNode(bNode *editorNode);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
private:
void testSocketLink(NodeConverter &converter, const CompositorContext &context, int outputSocketNumber, RenderLayersBaseProg *operation) const;
void testSocketLink(NodeConverter &converter,
const CompositorContext &context,
NodeOutput *output,
RenderLayersProg *operation,
Scene *scene,
int layerId,
bool is_preview) const;
};

View File

@ -34,17 +34,18 @@ extern "C" {
/* ******** Render Layers Base Prog ******** */
RenderLayersBaseProg::RenderLayersBaseProg(int renderpass, int elementsize) : NodeOperation()
RenderLayersProg::RenderLayersProg(const char *passName, DataType type, int elementsize) : NodeOperation(), m_passName(passName)
{
this->m_renderpass = renderpass;
this->setScene(NULL);
this->m_inputBuffer = NULL;
this->m_elementsize = elementsize;
this->m_rd = NULL;
this->addOutputSocket(type);
}
void RenderLayersBaseProg::initExecution()
void RenderLayersProg::initExecution()
{
Scene *scene = this->getScene();
Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL;
@ -59,10 +60,7 @@ void RenderLayersBaseProg::initExecution()
RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
if (rl) {
this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass, this->m_viewName);
if (this->m_inputBuffer == NULL && this->m_renderpass == SCE_PASS_COMBINED) {
this->m_inputBuffer = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, this->m_viewName);
}
this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_passName.c_str(), this->m_viewName);
}
}
}
@ -72,7 +70,7 @@ void RenderLayersBaseProg::initExecution()
}
}
void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler)
void RenderLayersProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler)
{
unsigned int offset;
int width = this->getWidth(), height = this->getHeight();
@ -111,7 +109,7 @@ void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, Pi
}
}
void RenderLayersBaseProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
void RenderLayersProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
#if 0
const RenderData *rd = this->m_rd;
@ -173,12 +171,12 @@ void RenderLayersBaseProg::executePixelSampled(float output[4], float x, float y
}
}
void RenderLayersBaseProg::deinitExecution()
void RenderLayersProg::deinitExecution()
{
this->m_inputBuffer = NULL;
}
void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2])
void RenderLayersProg::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2])
{
Scene *sce = this->getScene();
Render *re = (sce) ? RE_GetRender(sce->id.name) : NULL;
@ -207,13 +205,6 @@ void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsig
}
/* ******** Render Layers AO Operation ******** */
RenderLayersAOOperation::RenderLayersAOOperation() : RenderLayersBaseProg(SCE_PASS_AO, 3)
{
this->addOutputSocket(COM_DT_COLOR);
}
void RenderLayersAOOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
float *inputBuffer = this->getInputBuffer();
@ -227,12 +218,6 @@ void RenderLayersAOOperation::executePixelSampled(float output[4], float x, floa
}
/* ******** Render Layers Alpha Operation ******** */
RenderLayersAlphaProg::RenderLayersAlphaProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4)
{
this->addOutputSocket(COM_DT_VALUE);
}
void RenderLayersAlphaProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
float *inputBuffer = this->getInputBuffer();
@ -247,27 +232,7 @@ void RenderLayersAlphaProg::executePixelSampled(float output[4], float x, float
}
}
/* ******** Render Layers Color Operation ******** */
RenderLayersColorOperation::RenderLayersColorOperation() : RenderLayersBaseProg(SCE_PASS_RGBA, 4)
{
this->addOutputSocket(COM_DT_COLOR);
}
/* ******** Render Layers Cycles Operation ******** */
RenderLayersCyclesOperation::RenderLayersCyclesOperation(int pass) : RenderLayersBaseProg(pass, 3)
{
this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Depth Operation ******** */
RenderLayersDepthProg::RenderLayersDepthProg() : RenderLayersBaseProg(SCE_PASS_Z, 1)
{
this->addOutputSocket(COM_DT_VALUE);
}
void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
int ix = x;
@ -281,135 +246,4 @@ void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float
unsigned int offset = (iy * this->getWidth() + ix);
output[0] = inputBuffer[offset];
}
}
/* ******** Render Layers Diffuse Operation ******** */
RenderLayersDiffuseOperation::RenderLayersDiffuseOperation() : RenderLayersBaseProg(SCE_PASS_DIFFUSE, 3)
{
this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Emit Operation ******** */
RenderLayersEmitOperation::RenderLayersEmitOperation() : RenderLayersBaseProg(SCE_PASS_EMIT, 3)
{
this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Environment Operation ******** */
RenderLayersEnvironmentOperation::RenderLayersEnvironmentOperation() : RenderLayersBaseProg(SCE_PASS_ENVIRONMENT, 3)
{
this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Image Operation ******** */
RenderLayersColorProg::RenderLayersColorProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4)
{
this->addOutputSocket(COM_DT_COLOR);
}
/* ******** Render Layers Indirect Operation ******** */
RenderLayersIndirectOperation::RenderLayersIndirectOperation() : RenderLayersBaseProg(SCE_PASS_INDIRECT, 3)
{
this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Material Index Operation ******** */
RenderLayersMaterialIndexOperation::RenderLayersMaterialIndexOperation() : RenderLayersBaseProg(SCE_PASS_INDEXMA, 1)
{
this->addOutputSocket(COM_DT_VALUE);
}
/* ******** Render Layers Mist Operation ******** */
RenderLayersMistOperation::RenderLayersMistOperation() : RenderLayersBaseProg(SCE_PASS_MIST, 1)
{
this->addOutputSocket(COM_DT_VALUE);
}
/* ******** Render Layers Normal Operation ******** */
RenderLayersNormalOperation::RenderLayersNormalOperation() : RenderLayersBaseProg(SCE_PASS_NORMAL, 3)
{
this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Object Index Operation ******** */
RenderLayersObjectIndexOperation::RenderLayersObjectIndexOperation() : RenderLayersBaseProg(SCE_PASS_INDEXOB, 1)
{
this->addOutputSocket(COM_DT_VALUE);
}
/* ******** Render Layers Reflection Operation ******** */
RenderLayersReflectionOperation::RenderLayersReflectionOperation() : RenderLayersBaseProg(SCE_PASS_REFLECT, 3)
{
this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Refraction Operation ******** */
RenderLayersRefractionOperation::RenderLayersRefractionOperation() : RenderLayersBaseProg(SCE_PASS_REFRACT, 3)
{
this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Shadow Operation ******** */
RenderLayersShadowOperation::RenderLayersShadowOperation() : RenderLayersBaseProg(SCE_PASS_SHADOW, 3)
{
this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Specular Operation ******** */
RenderLayersSpecularOperation::RenderLayersSpecularOperation() : RenderLayersBaseProg(SCE_PASS_SPEC, 3)
{
this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Render Layers Speed Operation ******** */
RenderLayersSpeedOperation::RenderLayersSpeedOperation() : RenderLayersBaseProg(SCE_PASS_VECTOR, 4)
{
this->addOutputSocket(COM_DT_COLOR);
}
/* ******** Render Layers UV Operation ******** */
RenderLayersUVOperation::RenderLayersUVOperation() : RenderLayersBaseProg(SCE_PASS_UV, 3)
{
this->addOutputSocket(COM_DT_VECTOR);
}
/* ******** Debug Render Layers Cycles Operation ******** */
#ifdef WITH_CYCLES_DEBUG
RenderLayersCyclesDebugOperation::RenderLayersCyclesDebugOperation(
int pass,
int debug_pass_type)
: RenderLayersBaseProg(pass, RE_debug_pass_num_channels_get(debug_pass_type))
{
switch (m_elementsize) {
case 1:
this->addOutputSocket(COM_DT_VALUE);
break;
case 3:
this->addOutputSocket(COM_DT_VECTOR);
break;
case 4:
this->addOutputSocket(COM_DT_COLOR);
break;
default:
BLI_assert(!"Unkown debug pass type element size.");
}
}
#endif
}

View File

@ -40,7 +40,7 @@ extern "C" {
*
* @todo: rename to operation.
*/
class RenderLayersBaseProg : public NodeOperation {
class RenderLayersProg : public NodeOperation {
protected:
/**
* Reference to the scene object.
@ -65,7 +65,7 @@ protected:
/**
* renderpass where this operation needs to get its data from
*/
int m_renderpass;
std::string m_passName;
int m_elementsize;
@ -73,11 +73,6 @@ protected:
* @brief render data used for active rendering
*/
const RenderData *m_rd;
/**
* Constructor
*/
RenderLayersBaseProg(int renderpass, int elementsize);
/**
* Determine the output resolution. The resolution is retrieved from the Renderer
@ -91,6 +86,10 @@ protected:
void doInterpolation(float output[4], float x, float y, PixelSampler sampler);
public:
/**
* Constructor
*/
RenderLayersProg(const char *passName, DataType type, int elementsize);
/**
* setter for the scene field. Will be called from
* @see RenderLayerNode to set the actual scene where
@ -108,116 +107,25 @@ public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
};
class RenderLayersAOOperation : public RenderLayersBaseProg {
class RenderLayersAOOperation : public RenderLayersProg {
public:
RenderLayersAOOperation();
RenderLayersAOOperation(const char *passName, DataType type, int elementsize)
: RenderLayersProg(passName, type, elementsize) {}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
};
class RenderLayersAlphaProg : public RenderLayersBaseProg {
class RenderLayersAlphaProg : public RenderLayersProg {
public:
RenderLayersAlphaProg();
RenderLayersAlphaProg(const char *passName, DataType type, int elementsize)
: RenderLayersProg(passName, type, elementsize) {}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
};
class RenderLayersColorOperation : public RenderLayersBaseProg {
class RenderLayersDepthProg : public RenderLayersProg {
public:
RenderLayersColorOperation();
};
class RenderLayersCyclesOperation : public RenderLayersBaseProg {
public:
RenderLayersCyclesOperation(int pass);
};
class RenderLayersDepthProg : public RenderLayersBaseProg {
public:
RenderLayersDepthProg();
RenderLayersDepthProg(const char *passName, DataType type, int elementsize)
: RenderLayersProg(passName, type, elementsize) {}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
};
class RenderLayersDiffuseOperation : public RenderLayersBaseProg {
public:
RenderLayersDiffuseOperation();
};
class RenderLayersEmitOperation : public RenderLayersBaseProg {
public:
RenderLayersEmitOperation();
};
class RenderLayersEnvironmentOperation : public RenderLayersBaseProg {
public:
RenderLayersEnvironmentOperation();
};
/// @todo rename to image operation
class RenderLayersColorProg : public RenderLayersBaseProg {
public:
RenderLayersColorProg();
};
class RenderLayersIndirectOperation : public RenderLayersBaseProg {
public:
RenderLayersIndirectOperation();
};
class RenderLayersMaterialIndexOperation : public RenderLayersBaseProg {
public:
RenderLayersMaterialIndexOperation();
};
class RenderLayersMistOperation : public RenderLayersBaseProg {
public:
RenderLayersMistOperation();
};
class RenderLayersNormalOperation : public RenderLayersBaseProg {
public:
RenderLayersNormalOperation();
};
class RenderLayersObjectIndexOperation : public RenderLayersBaseProg {
public:
RenderLayersObjectIndexOperation();
};
class RenderLayersReflectionOperation : public RenderLayersBaseProg {
public:
RenderLayersReflectionOperation();
};
class RenderLayersRefractionOperation : public RenderLayersBaseProg {
public:
RenderLayersRefractionOperation();
};
class RenderLayersShadowOperation : public RenderLayersBaseProg {
public:
RenderLayersShadowOperation();
};
class RenderLayersSpecularOperation : public RenderLayersBaseProg {
public:
RenderLayersSpecularOperation();
};
class RenderLayersSpeedOperation : public RenderLayersBaseProg {
public:
RenderLayersSpeedOperation();
};
class RenderLayersUVOperation : public RenderLayersBaseProg {
public:
RenderLayersUVOperation();
};
#ifdef WITH_CYCLES_DEBUG
class RenderLayersCyclesDebugOperation : public RenderLayersBaseProg {
public:
RenderLayersCyclesDebugOperation(int pass,
int debug_pass_type);
};
#endif
#endif

View File

@ -210,7 +210,7 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu
}
else {
if (rr->renlay == NULL) return;
rectf = RE_RenderLayerGetPass(rr->renlay, SCE_PASS_COMBINED, viewname);
rectf = RE_RenderLayerGetPass(rr->renlay, RE_PASSNAME_COMBINED, viewname);
}
}
if (rectf == NULL) return;

View File

@ -189,8 +189,12 @@ void ED_render_engine_changed(Main *bmain)
RE_FreePersistentData();
for (scene = bmain->scene.first; scene; scene = scene->id.next)
for (scene = bmain->scene.first; scene; scene = scene->id.next) {
ED_render_id_flush_update(bmain, &scene->id);
if (scene->nodetree) {
ntreeCompositUpdateRLayers(scene->nodetree);
}
}
}
/***************************** Updates ***********************************

View File

@ -428,7 +428,6 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
RenderPass *rpass;
const char *fake_name;
int nr;
int passflag = 0;
/* may have been freed since drawing */
rr = BKE_image_acquire_renderresult(scene, image);
@ -450,30 +449,31 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
fake_name = ui_imageuser_pass_fake_name(rl);
if (fake_name) {
BLI_strncpy(rpass_fake.internal_name, fake_name, sizeof(rpass_fake.internal_name));
BLI_strncpy(rpass_fake.name, fake_name, sizeof(rpass_fake.name));
nr += 1;
}
ListBase added_passes;
BLI_listbase_clear(&added_passes);
/* rendered results don't have a Combined pass */
/* multiview: the ordering must be ascending, so the left-most pass is always the one picked */
for (rpass = rl ? rl->passes.first : NULL; rpass; rpass = rpass->next, nr++) {
/* just show one pass of each kind */
if (passflag & rpass->passtype)
if (BLI_findstring_ptr(&added_passes, rpass->name, offsetof(LinkData, data))) {
continue;
}
BLI_addtail(&added_passes, BLI_genericNodeN(rpass->name));
passflag |= rpass->passtype;
final:
uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->internal_name), 0, 0,
uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->name), 0, 0,
UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, (float) nr, 0.0, 0, -1, "");
}
BLI_freelistN(&added_passes);
if (fake_name) {
fake_name = NULL;
rpass = &rpass_fake;
nr = 0;
goto final;
uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass_fake.name), 0, 0,
UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, 0.0f, 0.0, 0, -1, "");
}
BKE_image_release_renderresult(scene, image);
@ -633,7 +633,7 @@ static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt
int rp_index = iuser->pass + 1;
for (rp = rpass->next; rp; rp = rp->next, rp_index++) {
if (rp->passtype != rpass->passtype) {
if (!STREQ(rp->name, rpass->name)) {
iuser->pass = rp_index;
changed = true;
break;
@ -650,7 +650,7 @@ static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt
}
for (rp = rl->passes.first; rp; rp = rp->next, rp_index++) {
if (rp->passtype == rpass->passtype) {
if (STREQ(rp->name, rpass->name)) {
iuser->pass = rp_index - 1;
changed = true;
break;
@ -769,7 +769,7 @@ static void uiblock_layer_pass_buttons(
fake_name = ui_imageuser_pass_fake_name(rl);
rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass - (fake_name ? 1 : 0)) : NULL);
display_name = rpass ? rpass->internal_name : (fake_name ? fake_name : "");
display_name = rpass ? rpass->name : (fake_name ? fake_name : "");
rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
but = uiDefMenuBut(
block, ui_imageuser_pass_menu, rnd_pt, IFACE_(display_name),

View File

@ -3069,6 +3069,7 @@ static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr,
bNode *node = node_ptr->data;
bNodeSocket *sock = ptr->data;
int type = sock->typeinfo->type;
bool connected_to_virtual = (sock->link && (sock->link->fromsock->flag & SOCK_VIRTUAL));
/*int subtype = sock->typeinfo->subtype;*/
/* XXX not nice, eventually give this node its own socket type ... */
@ -3076,8 +3077,8 @@ static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr,
node_file_output_socket_draw(C, layout, ptr, node_ptr);
return;
}
if ((sock->in_out == SOCK_OUT) || (sock->flag & SOCK_IN_USE) || (sock->flag & SOCK_HIDE_VALUE)) {
if ((sock->in_out == SOCK_OUT) || ((sock->flag & SOCK_IN_USE) && !connected_to_virtual) || (sock->flag & SOCK_HIDE_VALUE)) {
node_socket_button_label(C, layout, ptr, node_ptr, text);
return;
}
@ -3590,6 +3591,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
{
bool do_shaded = false;
bool do_triple = false;
bool do_dashed = false;
int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE;
if (link->fromsock == NULL && link->tosock == NULL)
@ -3606,7 +3608,9 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
return;
if (link->fromsock->flag & SOCK_UNAVAIL)
return;
if ((link->fromsock->flag & SOCK_VIRTUAL) || (link->fromsock->flag & SOCK_VIRTUAL))
do_dashed = true;
if (link->flag & NODE_LINK_VALID) {
/* special indicated link, on drop-node */
if (link->flag & NODE_LINKFLAG_HILITE) {
@ -3626,8 +3630,10 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
th_col1 = TH_REDALERT;
}
}
if (do_dashed) setlinestyle(3);
node_draw_link_bezier(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
if (do_dashed) setlinestyle(0);
// node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
}

View File

@ -505,8 +505,6 @@ void ED_node_composit_default(const bContext *C, struct Scene *sce)
nodeAddLink(sce->nodetree, in, fromsock, out, tosock);
ntreeUpdateTree(CTX_data_main(C), sce->nodetree);
// XXX ntreeCompositForceHidden(sce->nodetree);
}
/* assumes nothing being done in ntree yet, sets the default in/out node */
@ -585,14 +583,6 @@ void snode_set_context(const bContext *C)
if (snode->nodetree != ntree || snode->id != id || snode->from != from || snode->treepath.last == NULL) {
ED_node_tree_start(snode, ntree, id, from);
}
/* XXX Legacy hack to update render layer node outputs.
* This should be handled by the depsgraph eventually ...
*/
if (ED_node_is_compositor(snode) && snode->nodetree) {
/* update output sockets based on available layers */
ntreeCompositForceHidden(snode->nodetree);
}
}
void snode_update(SpaceNode *snode, bNode *node)

View File

@ -448,15 +448,13 @@ static void prepare(Render *re, SceneRenderLayer *srl)
RenderLayer *rl = RE_GetRenderLayer(re->result, srl->name);
bool diffuse = false, z = false;
for (RenderPass *rpass = (RenderPass *)rl->passes.first; rpass; rpass = rpass->next) {
switch (rpass->passtype) {
case SCE_PASS_DIFFUSE:
if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) {
controller->setPassDiffuse(rpass->rect, rpass->rectx, rpass->recty);
diffuse = true;
break;
case SCE_PASS_Z:
}
if (STREQ(rpass->name, RE_PASSNAME_Z)) {
controller->setPassZ(rpass->rect, rpass->rectx, rpass->recty);
z = true;
break;
}
}
if (G.debug & G_DEBUG_FREESTYLE) {
@ -492,7 +490,7 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r
return;
}
src = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, freestyle_render->viewname);
src = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, freestyle_render->viewname);
if (!src) {
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "No source result image to composite" << endl;
@ -512,7 +510,7 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r
}
return;
}
dest = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname);
dest = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, re->viewname);
if (!dest) {
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "No destination result image to composite to" << endl;

View File

@ -159,7 +159,8 @@ typedef enum eNodeSocketFlag {
SOCK_COLLAPSED = 64, /* socket collapsed in UI */
SOCK_HIDE_VALUE = 128, /* hide socket value, if it gets auto default */
SOCK_AUTO_HIDDEN__DEPRECATED = 256, /* socket hidden automatically, to distinguish from manually hidden */
SOCK_NO_INTERNAL_LINK = 512
SOCK_NO_INTERNAL_LINK = 512,
SOCK_VIRTUAL = 1024 /* socket behaves like SOCK_UNAVAIL, but is drawn with dashed links */
} eNodeSocketFlag;
/* limit data in bNode to what we want to see saved? */
@ -569,9 +570,9 @@ typedef struct NodeEllipseMask {
/* layer info for image node outputs */
typedef struct NodeImageLayer {
/* index in the Image->layers->passes lists */
int pass_index;
/* render pass flag, in case this is an original render pass */
int pass_flag;
int pass_index DNA_DEPRECATED;
/* render pass name */
char pass_name[64]; /* amount defined in openexr_multi.h */
} NodeImageLayer;
typedef struct NodeBlurData {

View File

@ -229,7 +229,9 @@ typedef struct SceneRenderLayer {
int samples;
float pass_alpha_threshold;
IDProperty *prop;
struct FreestyleConfig freestyleConfig;
} SceneRenderLayer;
@ -283,9 +285,43 @@ typedef enum ScenePassType {
SCE_PASS_SUBSURFACE_DIRECT = (1 << 28),
SCE_PASS_SUBSURFACE_INDIRECT = (1 << 29),
SCE_PASS_SUBSURFACE_COLOR = (1 << 30),
SCE_PASS_DEBUG = (1 << 31), /* This is a virtual pass. */
} ScenePassType;
#define RE_PASSNAME_COMBINED "Combined"
#define RE_PASSNAME_Z "Depth"
#define RE_PASSNAME_VECTOR "Vector"
#define RE_PASSNAME_NORMAL "Normal"
#define RE_PASSNAME_UV "UV"
#define RE_PASSNAME_RGBA "Color"
#define RE_PASSNAME_EMIT "Emit"
#define RE_PASSNAME_DIFFUSE "Diffuse"
#define RE_PASSNAME_SPEC "Spec"
#define RE_PASSNAME_SHADOW "Shadow"
#define RE_PASSNAME_AO "AO"
#define RE_PASSNAME_ENVIRONMENT "Env"
#define RE_PASSNAME_INDIRECT "Indirect"
#define RE_PASSNAME_REFLECT "Reflect"
#define RE_PASSNAME_REFRACT "Refract"
#define RE_PASSNAME_INDEXOB "IndexOB"
#define RE_PASSNAME_INDEXMA "IndexMA"
#define RE_PASSNAME_MIST "Mist"
#define RE_PASSNAME_RAYHITS "RayHits"
#define RE_PASSNAME_DIFFUSE_DIRECT "DiffDir"
#define RE_PASSNAME_DIFFUSE_INDIRECT "DiffInd"
#define RE_PASSNAME_DIFFUSE_COLOR "DiffCol"
#define RE_PASSNAME_GLOSSY_DIRECT "GlossDir"
#define RE_PASSNAME_GLOSSY_INDIRECT "GlossInd"
#define RE_PASSNAME_GLOSSY_COLOR "GlossCol"
#define RE_PASSNAME_TRANSM_DIRECT "TransDir"
#define RE_PASSNAME_TRANSM_INDIRECT "TransInd"
#define RE_PASSNAME_TRANSM_COLOR "TransCol"
#define RE_PASSNAME_SUBSURFACE_DIRECT "SubsurfaceDir"
#define RE_PASSNAME_SUBSURFACE_INDIRECT "SubsurfaceInd"
#define RE_PASSNAME_SUBSURFACE_COLOR "SubsurfaceCol"
/* note, srl->passflag is treestore element 'nr' in outliner, short still... */
/* View - MultiView */

View File

@ -176,9 +176,6 @@ set(INC_SYS
if(WITH_CYCLES)
add_definitions(-DWITH_CYCLES)
if(WITH_CYCLES_DEBUG)
add_definitions(-DWITH_CYCLES_DEBUG)
endif()
endif()
if(WITH_PYTHON)

View File

@ -64,6 +64,8 @@
#include "RE_render_ext.h"
#include "NOD_composite.h"
EnumPropertyItem rna_enum_node_socket_in_out_items[] = {
{ SOCK_IN, "IN", 0, "Input", "" },
{ SOCK_OUT, "OUT", 0, "Output", "" },
@ -2608,7 +2610,7 @@ static void rna_Node_image_layer_update(Main *bmain, Scene *scene, PointerRNA *p
rna_Node_update(bmain, scene, ptr);
if (scene->nodetree != NULL) {
ntreeCompositForceHidden(scene->nodetree);
ntreeCompositUpdateRLayers(scene->nodetree);
}
}
@ -2747,7 +2749,7 @@ static void rna_Node_scene_layer_update(Main *bmain, Scene *scene, PointerRNA *p
{
rna_Node_update(bmain, scene, ptr);
if (scene->nodetree != NULL) {
ntreeCompositForceHidden(scene->nodetree);
ntreeCompositUpdateRLayers(scene->nodetree);
}
}
@ -4796,7 +4798,7 @@ static void def_cmp_render_layers(StructRNA *srna)
RNA_def_property_struct_type(prop, "Scene");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Scene", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_scene_layer_update");
prop = RNA_def_property(srna, "layer", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "custom1");
@ -6922,6 +6924,11 @@ static void rna_def_node_socket(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Enabled", "Enable the socket");
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "is_virtual", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_VIRTUAL);
RNA_def_property_ui_text(prop, "Virtual", "Socket is Virtual");
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "link_limit", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "limit");
RNA_def_property_int_funcs(prop, NULL, "rna_NodeSocket_link_limit_set", NULL);

View File

@ -26,6 +26,7 @@
#include <stdlib.h>
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@ -41,6 +42,7 @@
#include "RE_pipeline.h"
/* Deprecated, only provided for API compatibility. */
EnumPropertyItem rna_enum_render_pass_type_items[] = {
{SCE_PASS_COMBINED, "COMBINED", 0, "Combined", ""},
{SCE_PASS_Z, "Z", 0, "Z", ""},
@ -77,18 +79,6 @@ EnumPropertyItem rna_enum_render_pass_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
EnumPropertyItem rna_enum_render_pass_debug_type_items[] = {
{RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES, "BVH_TRAVERSED_NODES", 0, "BVH Traversed Nodes",
"Number of nodes traversed in BVH for the camera rays"},
{RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES, "BVH_TRAVERSED_INSTANCES", 0, "BVH Traversed Instances",
"Number of BVH instances traversed by camera rays"},
{RENDER_PASS_DEBUG_BVH_INTERSECTIONS, "BVH_INTERSECTIONS", 0, "BVH Intersections",
"Number of primitive intersections performed by the camera rays"},
{RENDER_PASS_DEBUG_RAY_BOUNCES, "RAY_BOUNCES", 0, "Ray Steps",
"Number of bounces done by the main integration loop"},
{0, NULL, 0, NULL, NULL}
};
EnumPropertyItem rna_enum_bake_pass_type_items[] = {
{SCE_PASS_COMBINED, "COMBINED", 0, "Combined", ""},
{SCE_PASS_AO, "AO", 0, "AO", ""},
@ -261,6 +251,24 @@ static void engine_update_script_node(RenderEngine *engine, struct bNodeTree *nt
RNA_parameter_list_free(&list);
}
static void engine_update_render_passes(RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl)
{
extern FunctionRNA rna_RenderEngine_update_render_passes_func;
PointerRNA ptr;
ParameterList list;
FunctionRNA *func;
RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
func = &rna_RenderEngine_update_render_passes_func;
RNA_parameter_list_create(&list, &ptr, func);
RNA_parameter_set_lookup(&list, "scene", &scene);
RNA_parameter_set_lookup(&list, "renderlayer", &srl);
engine->type->ext.call(NULL, &ptr, func, &list);
RNA_parameter_list_free(&list);
}
/* RenderEngine registration */
static void rna_RenderEngine_unregister(Main *UNUSED(bmain), StructRNA *type)
@ -281,7 +289,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
RenderEngineType *et, dummyet = {NULL};
RenderEngine dummyengine = {NULL};
PointerRNA dummyptr;
int have_function[6];
int have_function[7];
/* setup dummy engine & engine type to store static properties in */
dummyengine.type = &dummyet;
@ -323,6 +331,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
et->view_update = (have_function[3]) ? engine_view_update : NULL;
et->view_draw = (have_function[4]) ? engine_view_draw : NULL;
et->update_script_node = (have_function[5]) ? engine_update_script_node : NULL;
et->update_render_passes = (have_function[6]) ? engine_update_render_passes : NULL;
BLI_addtail(&R_engines, et);
@ -419,6 +428,11 @@ static RenderPass *rna_RenderPass_find_by_type(RenderLayer *rl, int passtype, co
return RE_pass_find_by_type(rl, passtype, view);
}
static RenderPass *rna_RenderPass_find_by_name(RenderLayer *rl, const char *name, const char *view)
{
return RE_pass_find_by_name(rl, name, view);
}
#else /* RNA_RUNTIME */
static void rna_def_render_engine(BlenderRNA *brna)
@ -429,6 +443,13 @@ static void rna_def_render_engine(BlenderRNA *brna)
FunctionRNA *func;
PropertyRNA *parm;
static EnumPropertyItem render_pass_type_items[] = {
{SOCK_FLOAT, "VALUE", 0, "Value", ""},
{SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
{SOCK_RGBA, "COLOR", 0, "Color", ""},
{0, NULL, 0, NULL, NULL}
};
srna = RNA_def_struct(brna, "RenderEngine", NULL);
RNA_def_struct_sdna(srna, "RenderEngine");
RNA_def_struct_ui_text(srna, "Render Engine", "Render engine");
@ -497,6 +518,12 @@ static void rna_def_render_engine(BlenderRNA *brna)
func = RNA_def_function(srna, "tag_update", "engine_tag_update");
RNA_def_function_ui_description(func, "Request update call for viewport rendering");
func = RNA_def_function(srna, "update_render_passes", NULL);
RNA_def_function_ui_description(func, "Update the render passes that will be generated");
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
parm = RNA_def_pointer(func, "scene", "Scene", "", "");
parm = RNA_def_pointer(func, "renderlayer", "SceneRenderLayer", "", "");
func = RNA_def_function(srna, "begin_result", "RE_engine_begin_result");
RNA_def_function_ui_description(func, "Create render result to write linear floating point render layers and passes");
parm = RNA_def_int(func, "x", 0, 0, INT_MAX, "X", "", 0, INT_MAX);
@ -524,6 +551,17 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_def_boolean(func, "cancel", 0, "Cancel", "Don't mark tile as done, don't merge results unless forced");
RNA_def_boolean(func, "do_merge_results", 0, "Merge Results", "Merge results even if cancel=true");
func = RNA_def_function(srna, "add_pass", "RE_engine_add_pass");
RNA_def_function_ui_description(func, "Add a pass to the render layer");
parm = RNA_def_string(func, "name", NULL, 0, "Name", "Name of the Pass, without view or channel tag");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_int(func, "channels", 0, 0, INT_MAX, "Channels", "", 0, INT_MAX);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_string(func, "chan_id", NULL, 0, "Channel IDs", "Channel names, one character per channel");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
RNA_def_string(func, "layer", NULL, 0, "Layer", "Single layer to add render pass to"); /* NULL ok here */
func = RNA_def_function(srna, "test_break", "RE_engine_test_break");
RNA_def_function_ui_description(func, "Test if the render operation should been canceled, this is a fast call that should be used regularly for responsiveness");
parm = RNA_def_boolean(func, "do_break", 0, "Break", "");
@ -646,6 +684,21 @@ static void rna_def_render_engine(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_highlight_tiles", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", RE_ENGINE_HIGHLIGHT_TILES);
func = RNA_def_function(srna, "register_pass", "RE_engine_register_pass");
RNA_def_function_ui_description(func, "Register a render pass that will be part of the render with the current settings");
prop = RNA_def_pointer(func, "scene", "Scene", "", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
prop = RNA_def_pointer(func, "srl", "SceneRenderLayer", "", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
prop = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
prop = RNA_def_int(func, "channels", 1, 1, 8, "Channels", "", 1, 4);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
prop = RNA_def_string(func, "chanid", NULL, 8, "Channel IDs", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
prop = RNA_def_enum(func, "type", render_pass_type_items, SOCK_FLOAT, "Type", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
/* registration */
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
@ -774,6 +827,15 @@ static void rna_def_render_passes(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_pointer(func, "render_pass", "RenderPass", "", "The matching render pass");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "find_by_name", "rna_RenderPass_find_by_name");
RNA_def_function_ui_description(func, "Get the render pass for a given name and view");
parm = RNA_def_string(func, "name", RE_PASSNAME_COMBINED, 0, "Pass", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_string(func, "view", NULL, 0, "View", "Render view to get pass from"); /* NULL ok here */
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_pointer(func, "render_pass", "RenderPass", "", "The matching render pass");
RNA_def_function_return(func, parm);
}
static void rna_def_render_layer(BlenderRNA *brna)
@ -822,6 +884,11 @@ static void rna_def_render_pass(BlenderRNA *brna)
RNA_define_verify_sdna(0);
prop = RNA_def_property(srna, "fullname", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "fullname");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_struct_name_property(srna, prop);
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "name");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@ -835,11 +902,6 @@ static void rna_def_render_pass(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "channels");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "passtype");
RNA_def_property_enum_items(prop, rna_enum_render_pass_type_items);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "rect", PROP_FLOAT, PROP_NONE);
RNA_def_property_flag(prop, PROP_DYNAMIC);
RNA_def_property_multi_array(prop, 2, NULL);
@ -850,11 +912,6 @@ static void rna_def_render_pass(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "view_id");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "debug_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "debug_type");
RNA_def_property_enum_items(prop, rna_enum_render_pass_debug_type_items);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_define_verify_sdna(1);
}

View File

@ -448,6 +448,7 @@ EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = {
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_node.h"
@ -1608,6 +1609,18 @@ static void rna_Scene_use_view_map_cache_update(Main *UNUSED(bmain), Scene *UNUS
#endif
}
static IDProperty *rna_SceneRenderLayer_idprops(PointerRNA *ptr, bool create)
{
SceneRenderLayer *srl = (SceneRenderLayer *)ptr->data;
if (create && !srl->prop) {
IDPropertyTemplate val = {0};
srl->prop = IDP_New(IDP_GROUP, &val, "SceneRenderLayer ID properties");
}
return srl->prop;
}
static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value)
{
Scene *scene = (Scene *)ptr->id.data;
@ -1712,11 +1725,18 @@ static void rna_SceneRenderLayer_pass_update(Main *bmain, Scene *activescene, Po
Scene *scene = (Scene *)ptr->id.data;
if (scene->nodetree)
ntreeCompositForceHidden(scene->nodetree);
ntreeCompositUpdateRLayers(scene->nodetree);
rna_Scene_glsl_update(bmain, activescene, ptr);
}
static void rna_SceneRenderLayer_update_render_passes(ID *id)
{
Scene *scene = (Scene*) id;
if (scene->nodetree)
ntreeCompositUpdateRLayers(scene->nodetree);
}
static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->data;
@ -5072,14 +5092,20 @@ static void rna_def_scene_render_layer(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
FunctionRNA *func;
srna = RNA_def_struct(brna, "SceneRenderLayer", NULL);
RNA_def_struct_ui_text(srna, "Scene Render Layer", "Render layer");
RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
RNA_def_struct_path_func(srna, "rna_SceneRenderLayer_path");
RNA_def_struct_idprops_func(srna, "rna_SceneRenderLayer_idprops");
rna_def_render_layer_common(srna, 1);
func = RNA_def_function(srna, "update_render_passes", "rna_SceneRenderLayer_update_render_passes");
RNA_def_function_ui_description(func, "Requery the enabled render passes from the render engine");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF);
/* Freestyle */
rna_def_freestyle_settings(brna);
@ -6742,14 +6768,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "BakeSettings");
RNA_def_property_ui_text(prop, "Bake Data", "");
/* Debugging settings. */
#ifdef WITH_CYCLES_DEBUG
prop = RNA_def_property(srna, "debug_pass_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_render_pass_debug_type_items);
RNA_def_property_ui_text(prop, "Debug Pass Type", "Type of the debug pass to use");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
#endif
/* Nestled Data */
/* *** Non-Animated *** */
RNA_define_animate_sdna(false);

View File

@ -289,8 +289,4 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
if(WITH_CYCLES AND WITH_CYCLES_DEBUG)
add_definitions(-DWITH_CYCLES_DEBUG)
endif()
blender_add_lib(bf_nodes "${SRC}" "${INC}" "${INC_SYS}")

View File

@ -139,6 +139,8 @@ void register_node_type_cmp_trackpos(void);
void register_node_type_cmp_planetrackdeform(void);
void register_node_type_cmp_cornerpin(void);
void node_cmp_rlayers_force_hidden_passes(struct bNode *node);
void node_cmp_rlayers_outputs(struct bNodeTree *ntree, struct bNode *node);
void node_cmp_rlayers_register_pass(struct bNodeTree *ntree, struct bNode *node, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int type);
const char *node_cmp_rlayers_sock_to_pass(int sock_index);
#endif

View File

@ -240,8 +240,15 @@ void ntreeCompositExecTree(Scene *scene, bNodeTree *ntree, RenderData *rd, int r
/* *********************************************** */
/* based on rules, force sockets hidden always */
void ntreeCompositForceHidden(bNodeTree *ntree)
/* Update the outputs of the render layer nodes.
* Since the outputs depend on the render engine, this part is a bit complex:
* - ntreeCompositUpdateRLayers is called and loops over all render layer nodes
* - Each render layer node calls the update function of the render engine that's used for its scene
* - The render engine calls RE_engine_register_pass for each pass
* - RE_engine_register_pass calls ntreeCompositRegisterPass,
* which calls node_cmp_rlayers_register_pass for every render layer node
*/
void ntreeCompositUpdateRLayers(bNodeTree *ntree)
{
bNode *node;
@ -249,16 +256,20 @@ void ntreeCompositForceHidden(bNodeTree *ntree)
for (node = ntree->nodes.first; node; node = node->next) {
if (node->type == CMP_NODE_R_LAYERS)
node_cmp_rlayers_force_hidden_passes(node);
/* XXX this stuff is called all the time, don't want that.
* Updates should only happen when actually necessary.
*/
#if 0
else if (node->type == CMP_NODE_IMAGE) {
nodeUpdate(ntree, node);
}
#endif
node_cmp_rlayers_outputs(ntree, node);
}
}
void ntreeCompositRegisterPass(bNodeTree *ntree, Scene *scene, SceneRenderLayer *srl, const char *name, int type)
{
bNode *node;
if (ntree == NULL) return;
for (node = ntree->nodes.first; node; node = node->next) {
if (node->type == CMP_NODE_R_LAYERS)
node_cmp_rlayers_register_pass(ntree, node, scene, srl, name, type);
}
}

View File

@ -32,192 +32,104 @@
#include "node_composite_util.h"
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
#include "DNA_scene_types.h"
#include "RE_engine.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
#ifdef WITH_CYCLES_DEBUG
# include "RE_pipeline.h"
#endif
/* **************** IMAGE (and RenderResult, multilayer image) ******************** */
static bNodeSocketTemplate cmp_node_rlayers_out[] = {
{ SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Z"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 0, N_("UV"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 0, N_("Speed"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Diffuse"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Specular"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Shadow"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("AO"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Reflect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Refract"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("IndexOB"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("IndexMA"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Mist"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Emit"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Environment"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Diffuse Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Diffuse Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Diffuse Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Glossy Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Glossy Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Glossy Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Transmission Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Transmission Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Transmission Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Subsurface Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Subsurface Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_("Subsurface Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
#ifdef WITH_CYCLES_DEBUG
{ SOCK_RGBA, 0, N_("Debug"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
#endif
{ SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_(RE_PASSNAME_Z), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 0, N_(RE_PASSNAME_NORMAL), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 0, N_(RE_PASSNAME_UV), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 0, N_(RE_PASSNAME_VECTOR), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_RGBA), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_SPEC), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_SHADOW), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_AO), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_REFLECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_REFRACT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_(RE_PASSNAME_INDEXOB), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_(RE_PASSNAME_INDEXMA), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_(RE_PASSNAME_MIST), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_EMIT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_ENVIRONMENT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
static bNodeSocket *cmp_node_image_add_render_pass_output(bNodeTree *ntree, bNode *node, int pass, int rres_index)
static void cmp_node_image_add_pass_output(bNodeTree *ntree, bNode *node,
const char *name, const char *passname,
int rres_index, int type, int is_rlayers,
LinkNodePair *available_sockets, int *prev_index)
{
bNodeSocket *sock;
NodeImageLayer *sockdata;
sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT);
/* extra socket info */
sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
sock->storage = sockdata;
sockdata->pass_flag = pass;
return sock;
}
int sock_index = BLI_findstringindex(&node->outputs, name, offsetof(bNodeSocket, name));
static void cmp_node_image_add_render_pass_outputs(bNodeTree *ntree, bNode *node, int passflag)
{
if (passflag & SCE_PASS_COMBINED) {
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_IMAGE);
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_ALPHA);
}
if (passflag & SCE_PASS_Z)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_Z, RRES_OUT_Z);
if (passflag & SCE_PASS_NORMAL)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_NORMAL, RRES_OUT_NORMAL);
if (passflag & SCE_PASS_VECTOR)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_VECTOR, RRES_OUT_VEC);
if (passflag & SCE_PASS_UV)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_UV, RRES_OUT_UV);
if (passflag & SCE_PASS_RGBA)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_RGBA, RRES_OUT_RGBA);
if (passflag & SCE_PASS_DIFFUSE)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE, RRES_OUT_DIFF);
if (passflag & SCE_PASS_SPEC)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SPEC, RRES_OUT_SPEC);
if (passflag & SCE_PASS_SHADOW)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SHADOW, RRES_OUT_SHADOW);
if (passflag & SCE_PASS_AO)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_AO, RRES_OUT_AO);
if (passflag & SCE_PASS_REFLECT)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFLECT, RRES_OUT_REFLECT);
if (passflag & SCE_PASS_REFRACT)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFRACT, RRES_OUT_REFRACT);
if (passflag & SCE_PASS_INDIRECT)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDIRECT, RRES_OUT_INDIRECT);
if (passflag & SCE_PASS_INDEXOB)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXOB, RRES_OUT_INDEXOB);
if (passflag & SCE_PASS_INDEXMA)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXMA, RRES_OUT_INDEXMA);
if (passflag & SCE_PASS_MIST)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_MIST, RRES_OUT_MIST);
if (passflag & SCE_PASS_EMIT)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_EMIT, RRES_OUT_EMIT);
if (passflag & SCE_PASS_ENVIRONMENT)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_ENVIRONMENT, RRES_OUT_ENV);
if (passflag & SCE_PASS_DIFFUSE_DIRECT)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_DIRECT, RRES_OUT_DIFF_DIRECT);
if (passflag & SCE_PASS_DIFFUSE_INDIRECT)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_INDIRECT, RRES_OUT_DIFF_INDIRECT);
if (passflag & SCE_PASS_DIFFUSE_COLOR)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_COLOR, RRES_OUT_DIFF_COLOR);
if (passflag & SCE_PASS_GLOSSY_DIRECT)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_DIRECT, RRES_OUT_GLOSSY_DIRECT);
if (passflag & SCE_PASS_GLOSSY_INDIRECT)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_INDIRECT, RRES_OUT_GLOSSY_INDIRECT);
if (passflag & SCE_PASS_GLOSSY_COLOR)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_COLOR, RRES_OUT_GLOSSY_COLOR);
if (passflag & SCE_PASS_TRANSM_DIRECT)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_DIRECT, RRES_OUT_TRANSM_DIRECT);
if (passflag & SCE_PASS_TRANSM_INDIRECT)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_INDIRECT, RRES_OUT_TRANSM_INDIRECT);
if (passflag & SCE_PASS_TRANSM_COLOR)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_COLOR, RRES_OUT_TRANSM_COLOR);
if (passflag & SCE_PASS_SUBSURFACE_DIRECT)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_DIRECT, RRES_OUT_SUBSURFACE_DIRECT);
if (passflag & SCE_PASS_SUBSURFACE_INDIRECT)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_INDIRECT, RRES_OUT_SUBSURFACE_INDIRECT);
if (passflag & SCE_PASS_SUBSURFACE_COLOR)
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_COLOR, RRES_OUT_SUBSURFACE_COLOR);
if (sock_index < 0) {
/* The first 31 sockets always are the legacy hardcoded sockets.
* Any dynamically allocated sockets follow afterwards, and are sorted in the order in which they were stored in the RenderResult.
* Therefore, we remember the index of the last matched socket. New sockets are placed behind the previously traversed one, but always after the first 31. */
int after_index = *prev_index;
if (is_rlayers && after_index < 30)
after_index = 30;
#ifdef WITH_CYCLES_DEBUG
cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DEBUG, RRES_OUT_DEBUG);
#endif
}
static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, RenderLayer *rl)
{
bNodeSocket *sock;
NodeImageLayer *sockdata;
RenderPass *rpass;
int index;
int passflag = 0;
for (rpass = rl->passes.first, index = 0; rpass; rpass = rpass->next, ++index) {
int type;
if (rpass->channels == 1)
type = SOCK_FLOAT;
else
type = SOCK_RGBA;
/* we only need one socket per type */
if (passflag & rpass->passtype)
continue;
passflag |= rpass->passtype;
sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, rpass->internal_name, rpass->internal_name);
if (rres_index >= 0) {
sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT);
}
else {
sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, name, name);
}
/* extra socket info */
sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
sock->storage = sockdata;
sockdata->pass_index = index;
sockdata->pass_flag = rpass->passtype;
if (rpass->passtype == SCE_PASS_COMBINED) {
sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, SOCK_FLOAT, PROP_NONE, "Alpha", "Alpha");
sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
sock->storage = sockdata;
sockdata->pass_index = index;
sockdata->pass_flag = rpass->passtype;
BLI_strncpy(sockdata->pass_name, passname, sizeof(sockdata->pass_name));
sock_index = BLI_listbase_count(&node->outputs)-1;
if (sock_index != after_index+1) {
bNodeSocket *after_sock = BLI_findlink(&node->outputs, after_index);
BLI_remlink(&node->outputs, sock);
BLI_insertlinkafter(&node->outputs, after_sock, sock);
}
}
else {
sock = BLI_findlink(&node->outputs, sock_index);
}
BLI_linklist_append(available_sockets, sock);
*prev_index = sock_index;
}
static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node, LinkNodePair *available_sockets)
{
Image *ima = (Image *)node->id;
ImBuf *ibuf;
int prev_index = -1;
if (ima) {
ImageUser *iuser = node->storage;
ImageUser load_iuser = {NULL};
ImBuf *ibuf;
int offset = BKE_image_sequence_guess_offset(ima);
/* It is possible that image user in this node is not
@ -238,104 +150,150 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
RenderLayer *rl = BLI_findlink(&ima->rr->layers, iuser->layer);
if (rl) {
if (ima->type != IMA_TYPE_MULTILAYER)
cmp_node_image_add_render_pass_outputs(ntree, node, rl->passflag);
else
cmp_node_image_add_multilayer_outputs(ntree, node, rl);
RenderPass *rpass;
for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
int type;
if (rpass->channels == 1)
type = SOCK_FLOAT;
else
type = SOCK_RGBA;
/* Special handling for the Combined pass to ensure compatibility. */
if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
cmp_node_image_add_pass_output(ntree, node, "Image", rpass->name, -1, type, false, available_sockets, &prev_index);
cmp_node_image_add_pass_output(ntree, node, "Alpha", rpass->name, -1, SOCK_FLOAT, false, available_sockets, &prev_index);
}
else {
cmp_node_image_add_pass_output(ntree, node, rpass->name, rpass->name, -1, type, false, available_sockets, &prev_index);
}
}
BKE_image_release_ibuf(ima, ibuf, NULL);
return;
}
else
cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA);
}
else
cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA | RRES_OUT_Z);
}
cmp_node_image_add_pass_output(ntree, node, "Image", RE_PASSNAME_COMBINED, RRES_OUT_IMAGE, SOCK_RGBA, false, available_sockets, &prev_index);
cmp_node_image_add_pass_output(ntree, node, "Alpha", RE_PASSNAME_COMBINED, RRES_OUT_ALPHA, SOCK_FLOAT, false, available_sockets, &prev_index);
if (ima) {
if (!ima->rr) {
cmp_node_image_add_pass_output(ntree, node, RE_PASSNAME_Z, RE_PASSNAME_Z, RRES_OUT_Z, SOCK_FLOAT, false, available_sockets, &prev_index);
}
BKE_image_release_ibuf(ima, ibuf, NULL);
}
else
cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA);
}
static bNodeSocket *cmp_node_image_output_find_match(bNode *UNUSED(node), bNodeSocket *newsock, ListBase *oldsocklist)
typedef struct RLayerUpdateData {
LinkNodePair *available_sockets;
int prev_index;
} RLayerUpdateData;
void node_cmp_rlayers_register_pass(bNodeTree *ntree, bNode *node, Scene *scene, SceneRenderLayer *srl, const char *name, int type)
{
bNodeSocket *sock;
for (sock = oldsocklist->first; sock; sock = sock->next)
if (STREQ(sock->name, newsock->name))
return sock;
return NULL;
RLayerUpdateData *data = node->storage;
if (scene == NULL || srl == NULL || data == NULL || node->id != scene) {
return;
}
SceneRenderLayer *node_srl = BLI_findlink(&scene->r.layers, node->custom1);
if (node_srl != srl) {
return;
}
/* Special handling for the Combined pass to ensure compatibility. */
if (STREQ(name, RE_PASSNAME_COMBINED)) {
cmp_node_image_add_pass_output(ntree, node, "Image", name, -1, type, true, data->available_sockets, &data->prev_index);
cmp_node_image_add_pass_output(ntree, node, "Alpha", name, -1, SOCK_FLOAT, true, data->available_sockets, &data->prev_index);
}
else {
cmp_node_image_add_pass_output(ntree, node, name, name, -1, type, true, data->available_sockets, &data->prev_index);
}
}
static bNodeSocket *cmp_node_image_output_relink(bNode *node, bNodeSocket *oldsock, int oldindex)
static void cmp_node_rlayer_create_outputs(bNodeTree *ntree, bNode *node, LinkNodePair *available_sockets)
{
bNodeSocket *sock;
/* first try to find matching socket name */
for (sock = node->outputs.first; sock; sock = sock->next)
if (STREQ(sock->name, oldsock->name))
return sock;
/* no matching name, simply link to same index */
return BLI_findlink(&node->outputs, oldindex);
}
Scene *scene = (Scene *)node->id;
static void cmp_node_image_sync_output(bNode *UNUSED(node), bNodeSocket *UNUSED(newsock), bNodeSocket *UNUSED(oldsock))
{
/* pass */
if (scene) {
RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
if(engine_type && engine_type->update_render_passes) {
SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, node->custom1);
if(srl) {
RLayerUpdateData *data = MEM_mallocN(sizeof(RLayerUpdateData), "render layer update data");
data->available_sockets = available_sockets;
data->prev_index = -1;
node->storage = data;
RenderEngine *engine = RE_engine_create(engine_type);
engine_type->update_render_passes(engine, scene, srl);
RE_engine_free(engine);
MEM_freeN(data);
node->storage = NULL;
return;
}
}
}
int prev_index = -1;
cmp_node_image_add_pass_output(ntree, node, "Image", RE_PASSNAME_COMBINED, RRES_OUT_IMAGE, SOCK_RGBA, true, available_sockets, &prev_index);
cmp_node_image_add_pass_output(ntree, node, "Alpha", RE_PASSNAME_COMBINED, RRES_OUT_ALPHA, SOCK_FLOAT, true, available_sockets, &prev_index);
}
/* XXX make this into a generic socket verification function for dynamic socket replacement (multilayer, groups, static templates) */
static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node)
static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node, bool rlayer)
{
bNodeSocket *newsock, *oldsock, *oldsock_next;
ListBase oldsocklist;
int oldindex;
bNodeLink *link;
/* store current nodes in oldsocklist, then clear socket list */
oldsocklist = node->outputs;
BLI_listbase_clear(&node->outputs);
bNodeSocket *sock, *sock_next;
LinkNodePair available_sockets = {NULL, NULL};
int sock_index;
/* XXX make callback */
cmp_node_image_create_outputs(ntree, node);
for (newsock = node->outputs.first; newsock; newsock = newsock->next) {
/* XXX make callback */
oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist);
if (oldsock) {
/* XXX make callback */
cmp_node_image_sync_output(node, newsock, oldsock);
if (rlayer)
cmp_node_rlayer_create_outputs(ntree, node, &available_sockets);
else
cmp_node_image_create_outputs(ntree, node, &available_sockets);
/* Get rid of sockets whose passes are not available in the image.
* If sockets that are not available would be deleted, the connections to them would be lost
* when e.g. opening a file (since there's no render at all yet).
* Therefore, sockets with connected links will just be set as unavailable.
*
* Another important detail comes from compatibility with the older socket model, where there
* was a fixed socket per pass type that was just hidden or not. Therefore, older versions expect
* the first 31 passes to belong to a specific pass type.
* So, we keep those 31 always allocated before the others as well, even if they have no links attached. */
sock_index = 0;
for (sock = node->outputs.first; sock; sock = sock_next, sock_index++) {
sock_next = sock->next;
if (BLI_linklist_index(available_sockets.list, sock) >= 0) {
sock->flag &= ~(SOCK_UNAVAIL | SOCK_HIDDEN);
}
}
/* move links to new socket */
for (oldsock = oldsocklist.first, oldindex = 0; oldsock; oldsock = oldsock->next, ++oldindex) {
newsock = cmp_node_image_output_relink(node, oldsock, oldindex);
if (newsock) {
else {
bNodeLink *link;
for (link = ntree->links.first; link; link = link->next) {
if (link->fromsock == oldsock)
link->fromsock = newsock;
if (link->fromsock == sock) break;
}
if (!link && sock_index > 30) {
MEM_freeN(sock->storage);
nodeRemoveSocket(ntree, node, sock);
}
else {
sock->flag |= SOCK_UNAVAIL;
}
}
}
/* delete old sockets
* XXX oldsock is not actually in the node->outputs list any more,
* but the nodeRemoveSocket function works anyway. In future this
* should become part of the core code, so can take care of this behavior.
*/
for (oldsock = oldsocklist.first; oldsock; oldsock = oldsock_next) {
oldsock_next = oldsock->next;
MEM_freeN(oldsock->storage);
nodeRemoveSocket(ntree, node, oldsock);
}
BLI_linklist_free(available_sockets.list, NULL);
}
static void cmp_node_image_update(bNodeTree *ntree, bNode *node)
{
/* avoid unnecessary updates, only changes to the image/image user data are of interest */
if (node->update & NODE_UPDATE_ID)
cmp_node_image_verify_outputs(ntree, node);
cmp_node_image_verify_outputs(ntree, node, false);
}
static void node_composit_init_image(bNodeTree *ntree, bNode *node)
@ -348,7 +306,7 @@ static void node_composit_init_image(bNodeTree *ntree, bNode *node)
iuser->ok = 1;
/* setup initial outputs */
cmp_node_image_verify_outputs(ntree, node);
cmp_node_image_verify_outputs(ntree, node, false);
}
static void node_composit_free_image(bNode *node)
@ -388,87 +346,45 @@ void register_node_type_cmp_image(void)
/* **************** RENDER RESULT ******************** */
static void set_output_visible(bNode *node, int passflag, int index, int pass)
void node_cmp_rlayers_outputs(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock = BLI_findlink(&node->outputs, index);
bool pass_enabled = ((passflag & pass) != 0);
#ifdef WITH_CYCLES_DEBUG
pass_enabled |= (pass == SCE_PASS_DEBUG);
#endif
/* clear the SOCK_HIDDEN flag as well, in case a socket was hidden before */
if (pass_enabled)
sock->flag &= ~(SOCK_HIDDEN | SOCK_UNAVAIL);
else
sock->flag |= SOCK_UNAVAIL;
cmp_node_image_verify_outputs(ntree, node, true);
}
/* clumsy checking... should do dynamic outputs once */
void node_cmp_rlayers_force_hidden_passes(bNode *node)
const char* node_cmp_rlayers_sock_to_pass(int sock_index)
{
Scene *scene = (Scene *)node->id;
SceneRenderLayer *srl;
int passflag;
bNodeSocket *sock;
/* must always have valid scene pointer */
if (!scene)
return;
srl = BLI_findlink(&scene->r.layers, node->custom1);
if (!srl)
return;
passflag = srl->passflag;
for (sock = node->outputs.first; sock; sock = sock->next)
sock->flag &= ~SOCK_UNAVAIL;
set_output_visible(node, passflag, RRES_OUT_IMAGE, SCE_PASS_COMBINED);
set_output_visible(node, passflag, RRES_OUT_ALPHA, SCE_PASS_COMBINED);
set_output_visible(node, passflag, RRES_OUT_Z, SCE_PASS_Z);
set_output_visible(node, passflag, RRES_OUT_NORMAL, SCE_PASS_NORMAL);
set_output_visible(node, passflag, RRES_OUT_VEC, SCE_PASS_VECTOR);
set_output_visible(node, passflag, RRES_OUT_UV, SCE_PASS_UV);
set_output_visible(node, passflag, RRES_OUT_RGBA, SCE_PASS_RGBA);
set_output_visible(node, passflag, RRES_OUT_DIFF, SCE_PASS_DIFFUSE);
set_output_visible(node, passflag, RRES_OUT_SPEC, SCE_PASS_SPEC);
set_output_visible(node, passflag, RRES_OUT_SHADOW, SCE_PASS_SHADOW);
set_output_visible(node, passflag, RRES_OUT_AO, SCE_PASS_AO);
set_output_visible(node, passflag, RRES_OUT_REFLECT, SCE_PASS_REFLECT);
set_output_visible(node, passflag, RRES_OUT_REFRACT, SCE_PASS_REFRACT);
set_output_visible(node, passflag, RRES_OUT_INDIRECT, SCE_PASS_INDIRECT);
set_output_visible(node, passflag, RRES_OUT_INDEXOB, SCE_PASS_INDEXOB);
set_output_visible(node, passflag, RRES_OUT_INDEXMA, SCE_PASS_INDEXMA);
set_output_visible(node, passflag, RRES_OUT_MIST, SCE_PASS_MIST);
set_output_visible(node, passflag, RRES_OUT_EMIT, SCE_PASS_EMIT);
set_output_visible(node, passflag, RRES_OUT_ENV, SCE_PASS_ENVIRONMENT);
set_output_visible(node, passflag, RRES_OUT_DIFF_DIRECT, SCE_PASS_DIFFUSE_DIRECT);
set_output_visible(node, passflag, RRES_OUT_DIFF_INDIRECT, SCE_PASS_DIFFUSE_INDIRECT);
set_output_visible(node, passflag, RRES_OUT_DIFF_COLOR, SCE_PASS_DIFFUSE_COLOR);
set_output_visible(node, passflag, RRES_OUT_GLOSSY_DIRECT, SCE_PASS_GLOSSY_DIRECT);
set_output_visible(node, passflag, RRES_OUT_GLOSSY_INDIRECT, SCE_PASS_GLOSSY_INDIRECT);
set_output_visible(node, passflag, RRES_OUT_GLOSSY_COLOR, SCE_PASS_GLOSSY_COLOR);
set_output_visible(node, passflag, RRES_OUT_TRANSM_DIRECT, SCE_PASS_TRANSM_DIRECT);
set_output_visible(node, passflag, RRES_OUT_TRANSM_INDIRECT, SCE_PASS_TRANSM_INDIRECT);
set_output_visible(node, passflag, RRES_OUT_TRANSM_COLOR, SCE_PASS_TRANSM_COLOR);
set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_DIRECT, SCE_PASS_SUBSURFACE_DIRECT);
set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_INDIRECT, SCE_PASS_SUBSURFACE_INDIRECT);
set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_COLOR, SCE_PASS_SUBSURFACE_COLOR);
#ifdef WITH_CYCLES_DEBUG
set_output_visible(node, passflag, RRES_OUT_DEBUG, SCE_PASS_DEBUG);
#endif
const char* sock_to_passname[] = {
RE_PASSNAME_COMBINED, RE_PASSNAME_COMBINED,
RE_PASSNAME_Z, RE_PASSNAME_NORMAL, RE_PASSNAME_UV, RE_PASSNAME_VECTOR, RE_PASSNAME_RGBA,
RE_PASSNAME_DIFFUSE, RE_PASSNAME_SPEC, RE_PASSNAME_SHADOW, RE_PASSNAME_AO,
RE_PASSNAME_REFLECT, RE_PASSNAME_REFRACT, RE_PASSNAME_INDIRECT,
RE_PASSNAME_INDEXOB, RE_PASSNAME_INDEXMA, RE_PASSNAME_MIST, RE_PASSNAME_EMIT, RE_PASSNAME_ENVIRONMENT,
RE_PASSNAME_DIFFUSE_DIRECT, RE_PASSNAME_DIFFUSE_INDIRECT, RE_PASSNAME_DIFFUSE_COLOR,
RE_PASSNAME_GLOSSY_DIRECT, RE_PASSNAME_GLOSSY_INDIRECT, RE_PASSNAME_GLOSSY_COLOR,
RE_PASSNAME_TRANSM_DIRECT, RE_PASSNAME_TRANSM_INDIRECT, RE_PASSNAME_TRANSM_COLOR,
RE_PASSNAME_SUBSURFACE_DIRECT, RE_PASSNAME_SUBSURFACE_INDIRECT, RE_PASSNAME_SUBSURFACE_COLOR
};
if (sock_index > 30) {
return NULL;
}
return sock_to_passname[sock_index];
}
static void node_composit_init_rlayers(const bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
bNode *node = ptr->data;
int sock_index = 0;
node->id = &scene->id;
node_cmp_rlayers_force_hidden_passes(node);
for (bNodeSocket *sock = node->outputs.first; sock; sock = sock->next, sock_index++)
{
NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
sock->storage = sockdata;
BLI_strncpy(sockdata->pass_name, node_cmp_rlayers_sock_to_pass(sock_index), sizeof(sockdata->pass_name));
}
}
static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree)
@ -489,6 +405,29 @@ static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree
return false;
}
static void node_composit_free_rlayers(bNode *node)
{
bNodeSocket *sock;
/* free extra socket info */
for (sock = node->outputs.first; sock; sock = sock->next)
MEM_freeN(sock->storage);
}
static void node_composit_copy_rlayers(bNodeTree *UNUSED(dest_ntree), bNode *UNUSED(dest_node), bNode *src_node)
{
bNodeSocket *sock;
/* copy extra socket info */
for (sock = src_node->outputs.first; sock; sock = sock->next)
sock->new_sock->storage = MEM_dupallocN(sock->storage);
}
static void cmp_node_rlayers_update(bNodeTree *ntree, bNode *node)
{
cmp_node_image_verify_outputs(ntree, node, true);
}
void register_node_type_cmp_rlayers(void)
{
static bNodeType ntype;
@ -497,6 +436,9 @@ void register_node_type_cmp_rlayers(void)
node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out);
ntype.initfunc_api = node_composit_init_rlayers;
ntype.poll = node_composit_poll_rlayers;
node_type_storage(&ntype, NULL, node_composit_free_rlayers, node_composit_copy_rlayers);
node_type_update(&ntype, cmp_node_rlayers_update, NULL);
node_type_init(&ntype, node_cmp_rlayers_outputs);
nodeRegisterType(&ntype);
}

View File

@ -34,6 +34,7 @@ set(INC
../depsgraph
../makesdna
../makesrna
../nodes
../physics
../../../intern/atomic
../../../intern/guardedalloc
@ -165,10 +166,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
if(WITH_CYCLES AND WITH_CYCLES_DEBUG)
add_definitions(-DWITH_CYCLES_DEBUG)
endif()
if(APPLE)
# SSE math is enabled by default on x86_64
if(CMAKE_OSX_ARCHITECTURES MATCHES "i386")

View File

@ -96,6 +96,7 @@ typedef struct RenderEngineType {
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);
/* RNA integration */
ExtensionRNA ext;
@ -139,6 +140,7 @@ void RE_result_load_from_file(struct RenderResult *result, struct ReportList *re
struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname);
void RE_engine_update_result(RenderEngine *engine, struct RenderResult *result);
void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername);
void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int merge_results);
const char *RE_engine_active_view_get(RenderEngine *engine);
@ -160,6 +162,9 @@ 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,
const char *name, int channels, const char *chanid, int type);
/* Engine Types */
void RE_engines_init(void);

View File

@ -83,25 +83,19 @@ typedef struct RenderView {
typedef struct RenderPass {
struct RenderPass *next, *prev;
int passtype, channels;
int channels;
char name[64]; /* amount defined in openexr_multi.h */
char chan_id[8]; /* amount defined in openexr_multi.h */
float *rect;
int rectx, recty;
char internal_name[64]; /* EXR_PASS_MAXNAME */
char fullname[64]; /* EXR_PASS_MAXNAME */
char view[64]; /* EXR_VIEW_MAXNAME */
int view_id; /* quick lookup */
int debug_type;
int pad;
} RenderPass;
enum {
RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES = 0,
RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES = 1,
RENDER_PASS_DEBUG_RAY_BOUNCES = 2,
RENDER_PASS_DEBUG_BVH_INTERSECTIONS = 3,
};
/* a renderlayer is a full image, but with all passes and samples */
/* size of the rects is defined in RenderResult */
@ -236,7 +230,7 @@ void RE_render_result_rect_from_ibuf(
struct ImBuf *ibuf, const int view_id);
struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name);
float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, int passtype, const char *viewname);
float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, const char *name, const char *viewname);
/* add passes for grease pencil */
struct RenderPass *RE_create_gp_pass(struct RenderResult *rr, const char *layername, const char *viewname);
@ -345,6 +339,7 @@ int RE_seq_render_active(struct Scene *scene, struct RenderData *rd);
bool RE_layers_have_name(struct RenderResult *result);
struct RenderPass *RE_pass_find_by_name(volatile struct RenderLayer *rl, const char *name, const char *viewname);
struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname);
/* shaded view or baking options */
@ -394,13 +389,5 @@ struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char *
RenderResult *RE_DuplicateRenderResult(RenderResult *rr);
/******* Debug pass helper functions *********/
#ifdef WITH_CYCLES_DEBUG
int RE_debug_pass_num_channels_get(int pass_type);
const char *RE_debug_pass_name_get(int pass_type);
int RE_debug_pass_type_get(struct Render *re);
#endif
#endif /* __RE_PIPELINE_H__ */

View File

@ -67,6 +67,11 @@ void render_result_views_new(struct RenderResult *rr, struct RenderData *rd);
void render_result_merge(struct RenderResult *rr, struct RenderResult *rrpart);
/* Add Passes */
void render_result_clone_passes(struct Render *re, struct RenderResult *rr, const char *viewname);
void render_result_add_pass(struct RenderResult *rr, const char *name, int channels, const char *chan_id, const char *layername, const char *viewname);
/* Free */
void render_result_free(struct RenderResult *rr);
@ -84,7 +89,7 @@ void render_result_exr_file_begin(struct Render *re);
void render_result_exr_file_end(struct Render *re);
/* render pass wrapper for gpencil */
struct RenderPass *gp_add_pass(struct RenderResult *rr, struct RenderLayer *rl, int channels, int passtype, const char *viewname);
struct RenderPass *gp_add_pass(struct RenderResult *rr, struct RenderLayer *rl, int channels, const char *name, const char *viewname);
void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart, const char *viewname);

View File

@ -34,6 +34,12 @@
#include "render_types.h"
#include "RE_engine.h"
#include "DNA_node_types.h"
#include "NOD_composite.h"
struct ShadeInput;
struct ShadeResult;
struct World;
@ -77,6 +83,8 @@ void zbufshade_sss_tile(struct RenderPart *pa);
int get_sample_layers(struct RenderPart *pa, struct RenderLayer *rl, struct RenderLayer **rlpp);
void render_internal_update_passes(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl);
/* -------- ray.c ------- */

View File

@ -499,7 +499,7 @@ static void render_envmap(Render *re, EnvMap *env)
float *rect;
/* envmap is rendered independently of multiview */
rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, "");
rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, "");
ibuf = IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect | IB_rectfloat);
memcpy(ibuf->rect_float, rect, ibuf->channels * ibuf->x * ibuf->y * sizeof(float));

View File

@ -62,13 +62,14 @@
#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,
NULL, NULL, NULL, NULL, NULL, NULL, render_internal_update_passes,
{NULL, NULL, NULL}
};
@ -77,7 +78,7 @@ static RenderEngineType internal_render_type = {
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, NULL, NULL, NULL,
{NULL, NULL, NULL}
};
@ -212,6 +213,8 @@ RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w,
/* can be NULL if we CLAMP the width or height to 0 */
if (result) {
render_result_clone_passes(re, result, viewname);
RenderPart *pa;
/* Copy EXR tile settings, so pipeline knows whether this is a result
@ -245,6 +248,17 @@ void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
}
}
void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername)
{
Render *re = engine->re;
if (!re || !re->result) {
return;
}
render_result_add_pass(re->result, name, channels, chan_id, layername, NULL);
}
void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel, int merge_results)
{
Render *re = engine->re;
@ -760,3 +774,16 @@ 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,
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)) {
return;
}
if (scene->nodetree) {
ntreeCompositRegisterPass(scene->nodetree, scene, srl, name, type);
}
}

View File

@ -239,9 +239,9 @@ void RE_FreeRenderResult(RenderResult *res)
render_result_free(res);
}
float *RE_RenderLayerGetPass(volatile RenderLayer *rl, int passtype, const char *viewname)
float *RE_RenderLayerGetPass(volatile RenderLayer *rl, const char *name, const char *viewname)
{
RenderPass *rpass = RE_pass_find_by_type(rl, passtype, viewname);
RenderPass *rpass = RE_pass_find_by_name(rl, name, viewname);
return rpass ? rpass->rect : NULL;
}
@ -382,13 +382,13 @@ void RE_AcquireResultImageViews(Render *re, RenderResult *rr)
if (rl) {
if (rv->rectf == NULL) {
for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) {
rview->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rview->name);
rview->rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, rview->name);
}
}
if (rv->rectz == NULL) {
for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) {
rview->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rview->name);
rview->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rview->name);
}
}
}
@ -442,10 +442,10 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id)
if (rl) {
if (rv->rectf == NULL)
rr->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rv->name);
rr->rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, rv->name);
if (rv->rectz == NULL)
rr->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rv->name);
rr->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rv->name);
}
rr->have_combined = (rv->rectf != NULL);
@ -842,7 +842,7 @@ static void render_result_rescale(Render *re)
if (src_rectf == NULL) {
RenderLayer *rl = render_get_active_layer(re, re->result);
if (rl != NULL) {
src_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, NULL);
src_rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, NULL);
}
}
@ -861,7 +861,7 @@ static void render_result_rescale(Render *re)
RenderLayer *rl;
rl = render_get_active_layer(re, re->result);
if (rl != NULL) {
dst_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, NULL);
dst_rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, NULL);
}
}
@ -1655,7 +1655,7 @@ static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float b
/* passes are allocated in sync */
rpass1 = rl1->passes.first;
for (rpass = rl->passes.first; rpass && rpass1; rpass = rpass->next, rpass1 = rpass1->next) {
if ((rpass->passtype & SCE_PASS_COMBINED) && key_alpha)
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);
@ -1855,6 +1855,8 @@ static void render_result_uncrop(Render *re)
rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
render_result_clone_passes(re, rres, NULL);
render_result_merge(rres, re->result);
render_result_free(re->result);
re->result = rres;
@ -3887,7 +3889,7 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char
/* multiview: since the API takes no 'view', we use the first combined pass found */
for (rpass = layer->passes.first; rpass; rpass = rpass->next)
if (rpass->passtype == SCE_PASS_COMBINED)
if (STREQ(rpass->name, RE_PASSNAME_COMBINED))
break;
if (rpass == NULL)
@ -4013,13 +4015,12 @@ bool RE_layers_have_name(struct RenderResult *rr)
return false;
}
RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const char *viewname)
RenderPass *RE_pass_find_by_name(volatile RenderLayer *rl, const char *name, const char *viewname)
{
RenderPass *rp = NULL;
for (rp = rl->passes.last; rp; rp = rp->prev) {
if (rp->passtype == passtype) {
if (STREQ(rp->name, name)) {
if (viewname == NULL || viewname[0] == '\0')
break;
else if (STREQ(rp->view, viewname))
@ -4029,6 +4030,50 @@ RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const c
return rp;
}
/* Only provided for API compatibility, don't use this in new code! */
RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const char *viewname)
{
#define CHECK_PASS(NAME) \
if (passtype == SCE_PASS_ ## NAME) \
return RE_pass_find_by_name(rl, RE_PASSNAME_ ## NAME, viewname);
CHECK_PASS(COMBINED);
CHECK_PASS(Z);
CHECK_PASS(VECTOR);
CHECK_PASS(NORMAL);
CHECK_PASS(UV);
CHECK_PASS(RGBA);
CHECK_PASS(EMIT);
CHECK_PASS(DIFFUSE);
CHECK_PASS(SPEC);
CHECK_PASS(SHADOW);
CHECK_PASS(AO);
CHECK_PASS(ENVIRONMENT);
CHECK_PASS(INDIRECT);
CHECK_PASS(REFLECT);
CHECK_PASS(REFRACT);
CHECK_PASS(INDEXOB);
CHECK_PASS(INDEXMA);
CHECK_PASS(MIST);
CHECK_PASS(RAYHITS);
CHECK_PASS(DIFFUSE_DIRECT);
CHECK_PASS(DIFFUSE_INDIRECT);
CHECK_PASS(DIFFUSE_COLOR);
CHECK_PASS(GLOSSY_DIRECT);
CHECK_PASS(GLOSSY_INDIRECT);
CHECK_PASS(GLOSSY_COLOR);
CHECK_PASS(TRANSM_DIRECT);
CHECK_PASS(TRANSM_INDIRECT);
CHECK_PASS(TRANSM_COLOR);
CHECK_PASS(SUBSURFACE_DIRECT);
CHECK_PASS(SUBSURFACE_INDIRECT);
CHECK_PASS(SUBSURFACE_COLOR);
#undef CHECK_PASS
return NULL;
}
/* create a renderlayer and renderpass for grease pencil layer */
RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const char *viewname)
{
@ -4046,7 +4091,7 @@ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const cha
}
/* clear previous pass if exist or the new image will be over previous one*/
RenderPass *rp = RE_pass_find_by_type(rl, SCE_PASS_COMBINED, viewname);
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname);
if (rp) {
if (rp->rect) {
MEM_freeN(rp->rect);
@ -4054,5 +4099,5 @@ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const cha
BLI_freelinkN(&rl->passes, rp);
}
/* create a totally new pass */
return gp_add_pass(rr, rl, 4, SCE_PASS_COMBINED, viewname);
return gp_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, viewname);
}

View File

@ -173,363 +173,72 @@ void render_result_views_shallowdelete(RenderResult *rr)
}
}
static const char *name_from_passtype(int passtype, int channel)
static char* set_pass_name(char *outname, const char *name, int channel, const char *chan_id)
{
if (passtype == SCE_PASS_COMBINED) {
if (channel == -1) return "Combined";
if (channel == 0) return "Combined.R";
if (channel == 1) return "Combined.G";
if (channel == 2) return "Combined.B";
return "Combined.A";
BLI_strncpy(outname, name, EXR_PASS_MAXNAME);
if (channel >= 0) {
char token[3] = {'.', chan_id[channel], '\0'};
strncat(outname, token, EXR_PASS_MAXNAME);
}
if (passtype == SCE_PASS_Z) {
if (channel == -1) return "Depth";
return "Depth.Z";
}
if (passtype == SCE_PASS_VECTOR) {
if (channel == -1) return "Vector";
if (channel == 0) return "Vector.X";
if (channel == 1) return "Vector.Y";
if (channel == 2) return "Vector.Z";
return "Vector.W";
}
if (passtype == SCE_PASS_NORMAL) {
if (channel == -1) return "Normal";
if (channel == 0) return "Normal.X";
if (channel == 1) return "Normal.Y";
return "Normal.Z";
}
if (passtype == SCE_PASS_UV) {
if (channel == -1) return "UV";
if (channel == 0) return "UV.U";
if (channel == 1) return "UV.V";
return "UV.A";
}
if (passtype == SCE_PASS_RGBA) {
if (channel == -1) return "Color";
if (channel == 0) return "Color.R";
if (channel == 1) return "Color.G";
if (channel == 2) return "Color.B";
return "Color.A";
}
if (passtype == SCE_PASS_EMIT) {
if (channel == -1) return "Emit";
if (channel == 0) return "Emit.R";
if (channel == 1) return "Emit.G";
return "Emit.B";
}
if (passtype == SCE_PASS_DIFFUSE) {
if (channel == -1) return "Diffuse";
if (channel == 0) return "Diffuse.R";
if (channel == 1) return "Diffuse.G";
return "Diffuse.B";
}
if (passtype == SCE_PASS_SPEC) {
if (channel == -1) return "Spec";
if (channel == 0) return "Spec.R";
if (channel == 1) return "Spec.G";
return "Spec.B";
}
if (passtype == SCE_PASS_SHADOW) {
if (channel == -1) return "Shadow";
if (channel == 0) return "Shadow.R";
if (channel == 1) return "Shadow.G";
return "Shadow.B";
}
if (passtype == SCE_PASS_AO) {
if (channel == -1) return "AO";
if (channel == 0) return "AO.R";
if (channel == 1) return "AO.G";
return "AO.B";
}
if (passtype == SCE_PASS_ENVIRONMENT) {
if (channel == -1) return "Env";
if (channel == 0) return "Env.R";
if (channel == 1) return "Env.G";
return "Env.B";
}
if (passtype == SCE_PASS_INDIRECT) {
if (channel == -1) return "Indirect";
if (channel == 0) return "Indirect.R";
if (channel == 1) return "Indirect.G";
return "Indirect.B";
}
if (passtype == SCE_PASS_REFLECT) {
if (channel == -1) return "Reflect";
if (channel == 0) return "Reflect.R";
if (channel == 1) return "Reflect.G";
return "Reflect.B";
}
if (passtype == SCE_PASS_REFRACT) {
if (channel == -1) return "Refract";
if (channel == 0) return "Refract.R";
if (channel == 1) return "Refract.G";
return "Refract.B";
}
if (passtype == SCE_PASS_INDEXOB) {
if (channel == -1) return "IndexOB";
return "IndexOB.X";
}
if (passtype == SCE_PASS_INDEXMA) {
if (channel == -1) return "IndexMA";
return "IndexMA.X";
}
if (passtype == SCE_PASS_MIST) {
if (channel == -1) return "Mist";
return "Mist.Z";
}
if (passtype == SCE_PASS_RAYHITS) {
if (channel == -1) return "Rayhits";
if (channel == 0) return "Rayhits.R";
if (channel == 1) return "Rayhits.G";
return "Rayhits.B";
}
if (passtype == SCE_PASS_DIFFUSE_DIRECT) {
if (channel == -1) return "DiffDir";
if (channel == 0) return "DiffDir.R";
if (channel == 1) return "DiffDir.G";
return "DiffDir.B";
}
if (passtype == SCE_PASS_DIFFUSE_INDIRECT) {
if (channel == -1) return "DiffInd";
if (channel == 0) return "DiffInd.R";
if (channel == 1) return "DiffInd.G";
return "DiffInd.B";
}
if (passtype == SCE_PASS_DIFFUSE_COLOR) {
if (channel == -1) return "DiffCol";
if (channel == 0) return "DiffCol.R";
if (channel == 1) return "DiffCol.G";
return "DiffCol.B";
}
if (passtype == SCE_PASS_GLOSSY_DIRECT) {
if (channel == -1) return "GlossDir";
if (channel == 0) return "GlossDir.R";
if (channel == 1) return "GlossDir.G";
return "GlossDir.B";
}
if (passtype == SCE_PASS_GLOSSY_INDIRECT) {
if (channel == -1) return "GlossInd";
if (channel == 0) return "GlossInd.R";
if (channel == 1) return "GlossInd.G";
return "GlossInd.B";
}
if (passtype == SCE_PASS_GLOSSY_COLOR) {
if (channel == -1) return "GlossCol";
if (channel == 0) return "GlossCol.R";
if (channel == 1) return "GlossCol.G";
return "GlossCol.B";
}
if (passtype == SCE_PASS_TRANSM_DIRECT) {
if (channel == -1) return "TransDir";
if (channel == 0) return "TransDir.R";
if (channel == 1) return "TransDir.G";
return "TransDir.B";
}
if (passtype == SCE_PASS_TRANSM_INDIRECT) {
if (channel == -1) return "TransInd";
if (channel == 0) return "TransInd.R";
if (channel == 1) return "TransInd.G";
return "TransInd.B";
}
if (passtype == SCE_PASS_TRANSM_COLOR) {
if (channel == -1) return "TransCol";
if (channel == 0) return "TransCol.R";
if (channel == 1) return "TransCol.G";
return "TransCol.B";
}
if (passtype == SCE_PASS_SUBSURFACE_DIRECT) {
if (channel == -1) return "SubsurfaceDir";
if (channel == 0) return "SubsurfaceDir.R";
if (channel == 1) return "SubsurfaceDir.G";
return "SubsurfaceDir.B";
}
if (passtype == SCE_PASS_SUBSURFACE_INDIRECT) {
if (channel == -1) return "SubsurfaceInd";
if (channel == 0) return "SubsurfaceInd.R";
if (channel == 1) return "SubsurfaceInd.G";
return "SubsurfaceInd.B";
}
if (passtype == SCE_PASS_SUBSURFACE_COLOR) {
if (channel == -1) return "SubsurfaceCol";
if (channel == 0) return "SubsurfaceCol.R";
if (channel == 1) return "SubsurfaceCol.G";
return "SubsurfaceCol.B";
}
return "Unknown";
return outname;
}
static int passtype_from_name(const char *str, int passflag)
static void set_pass_full_name(char *fullname, const char *name, int channel, const char *view, const char *chan_id)
{
/* We do not really support several pass of the same types, so in case we are opening an EXR file with several pass
* names detected as same pass type, only return that pass type the first time, and return 'uknown' for the others.
* See T48466. */
#define RETURN_PASS(_passtype) return (passflag & (_passtype)) ? 0 : (_passtype)
if (STRPREFIX(str, "Combined"))
RETURN_PASS(SCE_PASS_COMBINED);
if (STRPREFIX(str, "Depth"))
RETURN_PASS(SCE_PASS_Z);
if (STRPREFIX(str, "Vector"))
RETURN_PASS(SCE_PASS_VECTOR);
if (STRPREFIX(str, "Normal"))
RETURN_PASS(SCE_PASS_NORMAL);
if (STRPREFIX(str, "UV"))
RETURN_PASS(SCE_PASS_UV);
if (STRPREFIX(str, "Color"))
RETURN_PASS(SCE_PASS_RGBA);
if (STRPREFIX(str, "Emit"))
RETURN_PASS(SCE_PASS_EMIT);
if (STRPREFIX(str, "Diffuse"))
RETURN_PASS(SCE_PASS_DIFFUSE);
if (STRPREFIX(str, "Spec"))
RETURN_PASS(SCE_PASS_SPEC);
if (STRPREFIX(str, "Shadow"))
RETURN_PASS(SCE_PASS_SHADOW);
if (STRPREFIX(str, "AO"))
RETURN_PASS(SCE_PASS_AO);
if (STRPREFIX(str, "Env"))
RETURN_PASS(SCE_PASS_ENVIRONMENT);
if (STRPREFIX(str, "Indirect"))
RETURN_PASS(SCE_PASS_INDIRECT);
if (STRPREFIX(str, "Reflect"))
RETURN_PASS(SCE_PASS_REFLECT);
if (STRPREFIX(str, "Refract"))
RETURN_PASS(SCE_PASS_REFRACT);
if (STRPREFIX(str, "IndexOB"))
RETURN_PASS(SCE_PASS_INDEXOB);
if (STRPREFIX(str, "IndexMA"))
RETURN_PASS(SCE_PASS_INDEXMA);
if (STRPREFIX(str, "Mist"))
RETURN_PASS(SCE_PASS_MIST);
if (STRPREFIX(str, "RayHits"))
RETURN_PASS(SCE_PASS_RAYHITS);
if (STRPREFIX(str, "DiffDir"))
RETURN_PASS(SCE_PASS_DIFFUSE_DIRECT);
if (STRPREFIX(str, "DiffInd"))
RETURN_PASS(SCE_PASS_DIFFUSE_INDIRECT);
if (STRPREFIX(str, "DiffCol"))
RETURN_PASS(SCE_PASS_DIFFUSE_COLOR);
if (STRPREFIX(str, "GlossDir"))
RETURN_PASS(SCE_PASS_GLOSSY_DIRECT);
if (STRPREFIX(str, "GlossInd"))
RETURN_PASS(SCE_PASS_GLOSSY_INDIRECT);
if (STRPREFIX(str, "GlossCol"))
RETURN_PASS(SCE_PASS_GLOSSY_COLOR);
if (STRPREFIX(str, "TransDir"))
RETURN_PASS(SCE_PASS_TRANSM_DIRECT);
if (STRPREFIX(str, "TransInd"))
RETURN_PASS(SCE_PASS_TRANSM_INDIRECT);
if (STRPREFIX(str, "TransCol"))
RETURN_PASS(SCE_PASS_TRANSM_COLOR);
if (STRPREFIX(str, "SubsurfaceDir"))
RETURN_PASS(SCE_PASS_SUBSURFACE_DIRECT);
if (STRPREFIX(str, "SubsurfaceInd"))
RETURN_PASS(SCE_PASS_SUBSURFACE_INDIRECT);
if (STRPREFIX(str, "SubsurfaceCol"))
RETURN_PASS(SCE_PASS_SUBSURFACE_COLOR);
return 0;
#undef RETURN_PASS
}
static void set_pass_name(char *passname, int passtype, int channel, const char *view)
{
const char delims[] = {'.', '\0'};
const char *sep;
const char *token;
size_t len;
const char *passtype_name = name_from_passtype(passtype, channel);
if (view == NULL || view[0] == '\0') {
BLI_strncpy(passname, passtype_name, EXR_PASS_MAXNAME);
return;
BLI_strncpy(fullname, name, EXR_PASS_MAXNAME);
if (view && view[0]) {
strncat(fullname, ".", EXR_PASS_MAXNAME);
strncat(fullname, view, EXR_PASS_MAXNAME);
}
len = BLI_str_rpartition(passtype_name, delims, &sep, &token);
if (sep) {
BLI_snprintf(passname, EXR_PASS_MAXNAME, "%.*s.%s.%s", (int)len, passtype_name, view, token);
}
else {
BLI_snprintf(passname, EXR_PASS_MAXNAME, "%s.%s", passtype_name, view);
if (channel >= 0) {
char token[3] = {'.', chan_id[channel], '\0'};
strncat(fullname, token, EXR_PASS_MAXNAME);
}
}
/********************************** New **************************************/
static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype, const char *viewname)
static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname, const char *chan_id)
{
const int view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name));
const char *typestr = name_from_passtype(passtype, -1);
RenderPass *rpass = MEM_callocN(sizeof(RenderPass), typestr);
RenderPass *rpass = MEM_callocN(sizeof(RenderPass), name);
size_t rectsize = ((size_t)rr->rectx) * rr->recty * channels;
rpass->passtype = passtype;
rpass->channels = channels;
rpass->rectx = rl->rectx;
rpass->recty = rl->recty;
rpass->view_id = view_id;
set_pass_name(rpass->name, rpass->passtype, -1, viewname);
BLI_strncpy(rpass->internal_name, typestr, sizeof(rpass->internal_name));
BLI_strncpy(rpass->name, name, sizeof(rpass->name));
BLI_strncpy(rpass->chan_id, chan_id, sizeof(rpass->chan_id));
BLI_strncpy(rpass->view, viewname, sizeof(rpass->view));
set_pass_full_name(rpass->fullname, rpass->name, -1, rpass->view, rpass->chan_id);
if (rl->exrhandle) {
int a;
for (a = 0; a < channels; a++)
IMB_exr_add_channel(rl->exrhandle, rl->name, name_from_passtype(passtype, a), viewname, 0, 0, NULL, false);
for (a = 0; a < channels; a++) {
char passname[EXR_PASS_MAXNAME];
IMB_exr_add_channel(rl->exrhandle, rl->name, set_pass_name(passname, rpass->name, a, rpass->chan_id), viewname, 0, 0, NULL, false);
}
}
else {
float *rect;
int x;
rpass->rect = MEM_mapallocN(sizeof(float) * rectsize, typestr);
rpass->rect = MEM_mapallocN(sizeof(float) * rectsize, name);
if (rpass->rect == NULL) {
MEM_freeN(rpass);
return NULL;
}
if (passtype == SCE_PASS_VECTOR) {
if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
/* initialize to max speed */
rect = rpass->rect;
for (x = rectsize - 1; x >= 0; x--)
rect[x] = PASS_VECTOR_MAX;
}
else if (passtype == SCE_PASS_Z) {
else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
rect = rpass->rect;
for (x = rectsize - 1; x >= 0; x--)
rect[x] = 10e10;
@ -541,59 +250,11 @@ static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int
return rpass;
}
/* wrapper called from render_opengl */
RenderPass *gp_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype, const char *viewname)
RenderPass *gp_add_pass(RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname)
{
return render_layer_add_pass(rr, rl, channels, passtype, viewname);
return render_layer_add_pass(rr, rl, channels, name, viewname, "RGBA");
}
#ifdef WITH_CYCLES_DEBUG
const char *RE_debug_pass_name_get(int debug_type)
{
switch (debug_type) {
case RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES:
return "BVH Traversed Nodes";
case RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES:
return "BVH Traversed Instances";
case RENDER_PASS_DEBUG_BVH_INTERSECTIONS:
return "BVH Primitive Intersections";
case RENDER_PASS_DEBUG_RAY_BOUNCES:
return "Ray Bounces";
}
return "Unknown";
}
int RE_debug_pass_num_channels_get(int UNUSED(debug_type))
{
/* Only single case currently, might be handy for further debug passes. */
return 1;
}
static RenderPass *render_layer_add_debug_pass(RenderResult *rr,
RenderLayer *rl,
int pass_type,
int debug_type,
const char *view)
{
const char *name = RE_debug_pass_name_get(debug_type);
int channels = RE_debug_pass_num_channels_get(debug_type);
RenderPass *rpass = render_layer_add_pass(rr, rl, channels, pass_type, view);
if (rpass == NULL) {
return NULL;
}
rpass->debug_type = debug_type;
BLI_strncpy(rpass->name,
name,
sizeof(rpass->name));
BLI_strncpy(rpass->internal_name, rpass->name, sizeof(rpass->internal_name));
return rpass;
}
int RE_debug_pass_type_get(Render *re)
{
return re->r.debug_pass_type;
}
#endif
/* called by main render as well for parts */
/* will read info from Render *re to define layers */
/* called in threads */
@ -683,89 +344,77 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
if (rr->do_exr_tile)
IMB_exr_add_view(rl->exrhandle, view);
#define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, passtype, viewname) \
#define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, name, viewname, chan_id) \
do { \
if (render_layer_add_pass(rr, rl, channels, passtype, viewname) == NULL) { \
if (render_layer_add_pass(rr, rl, channels, name, viewname, chan_id) == NULL) { \
render_result_free(rr); \
return NULL; \
} \
} while (false)
/* a renderlayer should always have a Combined pass*/
render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view);
render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA");
if (srl->passflag & SCE_PASS_Z)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_Z, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_Z, view, "Z");
if (srl->passflag & SCE_PASS_VECTOR)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, SCE_PASS_VECTOR, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_VECTOR, view, "XYZW");
if (srl->passflag & SCE_PASS_NORMAL)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_NORMAL, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_NORMAL, view, "XYZ");
if (srl->passflag & SCE_PASS_UV)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_UV, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA");
if (srl->passflag & SCE_PASS_RGBA)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, SCE_PASS_RGBA, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RGBA, view, "RGBA");
if (srl->passflag & SCE_PASS_EMIT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_EMIT, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_EMIT, view, "RGB");
if (srl->passflag & SCE_PASS_DIFFUSE)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE, view, "RGB");
if (srl->passflag & SCE_PASS_SPEC)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SPEC, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SPEC, view, "RGB");
if (srl->passflag & SCE_PASS_AO)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_AO, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_AO, view, "RGB");
if (srl->passflag & SCE_PASS_ENVIRONMENT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_ENVIRONMENT, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_ENVIRONMENT, view, "RGB");
if (srl->passflag & SCE_PASS_INDIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_INDIRECT, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_INDIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_SHADOW)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SHADOW, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SHADOW, view, "RGB");
if (srl->passflag & SCE_PASS_REFLECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_REFLECT, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_REFLECT, view, "RGB");
if (srl->passflag & SCE_PASS_REFRACT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_REFRACT, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_REFRACT, view, "RGB");
if (srl->passflag & SCE_PASS_INDEXOB)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_INDEXOB, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXOB, view, "X");
if (srl->passflag & SCE_PASS_INDEXMA)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_INDEXMA, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXMA, view, "X");
if (srl->passflag & SCE_PASS_MIST)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_MIST, view);
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, SCE_PASS_RAYHITS, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RAYHITS, view, "RGB");
if (srl->passflag & SCE_PASS_DIFFUSE_DIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE_DIRECT, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_DIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_DIFFUSE_INDIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE_INDIRECT, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_INDIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_DIFFUSE_COLOR)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE_COLOR, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_COLOR, view, "RGB");
if (srl->passflag & SCE_PASS_GLOSSY_DIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_GLOSSY_DIRECT, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_DIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_GLOSSY_INDIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_GLOSSY_INDIRECT, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_INDIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_GLOSSY_COLOR)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_GLOSSY_COLOR, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_COLOR, view, "RGB");
if (srl->passflag & SCE_PASS_TRANSM_DIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_TRANSM_DIRECT, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_DIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_TRANSM_INDIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_TRANSM_INDIRECT, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_INDIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_TRANSM_COLOR)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_TRANSM_COLOR, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_COLOR, view, "RGB");
if (srl->passflag & SCE_PASS_SUBSURFACE_DIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SUBSURFACE_DIRECT, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_DIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SUBSURFACE_INDIRECT, view);
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_INDIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SUBSURFACE_COLOR, view);
#ifdef WITH_CYCLES_DEBUG
if (BKE_scene_use_new_shading_nodes(re->scene)) {
if (render_layer_add_debug_pass(rr, rl, SCE_PASS_DEBUG,
re->r.debug_pass_type, view) == NULL)
{
render_result_free(rr);
return NULL;
}
}
#endif
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB");
#undef RENDER_LAYER_ADD_PASS_SAFE
}
}
@ -794,7 +443,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
IMB_exr_add_view(rl->exrhandle, view);
/* a renderlayer should always have a Combined pass */
render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view);
render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, view, "RGBA");
}
/* note, this has to be in sync with scene.c */
@ -813,6 +462,60 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
return rr;
}
void render_result_clone_passes(Render *re, RenderResult *rr, const char *viewname)
{
RenderLayer *rl;
RenderPass *main_rp;
for (rl = rr->layers.first; rl; rl = rl->next) {
RenderLayer *main_rl = BLI_findstring(&re->result->layers, rl->name, offsetof(RenderLayer, name));
if (!main_rl) {
continue;
}
for (main_rp = main_rl->passes.first; main_rp; main_rp = main_rp->next) {
if (viewname && viewname[0] && !STREQ(main_rp->view, viewname)) {
continue;
}
/* Compare fullname to make sure that the view also is equal. */
RenderPass *rp = BLI_findstring(&rl->passes, main_rp->fullname, offsetof(RenderPass, fullname));
if (!rp) {
render_layer_add_pass(rr, rl, main_rp->channels, main_rp->name, main_rp->view, main_rp->chan_id);
}
}
}
}
void render_result_add_pass(RenderResult *rr, const char *name, int channels, const char *chan_id, const char *layername, const char *viewname)
{
RenderLayer *rl;
RenderPass *rp;
RenderView *rv;
for (rl = rr->layers.first; rl; rl = rl->next) {
if (layername && layername[0] && !STREQ(rl->name, layername)) {
continue;
}
for (rv = rr->views.first; rv; rv = rv->next) {
const char *view = rv->name;
if (viewname && viewname[0] && !STREQ(view, viewname)) continue;
/* Ensure that the pass doesn't exist yet. */
for (rp = rl->passes.first; rp; rp = rp->next) {
if (!STREQ(rp->name, name)) continue;
if (!STREQ(rp->view, view)) continue;
}
if (!rp) {
render_layer_add_pass(rr, rl, channels, name, view, chan_id);
}
}
}
}
/* 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)
{
@ -830,6 +533,50 @@ RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *part
return lb->first;
}
static int passtype_from_name(const char *name)
{
const char delim[] = {'.', '\0'};
const char *sep, *suf;
int len = BLI_str_partition(name, delim, &sep, &suf);
#define CHECK_PASS(NAME) if (STREQLEN(name, RE_PASSNAME_ ## NAME, len)) return SCE_PASS_ ## NAME
CHECK_PASS(COMBINED);
CHECK_PASS(Z);
CHECK_PASS(VECTOR);
CHECK_PASS(NORMAL);
CHECK_PASS(UV);
CHECK_PASS(RGBA);
CHECK_PASS(EMIT);
CHECK_PASS(DIFFUSE);
CHECK_PASS(SPEC);
CHECK_PASS(SHADOW);
CHECK_PASS(AO);
CHECK_PASS(ENVIRONMENT);
CHECK_PASS(INDIRECT);
CHECK_PASS(REFLECT);
CHECK_PASS(REFRACT);
CHECK_PASS(INDEXOB);
CHECK_PASS(INDEXMA);
CHECK_PASS(MIST);
CHECK_PASS(RAYHITS);
CHECK_PASS(DIFFUSE_DIRECT);
CHECK_PASS(DIFFUSE_INDIRECT);
CHECK_PASS(DIFFUSE_COLOR);
CHECK_PASS(GLOSSY_DIRECT);
CHECK_PASS(GLOSSY_INDIRECT);
CHECK_PASS(GLOSSY_COLOR);
CHECK_PASS(TRANSM_DIRECT);
CHECK_PASS(TRANSM_INDIRECT);
CHECK_PASS(TRANSM_COLOR);
CHECK_PASS(SUBSURFACE_DIRECT);
CHECK_PASS(SUBSURFACE_INDIRECT);
CHECK_PASS(SUBSURFACE_COLOR);
#undef CHECK_PASS
return 0;
}
/* callbacks for render_result_new_from_exr */
static void *ml_addlayer_cb(void *base, const char *str)
{
@ -843,36 +590,30 @@ static void *ml_addlayer_cb(void *base, const char *str)
return rl;
}
static void ml_addpass_cb(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id, const char *view)
static void ml_addpass_cb(void *base, void *lay, const char *name, float *rect, int totchan, const char *chan_id, const char *view)
{
RenderResult *rr = base;
RenderLayer *rl = lay;
RenderPass *rpass = MEM_callocN(sizeof(RenderPass), "loaded pass");
int a;
BLI_addtail(&rl->passes, rpass);
rpass->channels = totchan;
rpass->passtype = passtype_from_name(str, rl->passflag);
if (rpass->passtype == 0)
printf("unknown pass %s\n", str);
rl->passflag |= rpass->passtype;
rl->passflag |= passtype_from_name(name);
/* channel id chars */
for (a = 0; a < totchan; a++)
rpass->chan_id[a] = chan_id[a];
BLI_strncpy(rpass->chan_id, chan_id, sizeof(rpass->chan_id));
rpass->rect = rect;
BLI_strncpy(rpass->name, name, EXR_PASS_MAXNAME);
BLI_strncpy(rpass->view, view, sizeof(rpass->view));
set_pass_full_name(rpass->fullname, name, -1, view, rpass->chan_id);
if (view[0] != '\0') {
BLI_snprintf(rpass->name, sizeof(rpass->name), "%s.%s", str, view);
rpass->view_id = BLI_findstringindex(&rr->views, view, offsetof(RenderView, name));
}
else {
BLI_strncpy(rpass->name, str, sizeof(rpass->name));
rpass->view_id = 0;
}
BLI_strncpy(rpass->view, view, sizeof(rpass->view));
BLI_strncpy(rpass->internal_name, str, sizeof(rpass->internal_name));
}
static void *ml_addview_cb(void *base, const char *str)
@ -912,12 +653,30 @@ static int order_render_passes(const void *a, const void *b)
// 1 if a is after b
RenderPass *rpa = (RenderPass *) a;
RenderPass *rpb = (RenderPass *) b;
unsigned int passtype_a = passtype_from_name(rpa->name);
unsigned int passtype_b = passtype_from_name(rpb->name);
if (rpa->passtype > rpb->passtype)
/* Render passes with default type always go first. */
if (passtype_b && !passtype_a)
return 1;
else if (rpa->passtype < rpb->passtype)
if (passtype_a && !passtype_b)
return 0;
if (passtype_a && passtype_b) {
if (passtype_a > passtype_b)
return 1;
else if (passtype_a < passtype_b)
return 0;
}
else {
int cmp = strncmp(rpa->name, rpb->name, EXR_PASS_MAXNAME);
if (cmp > 0)
return 1;
if (cmp < 0)
return 0;
}
/* they have the same type */
/* left first */
if (STREQ(rpa->view, STEREO_LEFT_NAME))
@ -1049,7 +808,7 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart)
rpass = rpass->next)
{
/* renderresult have all passes, renderpart only the active view's passes */
if (strcmp(rpassp->name, rpass->name) != 0)
if (strcmp(rpassp->fullname, rpass->fullname) != 0)
continue;
do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels);
@ -1061,21 +820,6 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart)
}
}
/* for passes read from files, these have names stored */
static char *make_pass_name(RenderPass *rpass, int chan)
{
static char name[EXR_PASS_MAXNAME];
int len;
BLI_strncpy(name, rpass->name, EXR_PASS_MAXNAME);
len = strlen(name);
name[len] = '.';
name[len + 1] = rpass->chan_id[chan];
name[len + 2] = 0;
return name;
}
/* called from within UI and render pipeline, saves both rendered result as a file-read result
* if multiview is true saves all views in a multiview exr
* else if view is not NULL saves single view
@ -1136,8 +880,10 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil
IMB_exr_add_view(exrhandle, rview->name);
if (rview->rectf) {
char passname[EXR_PASS_MAXNAME];
for (a = 0; a < 4; a++) {
IMB_exr_add_channel(exrhandle, "Composite", name_from_passtype(SCE_PASS_COMBINED, a),
set_pass_name(passname, RE_PASSNAME_COMBINED, a, "RGBA");
IMB_exr_add_channel(exrhandle, RE_PASSNAME_COMBINED, passname,
chan_view, 4, 4 * width, rview->rectf + a,
use_half_float);
}
@ -1150,6 +896,7 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil
/* passes are allocated in sync */
for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
const int xstride = rpass->channels;
char passname[EXR_PASS_MAXNAME];
if (is_mono) {
if (!STREQ(view, rpass->view)) {
@ -1163,16 +910,10 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil
}
for (a = 0; a < xstride; a++) {
if (rpass->passtype) {
IMB_exr_add_channel(exrhandle, rl->name, name_from_passtype(rpass->passtype, a), chan_view,
xstride, xstride * width, rpass->rect + a,
rpass->passtype == SCE_PASS_Z ? false : use_half_float);
}
else {
IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), chan_view,
xstride, xstride * width, rpass->rect + a,
use_half_float);
}
set_pass_name(passname, rpass->name, a, rpass->chan_id);
IMB_exr_add_channel(exrhandle, rl->name, passname, chan_view,
xstride, xstride * width, rpass->rect + a,
STREQ(rpass->name, RE_PASSNAME_Z) ? false : use_half_float);
}
}
}
@ -1281,12 +1022,12 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, cons
for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) {
const int xstride = rpassp->channels;
int a;
char passname[EXR_PASS_MAXNAME];
char fullname[EXR_PASS_MAXNAME];
for (a = 0; a < xstride; a++) {
set_pass_name(passname, rpassp->passtype, a, rpassp->view);
set_pass_full_name(fullname, rpassp->name, a, viewname, rpassp->chan_id);
IMB_exr_set_channel(rl->exrhandle, rlp->name, passname,
IMB_exr_set_channel(rl->exrhandle, rlp->name, fullname,
xstride, xstride * rrpart->rectx, rpassp->rect + a + xstride * offs);
}
}
@ -1449,15 +1190,15 @@ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, c
for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
const int xstride = rpass->channels;
int a;
char passname[EXR_PASS_MAXNAME];
char fullname[EXR_PASS_MAXNAME];
for (a = 0; a < xstride; a++) {
set_pass_name(passname, rpass->passtype, a, rpass->view);
IMB_exr_set_channel(exrhandle, rl->name, passname,
set_pass_full_name(fullname, rpass->name, a, rpass->view, rpass->chan_id);
IMB_exr_set_channel(exrhandle, rl->name, fullname,
xstride, xstride * rectx, rpass->rect + a);
}
set_pass_name(rpass->name, rpass->passtype, -1, rpass->view);
set_pass_full_name(rpass->fullname, rpass->name, -1, rpass->view, rpass->chan_id);
}
}

View File

@ -182,7 +182,7 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in
if (fullsample) {
for (sample=0; sample<totsample; sample++)
if (ps->mask & (1 << sample)) {
float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
addalphaAddfacFloat(pass + od*4, col, har->add);
}
}
@ -217,7 +217,7 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in
if (fullsample) {
for (sample=0; sample<totsample; sample++)
if (!(mask & (1 << sample))) {
float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
addalphaAddfacFloat(pass + od*4, col, har->add);
}
}
@ -228,7 +228,7 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in
col[3]= accol[3];
for (sample=0; sample<totsample; sample++) {
float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
addalphaAddfacFloat(pass + od*4, col, har->add);
}
}
@ -312,7 +312,7 @@ static void halo_tile(RenderPart *pa, RenderLayer *rl)
if ((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) {
if (shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec)) {
for (sample=0; sample<totsample; sample++) {
float * rect= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
float * rect= RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
addalphaAddfacFloat(rect + od*4, col, har->add);
}
}
@ -367,7 +367,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
if (fullsample) {
for (sample=0; sample<totsample; sample++) {
if (ps->mask & (1 << sample)) {
pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
pass += od * 4;
pass[0]+= col[0];
pass[1]+= col[1];
@ -379,7 +379,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
}
else {
fac= ((float)count)/(float)R.osa;
pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
pass = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname);
pass += od * 4;
pass[0]+= fac*col[0];
pass[1]+= fac*col[1];
@ -401,7 +401,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
for (sample=0; sample<totsample; sample++) {
if (!(mask & (1 << sample))) {
pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
pass += od * 4;
pass[0]+= col[0];
pass[1]+= col[1];
@ -413,7 +413,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
}
else {
fac= ((float)R.osa-totsamp)/(float)R.osa;
pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
pass = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname);
pass += od * 4;
pass[0]+= fac*col[0];
pass[1]+= fac*col[1];
@ -433,7 +433,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
renderspothalo(&shi, col, 1.0f);
for (sample=0; sample<totsample; sample++) {
pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
pass += od * 4;
pass[0]+= col[0];
pass[1]+= col[1];
@ -462,101 +462,96 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
float *fp, *col= NULL;
int pixsize= 3;
switch (rpass->passtype) {
case SCE_PASS_COMBINED:
add_filt_fmask(curmask, shr->combined, rpass->rect + 4*offset, rectx);
break;
case SCE_PASS_Z:
fp= rpass->rect + offset;
*fp= shr->z;
break;
case SCE_PASS_RGBA:
col= shr->col;
pixsize= 4;
break;
case SCE_PASS_EMIT:
col= shr->emit;
break;
case SCE_PASS_DIFFUSE:
col= shr->diff;
break;
case SCE_PASS_SPEC:
col= shr->spec;
break;
case SCE_PASS_SHADOW:
col= shr->shad;
break;
case SCE_PASS_AO:
col= shr->ao;
break;
case SCE_PASS_ENVIRONMENT:
col= shr->env;
break;
case SCE_PASS_INDIRECT:
col= shr->indirect;
break;
case SCE_PASS_REFLECT:
col= shr->refl;
break;
case SCE_PASS_REFRACT:
col= shr->refr;
break;
case SCE_PASS_NORMAL:
col= shr->nor;
break;
case SCE_PASS_UV:
/* box filter only, gauss will screwup UV too much */
if (shi->totuv) {
float mult= (float)count_mask(curmask)/(float)R.osa;
fp= rpass->rect + 3*offset;
fp[0]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[0]);
fp[1]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[1]);
fp[2]+= mult;
}
break;
case SCE_PASS_INDEXOB:
/* no filter */
if (shi->vlr) {
fp= rpass->rect + offset;
if (*fp==0.0f)
*fp= (float)shi->obr->ob->index;
}
break;
case SCE_PASS_INDEXMA:
/* no filter */
if (shi->vlr) {
fp= rpass->rect + offset;
if (*fp==0.0f)
*fp= (float)shi->mat->index;
}
break;
case SCE_PASS_MIST:
/* */
col= &shr->mist;
pixsize= 1;
break;
case SCE_PASS_VECTOR:
{
/* add minimum speed in pixel, no filter */
fp= rpass->rect + 4*offset;
if ( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) {
fp[0]= shr->winspeed[0];
fp[1]= shr->winspeed[1];
}
if ( (ABS(shr->winspeed[2]) + ABS(shr->winspeed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) {
fp[2]= shr->winspeed[2];
fp[3]= shr->winspeed[3];
}
break;
}
case SCE_PASS_RAYHITS:
/* */
col= shr->rayhits;
pixsize= 4;
break;
if(STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
add_filt_fmask(curmask, shr->combined, rpass->rect + 4*offset, rectx);
}
else if(STREQ(rpass->name, RE_PASSNAME_Z)) {
fp = rpass->rect + offset;
*fp = shr->z;
}
else 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_UV)) {
/* box filter only, gauss will screwup UV too much */
if (shi->totuv) {
float mult = (float)count_mask(curmask)/(float)R.osa;
fp = rpass->rect + 3*offset;
fp[0]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[0]);
fp[1]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[1]);
fp[2]+= mult;
}
}
else if(STREQ(rpass->name, RE_PASSNAME_INDEXOB)) {
/* no filter */
if (shi->vlr) {
fp = rpass->rect + offset;
if (*fp==0.0f)
*fp = (float)shi->obr->ob->index;
}
}
else if(STREQ(rpass->name, RE_PASSNAME_INDEXMA)) {
/* no filter */
if (shi->vlr) {
fp = rpass->rect + offset;
if (*fp==0.0f)
*fp = (float)shi->mat->index;
}
}
else if(STREQ(rpass->name, RE_PASSNAME_MIST)) {
/* */
col = &shr->mist;
pixsize = 1;
}
else if(STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
/* add minimum speed in pixel, no filter */
fp = rpass->rect + 4*offset;
if ( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) {
fp[0] = shr->winspeed[0];
fp[1] = shr->winspeed[1];
}
if ( (ABS(shr->winspeed[2]) + ABS(shr->winspeed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) {
fp[2] = shr->winspeed[2];
fp[3] = shr->winspeed[3];
}
}
else if(STREQ(rpass->name, RE_PASSNAME_RAYHITS)) {
/* */
col = shr->rayhits;
pixsize= 4;
}
if (col) {
fp= rpass->rect + pixsize*offset;
add_filt_fmask_pixsize(curmask, col, fp, rectx, pixsize);
@ -574,86 +569,85 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult
float *col= NULL, uvcol[3];
int a, pixsize= 3;
switch (rpass->passtype) {
case SCE_PASS_COMBINED:
/* copy combined to use for preview */
copy_v4_v4(rpass->rect + 4*offset, shr->combined);
break;
case SCE_PASS_Z:
fp= rpass->rect + offset;
*fp= shr->z;
break;
case SCE_PASS_RGBA:
col= shr->col;
pixsize= 4;
break;
case SCE_PASS_EMIT:
col= shr->emit;
break;
case SCE_PASS_DIFFUSE:
col= shr->diff;
break;
case SCE_PASS_SPEC:
col= shr->spec;
break;
case SCE_PASS_SHADOW:
col= shr->shad;
break;
case SCE_PASS_AO:
col= shr->ao;
break;
case SCE_PASS_ENVIRONMENT:
col= shr->env;
break;
case SCE_PASS_INDIRECT:
col= shr->indirect;
break;
case SCE_PASS_REFLECT:
col= shr->refl;
break;
case SCE_PASS_REFRACT:
col= shr->refr;
break;
case SCE_PASS_NORMAL:
col= shr->nor;
break;
case SCE_PASS_UV:
if (shi->totuv) {
uvcol[0]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[0];
uvcol[1]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[1];
uvcol[2]= 1.0f;
col= uvcol;
}
break;
case SCE_PASS_VECTOR:
col= shr->winspeed;
pixsize= 4;
break;
case SCE_PASS_INDEXOB:
if (shi->vlr) {
fp= rpass->rect + offset;
*fp= (float)shi->obr->ob->index;
}
break;
case SCE_PASS_INDEXMA:
if (shi->vlr) {
fp= rpass->rect + offset;
*fp= (float)shi->mat->index;
}
break;
case SCE_PASS_MIST:
fp= rpass->rect + offset;
*fp= shr->mist;
break;
case SCE_PASS_RAYHITS:
col= shr->rayhits;
pixsize= 4;
break;
if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
/* copy combined to use for preview */
copy_v4_v4(rpass->rect + 4*offset, shr->combined);
}
else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
fp = rpass->rect + offset;
*fp = shr->z;
}
else 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_UV)) {
if (shi->totuv) {
uvcol[0] = 0.5f + 0.5f*shi->uv[shi->actuv].uv[0];
uvcol[1] = 0.5f + 0.5f*shi->uv[shi->actuv].uv[1];
uvcol[2] = 1.0f;
col = uvcol;
}
}
else if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
col = shr->winspeed;
pixsize = 4;
}
else if (STREQ(rpass->name, RE_PASSNAME_INDEXOB)) {
if (shi->vlr) {
fp = rpass->rect + offset;
*fp = (float)shi->obr->ob->index;
}
}
else if (STREQ(rpass->name, RE_PASSNAME_INDEXMA)) {
if (shi->vlr) {
fp = rpass->rect + offset;
*fp = (float)shi->mat->index;
}
}
else if (STREQ(rpass->name, RE_PASSNAME_MIST)) {
fp = rpass->rect + offset;
*fp = shr->mist;
}
else if (STREQ(rpass->name, RE_PASSNAME_RAYHITS)) {
col = shr->rayhits;
pixsize = 4;
}
if (col) {
fp= rpass->rect + pixsize*offset;
fp = rpass->rect + pixsize*offset;
for (a=0; a<pixsize; a++)
fp[a]= col[a];
fp[a] = col[a];
}
}
}
@ -696,7 +690,7 @@ static void sky_tile(RenderPart *pa, RenderLayer *rl)
bool done = false;
for (sample= 0; sample<totsample; sample++) {
float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
pass += od;
if (pass[3]<1.0f) {
@ -737,7 +731,7 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl)
/* check that z pass is enabled */
if (pa->rectz==NULL) return;
for (zpass= rl->passes.first; zpass; zpass= zpass->next)
if (zpass->passtype==SCE_PASS_Z)
if (STREQ(zpass->name, RE_PASSNAME_Z))
break;
if (zpass==NULL) return;
@ -758,8 +752,8 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl)
int sample;
for (sample=0; sample<totsample; sample++) {
const float *zrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_Z, R.viewname) + od;
float *rgbrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname) + 4*od;
const float *zrect = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_Z, R.viewname) + od;
float *rgbrect = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname) + 4*od;
float rgb[3] = {0};
bool done = false;
@ -994,7 +988,7 @@ static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl)
return;
for (sample= 0; sample<totsample; sample++) {
float *rectf = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
float *rectf = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) {
rectf[0] = MAX2(rectf[0], 0.0f);
@ -1076,7 +1070,7 @@ static void reset_sky_speed(RenderPart *pa, RenderLayer *rl)
totsample= get_sample_layers(pa, rl, rlpp);
for (sample= 0; sample<totsample; sample++) {
fp= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_VECTOR, R.viewname);
fp= RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_VECTOR, R.viewname);
if (fp==NULL) break;
for (a= 4*pa->rectx*pa->recty - 1; a>=0; a--)
@ -1187,7 +1181,7 @@ void zbufshadeDA_tile(RenderPart *pa)
pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
for (rl= rr->layers.first; rl; rl= rl->next) {
float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
float *rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname);
if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK))
pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask");
@ -1339,7 +1333,7 @@ void zbufshade_tile(RenderPart *pa)
pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
for (rl= rr->layers.first; rl; rl= rl->next) {
float *rect= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
float *rect= RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname);
if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK))
pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask");
@ -1676,7 +1670,7 @@ void zbufshade_sss_tile(RenderPart *pa)
return;
}
fcol= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
fcol= RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname);
co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo");
color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor");
@ -1969,7 +1963,7 @@ void add_halo_flare(Render *re)
if ((rl->layflag & SCE_LAY_HALO) == 0)
continue;
rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname);
rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, re->viewname);
if (rect==NULL)
continue;
@ -1998,3 +1992,37 @@ void add_halo_flare(Render *re)
}
}
void render_internal_update_passes(RenderEngine *engine, Scene *scene, SceneRenderLayer *srl)
{
int type;
RE_engine_register_pass(engine, scene, srl, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA);
#define CHECK_PASS(name, channels, chanid) \
if (srl->passflag & (SCE_PASS_ ## name)) { \
if (channels == 4) type = SOCK_RGBA; \
else if (channels == 3) type = SOCK_VECTOR; \
else type = SOCK_FLOAT; \
RE_engine_register_pass(engine, scene, srl, RE_PASSNAME_ ## name, channels, chanid, type); \
}
CHECK_PASS(Z, 1, "Z");
CHECK_PASS(VECTOR, 4, "XYZW");
CHECK_PASS(NORMAL, 3, "XYZ");
CHECK_PASS(UV, 3, "UVA");
CHECK_PASS(RGBA, 4, "RGBA");
CHECK_PASS(EMIT, 3, "RGB");
CHECK_PASS(DIFFUSE, 3, "RGB");
CHECK_PASS(SPEC, 3, "RGB");
CHECK_PASS(AO, 3, "RGB");
CHECK_PASS(ENVIRONMENT, 3, "RGB");
CHECK_PASS(INDIRECT, 3, "RGB");
CHECK_PASS(SHADOW, 3, "RGB");
CHECK_PASS(REFLECT, 3, "RGB");
CHECK_PASS(REFRACT, 3, "RGB");
CHECK_PASS(INDEXOB, 1, "X");
CHECK_PASS(INDEXMA, 1, "X");
CHECK_PASS(MIST, 1, "Z");
#undef CHECK_PASS
}

View File

@ -3494,7 +3494,7 @@ static void add_transp_speed(RenderLayer *rl, int offset, float speed[4], float
RenderPass *rpass;
for (rpass= rl->passes.first; rpass; rpass= rpass->next) {
if (rpass->passtype==SCE_PASS_VECTOR) {
if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
float *fp= rpass->rect + 4*offset;
if (speed==NULL) {
@ -3528,7 +3528,7 @@ static void add_transp_obindex(RenderLayer *rl, int offset, Object *ob)
RenderPass *rpass;
for (rpass= rl->passes.first; rpass; rpass= rpass->next) {
if (rpass->passtype == SCE_PASS_INDEXOB) {
if (STREQ(rpass->name, RE_PASSNAME_INDEXOB)) {
float *fp= rpass->rect + offset;
*fp= (float)ob->index;
break;
@ -3541,7 +3541,7 @@ static void add_transp_material_index(RenderLayer *rl, int offset, Material *mat
RenderPass *rpass;
for (rpass= rl->passes.first; rpass; rpass= rpass->next) {
if (rpass->passtype == SCE_PASS_INDEXMA) {
if (STREQ(rpass->name, RE_PASSNAME_INDEXMA)) {
float *fp= rpass->rect + offset;
*fp= (float)mat->index;
break;
@ -3558,78 +3558,74 @@ static void merge_transp_passes(RenderLayer *rl, ShadeResult *shr)
int delta= sizeof(ShadeResult)/4;
for (rpass= rl->passes.first; rpass; rpass= rpass->next) {
float *col= NULL;
int pixsize= 3;
float *col = NULL;
int pixsize = 3;
switch (rpass->passtype) {
case SCE_PASS_RGBA:
col= shr->col;
pixsize= 4;
break;
case SCE_PASS_EMIT:
col= shr->emit;
break;
case SCE_PASS_DIFFUSE:
col= shr->diff;
break;
case SCE_PASS_SPEC:
col= shr->spec;
break;
case SCE_PASS_SHADOW:
col= shr->shad;
break;
case SCE_PASS_AO:
col= shr->ao;
break;
case SCE_PASS_ENVIRONMENT:
col= shr->env;
break;
case SCE_PASS_INDIRECT:
col= shr->indirect;
break;
case SCE_PASS_REFLECT:
col= shr->refl;
break;
case SCE_PASS_REFRACT:
col= shr->refr;
break;
case SCE_PASS_NORMAL:
col= shr->nor;
break;
case SCE_PASS_MIST:
col= &shr->mist;
pixsize= 1;
break;
case SCE_PASS_Z:
col= &shr->z;
pixsize= 1;
break;
case SCE_PASS_VECTOR:
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++) {
{
ShadeResult *shr_t= shr+1;
float *fp= shr->winspeed; /* was initialized */
int samp;
if (shr_t->combined[3] > 0.0f) {
const float *speed = shr_t->winspeed;
/* 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 ( (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;
}
}
if (col) {
const float *fp= col+delta;
int samp;
@ -3661,53 +3657,51 @@ static void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, flo
float *fp, *col= NULL;
int pixsize= 3;
switch (rpass->passtype) {
case SCE_PASS_Z:
fp= rpass->rect + offset;
if (shr->z < *fp)
*fp= shr->z;
break;
case SCE_PASS_RGBA:
fp= rpass->rect + 4*offset;
addAlphaOverFloat(fp, shr->col);
break;
case SCE_PASS_EMIT:
col= shr->emit;
break;
case SCE_PASS_DIFFUSE:
col= shr->diff;
break;
case SCE_PASS_SPEC:
col= shr->spec;
break;
case SCE_PASS_SHADOW:
col= shr->shad;
break;
case SCE_PASS_AO:
col= shr->ao;
break;
case SCE_PASS_ENVIRONMENT:
col= shr->env;
break;
case SCE_PASS_INDIRECT:
col= shr->indirect;
break;
case SCE_PASS_REFLECT:
col= shr->refl;
break;
case SCE_PASS_REFRACT:
col= shr->refr;
break;
case SCE_PASS_NORMAL:
col= shr->nor;
break;
case SCE_PASS_MIST:
col= &shr->mist;
pixsize= 1;
break;
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) {
if (col) {
fp= rpass->rect + pixsize*offset;
fp[0]= col[0] + (1.0f-alpha)*fp[0];
if (pixsize==3) {
@ -3964,7 +3958,7 @@ static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf
float *fp, *col;
int a;
fp = RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR, R.viewname);
fp = RE_RenderLayerGetPass(rl, RE_PASSNAME_VECTOR, R.viewname);
if (fp==NULL) return;
col= rectf+3;
@ -4058,7 +4052,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
/* zero alpha pixels get speed vector max again */
if (addpassflag & SCE_PASS_VECTOR)
if (rl->layflag & SCE_LAY_SOLID) {
float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
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 */
@ -4246,7 +4240,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
if (alpha != 0.0f) {
RenderLayer *rl_other = ssamp.rlpp[a];
float *rect = RE_RenderLayerGetPass(rl_other , SCE_PASS_COMBINED, R.viewname);
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);

View File

@ -230,7 +230,7 @@ void EDBM_mesh_normals_update(struct BMEditMesh *em) RET_NONE
void *g_system;
bool EDBM_mtexpoly_check(struct BMEditMesh *em) RET_ZERO
float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL
float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, const char *name, const char *viewname) RET_NULL
float RE_filter_value(int type, float x) RET_ZERO
struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name) RET_NULL
void RE_texture_rng_init() RET_NONE
@ -244,6 +244,7 @@ float RE_engine_get_camera_shift_x(struct RenderEngine *engine, struct Object *c
int RE_engine_get_spherical_stereo(struct RenderEngine *engine, struct Object *camera) RET_ZERO
void RE_SetActiveRenderView(struct Render *re, const char *viewname) RET_NONE
struct RenderPass *RE_pass_find_by_name(volatile struct RenderLayer *rl, const char *name, const char *viewname) RET_NULL
struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL
bool RE_HasFakeLayer(RenderResult *res) RET_ZERO
@ -653,6 +654,7 @@ struct RenderData *RE_engine_get_render_data(struct Render *re) RET_NULL
void RE_engine_update_result(struct RenderEngine *engine, struct RenderResult *result) RET_NONE
void RE_engine_update_progress(struct RenderEngine *engine, float progress) RET_NONE
void RE_engine_set_error_message(RenderEngine *engine, const char *msg) RET_NONE
void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername) RET_NONE
void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int merge_results) RET_NONE
void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info) RET_NONE
void RE_layer_load_from_file(struct RenderLayer *layer, struct ReportList *reports, const char *filename, int x, int y) RET_NONE
@ -678,6 +680,7 @@ void RE_point_density_free(struct PointDensity *pd) RET_NONE
void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]) RET_NONE
void RE_FreeAllPersistentData(void) RET_NONE
float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) RET_ZERO
void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int channels, const char *chanid, int type) RET_NONE
/* python */
struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet) RET_NULL