Merge branch 'master' into blender2.8
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -208,3 +208,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')
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -78,7 +78,7 @@ def use_cuda(context):
|
||||
def use_branched_path(context):
|
||||
cscene = context.scene.cycles
|
||||
|
||||
return (cscene.progressive == 'BRANCHED_PATH' and not use_opencl(context))
|
||||
return (cscene.progressive == 'BRANCHED_PATH')
|
||||
|
||||
|
||||
def use_sample_all_lights(context):
|
||||
@@ -156,7 +156,6 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
|
||||
|
||||
row = layout.row()
|
||||
sub = row.row()
|
||||
sub.active = get_device_type(context) != 'OPENCL' or use_cpu(context)
|
||||
sub.prop(cscene, "progressive", text="")
|
||||
row.prop(cscene, "use_square_samples")
|
||||
|
||||
@@ -477,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()
|
||||
|
||||
@@ -528,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):
|
||||
|
||||
@@ -776,17 +776,17 @@ static void ExportCurveTriangleVcol(ParticleCurveData *CData,
|
||||
|
||||
for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
|
||||
for(int section = 0; section < resol; section++) {
|
||||
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
|
||||
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
|
||||
vertexindex++;
|
||||
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
|
||||
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
|
||||
vertexindex++;
|
||||
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
|
||||
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
|
||||
vertexindex++;
|
||||
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
|
||||
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
|
||||
vertexindex++;
|
||||
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
|
||||
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
|
||||
vertexindex++;
|
||||
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
|
||||
cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
|
||||
vertexindex++;
|
||||
}
|
||||
}
|
||||
@@ -1004,7 +1004,7 @@ void BlenderSync::sync_curves(Mesh *mesh,
|
||||
|
||||
for(size_t curve = 0; curve < CData.curve_vcol.size(); curve++)
|
||||
if(!(CData.curve_keynum[curve] <= 1 || CData.curve_length[curve] == 0.0f))
|
||||
fdata[i++] = color_srgb_to_scene_linear(CData.curve_vcol[curve]);
|
||||
fdata[i++] = color_srgb_to_scene_linear_v3(CData.curve_vcol[curve]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,7 +356,7 @@ static void attr_create_vertex_color(Scene *scene,
|
||||
int n = p->loop_total();
|
||||
for(int i = 0; i < n; i++) {
|
||||
float3 color = get_float3(l->data[p->loop_start() + i].color());
|
||||
*(cdata++) = color_float_to_byte(color_srgb_to_scene_linear(color));
|
||||
*(cdata++) = color_float_to_byte(color_srgb_to_scene_linear_v3(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -380,11 +380,11 @@ static void attr_create_vertex_color(Scene *scene,
|
||||
face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);
|
||||
|
||||
uchar4 colors[4];
|
||||
colors[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1())));
|
||||
colors[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2())));
|
||||
colors[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3())));
|
||||
colors[0] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color1())));
|
||||
colors[1] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color2())));
|
||||
colors[2] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color3())));
|
||||
if(nverts[i] == 4) {
|
||||
colors[3] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4())));
|
||||
colors[3] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color4())));
|
||||
}
|
||||
|
||||
cdata[0] = colors[tri_a[0]];
|
||||
|
||||
@@ -815,6 +815,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);
|
||||
|
||||
@@ -247,90 +247,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();
|
||||
@@ -487,22 +403,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;
|
||||
@@ -757,19 +662,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]);
|
||||
}
|
||||
|
||||
@@ -481,6 +481,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,
|
||||
|
||||
@@ -68,6 +68,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,
|
||||
@@ -94,6 +96,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);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "kernel/kernel_types.h"
|
||||
#include "kernel/split/kernel_split_data_types.h"
|
||||
|
||||
#include "util/util_logging.h"
|
||||
#include "util/util_time.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@@ -38,6 +39,8 @@ DeviceSplitKernel::DeviceSplitKernel(Device *device) : device(device)
|
||||
kernel_do_volume = NULL;
|
||||
kernel_queue_enqueue = NULL;
|
||||
kernel_indirect_background = NULL;
|
||||
kernel_shader_setup = NULL;
|
||||
kernel_shader_sort = NULL;
|
||||
kernel_shader_eval = NULL;
|
||||
kernel_holdout_emission_blurring_pathtermination_ao = NULL;
|
||||
kernel_subsurface_scatter = NULL;
|
||||
@@ -63,6 +66,8 @@ DeviceSplitKernel::~DeviceSplitKernel()
|
||||
delete kernel_do_volume;
|
||||
delete kernel_queue_enqueue;
|
||||
delete kernel_indirect_background;
|
||||
delete kernel_shader_setup;
|
||||
delete kernel_shader_sort;
|
||||
delete kernel_shader_eval;
|
||||
delete kernel_holdout_emission_blurring_pathtermination_ao;
|
||||
delete kernel_subsurface_scatter;
|
||||
@@ -88,6 +93,8 @@ bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures& requested_fe
|
||||
LOAD_KERNEL(do_volume);
|
||||
LOAD_KERNEL(queue_enqueue);
|
||||
LOAD_KERNEL(indirect_background);
|
||||
LOAD_KERNEL(shader_setup);
|
||||
LOAD_KERNEL(shader_sort);
|
||||
LOAD_KERNEL(shader_eval);
|
||||
LOAD_KERNEL(holdout_emission_blurring_pathtermination_ao);
|
||||
LOAD_KERNEL(subsurface_scatter);
|
||||
@@ -108,6 +115,9 @@ bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures& requested_fe
|
||||
size_t DeviceSplitKernel::max_elements_for_max_buffer_size(device_memory& kg, device_memory& data, uint64_t max_buffer_size)
|
||||
{
|
||||
uint64_t size_per_element = state_buffer_size(kg, data, 1024) / 1024;
|
||||
VLOG(1) << "Split state element size: "
|
||||
<< string_human_readable_number(size_per_element) << " bytes. ("
|
||||
<< string_human_readable_size(size_per_element) << ").";
|
||||
return max_buffer_size / size_per_element;
|
||||
}
|
||||
|
||||
@@ -237,9 +247,12 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
|
||||
ENQUEUE_SPLIT_KERNEL(do_volume, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(indirect_background, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(shader_setup, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(shader_sort, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(shader_eval, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(holdout_emission_blurring_pathtermination_ao, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(subsurface_scatter, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(direct_lighting, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(shadow_blocked_ao, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(shadow_blocked_dl, global_size, local_size);
|
||||
|
||||
@@ -61,6 +61,8 @@ private:
|
||||
SplitKernelFunction *kernel_do_volume;
|
||||
SplitKernelFunction *kernel_queue_enqueue;
|
||||
SplitKernelFunction *kernel_indirect_background;
|
||||
SplitKernelFunction *kernel_shader_setup;
|
||||
SplitKernelFunction *kernel_shader_sort;
|
||||
SplitKernelFunction *kernel_shader_eval;
|
||||
SplitKernelFunction *kernel_holdout_emission_blurring_pathtermination_ao;
|
||||
SplitKernelFunction *kernel_subsurface_scatter;
|
||||
|
||||
@@ -31,19 +31,16 @@ CCL_NAMESPACE_BEGIN
|
||||
/* Work around AMD driver hangs by ensuring each command is finished before doing anything else. */
|
||||
# undef clEnqueueNDRangeKernel
|
||||
# define clEnqueueNDRangeKernel(a, b, c, d, e, f, g, h, i) \
|
||||
clFinish(a); \
|
||||
CLEW_GET_FUN(__clewEnqueueNDRangeKernel)(a, b, c, d, e, f, g, h, i); \
|
||||
clFinish(a);
|
||||
|
||||
# undef clEnqueueWriteBuffer
|
||||
# define clEnqueueWriteBuffer(a, b, c, d, e, f, g, h, i) \
|
||||
clFinish(a); \
|
||||
CLEW_GET_FUN(__clewEnqueueWriteBuffer)(a, b, c, d, e, f, g, h, i); \
|
||||
clFinish(a);
|
||||
|
||||
# undef clEnqueueReadBuffer
|
||||
# define clEnqueueReadBuffer(a, b, c, d, e, f, g, h, i) \
|
||||
clFinish(a); \
|
||||
CLEW_GET_FUN(__clewEnqueueReadBuffer)(a, b, c, d, e, f, g, h, i); \
|
||||
clFinish(a);
|
||||
#endif /* CYCLES_DISABLE_DRIVER_WORKAROUNDS */
|
||||
|
||||
@@ -21,6 +21,8 @@ set(SRC
|
||||
kernels/opencl/kernel_lamp_emission.cl
|
||||
kernels/opencl/kernel_do_volume.cl
|
||||
kernels/opencl/kernel_indirect_background.cl
|
||||
kernels/opencl/kernel_shader_setup.cl
|
||||
kernels/opencl/kernel_shader_sort.cl
|
||||
kernels/opencl/kernel_shader_eval.cl
|
||||
kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl
|
||||
kernels/opencl/kernel_subsurface_scatter.cl
|
||||
@@ -235,6 +237,7 @@ set(SRC_UTIL_HEADERS
|
||||
)
|
||||
|
||||
set(SRC_SPLIT_HEADERS
|
||||
split/kernel_branched.h
|
||||
split/kernel_buffer_update.h
|
||||
split/kernel_data_init.h
|
||||
split/kernel_direct_lighting.h
|
||||
@@ -247,6 +250,8 @@ set(SRC_SPLIT_HEADERS
|
||||
split/kernel_path_init.h
|
||||
split/kernel_queue_enqueue.h
|
||||
split/kernel_scene_intersect.h
|
||||
split/kernel_shader_setup.h
|
||||
split/kernel_shader_sort.h
|
||||
split/kernel_shader_eval.h
|
||||
split/kernel_shadow_blocked_ao.h
|
||||
split/kernel_shadow_blocked_dl.h
|
||||
@@ -456,6 +461,8 @@ delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_scene_interse
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_lamp_emission.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_do_volume.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_indirect_background.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shader_setup.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shader_sort.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shader_eval.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_subsurface_scatter.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
|
||||
@@ -58,7 +58,7 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg,
|
||||
ShaderData *sd,
|
||||
ShaderData *emission_sd,
|
||||
PathRadiance *L,
|
||||
PathState *state,
|
||||
ccl_addr_space PathState *state,
|
||||
RNG *rng,
|
||||
float3 throughput,
|
||||
float3 ao_alpha)
|
||||
@@ -98,6 +98,8 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg,
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __SPLIT_KERNEL__
|
||||
|
||||
ccl_device void kernel_path_indirect(KernelGlobals *kg,
|
||||
ShaderData *sd,
|
||||
ShaderData *emission_sd,
|
||||
@@ -818,5 +820,7 @@ ccl_device void kernel_path_trace(KernelGlobals *kg,
|
||||
path_rng_end(kg, rng_state, rng);
|
||||
}
|
||||
|
||||
#endif /* __SPLIT_KERNEL__ */
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg,
|
||||
ShaderData *sd,
|
||||
ShaderData *emission_sd,
|
||||
PathRadiance *L,
|
||||
PathState *state,
|
||||
ccl_addr_space PathState *state,
|
||||
RNG *rng,
|
||||
float3 throughput)
|
||||
{
|
||||
@@ -65,6 +65,7 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg,
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __SPLIT_KERNEL__
|
||||
|
||||
/* bounce off surface and integrate indirect light */
|
||||
ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGlobals *kg,
|
||||
@@ -648,6 +649,8 @@ ccl_device void kernel_branched_path_trace(KernelGlobals *kg,
|
||||
path_rng_end(kg, rng_state, rng);
|
||||
}
|
||||
|
||||
#endif /* __SPLIT_KERNEL__ */
|
||||
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -155,7 +155,7 @@ ccl_device bool kernel_branched_path_surface_bounce(
|
||||
ccl_addr_space float3 *throughput,
|
||||
ccl_addr_space PathState *state,
|
||||
PathRadiance *L,
|
||||
Ray *ray)
|
||||
ccl_addr_space Ray *ray)
|
||||
{
|
||||
/* sample BSDF */
|
||||
float bsdf_pdf;
|
||||
|
||||
@@ -417,9 +417,8 @@ ccl_device_noinline void subsurface_scatter_multi_setup(
|
||||
subsurface_scatter_setup_diffuse_bsdf(sd, sc, weight, true, N);
|
||||
}
|
||||
|
||||
#ifndef __SPLIT_KERNEL__
|
||||
/* subsurface scattering step, from a point on the surface to another nearby point on the same object */
|
||||
ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, PathState *state,
|
||||
ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_global PathState *state,
|
||||
int state_flag, ShaderClosure *sc, uint *lcg_state, float disk_u, float disk_v, bool all)
|
||||
{
|
||||
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
@@ -507,7 +506,6 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, PathS
|
||||
/* setup diffuse bsdf */
|
||||
subsurface_scatter_setup_diffuse_bsdf(sd, sc, eval, (ss_isect.num_hits > 0), N);
|
||||
}
|
||||
#endif /* ! __SPLIT_KERNEL__ */
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -64,6 +64,18 @@ CCL_NAMESPACE_BEGIN
|
||||
# define WORK_POOL_SIZE WORK_POOL_SIZE_CPU
|
||||
#endif
|
||||
|
||||
|
||||
#define SHADER_SORT_BLOCK_SIZE 2048
|
||||
|
||||
#ifdef __KERNEL_OPENCL__
|
||||
# define SHADER_SORT_LOCAL_SIZE 64
|
||||
#elif defined(__KERNEL_CUDA__)
|
||||
# define SHADER_SORT_LOCAL_SIZE 32
|
||||
#else
|
||||
# define SHADER_SORT_LOCAL_SIZE 1
|
||||
#endif
|
||||
|
||||
|
||||
/* device capabilities */
|
||||
#ifdef __KERNEL_CPU__
|
||||
# ifdef __KERNEL_SSE2__
|
||||
@@ -71,22 +83,18 @@ CCL_NAMESPACE_BEGIN
|
||||
# endif
|
||||
# define __KERNEL_SHADING__
|
||||
# define __KERNEL_ADV_SHADING__
|
||||
# ifndef __SPLIT_KERNEL__
|
||||
# define __BRANCHED_PATH__
|
||||
# endif
|
||||
# define __BRANCHED_PATH__
|
||||
# ifdef WITH_OSL
|
||||
# define __OSL__
|
||||
# endif
|
||||
# define __SUBSURFACE__
|
||||
# define __PRINCIPLED__
|
||||
# define __SUBSURFACE__
|
||||
# define __CMJ__
|
||||
# define __VOLUME__
|
||||
# define __VOLUME_SCATTER__
|
||||
# define __SHADOW_RECORD_ALL__
|
||||
# ifndef __SPLIT_KERNEL__
|
||||
# define __VOLUME_DECOUPLED__
|
||||
# define __VOLUME_RECORD_ALL__
|
||||
# endif
|
||||
# define __VOLUME_DECOUPLED__
|
||||
# define __VOLUME_RECORD_ALL__
|
||||
#endif /* __KERNEL_CPU__ */
|
||||
|
||||
#ifdef __KERNEL_CUDA__
|
||||
@@ -138,6 +146,7 @@ CCL_NAMESPACE_BEGIN
|
||||
# define __VOLUME_SCATTER__
|
||||
# define __SHADOW_RECORD_ALL__
|
||||
# define __CMJ__
|
||||
# define __BRANCHED_PATH__
|
||||
# endif /* __KERNEL_OPENCL_AMD__ */
|
||||
|
||||
# ifdef __KERNEL_OPENCL_INTEL_CPU__
|
||||
@@ -1300,7 +1309,6 @@ typedef ccl_addr_space struct DebugData {
|
||||
* Queue 3 - Shadow ray cast kernel - AO
|
||||
* Queeu 4 - Shadow ray cast kernel - direct lighting
|
||||
*/
|
||||
#define NUM_QUEUES 4
|
||||
|
||||
/* Queue names */
|
||||
enum QueueNumber {
|
||||
@@ -1313,22 +1321,40 @@ enum QueueNumber {
|
||||
* 3. Rays to be regenerated
|
||||
* are enqueued here.
|
||||
*/
|
||||
QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS = 1,
|
||||
QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
|
||||
|
||||
/* All rays for which a shadow ray should be cast to determine radiance
|
||||
* contribution for AO are enqueued here.
|
||||
*/
|
||||
QUEUE_SHADOW_RAY_CAST_AO_RAYS = 2,
|
||||
QUEUE_SHADOW_RAY_CAST_AO_RAYS,
|
||||
|
||||
/* All rays for which a shadow ray should be cast to determine radiance
|
||||
* contributing for direct lighting are enqueued here.
|
||||
*/
|
||||
QUEUE_SHADOW_RAY_CAST_DL_RAYS = 3,
|
||||
QUEUE_SHADOW_RAY_CAST_DL_RAYS,
|
||||
|
||||
/* Rays sorted according to shader->id */
|
||||
QUEUE_SHADER_SORTED_RAYS,
|
||||
|
||||
#ifdef __BRANCHED_PATH__
|
||||
/* All rays moving to next iteration of the indirect loop for light */
|
||||
QUEUE_LIGHT_INDIRECT_ITER,
|
||||
# ifdef __VOLUME__
|
||||
/* All rays moving to next iteration of the indirect loop for volumes */
|
||||
QUEUE_VOLUME_INDIRECT_ITER,
|
||||
# endif
|
||||
# ifdef __SUBSURFACE__
|
||||
/* All rays moving to next iteration of the indirect loop for subsurface */
|
||||
QUEUE_SUBSURFACE_INDIRECT_ITER,
|
||||
# endif
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
|
||||
NUM_QUEUES
|
||||
};
|
||||
|
||||
/* We use RAY_STATE_MASK to get ray_state (enums 0 to 5) */
|
||||
#define RAY_STATE_MASK 0x007
|
||||
#define RAY_FLAG_MASK 0x0F8
|
||||
/* We use RAY_STATE_MASK to get ray_state */
|
||||
#define RAY_STATE_MASK 0x0F
|
||||
#define RAY_FLAG_MASK 0xF0
|
||||
enum RayState {
|
||||
RAY_INVALID = 0,
|
||||
/* Denotes ray is actively involved in path-iteration. */
|
||||
@@ -1343,14 +1369,22 @@ enum RayState {
|
||||
RAY_TO_REGENERATE,
|
||||
/* Denotes ray has been regenerated */
|
||||
RAY_REGENERATED,
|
||||
/* Flag's ray has to execute shadow blocked function in AO part */
|
||||
RAY_SHADOW_RAY_CAST_AO = 16,
|
||||
/* Flag's ray has to execute shadow blocked function in direct lighting part. */
|
||||
RAY_SHADOW_RAY_CAST_DL = 32,
|
||||
/* Denotes ray is moving to next iteration of the branched indirect loop */
|
||||
RAY_LIGHT_INDIRECT_NEXT_ITER,
|
||||
RAY_VOLUME_INDIRECT_NEXT_ITER,
|
||||
RAY_SUBSURFACE_INDIRECT_NEXT_ITER,
|
||||
|
||||
/* Ray flags */
|
||||
|
||||
/* Flags to denote that the ray is currently evaluating the branched indirect loop */
|
||||
RAY_BRANCHED_LIGHT_INDIRECT = (1 << 4),
|
||||
RAY_BRANCHED_VOLUME_INDIRECT = (1 << 5),
|
||||
RAY_BRANCHED_SUBSURFACE_INDIRECT = (1 << 6),
|
||||
RAY_BRANCHED_INDIRECT = (RAY_BRANCHED_LIGHT_INDIRECT | RAY_BRANCHED_VOLUME_INDIRECT | RAY_BRANCHED_SUBSURFACE_INDIRECT),
|
||||
};
|
||||
|
||||
#define ASSIGN_RAY_STATE(ray_state, ray_index, state) (ray_state[ray_index] = ((ray_state[ray_index] & RAY_FLAG_MASK) | state))
|
||||
#define IS_STATE(ray_state, ray_index, state) ((ray_state[ray_index] & RAY_STATE_MASK) == state)
|
||||
#define IS_STATE(ray_state, ray_index, state) ((ray_index) != QUEUE_EMPTY_SLOT && ((ray_state)[(ray_index)] & RAY_STATE_MASK) == (state))
|
||||
#define ADD_RAY_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] = (ray_state[ray_index] | flag))
|
||||
#define REMOVE_RAY_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] = (ray_state[ray_index] & (~flag)))
|
||||
#define IS_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] & flag)
|
||||
|
||||
@@ -77,6 +77,8 @@ DECLARE_SPLIT_KERNEL_FUNCTION(lamp_emission)
|
||||
DECLARE_SPLIT_KERNEL_FUNCTION(do_volume)
|
||||
DECLARE_SPLIT_KERNEL_FUNCTION(queue_enqueue)
|
||||
DECLARE_SPLIT_KERNEL_FUNCTION(indirect_background)
|
||||
DECLARE_SPLIT_KERNEL_FUNCTION(shader_setup)
|
||||
DECLARE_SPLIT_KERNEL_FUNCTION(shader_sort)
|
||||
DECLARE_SPLIT_KERNEL_FUNCTION(shader_eval)
|
||||
DECLARE_SPLIT_KERNEL_FUNCTION(holdout_emission_blurring_pathtermination_ao)
|
||||
DECLARE_SPLIT_KERNEL_FUNCTION(subsurface_scatter)
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
# include "kernel/split/kernel_do_volume.h"
|
||||
# include "kernel/split/kernel_queue_enqueue.h"
|
||||
# include "kernel/split/kernel_indirect_background.h"
|
||||
# include "kernel/split/kernel_shader_setup.h"
|
||||
# include "kernel/split/kernel_shader_sort.h"
|
||||
# include "kernel/split/kernel_shader_eval.h"
|
||||
# include "kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h"
|
||||
# include "kernel/split/kernel_subsurface_scatter.h"
|
||||
@@ -181,9 +183,11 @@ DEFINE_SPLIT_KERNEL_FUNCTION(lamp_emission)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION(do_volume)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(queue_enqueue, QueueEnqueueLocals)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION(indirect_background)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(shader_eval, uint)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(shader_setup, uint)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(shader_sort, ShaderSortLocals)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION(shader_eval)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(holdout_emission_blurring_pathtermination_ao, BackgroundAOLocals)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(subsurface_scatter, uint)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION(subsurface_scatter)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(direct_lighting, uint)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_ao)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_dl)
|
||||
@@ -209,6 +213,8 @@ void KERNEL_FUNCTION_FULL_NAME(register_functions)(void(*reg)(const char* name,
|
||||
REGISTER(do_volume);
|
||||
REGISTER(queue_enqueue);
|
||||
REGISTER(indirect_background);
|
||||
REGISTER(shader_setup);
|
||||
REGISTER(shader_sort);
|
||||
REGISTER(shader_eval);
|
||||
REGISTER(holdout_emission_blurring_pathtermination_ao);
|
||||
REGISTER(subsurface_scatter);
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#include "kernel/split/kernel_do_volume.h"
|
||||
#include "kernel/split/kernel_queue_enqueue.h"
|
||||
#include "kernel/split/kernel_indirect_background.h"
|
||||
#include "kernel/split/kernel_shader_setup.h"
|
||||
#include "kernel/split/kernel_shader_sort.h"
|
||||
#include "kernel/split/kernel_shader_eval.h"
|
||||
#include "kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h"
|
||||
#include "kernel/split/kernel_subsurface_scatter.h"
|
||||
@@ -108,9 +110,11 @@ DEFINE_SPLIT_KERNEL_FUNCTION(lamp_emission)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION(do_volume)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(queue_enqueue, QueueEnqueueLocals)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION(indirect_background)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(shader_eval, uint)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(shader_setup, uint)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(shader_sort, ShaderSortLocals)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION(shader_eval)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(holdout_emission_blurring_pathtermination_ao, BackgroundAOLocals)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(subsurface_scatter, uint)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION(subsurface_scatter)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(direct_lighting, uint)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_ao)
|
||||
DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_dl)
|
||||
|
||||
@@ -22,6 +22,5 @@ __kernel void kernel_ocl_path_trace_shader_eval(
|
||||
ccl_global char *kg,
|
||||
ccl_constant KernelData *data)
|
||||
{
|
||||
ccl_local unsigned int local_queue_atomics;
|
||||
kernel_shader_eval((KernelGlobals*)kg, &local_queue_atomics);
|
||||
kernel_shader_eval((KernelGlobals*)kg);
|
||||
}
|
||||
|
||||
27
intern/cycles/kernel/kernels/opencl/kernel_shader_setup.cl
Normal file
27
intern/cycles/kernel/kernels/opencl/kernel_shader_setup.cl
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2011-2017 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "kernel/kernel_compat_opencl.h"
|
||||
#include "kernel/split/kernel_split_common.h"
|
||||
#include "kernel/split/kernel_shader_setup.h"
|
||||
|
||||
__kernel void kernel_ocl_path_trace_shader_setup(
|
||||
ccl_global char *kg,
|
||||
ccl_constant KernelData *data)
|
||||
{
|
||||
ccl_local unsigned int local_queue_atomics;
|
||||
kernel_shader_setup((KernelGlobals*)kg, &local_queue_atomics);
|
||||
}
|
||||
28
intern/cycles/kernel/kernels/opencl/kernel_shader_sort.cl
Normal file
28
intern/cycles/kernel/kernels/opencl/kernel_shader_sort.cl
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2011-2017 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "kernel/kernel_compat_opencl.h"
|
||||
#include "kernel/split/kernel_split_common.h"
|
||||
#include "kernel/split/kernel_shader_sort.h"
|
||||
|
||||
__attribute__((reqd_work_group_size(64, 1, 1)))
|
||||
__kernel void kernel_ocl_path_trace_shader_sort(
|
||||
ccl_global char *kg,
|
||||
ccl_constant KernelData *data)
|
||||
{
|
||||
ccl_local ShaderSortLocals locals;
|
||||
kernel_shader_sort((KernelGlobals*)kg, &locals);
|
||||
}
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "kernel/kernels/opencl/kernel_do_volume.cl"
|
||||
#include "kernel/kernels/opencl/kernel_indirect_background.cl"
|
||||
#include "kernel/kernels/opencl/kernel_queue_enqueue.cl"
|
||||
#include "kernel/kernels/opencl/kernel_shader_setup.cl"
|
||||
#include "kernel/kernels/opencl/kernel_shader_sort.cl"
|
||||
#include "kernel/kernels/opencl/kernel_shader_eval.cl"
|
||||
#include "kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl"
|
||||
#include "kernel/kernels/opencl/kernel_subsurface_scatter.cl"
|
||||
|
||||
@@ -22,6 +22,5 @@ __kernel void kernel_ocl_path_trace_subsurface_scatter(
|
||||
ccl_global char *kg,
|
||||
ccl_constant KernelData *data)
|
||||
{
|
||||
ccl_local unsigned int local_queue_atomics;
|
||||
kernel_subsurface_scatter((KernelGlobals*)kg, &local_queue_atomics);
|
||||
kernel_subsurface_scatter((KernelGlobals*)kg);
|
||||
}
|
||||
|
||||
150
intern/cycles/kernel/split/kernel_branched.h
Normal file
150
intern/cycles/kernel/split/kernel_branched.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright 2011-2017 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
#ifdef __BRANCHED_PATH__
|
||||
|
||||
/* sets up the various state needed to do an indirect loop */
|
||||
ccl_device_inline void kernel_split_branched_path_indirect_loop_init(KernelGlobals *kg, int ray_index)
|
||||
{
|
||||
SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
|
||||
|
||||
/* save a copy of the state to restore later */
|
||||
#define BRANCHED_STORE(name) \
|
||||
branched_state->name = kernel_split_state.name[ray_index];
|
||||
|
||||
BRANCHED_STORE(path_state);
|
||||
BRANCHED_STORE(throughput);
|
||||
BRANCHED_STORE(ray);
|
||||
BRANCHED_STORE(sd);
|
||||
BRANCHED_STORE(isect);
|
||||
BRANCHED_STORE(ray_state);
|
||||
|
||||
#undef BRANCHED_STORE
|
||||
|
||||
/* set loop counters to intial position */
|
||||
branched_state->next_closure = 0;
|
||||
branched_state->next_sample = 0;
|
||||
}
|
||||
|
||||
/* ends an indirect loop and restores the previous state */
|
||||
ccl_device_inline void kernel_split_branched_path_indirect_loop_end(KernelGlobals *kg, int ray_index)
|
||||
{
|
||||
SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
|
||||
|
||||
/* restore state */
|
||||
#define BRANCHED_RESTORE(name) \
|
||||
kernel_split_state.name[ray_index] = branched_state->name;
|
||||
|
||||
BRANCHED_RESTORE(path_state);
|
||||
BRANCHED_RESTORE(throughput);
|
||||
BRANCHED_RESTORE(ray);
|
||||
BRANCHED_RESTORE(sd);
|
||||
BRANCHED_RESTORE(isect);
|
||||
BRANCHED_RESTORE(ray_state);
|
||||
|
||||
#undef BRANCHED_RESTORE
|
||||
|
||||
/* leave indirect loop */
|
||||
REMOVE_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_INDIRECT);
|
||||
}
|
||||
|
||||
/* bounce off surface and integrate indirect light */
|
||||
ccl_device_noinline bool kernel_split_branched_path_surface_indirect_light_iter(KernelGlobals *kg,
|
||||
int ray_index,
|
||||
float num_samples_adjust,
|
||||
ShaderData *saved_sd,
|
||||
bool reset_path_state)
|
||||
{
|
||||
SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
|
||||
|
||||
ShaderData *sd = saved_sd;
|
||||
RNG rng = kernel_split_state.rng[ray_index];
|
||||
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
|
||||
float3 throughput = branched_state->throughput;
|
||||
|
||||
for(int i = branched_state->next_closure; i < sd->num_closure; i++) {
|
||||
const ShaderClosure *sc = &sd->closure[i];
|
||||
|
||||
if(!CLOSURE_IS_BSDF(sc->type))
|
||||
continue;
|
||||
/* transparency is not handled here, but in outer loop */
|
||||
if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID)
|
||||
continue;
|
||||
|
||||
int num_samples;
|
||||
|
||||
if(CLOSURE_IS_BSDF_DIFFUSE(sc->type))
|
||||
num_samples = kernel_data.integrator.diffuse_samples;
|
||||
else if(CLOSURE_IS_BSDF_BSSRDF(sc->type))
|
||||
num_samples = 1;
|
||||
else if(CLOSURE_IS_BSDF_GLOSSY(sc->type))
|
||||
num_samples = kernel_data.integrator.glossy_samples;
|
||||
else
|
||||
num_samples = kernel_data.integrator.transmission_samples;
|
||||
|
||||
num_samples = ceil_to_int(num_samples_adjust*num_samples);
|
||||
|
||||
float num_samples_inv = num_samples_adjust/num_samples;
|
||||
RNG bsdf_rng = cmj_hash(rng, i);
|
||||
|
||||
for(int j = branched_state->next_sample; j < num_samples; j++) {
|
||||
ccl_global PathState *ps = &kernel_split_state.path_state[ray_index];
|
||||
if(reset_path_state) {
|
||||
*ps = branched_state->path_state;
|
||||
}
|
||||
|
||||
ccl_global float3 *tp = &kernel_split_state.throughput[ray_index];
|
||||
*tp = throughput;
|
||||
|
||||
ccl_global Ray *bsdf_ray = &kernel_split_state.ray[ray_index];
|
||||
|
||||
if(!kernel_branched_path_surface_bounce(kg,
|
||||
&bsdf_rng,
|
||||
sd,
|
||||
sc,
|
||||
j,
|
||||
num_samples,
|
||||
tp,
|
||||
ps,
|
||||
L,
|
||||
bsdf_ray))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* update state for next iteration */
|
||||
branched_state->next_closure = i;
|
||||
branched_state->next_sample = j+1;
|
||||
branched_state->num_samples = num_samples;
|
||||
|
||||
/* start the indirect path */
|
||||
*tp *= num_samples_inv;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
branched_state->next_sample = 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -105,21 +105,16 @@ void KERNEL_FUNCTION_FULL_NAME(data_init)(
|
||||
|
||||
/* Initialize queue data and queue index. */
|
||||
if(thread_index < queuesize) {
|
||||
/* Initialize active ray queue. */
|
||||
kernel_split_state.queue_data[QUEUE_ACTIVE_AND_REGENERATED_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
|
||||
/* Initialize background and buffer update queue. */
|
||||
kernel_split_state.queue_data[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
|
||||
/* Initialize shadow ray cast of AO queue. */
|
||||
kernel_split_state.queue_data[QUEUE_SHADOW_RAY_CAST_AO_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
|
||||
/* Initialize shadow ray cast of direct lighting queue. */
|
||||
kernel_split_state.queue_data[QUEUE_SHADOW_RAY_CAST_DL_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
|
||||
for(int i = 0; i < NUM_QUEUES; i++) {
|
||||
kernel_split_state.queue_data[i * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
|
||||
}
|
||||
}
|
||||
|
||||
if(thread_index == 0) {
|
||||
Queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = 0;
|
||||
Queue_index[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = 0;
|
||||
Queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS] = 0;
|
||||
Queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS] = 0;
|
||||
for(int i = 0; i < NUM_QUEUES; i++) {
|
||||
Queue_index[i] = 0;
|
||||
}
|
||||
|
||||
/* The scene-intersect kernel should not use the queues very first time.
|
||||
* since the queue would be empty.
|
||||
*/
|
||||
|
||||
@@ -56,23 +56,6 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
|
||||
kernel_split_params.queue_size,
|
||||
0);
|
||||
|
||||
#ifdef __COMPUTE_DEVICE_GPU__
|
||||
/* If we are executing on a GPU device, we exit all threads that are not
|
||||
* required.
|
||||
*
|
||||
* If we are executing on a CPU device, then we need to keep all threads
|
||||
* active since we have barrier() calls later in the kernel. CPU devices,
|
||||
* expect all threads to execute barrier statement.
|
||||
*/
|
||||
if(ray_index == QUEUE_EMPTY_SLOT) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __COMPUTE_DEVICE_GPU__
|
||||
if(ray_index != QUEUE_EMPTY_SLOT) {
|
||||
#endif
|
||||
|
||||
if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) {
|
||||
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
|
||||
ShaderData *sd = &kernel_split_state.sd[ray_index];
|
||||
@@ -80,25 +63,24 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
|
||||
/* direct lighting */
|
||||
#ifdef __EMISSION__
|
||||
RNG rng = kernel_split_state.rng[ray_index];
|
||||
|
||||
bool flag = (kernel_data.integrator.use_direct_light &&
|
||||
(sd->flag & SD_BSDF_HAS_EVAL));
|
||||
|
||||
# ifdef __BRANCHED_PATH__
|
||||
if(flag && kernel_data.integrator.branched) {
|
||||
flag = false;
|
||||
enqueue_flag = 1;
|
||||
}
|
||||
# endif /* __BRANCHED_PATH__ */
|
||||
|
||||
# ifdef __SHADOW_TRICKS__
|
||||
if(flag && state->flag & PATH_RAY_SHADOW_CATCHER) {
|
||||
flag = false;
|
||||
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
|
||||
float3 throughput = kernel_split_state.throughput[ray_index];
|
||||
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
|
||||
kernel_branched_path_surface_connect_light(kg,
|
||||
&rng,
|
||||
sd,
|
||||
emission_sd,
|
||||
state,
|
||||
throughput,
|
||||
1.0f,
|
||||
L,
|
||||
1);
|
||||
enqueue_flag = 1;
|
||||
}
|
||||
# endif /* __SHADOW_TRICKS__ */
|
||||
|
||||
if(flag) {
|
||||
/* Sample illumination from lights to find path contribution. */
|
||||
float light_t = path_state_rng_1D(kg, &rng, state, PRNG_LIGHT);
|
||||
@@ -129,7 +111,6 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
|
||||
kernel_split_state.bsdf_eval[ray_index] = L_light;
|
||||
kernel_split_state.is_lamp[ray_index] = is_lamp;
|
||||
/* Mark ray state for next shadow kernel. */
|
||||
ADD_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL);
|
||||
enqueue_flag = 1;
|
||||
}
|
||||
}
|
||||
@@ -138,10 +119,6 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
|
||||
#endif /* __EMISSION__ */
|
||||
}
|
||||
|
||||
#ifndef __COMPUTE_DEVICE_GPU__
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __EMISSION__
|
||||
/* Enqueue RAY_SHADOW_RAY_CAST_DL rays. */
|
||||
enqueue_ray_index_local(ray_index,
|
||||
@@ -152,6 +129,27 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_index);
|
||||
#endif
|
||||
|
||||
#ifdef __BRANCHED_PATH__
|
||||
/* Enqueue RAY_LIGHT_INDIRECT_NEXT_ITER rays
|
||||
* this is the last kernel before next_iteration_setup that uses local atomics so we do this here
|
||||
*/
|
||||
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
||||
if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
|
||||
*local_queue_atomics = 0;
|
||||
}
|
||||
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
||||
|
||||
ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
|
||||
enqueue_ray_index_local(ray_index,
|
||||
QUEUE_LIGHT_INDIRECT_ITER,
|
||||
IS_STATE(kernel_split_state.ray_state, ray_index, RAY_LIGHT_INDIRECT_NEXT_ITER),
|
||||
kernel_split_params.queue_size,
|
||||
local_queue_atomics,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_index);
|
||||
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -16,6 +16,81 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
#if defined(__BRANCHED_PATH__) && defined(__VOLUME__)
|
||||
|
||||
ccl_device_inline void kernel_split_branched_path_volume_indirect_light_init(KernelGlobals *kg, int ray_index)
|
||||
{
|
||||
kernel_split_branched_path_indirect_loop_init(kg, ray_index);
|
||||
|
||||
ADD_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_VOLUME_INDIRECT);
|
||||
}
|
||||
|
||||
ccl_device_noinline bool kernel_split_branched_path_volume_indirect_light_iter(KernelGlobals *kg, int ray_index)
|
||||
{
|
||||
SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
|
||||
|
||||
ShaderData *sd = &kernel_split_state.sd[ray_index];
|
||||
RNG rng = kernel_split_state.rng[ray_index];
|
||||
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
|
||||
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
|
||||
|
||||
/* GPU: no decoupled ray marching, scatter probalistically */
|
||||
int num_samples = kernel_data.integrator.volume_samples;
|
||||
float num_samples_inv = 1.0f/num_samples;
|
||||
|
||||
Ray volume_ray = branched_state->ray;
|
||||
volume_ray.t = (!IS_STATE(&branched_state->ray_state, 0, RAY_HIT_BACKGROUND)) ? branched_state->isect.t : FLT_MAX;
|
||||
|
||||
bool heterogeneous = volume_stack_is_heterogeneous(kg, branched_state->path_state.volume_stack);
|
||||
|
||||
for(int j = branched_state->next_sample; j < num_samples; j++) {
|
||||
ccl_global PathState *ps = &kernel_split_state.path_state[ray_index];
|
||||
*ps = branched_state->path_state;
|
||||
|
||||
ccl_global Ray *pray = &kernel_split_state.ray[ray_index];
|
||||
*pray = branched_state->ray;
|
||||
|
||||
ccl_global float3 *tp = &kernel_split_state.throughput[ray_index];
|
||||
*tp = branched_state->throughput * num_samples_inv;
|
||||
|
||||
/* branch RNG state */
|
||||
path_state_branch(ps, j, num_samples);
|
||||
|
||||
/* integrate along volume segment with distance sampling */
|
||||
VolumeIntegrateResult result = kernel_volume_integrate(
|
||||
kg, ps, sd, &volume_ray, L, tp, &rng, heterogeneous);
|
||||
|
||||
# ifdef __VOLUME_SCATTER__
|
||||
if(result == VOLUME_PATH_SCATTERED) {
|
||||
/* direct lighting */
|
||||
kernel_path_volume_connect_light(kg, &rng, sd, emission_sd, *tp, &branched_state->path_state, L);
|
||||
|
||||
/* indirect light bounce */
|
||||
if(!kernel_path_volume_bounce(kg, &rng, sd, tp, ps, L, pray)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* start the indirect path */
|
||||
branched_state->next_closure = 0;
|
||||
branched_state->next_sample = j+1;
|
||||
branched_state->num_samples = num_samples;
|
||||
|
||||
return true;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
kernel_split_branched_path_indirect_loop_end(kg, ray_index);
|
||||
|
||||
/* todo: avoid this calculation using decoupled ray marching */
|
||||
float3 throughput = kernel_split_state.throughput[ray_index];
|
||||
kernel_volume_shadow(kg, emission_sd, &kernel_split_state.path_state[ray_index], &volume_ray, &throughput);
|
||||
kernel_split_state.throughput[ray_index] = throughput;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* __BRANCHED_PATH__ && __VOLUME__ */
|
||||
|
||||
ccl_device void kernel_do_volume(KernelGlobals *kg)
|
||||
{
|
||||
@@ -23,37 +98,37 @@ ccl_device void kernel_do_volume(KernelGlobals *kg)
|
||||
/* We will empty this queue in this kernel. */
|
||||
if(ccl_global_id(0) == 0 && ccl_global_id(1) == 0) {
|
||||
kernel_split_params.queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = 0;
|
||||
# ifdef __BRANCHED_PATH__
|
||||
kernel_split_params.queue_index[QUEUE_VOLUME_INDIRECT_ITER] = 0;
|
||||
# endif /* __BRANCHED_PATH__ */
|
||||
}
|
||||
/* Fetch use_queues_flag. */
|
||||
char local_use_queues_flag = *kernel_split_params.use_queues_flag;
|
||||
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
||||
|
||||
int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
|
||||
if(local_use_queues_flag) {
|
||||
|
||||
if(*kernel_split_params.use_queues_flag) {
|
||||
ray_index = get_ray_index(kg, ray_index,
|
||||
QUEUE_ACTIVE_AND_REGENERATED_RAYS,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_size,
|
||||
1);
|
||||
if(ray_index == QUEUE_EMPTY_SLOT) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE) ||
|
||||
IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HIT_BACKGROUND)) {
|
||||
ccl_global char *ray_state = kernel_split_state.ray_state;
|
||||
|
||||
bool hit = ! IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HIT_BACKGROUND);
|
||||
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
|
||||
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
|
||||
|
||||
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
|
||||
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
|
||||
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
|
||||
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
|
||||
RNG rng = kernel_split_state.rng[ray_index];
|
||||
ccl_global Intersection *isect = &kernel_split_state.isect[ray_index];
|
||||
ShaderData *sd = &kernel_split_state.sd[ray_index];
|
||||
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
|
||||
|
||||
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
|
||||
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
|
||||
RNG rng = kernel_split_state.rng[ray_index];
|
||||
ccl_global Intersection *isect = &kernel_split_state.isect[ray_index];
|
||||
ShaderData *sd = &kernel_split_state.sd[ray_index];
|
||||
ShaderData *sd_input = &kernel_split_state.sd_DL_shadow[ray_index];
|
||||
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE) ||
|
||||
IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
|
||||
|
||||
bool hit = ! IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND);
|
||||
|
||||
/* Sanitize volume stack. */
|
||||
if(!hit) {
|
||||
@@ -64,31 +139,68 @@ ccl_device void kernel_do_volume(KernelGlobals *kg)
|
||||
Ray volume_ray = *ray;
|
||||
volume_ray.t = (hit)? isect->t: FLT_MAX;
|
||||
|
||||
bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack);
|
||||
# ifdef __BRANCHED_PATH__
|
||||
if(!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
|
||||
# endif /* __BRANCHED_PATH__ */
|
||||
bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack);
|
||||
|
||||
{
|
||||
/* integrate along volume segment with distance sampling */
|
||||
VolumeIntegrateResult result = kernel_volume_integrate(
|
||||
kg, state, sd, &volume_ray, L, throughput, &rng, heterogeneous);
|
||||
{
|
||||
/* integrate along volume segment with distance sampling */
|
||||
VolumeIntegrateResult result = kernel_volume_integrate(
|
||||
kg, state, sd, &volume_ray, L, throughput, &rng, heterogeneous);
|
||||
|
||||
# ifdef __VOLUME_SCATTER__
|
||||
if(result == VOLUME_PATH_SCATTERED) {
|
||||
/* direct lighting */
|
||||
kernel_path_volume_connect_light(kg, &rng, sd, sd_input, *throughput, state, L);
|
||||
if(result == VOLUME_PATH_SCATTERED) {
|
||||
/* direct lighting */
|
||||
kernel_path_volume_connect_light(kg, &rng, sd, emission_sd, *throughput, state, L);
|
||||
|
||||
/* indirect light bounce */
|
||||
if(kernel_path_volume_bounce(kg, &rng, sd, throughput, state, L, ray))
|
||||
ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED);
|
||||
else
|
||||
ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_UPDATE_BUFFER);
|
||||
/* indirect light bounce */
|
||||
if(kernel_path_volume_bounce(kg, &rng, sd, throughput, state, L, ray)) {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
|
||||
}
|
||||
else {
|
||||
kernel_split_path_end(kg, ray_index);
|
||||
}
|
||||
}
|
||||
# endif /* __VOLUME_SCATTER__ */
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifdef __BRANCHED_PATH__
|
||||
}
|
||||
else {
|
||||
kernel_split_branched_path_volume_indirect_light_init(kg, ray_index);
|
||||
|
||||
if(kernel_split_branched_path_volume_indirect_light_iter(kg, ray_index)) {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
|
||||
}
|
||||
}
|
||||
# endif /* __BRANCHED_PATH__ */
|
||||
}
|
||||
|
||||
kernel_split_state.rng[ray_index] = rng;
|
||||
}
|
||||
|
||||
#endif
|
||||
# ifdef __BRANCHED_PATH__
|
||||
/* iter loop */
|
||||
ray_index = get_ray_index(kg, ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0),
|
||||
QUEUE_VOLUME_INDIRECT_ITER,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_size,
|
||||
1);
|
||||
|
||||
if(IS_STATE(ray_state, ray_index, RAY_VOLUME_INDIRECT_NEXT_ITER)) {
|
||||
/* for render passes, sum and reset indirect light pass variables
|
||||
* for the next samples */
|
||||
path_radiance_sum_indirect(&kernel_split_state.path_radiance[ray_index]);
|
||||
path_radiance_reset_indirect(&kernel_split_state.path_radiance[ray_index]);
|
||||
|
||||
if(kernel_split_branched_path_volume_indirect_light_iter(kg, ray_index)) {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
|
||||
}
|
||||
}
|
||||
# endif /* __BRANCHED_PATH__ */
|
||||
|
||||
#endif /* __VOLUME__ */
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ CCL_NAMESPACE_BEGIN
|
||||
* - QUEUE_SHADOW_RAY_CAST_AO_RAYS will be filled with rays marked with
|
||||
* flag RAY_SHADOW_RAY_CAST_AO
|
||||
*/
|
||||
|
||||
ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
|
||||
KernelGlobals *kg,
|
||||
ccl_local_param BackgroundAOLocals *locals)
|
||||
@@ -62,8 +63,9 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
|
||||
}
|
||||
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
||||
|
||||
#ifdef __AO__
|
||||
char enqueue_flag = 0;
|
||||
char enqueue_flag_AO_SHADOW_RAY_CAST = 0;
|
||||
#endif
|
||||
int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
|
||||
ray_index = get_ray_index(kg, ray_index,
|
||||
QUEUE_ACTIVE_AND_REGENERATED_RAYS,
|
||||
@@ -155,8 +157,7 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
|
||||
kernel_split_state.L_transparent[ray_index] += average(holdout_weight*throughput);
|
||||
}
|
||||
if(sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
|
||||
enqueue_flag = 1;
|
||||
kernel_split_path_end(kg, ray_index);
|
||||
}
|
||||
}
|
||||
#endif /* __HOLDOUT__ */
|
||||
@@ -164,18 +165,31 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
|
||||
|
||||
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
|
||||
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
|
||||
/* Holdout mask objects do not write data passes. */
|
||||
kernel_write_data_passes(kg,
|
||||
buffer,
|
||||
L,
|
||||
sd,
|
||||
sample,
|
||||
state,
|
||||
throughput);
|
||||
|
||||
#ifdef __BRANCHED_PATH__
|
||||
if(!IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT))
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
{
|
||||
/* Holdout mask objects do not write data passes. */
|
||||
kernel_write_data_passes(kg,
|
||||
buffer,
|
||||
L,
|
||||
sd,
|
||||
sample,
|
||||
state,
|
||||
throughput);
|
||||
}
|
||||
|
||||
/* Blurring of bsdf after bounces, for rays that have a small likelihood
|
||||
* of following this particular path (diffuse, rough glossy.
|
||||
*/
|
||||
if(kernel_data.integrator.filter_glossy != FLT_MAX) {
|
||||
#ifndef __BRANCHED_PATH__
|
||||
if(kernel_data.integrator.filter_glossy != FLT_MAX)
|
||||
#else
|
||||
if(kernel_data.integrator.filter_glossy != FLT_MAX &&
|
||||
(!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)))
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
{
|
||||
float blur_pdf = kernel_data.integrator.filter_glossy*state->min_ray_pdf;
|
||||
if(blur_pdf < 1.0f) {
|
||||
float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f;
|
||||
@@ -201,19 +215,32 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
|
||||
* mainly due to the mixed in MIS that we use. gives too many unneeded
|
||||
* shader evaluations, only need emission if we are going to terminate.
|
||||
*/
|
||||
#ifndef __BRANCHED_PATH__
|
||||
float probability = path_state_terminate_probability(kg, state, throughput);
|
||||
#else
|
||||
float probability = 1.0f;
|
||||
|
||||
if(!kernel_data.integrator.branched) {
|
||||
probability = path_state_terminate_probability(kg, state, throughput);
|
||||
}
|
||||
else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
|
||||
int num_samples = kernel_split_state.branched_state[ray_index].num_samples;
|
||||
probability = path_state_terminate_probability(kg, state, throughput*num_samples);
|
||||
}
|
||||
else if(state->flag & PATH_RAY_TRANSPARENT) {
|
||||
probability = path_state_terminate_probability(kg, state, throughput);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(probability == 0.0f) {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
|
||||
enqueue_flag = 1;
|
||||
kernel_split_path_end(kg, ray_index);
|
||||
}
|
||||
|
||||
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
|
||||
if(probability != 1.0f) {
|
||||
float terminate = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_TERMINATE);
|
||||
if(terminate >= probability) {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
|
||||
enqueue_flag = 1;
|
||||
kernel_split_path_end(kg, ray_index);
|
||||
}
|
||||
else {
|
||||
kernel_split_state.throughput[ray_index] = throughput/probability;
|
||||
@@ -225,61 +252,23 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
|
||||
#ifdef __AO__
|
||||
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
|
||||
/* ambient occlusion */
|
||||
if(kernel_data.integrator.use_ambient_occlusion ||
|
||||
(sd->flag & SD_AO))
|
||||
{
|
||||
/* todo: solve correlation */
|
||||
float bsdf_u, bsdf_v;
|
||||
path_state_rng_2D(kg, &rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
|
||||
|
||||
float ao_factor = kernel_data.background.ao_factor;
|
||||
float3 ao_N;
|
||||
kernel_split_state.ao_bsdf[ray_index] = shader_bsdf_ao(kg, sd, ao_factor, &ao_N);
|
||||
kernel_split_state.ao_alpha[ray_index] = shader_bsdf_alpha(kg, sd);
|
||||
|
||||
float3 ao_D;
|
||||
float ao_pdf;
|
||||
sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
|
||||
|
||||
if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
|
||||
Ray _ray;
|
||||
_ray.P = ray_offset(sd->P, sd->Ng);
|
||||
_ray.D = ao_D;
|
||||
_ray.t = kernel_data.background.ao_distance;
|
||||
#ifdef __OBJECT_MOTION__
|
||||
_ray.time = sd->time;
|
||||
#endif
|
||||
_ray.dP = sd->dP;
|
||||
_ray.dD = differential3_zero();
|
||||
kernel_split_state.ao_light_ray[ray_index] = _ray;
|
||||
|
||||
ADD_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO);
|
||||
enqueue_flag_AO_SHADOW_RAY_CAST = 1;
|
||||
}
|
||||
if(kernel_data.integrator.use_ambient_occlusion || (sd->flag & SD_AO)) {
|
||||
enqueue_flag = 1;
|
||||
}
|
||||
}
|
||||
#endif /* __AO__ */
|
||||
kernel_split_state.rng[ray_index] = rng;
|
||||
|
||||
kernel_split_state.rng[ray_index] = rng;
|
||||
|
||||
#ifndef __COMPUTE_DEVICE_GPU__
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Enqueue RAY_UPDATE_BUFFER rays. */
|
||||
enqueue_ray_index_local(ray_index,
|
||||
QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
|
||||
enqueue_flag,
|
||||
kernel_split_params.queue_size,
|
||||
&locals->queue_atomics_bg,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_index);
|
||||
|
||||
#ifdef __AO__
|
||||
/* Enqueue to-shadow-ray-cast rays. */
|
||||
enqueue_ray_index_local(ray_index,
|
||||
QUEUE_SHADOW_RAY_CAST_AO_RAYS,
|
||||
enqueue_flag_AO_SHADOW_RAY_CAST,
|
||||
enqueue_flag,
|
||||
kernel_split_params.queue_size,
|
||||
&locals->queue_atomics_ao,
|
||||
kernel_split_state.queue_data,
|
||||
|
||||
@@ -34,7 +34,7 @@ ccl_device void kernel_indirect_background(KernelGlobals *kg)
|
||||
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
|
||||
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
|
||||
if(state->bounce > kernel_data.integrator.ao_bounces) {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
|
||||
kernel_split_path_end(kg, ray_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ ccl_device void kernel_indirect_background(KernelGlobals *kg)
|
||||
#ifdef __PASSES__
|
||||
if(!(kernel_data.film.pass_flag & PASS_BACKGROUND))
|
||||
#endif
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
|
||||
kernel_split_path_end(kg, ray_index);
|
||||
}
|
||||
|
||||
if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
|
||||
@@ -72,7 +72,7 @@ ccl_device void kernel_indirect_background(KernelGlobals *kg)
|
||||
float3 L_background = indirect_background(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, ray);
|
||||
path_radiance_accum_background(L, state, (*throughput), L_background);
|
||||
#endif
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
|
||||
kernel_split_path_end(kg, ray_index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,26 +49,29 @@ ccl_device void kernel_indirect_subsurface(KernelGlobals *kg)
|
||||
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
|
||||
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
|
||||
|
||||
if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) {
|
||||
ccl_addr_space SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index];
|
||||
kernel_path_subsurface_accum_indirect(ss_indirect, L);
|
||||
#ifdef __BRANCHED_PATH__
|
||||
if(!kernel_data.integrator.branched) {
|
||||
#endif
|
||||
if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) {
|
||||
ccl_addr_space SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index];
|
||||
kernel_path_subsurface_accum_indirect(ss_indirect, L);
|
||||
|
||||
/* Trace indirect subsurface rays by restarting the loop. this uses less
|
||||
* stack memory than invoking kernel_path_indirect.
|
||||
*/
|
||||
if(ss_indirect->num_rays) {
|
||||
kernel_path_subsurface_setup_indirect(kg,
|
||||
ss_indirect,
|
||||
state,
|
||||
ray,
|
||||
L,
|
||||
throughput);
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
|
||||
}
|
||||
else {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
|
||||
/* Trace indirect subsurface rays by restarting the loop. this uses less
|
||||
* stack memory than invoking kernel_path_indirect.
|
||||
*/
|
||||
if(ss_indirect->num_rays) {
|
||||
kernel_path_subsurface_setup_indirect(kg,
|
||||
ss_indirect,
|
||||
state,
|
||||
ray,
|
||||
L,
|
||||
throughput);
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
|
||||
}
|
||||
}
|
||||
#ifdef __BRANCHED_PATH__
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SUBSURFACE__ */
|
||||
|
||||
|
||||
@@ -44,6 +44,52 @@ CCL_NAMESPACE_BEGIN
|
||||
* - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with
|
||||
* RAY_TO_REGENERATE and more RAY_UPDATE_BUFFER rays.
|
||||
*/
|
||||
|
||||
#ifdef __BRANCHED_PATH__
|
||||
ccl_device_inline void kernel_split_branched_indirect_light_init(KernelGlobals *kg, int ray_index)
|
||||
{
|
||||
kernel_split_branched_path_indirect_loop_init(kg, ray_index);
|
||||
|
||||
ADD_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_LIGHT_INDIRECT);
|
||||
}
|
||||
|
||||
ccl_device void kernel_split_branched_indirect_light_end(KernelGlobals *kg, int ray_index)
|
||||
{
|
||||
kernel_split_branched_path_indirect_loop_end(kg, ray_index);
|
||||
|
||||
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
|
||||
ShaderData *sd = &kernel_split_state.sd[ray_index];
|
||||
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
|
||||
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
|
||||
|
||||
/* continue in case of transparency */
|
||||
*throughput *= shader_bsdf_transparency(kg, sd);
|
||||
|
||||
if(is_zero(*throughput)) {
|
||||
kernel_split_path_end(kg, ray_index);
|
||||
}
|
||||
else {
|
||||
/* Update Path State */
|
||||
state->flag |= PATH_RAY_TRANSPARENT;
|
||||
state->transparent_bounce++;
|
||||
|
||||
ray->P = ray_offset(sd->P, -sd->Ng);
|
||||
ray->t -= sd->ray_length; /* clipping works through transparent */
|
||||
|
||||
# ifdef __RAY_DIFFERENTIALS__
|
||||
ray->dP = sd->dP;
|
||||
ray->dD.dx = -sd->dI.dx;
|
||||
ray->dD.dy = -sd->dI.dy;
|
||||
# endif /* __RAY_DIFFERENTIALS__ */
|
||||
|
||||
# ifdef __VOLUME__
|
||||
/* enter/exit volume */
|
||||
kernel_volume_stack_enter_exit(kg, sd, state->volume_stack);
|
||||
# endif /* __VOLUME__ */
|
||||
}
|
||||
}
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
|
||||
ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
|
||||
ccl_local_param unsigned int *local_queue_atomics)
|
||||
{
|
||||
@@ -67,7 +113,6 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
|
||||
kernel_split_params.queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS] = 0;
|
||||
}
|
||||
|
||||
char enqueue_flag = 0;
|
||||
int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
|
||||
ray_index = get_ray_index(kg, ray_index,
|
||||
QUEUE_ACTIVE_AND_REGENERATED_RAYS,
|
||||
@@ -75,102 +120,125 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
|
||||
kernel_split_params.queue_size,
|
||||
0);
|
||||
|
||||
#ifdef __COMPUTE_DEVICE_GPU__
|
||||
/* If we are executing on a GPU device, we exit all threads that are not
|
||||
* required.
|
||||
*
|
||||
* If we are executing on a CPU device, then we need to keep all threads
|
||||
* active since we have barrier() calls later in the kernel. CPU devices,
|
||||
* expect all threads to execute barrier statement.
|
||||
*/
|
||||
if(ray_index == QUEUE_EMPTY_SLOT) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __COMPUTE_DEVICE_GPU__
|
||||
if(ray_index != QUEUE_EMPTY_SLOT) {
|
||||
#endif
|
||||
|
||||
/* Load ShaderData structure. */
|
||||
PathRadiance *L = NULL;
|
||||
ccl_global PathState *state = NULL;
|
||||
ccl_global char *ray_state = kernel_split_state.ray_state;
|
||||
|
||||
/* Path radiance update for AO/Direct_lighting's shadow blocked. */
|
||||
if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL) ||
|
||||
IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO))
|
||||
{
|
||||
state = &kernel_split_state.path_state[ray_index];
|
||||
L = &kernel_split_state.path_radiance[ray_index];
|
||||
float3 _throughput = kernel_split_state.throughput[ray_index];
|
||||
|
||||
if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO)) {
|
||||
float3 shadow = kernel_split_state.ao_light_ray[ray_index].P;
|
||||
// TODO(mai): investigate correctness here
|
||||
char update_path_radiance = (char)kernel_split_state.ao_light_ray[ray_index].t;
|
||||
if(update_path_radiance) {
|
||||
path_radiance_accum_ao(L,
|
||||
_throughput,
|
||||
kernel_split_state.ao_alpha[ray_index],
|
||||
kernel_split_state.ao_bsdf[ray_index],
|
||||
shadow,
|
||||
state->bounce);
|
||||
}
|
||||
else {
|
||||
path_radiance_accum_total_ao(L, _throughput, kernel_split_state.ao_bsdf[ray_index]);
|
||||
}
|
||||
REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO);
|
||||
}
|
||||
|
||||
if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL)) {
|
||||
float3 shadow = kernel_split_state.light_ray[ray_index].P;
|
||||
// TODO(mai): investigate correctness here
|
||||
char update_path_radiance = (char)kernel_split_state.light_ray[ray_index].t;
|
||||
BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index];
|
||||
if(update_path_radiance) {
|
||||
path_radiance_accum_light(L,
|
||||
_throughput,
|
||||
&L_light,
|
||||
shadow,
|
||||
1.0f,
|
||||
state->bounce,
|
||||
kernel_split_state.is_lamp[ray_index]);
|
||||
}
|
||||
else {
|
||||
path_radiance_accum_total_light(L, _throughput, &L_light);
|
||||
}
|
||||
REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL);
|
||||
}
|
||||
}
|
||||
|
||||
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
|
||||
bool active = IS_STATE(ray_state, ray_index, RAY_ACTIVE);
|
||||
if(active) {
|
||||
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
|
||||
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
|
||||
RNG rng = kernel_split_state.rng[ray_index];
|
||||
state = &kernel_split_state.path_state[ray_index];
|
||||
L = &kernel_split_state.path_radiance[ray_index];
|
||||
ShaderData *sd = &kernel_split_state.sd[ray_index];
|
||||
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
|
||||
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
|
||||
|
||||
/* Compute direct lighting and next bounce. */
|
||||
if(!kernel_path_surface_bounce(kg, &rng, &kernel_split_state.sd[ray_index], throughput, state, L, ray)) {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
|
||||
enqueue_flag = 1;
|
||||
#ifdef __BRANCHED_PATH__
|
||||
if(!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
|
||||
#endif
|
||||
/* Compute direct lighting and next bounce. */
|
||||
if(!kernel_path_surface_bounce(kg, &rng, sd, throughput, state, L, ray)) {
|
||||
kernel_split_path_end(kg, ray_index);
|
||||
}
|
||||
#ifdef __BRANCHED_PATH__
|
||||
}
|
||||
else {
|
||||
kernel_split_branched_indirect_light_init(kg, ray_index);
|
||||
|
||||
if(kernel_split_branched_path_surface_indirect_light_iter(kg,
|
||||
ray_index,
|
||||
1.0f,
|
||||
&kernel_split_state.branched_state[ray_index].sd,
|
||||
true))
|
||||
{
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
|
||||
}
|
||||
else {
|
||||
kernel_split_branched_indirect_light_end(kg, ray_index);
|
||||
}
|
||||
}
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
|
||||
kernel_split_state.rng[ray_index] = rng;
|
||||
}
|
||||
|
||||
#ifndef __COMPUTE_DEVICE_GPU__
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Enqueue RAY_UPDATE_BUFFER rays. */
|
||||
enqueue_ray_index_local(ray_index,
|
||||
QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
|
||||
enqueue_flag,
|
||||
IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER) && active,
|
||||
kernel_split_params.queue_size,
|
||||
local_queue_atomics,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_index);
|
||||
|
||||
#ifdef __BRANCHED_PATH__
|
||||
/* iter loop */
|
||||
if(ccl_global_id(0) == 0 && ccl_global_id(1) == 0) {
|
||||
kernel_split_params.queue_index[QUEUE_LIGHT_INDIRECT_ITER] = 0;
|
||||
}
|
||||
|
||||
ray_index = get_ray_index(kg, ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0),
|
||||
QUEUE_LIGHT_INDIRECT_ITER,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_size,
|
||||
1);
|
||||
|
||||
if(IS_STATE(ray_state, ray_index, RAY_LIGHT_INDIRECT_NEXT_ITER)) {
|
||||
/* for render passes, sum and reset indirect light pass variables
|
||||
* for the next samples */
|
||||
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
|
||||
|
||||
path_radiance_sum_indirect(L);
|
||||
path_radiance_reset_indirect(L);
|
||||
|
||||
if(kernel_split_branched_path_surface_indirect_light_iter(kg,
|
||||
ray_index,
|
||||
1.0f,
|
||||
&kernel_split_state.branched_state[ray_index].sd,
|
||||
true))
|
||||
{
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
|
||||
}
|
||||
else {
|
||||
kernel_split_branched_indirect_light_end(kg, ray_index);
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef __VOLUME__
|
||||
/* Enqueue RAY_VOLUME_INDIRECT_NEXT_ITER rays */
|
||||
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
||||
if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
|
||||
*local_queue_atomics = 0;
|
||||
}
|
||||
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
||||
|
||||
ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
|
||||
enqueue_ray_index_local(ray_index,
|
||||
QUEUE_VOLUME_INDIRECT_ITER,
|
||||
IS_STATE(kernel_split_state.ray_state, ray_index, RAY_VOLUME_INDIRECT_NEXT_ITER),
|
||||
kernel_split_params.queue_size,
|
||||
local_queue_atomics,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_index);
|
||||
|
||||
# endif /* __VOLUME__ */
|
||||
|
||||
# ifdef __SUBSURFACE__
|
||||
/* Enqueue RAY_SUBSURFACE_INDIRECT_NEXT_ITER rays */
|
||||
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
||||
if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
|
||||
*local_queue_atomics = 0;
|
||||
}
|
||||
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
||||
|
||||
ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
|
||||
enqueue_ray_index_local(ray_index,
|
||||
QUEUE_SUBSURFACE_INDIRECT_ITER,
|
||||
IS_STATE(kernel_split_state.ray_state, ray_index, RAY_SUBSURFACE_INDIRECT_NEXT_ITER),
|
||||
kernel_split_params.queue_size,
|
||||
local_queue_atomics,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_index);
|
||||
# endif /* __SUBSURFACE__ */
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 Blender Foundation
|
||||
* Copyright 2011-2017 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,54 +16,61 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* This kernel sets up the ShaderData structure from the values computed
|
||||
/* This kernel evaluates ShaderData structure from the values computed
|
||||
* by the previous kernels.
|
||||
*
|
||||
* It also identifies the rays of state RAY_TO_REGENERATE and enqueues them
|
||||
* in QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue.
|
||||
*/
|
||||
ccl_device void kernel_shader_eval(KernelGlobals *kg,
|
||||
ccl_local_param unsigned int *local_queue_atomics)
|
||||
ccl_device void kernel_shader_eval(KernelGlobals *kg)
|
||||
{
|
||||
/* Enqeueue RAY_TO_REGENERATE rays into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. */
|
||||
if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
|
||||
*local_queue_atomics = 0;
|
||||
}
|
||||
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
||||
|
||||
int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
|
||||
/* Sorting on cuda split is not implemented */
|
||||
#ifdef __KERNEL_CUDA__
|
||||
int queue_index = kernel_split_params.queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS];
|
||||
#else
|
||||
int queue_index = kernel_split_params.queue_index[QUEUE_SHADER_SORTED_RAYS];
|
||||
#endif
|
||||
if(ray_index >= queue_index) {
|
||||
return;
|
||||
}
|
||||
ray_index = get_ray_index(kg, ray_index,
|
||||
#ifdef __KERNEL_CUDA__
|
||||
QUEUE_ACTIVE_AND_REGENERATED_RAYS,
|
||||
#else
|
||||
QUEUE_SHADER_SORTED_RAYS,
|
||||
#endif
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_size,
|
||||
0);
|
||||
|
||||
char enqueue_flag = 0;
|
||||
if((ray_index != QUEUE_EMPTY_SLOT) && IS_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE)) {
|
||||
enqueue_flag = 1;
|
||||
if(ray_index == QUEUE_EMPTY_SLOT) {
|
||||
return;
|
||||
}
|
||||
|
||||
enqueue_ray_index_local(ray_index,
|
||||
QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
|
||||
enqueue_flag,
|
||||
kernel_split_params.queue_size,
|
||||
local_queue_atomics,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_index);
|
||||
|
||||
/* Continue on with shader evaluation. */
|
||||
if((ray_index != QUEUE_EMPTY_SLOT) && IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) {
|
||||
Intersection isect = kernel_split_state.isect[ray_index];
|
||||
ccl_global char *ray_state = kernel_split_state.ray_state;
|
||||
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
|
||||
RNG rng = kernel_split_state.rng[ray_index];
|
||||
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
|
||||
Ray ray = kernel_split_state.ray[ray_index];
|
||||
|
||||
shader_setup_from_ray(kg,
|
||||
&kernel_split_state.sd[ray_index],
|
||||
&isect,
|
||||
&ray);
|
||||
#ifndef __BRANCHED_PATH__
|
||||
float rbsdf = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_BSDF);
|
||||
shader_eval_surface(kg, &kernel_split_state.sd[ray_index], &rng, state, rbsdf, state->flag, SHADER_CONTEXT_MAIN);
|
||||
#else
|
||||
ShaderContext ctx = SHADER_CONTEXT_MAIN;
|
||||
float rbsdf = 0.0f;
|
||||
|
||||
if(!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
|
||||
rbsdf = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_BSDF);
|
||||
|
||||
}
|
||||
|
||||
if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
|
||||
ctx = SHADER_CONTEXT_INDIRECT;
|
||||
}
|
||||
|
||||
shader_eval_surface(kg, &kernel_split_state.sd[ray_index], &rng, state, rbsdf, state->flag, ctx);
|
||||
shader_merge_closures(&kernel_split_state.sd[ray_index]);
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
|
||||
kernel_split_state.rng[ray_index] = rng;
|
||||
}
|
||||
}
|
||||
|
||||
70
intern/cycles/kernel/split/kernel_shader_setup.h
Normal file
70
intern/cycles/kernel/split/kernel_shader_setup.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2011-2017 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* This kernel sets up the ShaderData structure from the values computed
|
||||
* by the previous kernels.
|
||||
*
|
||||
* It also identifies the rays of state RAY_TO_REGENERATE and enqueues them
|
||||
* in QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue.
|
||||
*/
|
||||
ccl_device void kernel_shader_setup(KernelGlobals *kg,
|
||||
ccl_local_param unsigned int *local_queue_atomics)
|
||||
{
|
||||
/* Enqeueue RAY_TO_REGENERATE rays into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. */
|
||||
if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
|
||||
*local_queue_atomics = 0;
|
||||
}
|
||||
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
||||
|
||||
int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
|
||||
int queue_index = kernel_split_params.queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS];
|
||||
if(ray_index >= queue_index) {
|
||||
return;
|
||||
}
|
||||
ray_index = get_ray_index(kg, ray_index,
|
||||
QUEUE_ACTIVE_AND_REGENERATED_RAYS,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_size,
|
||||
0);
|
||||
|
||||
if(ray_index == QUEUE_EMPTY_SLOT) {
|
||||
return;
|
||||
}
|
||||
|
||||
char enqueue_flag = (IS_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE)) ? 1 : 0;
|
||||
enqueue_ray_index_local(ray_index,
|
||||
QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
|
||||
enqueue_flag,
|
||||
kernel_split_params.queue_size,
|
||||
local_queue_atomics,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_index);
|
||||
|
||||
/* Continue on with shader evaluation. */
|
||||
if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) {
|
||||
Intersection isect = kernel_split_state.isect[ray_index];
|
||||
Ray ray = kernel_split_state.ray[ray_index];
|
||||
|
||||
shader_setup_from_ray(kg,
|
||||
&kernel_split_state.sd[ray_index],
|
||||
&isect,
|
||||
&ray);
|
||||
}
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
97
intern/cycles/kernel/split/kernel_shader_sort.h
Normal file
97
intern/cycles/kernel/split/kernel_shader_sort.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2011-2017 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
ccl_device void kernel_shader_sort(KernelGlobals *kg,
|
||||
ccl_local_param ShaderSortLocals *locals)
|
||||
{
|
||||
#ifndef __KERNEL_CUDA__
|
||||
int tid = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
|
||||
uint qsize = kernel_split_params.queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS];
|
||||
if(tid == 0) {
|
||||
kernel_split_params.queue_index[QUEUE_SHADER_SORTED_RAYS] = qsize;
|
||||
}
|
||||
|
||||
uint offset = (tid/SHADER_SORT_LOCAL_SIZE)*SHADER_SORT_BLOCK_SIZE;
|
||||
if(offset >= qsize) {
|
||||
return;
|
||||
}
|
||||
|
||||
int lid = ccl_local_id(1) * ccl_local_size(0) + ccl_local_id(0);
|
||||
uint input = QUEUE_ACTIVE_AND_REGENERATED_RAYS * (kernel_split_params.queue_size);
|
||||
uint output = QUEUE_SHADER_SORTED_RAYS * (kernel_split_params.queue_size);
|
||||
ccl_local uint *local_value = &locals->local_value[0];
|
||||
ccl_local ushort *local_index = &locals->local_index[0];
|
||||
|
||||
/* copy to local memory */
|
||||
for (uint i = 0; i < SHADER_SORT_BLOCK_SIZE; i += SHADER_SORT_LOCAL_SIZE) {
|
||||
uint idx = offset + i + lid;
|
||||
uint add = input + idx;
|
||||
uint value = (~0);
|
||||
if(idx < qsize) {
|
||||
int ray_index = kernel_split_state.queue_data[add];
|
||||
bool valid = (ray_index != QUEUE_EMPTY_SLOT) && IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE);
|
||||
if(valid) {
|
||||
value = kernel_split_state.sd[ray_index].shader & SHADER_MASK;
|
||||
}
|
||||
}
|
||||
local_value[i + lid] = value;
|
||||
local_index[i + lid] = i + lid;
|
||||
}
|
||||
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
||||
|
||||
/* skip sorting for cpu split kernel */
|
||||
# ifdef __KERNEL_OPENCL__
|
||||
|
||||
/* bitonic sort */
|
||||
for (uint length = 1; length < SHADER_SORT_BLOCK_SIZE; length <<= 1) {
|
||||
for (uint inc = length; inc > 0; inc >>= 1) {
|
||||
for (uint ii = 0; ii < SHADER_SORT_BLOCK_SIZE; ii += SHADER_SORT_LOCAL_SIZE) {
|
||||
uint i = lid + ii;
|
||||
bool direction = ((i & (length << 1)) != 0);
|
||||
uint j = i ^ inc;
|
||||
ushort ioff = local_index[i];
|
||||
ushort joff = local_index[j];
|
||||
uint iKey = local_value[ioff];
|
||||
uint jKey = local_value[joff];
|
||||
bool smaller = (jKey < iKey) || (jKey == iKey && j < i);
|
||||
bool swap = smaller ^ (j < i) ^ direction;
|
||||
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
||||
local_index[i] = (swap) ? joff : ioff;
|
||||
local_index[j] = (swap) ? ioff : joff;
|
||||
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif /* __KERNEL_OPENCL__ */
|
||||
|
||||
/* copy to destination */
|
||||
for (uint i = 0; i < SHADER_SORT_BLOCK_SIZE; i += SHADER_SORT_LOCAL_SIZE) {
|
||||
uint idx = offset + i + lid;
|
||||
uint lidx = local_index[i + lid];
|
||||
uint outi = output + idx;
|
||||
uint ini = input + offset + lidx;
|
||||
uint value = local_value[lidx];
|
||||
if(idx < qsize) {
|
||||
kernel_split_state.queue_data[outi] = (value == (~0)) ? QUEUE_EMPTY_SLOT : kernel_split_state.queue_data[ini];
|
||||
}
|
||||
}
|
||||
#endif /* __KERNEL_CUDA__ */
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
@@ -29,31 +29,29 @@ ccl_device void kernel_shadow_blocked_ao(KernelGlobals *kg)
|
||||
kernel_split_state.queue_data, kernel_split_params.queue_size, 1);
|
||||
}
|
||||
|
||||
if(ray_index == QUEUE_EMPTY_SLOT)
|
||||
if(ray_index == QUEUE_EMPTY_SLOT) {
|
||||
return;
|
||||
|
||||
/* Flag determining if we need to update L. */
|
||||
char update_path_radiance = 0;
|
||||
|
||||
if(IS_FLAG(kernel_split_state.ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO)) {
|
||||
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
|
||||
ccl_global Ray *light_ray_global = &kernel_split_state.ao_light_ray[ray_index];
|
||||
|
||||
float3 shadow;
|
||||
Ray ray = *light_ray_global;
|
||||
update_path_radiance = !(shadow_blocked(kg,
|
||||
&kernel_split_state.sd_DL_shadow[ray_index],
|
||||
state,
|
||||
&ray,
|
||||
&shadow));
|
||||
|
||||
*light_ray_global = ray;
|
||||
/* We use light_ray_global's P and t to store shadow and
|
||||
* update_path_radiance.
|
||||
*/
|
||||
light_ray_global->P = shadow;
|
||||
light_ray_global->t = update_path_radiance;
|
||||
}
|
||||
|
||||
ShaderData *sd = &kernel_split_state.sd[ray_index];
|
||||
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
|
||||
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
|
||||
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
|
||||
RNG rng = kernel_split_state.rng[ray_index];
|
||||
float3 throughput = kernel_split_state.throughput[ray_index];
|
||||
|
||||
#ifdef __BRANCHED_PATH__
|
||||
if(!kernel_data.integrator.branched || IS_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
|
||||
#endif
|
||||
kernel_path_ao(kg, sd, emission_sd, L, state, &rng, throughput, shader_bsdf_alpha(kg, sd));
|
||||
#ifdef __BRANCHED_PATH__
|
||||
}
|
||||
else {
|
||||
kernel_branched_path_ao(kg, sd, emission_sd, L, state, &rng, throughput);
|
||||
}
|
||||
#endif
|
||||
|
||||
kernel_split_state.rng[ray_index] = rng;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -32,28 +32,71 @@ ccl_device void kernel_shadow_blocked_dl(KernelGlobals *kg)
|
||||
if(ray_index == QUEUE_EMPTY_SLOT)
|
||||
return;
|
||||
|
||||
/* Flag determining if we need to update L. */
|
||||
char update_path_radiance = 0;
|
||||
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
|
||||
Ray ray = kernel_split_state.light_ray[ray_index];
|
||||
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
|
||||
ShaderData *sd = &kernel_split_state.sd[ray_index];
|
||||
float3 throughput = kernel_split_state.throughput[ray_index];
|
||||
RNG rng = kernel_split_state.rng[ray_index];
|
||||
|
||||
if(IS_FLAG(kernel_split_state.ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL)) {
|
||||
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
|
||||
ccl_global Ray *light_ray_global = &kernel_split_state.light_ray[ray_index];
|
||||
BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index];
|
||||
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
|
||||
bool is_lamp = kernel_split_state.is_lamp[ray_index];
|
||||
|
||||
float3 shadow;
|
||||
Ray ray = *light_ray_global;
|
||||
update_path_radiance = !(shadow_blocked(kg,
|
||||
&kernel_split_state.sd_DL_shadow[ray_index],
|
||||
state,
|
||||
&ray,
|
||||
&shadow));
|
||||
# if defined(__BRANCHED_PATH__) || defined(__SHADOW_TRICKS__)
|
||||
bool use_branched = false;
|
||||
int all = 0;
|
||||
|
||||
*light_ray_global = ray;
|
||||
/* We use light_ray_global's P and t to store shadow and
|
||||
* update_path_radiance.
|
||||
*/
|
||||
light_ray_global->P = shadow;
|
||||
light_ray_global->t = update_path_radiance;
|
||||
if(state->flag & PATH_RAY_SHADOW_CATCHER) {
|
||||
use_branched = true;
|
||||
all = 1;
|
||||
}
|
||||
# if defined(__BRANCHED_PATH__)
|
||||
else if(kernel_data.integrator.branched) {
|
||||
use_branched = true;
|
||||
|
||||
if(IS_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
|
||||
all = (kernel_data.integrator.sample_all_lights_indirect);
|
||||
}
|
||||
else
|
||||
{
|
||||
all = (kernel_data.integrator.sample_all_lights_direct);
|
||||
}
|
||||
}
|
||||
# endif /* __BRANCHED_PATH__ */
|
||||
|
||||
if(use_branched) {
|
||||
kernel_branched_path_surface_connect_light(kg,
|
||||
&rng,
|
||||
sd,
|
||||
emission_sd,
|
||||
state,
|
||||
throughput,
|
||||
1.0f,
|
||||
L,
|
||||
all);
|
||||
}
|
||||
else
|
||||
# endif /* defined(__BRANCHED_PATH__) || defined(__SHADOW_TRICKS__)*/
|
||||
{
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(!shadow_blocked(kg,
|
||||
emission_sd,
|
||||
state,
|
||||
&ray,
|
||||
&shadow))
|
||||
{
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, throughput, &L_light, shadow, 1.0f, state->bounce, is_lamp);
|
||||
}
|
||||
else {
|
||||
path_radiance_accum_total_light(L, throughput, &L_light);
|
||||
}
|
||||
}
|
||||
|
||||
kernel_split_state.rng[ray_index] = rng;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -37,41 +37,42 @@
|
||||
|
||||
#include "util/util_atomic.h"
|
||||
|
||||
#include "kernel/kernel_random.h"
|
||||
#include "kernel/kernel_projection.h"
|
||||
#include "kernel/kernel_montecarlo.h"
|
||||
#include "kernel/kernel_differential.h"
|
||||
#include "kernel/kernel_camera.h"
|
||||
|
||||
#include "kernel/geom/geom.h"
|
||||
#include "kernel/bvh/bvh.h"
|
||||
|
||||
#include "kernel/kernel_accumulate.h"
|
||||
#include "kernel/kernel_shader.h"
|
||||
#include "kernel/kernel_light.h"
|
||||
#include "kernel/kernel_passes.h"
|
||||
|
||||
#ifdef __SUBSURFACE__
|
||||
# include "kernel/kernel_subsurface.h"
|
||||
#endif
|
||||
|
||||
#ifdef __VOLUME__
|
||||
# include "kernel/kernel_volume.h"
|
||||
#endif
|
||||
|
||||
#include "kernel/kernel_path_state.h"
|
||||
#include "kernel/kernel_shadow.h"
|
||||
#include "kernel/kernel_emission.h"
|
||||
#include "kernel/kernel_path_common.h"
|
||||
#include "kernel/kernel_path_surface.h"
|
||||
#include "kernel/kernel_path_volume.h"
|
||||
#include "kernel/kernel_path_subsurface.h"
|
||||
|
||||
#ifdef __KERNEL_DEBUG__
|
||||
# include "kernel/kernel_debug.h"
|
||||
#include "kernel/kernel_path.h"
|
||||
#ifdef __BRANCHED_PATH__
|
||||
# include "kernel/kernel_path_branched.h"
|
||||
#endif
|
||||
|
||||
#include "kernel/kernel_queues.h"
|
||||
#include "kernel/kernel_work_stealing.h"
|
||||
|
||||
#ifdef __BRANCHED_PATH__
|
||||
# include "kernel/split/kernel_branched.h"
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_inline void kernel_split_path_end(KernelGlobals *kg, int ray_index)
|
||||
{
|
||||
ccl_global char *ray_state = kernel_split_state.ray_state;
|
||||
|
||||
#ifdef __BRANCHED_PATH__
|
||||
if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_LIGHT_INDIRECT)) {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_LIGHT_INDIRECT_NEXT_ITER);
|
||||
}
|
||||
else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_VOLUME_INDIRECT)) {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_VOLUME_INDIRECT_NEXT_ITER);
|
||||
}
|
||||
else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_SUBSURFACE_INDIRECT)) {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_SUBSURFACE_INDIRECT_NEXT_ITER);
|
||||
}
|
||||
else {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
|
||||
}
|
||||
#else
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
|
||||
#endif
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __KERNEL_SPLIT_H__ */
|
||||
|
||||
@@ -62,7 +62,46 @@ typedef struct SplitParams {
|
||||
SPLIT_DATA_ENTRY(DebugData, debug_data, 1)
|
||||
#else
|
||||
# define SPLIT_DATA_DEBUG_ENTRIES
|
||||
#endif
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef __BRANCHED_PATH__
|
||||
|
||||
typedef ccl_global struct SplitBranchedState {
|
||||
/* various state that must be kept and restored after an indirect loop */
|
||||
PathState path_state;
|
||||
float3 throughput;
|
||||
Ray ray;
|
||||
|
||||
struct ShaderData sd;
|
||||
Intersection isect;
|
||||
|
||||
char ray_state;
|
||||
|
||||
/* indirect loop state */
|
||||
int next_closure;
|
||||
int next_sample;
|
||||
int num_samples;
|
||||
|
||||
#ifdef __SUBSURFACE__
|
||||
int ss_next_closure;
|
||||
int ss_next_sample;
|
||||
int next_hit;
|
||||
int num_hits;
|
||||
|
||||
uint lcg_state;
|
||||
SubsurfaceIntersection ss_isect;
|
||||
|
||||
# ifdef __VOLUME__
|
||||
VolumeStack volume_stack[VOLUME_STACK_SIZE];
|
||||
# endif /* __VOLUME__ */
|
||||
#endif /*__SUBSURFACE__ */
|
||||
} SplitBranchedState;
|
||||
|
||||
#define SPLIT_DATA_BRANCHED_ENTRIES \
|
||||
SPLIT_DATA_ENTRY( SplitBranchedState, branched_state, 1)
|
||||
#else
|
||||
#define SPLIT_DATA_BRANCHED_ENTRIES
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
|
||||
#define SPLIT_DATA_ENTRIES \
|
||||
SPLIT_DATA_ENTRY(ccl_global RNG, rng, 1) \
|
||||
@@ -72,9 +111,6 @@ typedef struct SplitParams {
|
||||
SPLIT_DATA_ENTRY(ccl_global Ray, ray, 1) \
|
||||
SPLIT_DATA_ENTRY(ccl_global PathState, path_state, 1) \
|
||||
SPLIT_DATA_ENTRY(ccl_global Intersection, isect, 1) \
|
||||
SPLIT_DATA_ENTRY(ccl_global float3, ao_alpha, 1) \
|
||||
SPLIT_DATA_ENTRY(ccl_global float3, ao_bsdf, 1) \
|
||||
SPLIT_DATA_ENTRY(ccl_global Ray, ao_light_ray, 1) \
|
||||
SPLIT_DATA_ENTRY(ccl_global BsdfEval, bsdf_eval, 1) \
|
||||
SPLIT_DATA_ENTRY(ccl_global int, is_lamp, 1) \
|
||||
SPLIT_DATA_ENTRY(ccl_global Ray, light_ray, 1) \
|
||||
@@ -82,6 +118,7 @@ typedef struct SplitParams {
|
||||
SPLIT_DATA_ENTRY(ccl_global uint, work_array, 1) \
|
||||
SPLIT_DATA_ENTRY(ShaderData, sd, 1) \
|
||||
SPLIT_DATA_ENTRY(ShaderData, sd_DL_shadow, 1) \
|
||||
SPLIT_DATA_BRANCHED_ENTRIES \
|
||||
SPLIT_DATA_DEBUG_ENTRIES \
|
||||
|
||||
/* struct that holds pointers to data in the shared state buffer */
|
||||
@@ -125,6 +162,11 @@ typedef struct BackgroundAOLocals {
|
||||
uint queue_atomics_ao;
|
||||
} BackgroundAOLocals;
|
||||
|
||||
typedef struct ShaderSortLocals {
|
||||
uint local_value[SHADER_SORT_BLOCK_SIZE];
|
||||
ushort local_index[SHADER_SORT_BLOCK_SIZE];
|
||||
} ShaderSortLocals;
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __KERNEL_SPLIT_DATA_TYPES_H__ */
|
||||
|
||||
@@ -16,42 +16,206 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
#if defined(__BRANCHED_PATH__) && defined(__SUBSURFACE__)
|
||||
|
||||
ccl_device void kernel_subsurface_scatter(KernelGlobals *kg,
|
||||
ccl_local_param unsigned int* local_queue_atomics)
|
||||
ccl_device_inline void kernel_split_branched_path_subsurface_indirect_light_init(KernelGlobals *kg, int ray_index)
|
||||
{
|
||||
#ifdef __SUBSURFACE__
|
||||
if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
|
||||
*local_queue_atomics = 0;
|
||||
kernel_split_branched_path_indirect_loop_init(kg, ray_index);
|
||||
|
||||
SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
|
||||
|
||||
branched_state->ss_next_closure = 0;
|
||||
branched_state->ss_next_sample = 0;
|
||||
|
||||
branched_state->num_hits = 0;
|
||||
branched_state->next_hit = 0;
|
||||
|
||||
ADD_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_SUBSURFACE_INDIRECT);
|
||||
}
|
||||
|
||||
ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_iter(KernelGlobals *kg, int ray_index)
|
||||
{
|
||||
SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
|
||||
|
||||
ShaderData *sd = &branched_state->sd;
|
||||
RNG rng = kernel_split_state.rng[ray_index];
|
||||
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
|
||||
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
|
||||
|
||||
for(int i = branched_state->ss_next_closure; i < sd->num_closure; i++) {
|
||||
ShaderClosure *sc = &sd->closure[i];
|
||||
|
||||
if(!CLOSURE_IS_BSSRDF(sc->type))
|
||||
continue;
|
||||
|
||||
/* set up random number generator */
|
||||
if(branched_state->ss_next_sample == 0 && branched_state->next_hit == 0 &&
|
||||
branched_state->next_closure == 0 && branched_state->next_sample == 0)
|
||||
{
|
||||
branched_state->lcg_state = lcg_state_init(&rng,
|
||||
branched_state->path_state.rng_offset,
|
||||
branched_state->path_state.sample,
|
||||
0x68bc21eb);
|
||||
}
|
||||
int num_samples = kernel_data.integrator.subsurface_samples;
|
||||
float num_samples_inv = 1.0f/num_samples;
|
||||
RNG bssrdf_rng = cmj_hash(rng, i);
|
||||
|
||||
/* do subsurface scatter step with copy of shader data, this will
|
||||
* replace the BSSRDF with a diffuse BSDF closure */
|
||||
for(int j = branched_state->ss_next_sample; j < num_samples; j++) {
|
||||
ccl_global SubsurfaceIntersection *ss_isect = &branched_state->ss_isect;
|
||||
float bssrdf_u, bssrdf_v;
|
||||
path_branched_rng_2D(kg,
|
||||
&bssrdf_rng,
|
||||
&branched_state->path_state,
|
||||
j,
|
||||
num_samples,
|
||||
PRNG_BSDF_U,
|
||||
&bssrdf_u,
|
||||
&bssrdf_v);
|
||||
|
||||
/* intersection is expensive so avoid doing multiple times for the same input */
|
||||
if(branched_state->next_hit == 0 && branched_state->next_closure == 0 && branched_state->next_sample == 0) {
|
||||
RNG lcg_state = branched_state->lcg_state;
|
||||
SubsurfaceIntersection ss_isect_private;
|
||||
|
||||
branched_state->num_hits = subsurface_scatter_multi_intersect(kg,
|
||||
&ss_isect_private,
|
||||
sd,
|
||||
sc,
|
||||
&lcg_state,
|
||||
bssrdf_u, bssrdf_v,
|
||||
true);
|
||||
|
||||
branched_state->lcg_state = lcg_state;
|
||||
*ss_isect = ss_isect_private;
|
||||
}
|
||||
|
||||
#ifdef __VOLUME__
|
||||
Ray volume_ray = branched_state->ray;
|
||||
bool need_update_volume_stack =
|
||||
kernel_data.integrator.use_volumes &&
|
||||
sd->object_flag & SD_OBJECT_INTERSECTS_VOLUME;
|
||||
#endif /* __VOLUME__ */
|
||||
|
||||
/* compute lighting with the BSDF closure */
|
||||
for(int hit = branched_state->next_hit; hit < branched_state->num_hits; hit++) {
|
||||
ShaderData *bssrdf_sd = &kernel_split_state.sd[ray_index];
|
||||
*bssrdf_sd = *sd; /* note: copy happens each iteration of inner loop, this is
|
||||
* important as the indirect path will write into bssrdf_sd */
|
||||
|
||||
SubsurfaceIntersection ss_isect_private = *ss_isect;
|
||||
subsurface_scatter_multi_setup(kg,
|
||||
&ss_isect_private,
|
||||
hit,
|
||||
bssrdf_sd,
|
||||
&branched_state->path_state,
|
||||
branched_state->path_state.flag,
|
||||
sc,
|
||||
true);
|
||||
*ss_isect = ss_isect_private;
|
||||
|
||||
ccl_global PathState *hit_state = &kernel_split_state.path_state[ray_index];
|
||||
*hit_state = branched_state->path_state;
|
||||
|
||||
path_state_branch(hit_state, j, num_samples);
|
||||
|
||||
#ifdef __VOLUME__
|
||||
if(need_update_volume_stack) {
|
||||
/* Setup ray from previous surface point to the new one. */
|
||||
float3 P = ray_offset(bssrdf_sd->P, -bssrdf_sd->Ng);
|
||||
volume_ray.D = normalize_len(P - volume_ray.P, &volume_ray.t);
|
||||
|
||||
/* this next part is expensive as it does scene intersection so only do once */
|
||||
if(branched_state->next_closure == 0 && branched_state->next_sample == 0) {
|
||||
for(int k = 0; k < VOLUME_STACK_SIZE; k++) {
|
||||
branched_state->volume_stack[k] = hit_state->volume_stack[k];
|
||||
}
|
||||
|
||||
kernel_volume_stack_update_for_subsurface(kg,
|
||||
emission_sd,
|
||||
&volume_ray,
|
||||
branched_state->volume_stack);
|
||||
}
|
||||
|
||||
for(int k = 0; k < VOLUME_STACK_SIZE; k++) {
|
||||
hit_state->volume_stack[k] = branched_state->volume_stack[k];
|
||||
}
|
||||
}
|
||||
#endif /* __VOLUME__ */
|
||||
|
||||
#ifdef __EMISSION__
|
||||
if(branched_state->next_closure == 0 && branched_state->next_sample == 0) {
|
||||
/* direct light */
|
||||
if(kernel_data.integrator.use_direct_light) {
|
||||
int all = (kernel_data.integrator.sample_all_lights_direct) ||
|
||||
(branched_state->path_state.flag & PATH_RAY_SHADOW_CATCHER);
|
||||
kernel_branched_path_surface_connect_light(kg,
|
||||
&rng,
|
||||
bssrdf_sd,
|
||||
emission_sd,
|
||||
hit_state,
|
||||
branched_state->throughput,
|
||||
num_samples_inv,
|
||||
L,
|
||||
all);
|
||||
}
|
||||
}
|
||||
#endif /* __EMISSION__ */
|
||||
|
||||
/* indirect light */
|
||||
if(kernel_split_branched_path_surface_indirect_light_iter(kg,
|
||||
ray_index,
|
||||
num_samples_inv,
|
||||
bssrdf_sd,
|
||||
false))
|
||||
{
|
||||
branched_state->ss_next_closure = i;
|
||||
branched_state->ss_next_sample = j;
|
||||
branched_state->next_hit = hit;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
branched_state->next_closure = 0;
|
||||
}
|
||||
|
||||
branched_state->next_hit = 0;
|
||||
}
|
||||
|
||||
branched_state->ss_next_sample = 0;
|
||||
}
|
||||
|
||||
kernel_split_branched_path_indirect_loop_end(kg, ray_index);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* __BRANCHED_PATH__ && __SUBSURFACE__ */
|
||||
|
||||
ccl_device void kernel_subsurface_scatter(KernelGlobals *kg)
|
||||
{
|
||||
int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
|
||||
if(thread_index == 0) {
|
||||
/* We will empty both queues in this kernel. */
|
||||
kernel_split_params.queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = 0;
|
||||
kernel_split_params.queue_index[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = 0;
|
||||
}
|
||||
ccl_barrier(CCL_LOCAL_MEM_FENCE);
|
||||
|
||||
int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
|
||||
ray_index = get_ray_index(kg, ray_index,
|
||||
QUEUE_ACTIVE_AND_REGENERATED_RAYS,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_size,
|
||||
0);
|
||||
|
||||
#ifdef __COMPUTE_DEVICE_GPU__
|
||||
/* If we are executing on a GPU device, we exit all threads that are not
|
||||
* required.
|
||||
*
|
||||
* If we are executing on a CPU device, then we need to keep all threads
|
||||
* active since we have barrier() calls later in the kernel. CPU devices,
|
||||
* expect all threads to execute barrier statement.
|
||||
*/
|
||||
if(ray_index == QUEUE_EMPTY_SLOT) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
char enqueue_flag = 0;
|
||||
|
||||
#ifndef __COMPUTE_DEVICE_GPU__
|
||||
if(ray_index != QUEUE_EMPTY_SLOT) {
|
||||
#endif
|
||||
1);
|
||||
get_ray_index(kg, thread_index,
|
||||
QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_size,
|
||||
1);
|
||||
|
||||
#ifdef __SUBSURFACE__
|
||||
ccl_global char *ray_state = kernel_split_state.ray_state;
|
||||
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
|
||||
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
|
||||
@@ -64,34 +228,85 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg,
|
||||
|
||||
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
|
||||
if(sd->flag & SD_BSSRDF) {
|
||||
if(kernel_path_subsurface_scatter(kg,
|
||||
sd,
|
||||
emission_sd,
|
||||
L,
|
||||
state,
|
||||
&rng,
|
||||
ray,
|
||||
throughput,
|
||||
ss_indirect)) {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
|
||||
enqueue_flag = 1;
|
||||
|
||||
#ifdef __BRANCHED_PATH__
|
||||
if(!kernel_data.integrator.branched) {
|
||||
#endif
|
||||
if(kernel_path_subsurface_scatter(kg,
|
||||
sd,
|
||||
emission_sd,
|
||||
L,
|
||||
state,
|
||||
&rng,
|
||||
ray,
|
||||
throughput,
|
||||
ss_indirect)) {
|
||||
kernel_split_path_end(kg, ray_index);
|
||||
}
|
||||
#ifdef __BRANCHED_PATH__
|
||||
}
|
||||
else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
|
||||
float bssrdf_probability;
|
||||
ShaderClosure *sc = subsurface_scatter_pick_closure(kg, sd, &bssrdf_probability);
|
||||
|
||||
/* modify throughput for picking bssrdf or bsdf */
|
||||
*throughput *= bssrdf_probability;
|
||||
|
||||
/* do bssrdf scatter step if we picked a bssrdf closure */
|
||||
if(sc) {
|
||||
uint lcg_state = lcg_state_init(&rng, state->rng_offset, state->sample, 0x68bc21eb);
|
||||
|
||||
float bssrdf_u, bssrdf_v;
|
||||
path_state_rng_2D(kg,
|
||||
&rng,
|
||||
state,
|
||||
PRNG_BSDF_U,
|
||||
&bssrdf_u, &bssrdf_v);
|
||||
subsurface_scatter_step(kg,
|
||||
sd,
|
||||
state,
|
||||
state->flag,
|
||||
sc,
|
||||
&lcg_state,
|
||||
bssrdf_u, bssrdf_v,
|
||||
false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
kernel_split_branched_path_subsurface_indirect_light_init(kg, ray_index);
|
||||
|
||||
if(kernel_split_branched_path_subsurface_indirect_light_iter(kg, ray_index)) {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
kernel_split_state.rng[ray_index] = rng;
|
||||
}
|
||||
|
||||
#ifndef __COMPUTE_DEVICE_GPU__
|
||||
# ifdef __BRANCHED_PATH__
|
||||
if(ccl_global_id(0) == 0 && ccl_global_id(1) == 0) {
|
||||
kernel_split_params.queue_index[QUEUE_SUBSURFACE_INDIRECT_ITER] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Enqueue RAY_UPDATE_BUFFER rays. */
|
||||
enqueue_ray_index_local(ray_index,
|
||||
QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
|
||||
enqueue_flag,
|
||||
kernel_split_params.queue_size,
|
||||
local_queue_atomics,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_index);
|
||||
/* iter loop */
|
||||
ray_index = get_ray_index(kg, ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0),
|
||||
QUEUE_SUBSURFACE_INDIRECT_ITER,
|
||||
kernel_split_state.queue_data,
|
||||
kernel_split_params.queue_size,
|
||||
1);
|
||||
|
||||
if(IS_STATE(ray_state, ray_index, RAY_SUBSURFACE_INDIRECT_NEXT_ITER)) {
|
||||
/* for render passes, sum and reset indirect light pass variables
|
||||
* for the next samples */
|
||||
path_radiance_sum_indirect(&kernel_split_state.path_radiance[ray_index]);
|
||||
path_radiance_reset_indirect(&kernel_split_state.path_radiance[ray_index]);
|
||||
|
||||
if(kernel_split_branched_path_subsurface_indirect_light_iter(kg, ray_index)) {
|
||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
|
||||
}
|
||||
}
|
||||
# endif /* __BRANCHED_PATH__ */
|
||||
|
||||
#endif /* __SUBSURFACE__ */
|
||||
|
||||
|
||||
@@ -32,13 +32,7 @@ CCL_NAMESPACE_BEGIN
|
||||
ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb, uint use_alpha)
|
||||
{
|
||||
#ifdef __KERNEL_CPU__
|
||||
# ifdef __KERNEL_SSE2__
|
||||
ssef r_ssef;
|
||||
float4 &r = (float4 &)r_ssef;
|
||||
r = kernel_tex_image_interp(id, x, y);
|
||||
# else
|
||||
float4 r = kernel_tex_image_interp(id, x, y);
|
||||
# endif
|
||||
#elif defined(__KERNEL_OPENCL__)
|
||||
float4 r = kernel_tex_image_interp(kg, id, x, y);
|
||||
#else
|
||||
@@ -152,7 +146,10 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
|
||||
CUtexObject tex = kernel_tex_fetch(__bindless_mapping, id);
|
||||
/* float4, byte4 and half4 */
|
||||
const int texture_type = kernel_tex_type(id);
|
||||
if(texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 || texture_type == IMAGE_DATA_TYPE_HALF4) {
|
||||
if(texture_type == IMAGE_DATA_TYPE_FLOAT4 ||
|
||||
texture_type == IMAGE_DATA_TYPE_BYTE4 ||
|
||||
texture_type == IMAGE_DATA_TYPE_HALF4)
|
||||
{
|
||||
r = kernel_tex_image_interp_float4(tex, x, y);
|
||||
}
|
||||
/* float, byte and half */
|
||||
@@ -163,43 +160,22 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __KERNEL_SSE2__
|
||||
float alpha = r.w;
|
||||
const float alpha = r.w;
|
||||
|
||||
if(use_alpha && alpha != 1.0f && alpha != 0.0f) {
|
||||
r_ssef = r_ssef / ssef(alpha);
|
||||
r /= alpha;
|
||||
const int texture_type = kernel_tex_type(id);
|
||||
if(texture_type == IMAGE_DATA_TYPE_BYTE4 || texture_type == IMAGE_DATA_TYPE_BYTE) {
|
||||
r_ssef = min(r_ssef, ssef(1.0f));
|
||||
if(texture_type == IMAGE_DATA_TYPE_BYTE4 ||
|
||||
texture_type == IMAGE_DATA_TYPE_BYTE)
|
||||
{
|
||||
r = min(r, make_float4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
r.w = alpha;
|
||||
}
|
||||
|
||||
if(srgb) {
|
||||
r_ssef = color_srgb_to_scene_linear(r_ssef);
|
||||
r.w = alpha;
|
||||
r = color_srgb_to_scene_linear_v4(r);
|
||||
}
|
||||
#else
|
||||
if(use_alpha && r.w != 1.0f && r.w != 0.0f) {
|
||||
float invw = 1.0f/r.w;
|
||||
r.x *= invw;
|
||||
r.y *= invw;
|
||||
r.z *= invw;
|
||||
|
||||
const int texture_type = kernel_tex_type(id);
|
||||
if(texture_type == IMAGE_DATA_TYPE_BYTE4 || texture_type == IMAGE_DATA_TYPE_BYTE) {
|
||||
r.x = min(r.x, 1.0f);
|
||||
r.y = min(r.y, 1.0f);
|
||||
r.z = min(r.z, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if(srgb) {
|
||||
r.x = color_srgb_to_scene_linear(r.x);
|
||||
r.y = color_srgb_to_scene_linear(r.y);
|
||||
r.z = color_srgb_to_scene_linear(r.z);
|
||||
}
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -157,16 +157,6 @@ ccl_device float3 xyz_to_rgb(float x, float y, float z)
|
||||
0.055648f * x + -0.204043f * y + 1.057311f * z);
|
||||
}
|
||||
|
||||
#ifndef __KERNEL_OPENCL__
|
||||
|
||||
ccl_device float3 color_srgb_to_scene_linear(float3 c)
|
||||
{
|
||||
return make_float3(
|
||||
color_srgb_to_scene_linear(c.x),
|
||||
color_srgb_to_scene_linear(c.y),
|
||||
color_srgb_to_scene_linear(c.z));
|
||||
}
|
||||
|
||||
#ifdef __KERNEL_SSE2__
|
||||
/*
|
||||
* Calculate initial guess for arg^exp based on float representation
|
||||
@@ -222,17 +212,38 @@ ccl_device ssef color_srgb_to_scene_linear(const ssef &c)
|
||||
ssef gte = fastpow24(gtebase);
|
||||
return select(cmp, lt, gte);
|
||||
}
|
||||
#endif
|
||||
#endif /* __KERNEL_SSE2__ */
|
||||
|
||||
ccl_device float3 color_scene_linear_to_srgb(float3 c)
|
||||
ccl_device float3 color_srgb_to_scene_linear_v3(float3 c)
|
||||
{
|
||||
return make_float3(
|
||||
color_scene_linear_to_srgb(c.x),
|
||||
color_scene_linear_to_srgb(c.y),
|
||||
color_scene_linear_to_srgb(c.z));
|
||||
return make_float3(color_srgb_to_scene_linear(c.x),
|
||||
color_srgb_to_scene_linear(c.y),
|
||||
color_srgb_to_scene_linear(c.z));
|
||||
}
|
||||
|
||||
ccl_device float3 color_scene_linear_to_srgb_v3(float3 c)
|
||||
{
|
||||
return make_float3(color_scene_linear_to_srgb(c.x),
|
||||
color_scene_linear_to_srgb(c.y),
|
||||
color_scene_linear_to_srgb(c.z));
|
||||
}
|
||||
|
||||
ccl_device float4 color_srgb_to_scene_linear_v4(float4 c)
|
||||
{
|
||||
#ifdef __KERNEL_SSE2__
|
||||
ssef r_ssef;
|
||||
float4 &r = (float4 &)r_ssef;
|
||||
r = c;
|
||||
r_ssef = color_srgb_to_scene_linear(r_ssef);
|
||||
r.w = c.w;
|
||||
return r;
|
||||
#else
|
||||
return make_float4(color_srgb_to_scene_linear(c.x),
|
||||
color_srgb_to_scene_linear(c.y),
|
||||
color_srgb_to_scene_linear(c.z),
|
||||
c.w);
|
||||
#endif
|
||||
}
|
||||
|
||||
ccl_device float linear_rgb_to_gray(float3 c)
|
||||
{
|
||||
|
||||
@@ -983,7 +983,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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1623,6 +1623,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);
|
||||
|
||||
|
||||
@@ -2110,8 +2110,19 @@ static void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, FileData
|
||||
BLI_endian_switch_int32(&prop->data.val2);
|
||||
BLI_endian_switch_int64((int64_t *)&prop->data.val);
|
||||
}
|
||||
|
||||
break;
|
||||
case IDP_INT:
|
||||
case IDP_FLOAT:
|
||||
case IDP_ID:
|
||||
break; /* Nothing special to do here. */
|
||||
default:
|
||||
/* Unknown IDP type, nuke it (we cannot handle unknown types everywhere in code,
|
||||
* IDP are way too polymorphic to do it safely. */
|
||||
printf("%s: found unknown IDProperty type %d, reset to Integer one !\n", __func__, prop->type);
|
||||
/* Note: we do not attempt to free unknown prop, we have no way to know how to do that! */
|
||||
prop->type = IDP_INT;
|
||||
prop->subtype = 0;
|
||||
IDP_Int(prop) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3112,7 +3123,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) {
|
||||
@@ -6240,6 +6251,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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -1053,7 +1053,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);
|
||||
@@ -2738,6 +2738,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);
|
||||
}
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -248,7 +248,7 @@ DrawEngineType draw_engine_basic_type = {
|
||||
RenderEngineType DRW_engine_viewport_basic_type = {
|
||||
NULL, NULL,
|
||||
BASIC_ENGINE, N_("Basic"), RE_INTERNAL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
&draw_engine_basic_type,
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -658,7 +658,7 @@ DrawEngineType draw_engine_clay_type = {
|
||||
RenderEngineType DRW_engine_viewport_clay_type = {
|
||||
NULL, NULL,
|
||||
CLAY_ENGINE, N_("Clay"), RE_INTERNAL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, &CLAY_collection_settings_create,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, &CLAY_collection_settings_create,
|
||||
&draw_engine_clay_type,
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -712,7 +712,7 @@ DrawEngineType draw_engine_eevee_type = {
|
||||
RenderEngineType DRW_engine_viewport_eevee_type = {
|
||||
NULL, NULL,
|
||||
EEVEE_ENGINE, N_("Eevee"), RE_INTERNAL | RE_USE_SHADING_NODES,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, &EEVEE_collection_settings_create,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, &EEVEE_collection_settings_create,
|
||||
&draw_engine_eevee_type,
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -214,7 +214,7 @@ DrawEngineType draw_engine_external_type = {
|
||||
RenderEngineType DRW_engine_viewport_external_type = {
|
||||
NULL, NULL,
|
||||
EXTERNAL_ENGINE, N_("External"), RE_INTERNAL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
&draw_engine_external_type,
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -211,7 +211,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;
|
||||
|
||||
@@ -191,8 +191,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 ***********************************
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -3037,6 +3037,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 ... */
|
||||
@@ -3044,8 +3045,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;
|
||||
}
|
||||
@@ -3487,6 +3488,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)
|
||||
@@ -3503,7 +3505,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) {
|
||||
@@ -3523,8 +3527,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -513,8 +513,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 */
|
||||
@@ -593,14 +591,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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -226,7 +226,9 @@ typedef struct SceneRenderLayer {
|
||||
|
||||
int samples;
|
||||
float pass_alpha_threshold;
|
||||
|
||||
|
||||
IDProperty *prop;
|
||||
|
||||
struct FreestyleConfig freestyleConfig;
|
||||
} SceneRenderLayer;
|
||||
|
||||
@@ -280,9 +282,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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
@@ -43,6 +44,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", ""},
|
||||
@@ -79,18 +81,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", ""},
|
||||
@@ -281,6 +271,24 @@ static void engine_collection_settings_create(RenderEngine *engine, struct IDPro
|
||||
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)
|
||||
@@ -301,7 +309,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
|
||||
RenderEngineType *et, dummyet = {NULL};
|
||||
RenderEngine dummyengine = {NULL};
|
||||
PointerRNA dummyptr;
|
||||
int have_function[7];
|
||||
int have_function[8];
|
||||
|
||||
/* setup dummy engine & engine type to store static properties in */
|
||||
dummyengine.type = &dummyet;
|
||||
@@ -343,7 +351,8 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
|
||||
et->view_update = (have_function[3]) ? engine_view_update : NULL;
|
||||
et->render_to_view = (have_function[4]) ? engine_render_to_view : NULL;
|
||||
et->update_script_node = (have_function[5]) ? engine_update_script_node : NULL;
|
||||
et->collection_settings_create = (have_function[6]) ? engine_collection_settings_create : NULL;
|
||||
et->update_render_passes = (have_function[6]) ? engine_update_render_passes : NULL;
|
||||
et->collection_settings_create = (have_function[7]) ? engine_collection_settings_create : NULL;
|
||||
|
||||
RE_engines_register(bmain, et);
|
||||
|
||||
@@ -440,6 +449,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)
|
||||
@@ -450,6 +464,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");
|
||||
@@ -511,6 +532,12 @@ static void rna_def_render_engine(BlenderRNA *brna)
|
||||
parm = RNA_def_pointer(func, "node", "Node", "", "");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
|
||||
|
||||
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", "", "");
|
||||
|
||||
/* per-collection engine settings initialization */
|
||||
func = RNA_def_function(srna, "collection_settings_create", NULL);
|
||||
RNA_def_function_ui_description(func, "Create the per collection settings for the engine");
|
||||
@@ -553,6 +580,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", "");
|
||||
@@ -675,6 +713,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);
|
||||
@@ -803,6 +856,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)
|
||||
@@ -851,6 +913,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);
|
||||
@@ -864,11 +931,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);
|
||||
@@ -879,11 +941,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -462,6 +462,7 @@ EnumPropertyItem rna_enum_layer_collection_mode_settings_type_items[] = {
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_layer.h"
|
||||
#include "BKE_main.h"
|
||||
@@ -1627,6 +1628,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;
|
||||
@@ -1731,11 +1744,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;
|
||||
@@ -6464,14 +6484,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);
|
||||
|
||||
@@ -8155,14 +8181,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);
|
||||
|
||||
@@ -291,8 +291,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}")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ set(INC
|
||||
../depsgraph
|
||||
../makesdna
|
||||
../makesrna
|
||||
../nodes
|
||||
../physics
|
||||
../draw
|
||||
../../../intern/atomic
|
||||
@@ -166,10 +167,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")
|
||||
|
||||
@@ -102,6 +102,7 @@ typedef struct RenderEngineType {
|
||||
void (*render_to_view)(struct RenderEngine *engine, const struct bContext *context);
|
||||
|
||||
void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node);
|
||||
void (*update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl);
|
||||
|
||||
void (*collection_settings_create)(struct RenderEngine *engine, struct IDProperty *props);
|
||||
|
||||
@@ -149,6 +150,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);
|
||||
@@ -170,6 +172,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);
|
||||
|
||||
@@ -84,25 +84,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 */
|
||||
@@ -237,7 +231,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);
|
||||
@@ -347,6 +341,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 */
|
||||
@@ -396,13 +391,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__ */
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 ------- */
|
||||
|
||||
|
||||
@@ -497,7 +497,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));
|
||||
|
||||
|
||||
@@ -67,13 +67,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 | RE_USE_LEGACY_PIPELINE,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, render_internal_update_passes, NULL, NULL,
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -82,7 +83,7 @@ static RenderEngineType internal_render_type = {
|
||||
static RenderEngineType internal_game_type = {
|
||||
NULL, NULL,
|
||||
"BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME | RE_USE_LEGACY_PIPELINE,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -235,6 +236,8 @@ RenderResult *RE_engine_begin_result(
|
||||
|
||||
/* 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
|
||||
@@ -268,6 +271,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;
|
||||
@@ -753,3 +767,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,9 +240,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;
|
||||
}
|
||||
|
||||
@@ -383,13 +383,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -443,10 +443,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);
|
||||
@@ -844,7 +844,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -863,7 +863,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1657,7 +1657,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);
|
||||
@@ -1857,6 +1857,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;
|
||||
@@ -3880,7 +3882,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)
|
||||
@@ -4006,13 +4008,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))
|
||||
@@ -4022,6 +4023,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)
|
||||
{
|
||||
@@ -4039,7 +4084,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);
|
||||
@@ -4047,5 +4092,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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -234,7 +234,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
|
||||
@@ -248,6 +248,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
|
||||
|
||||
@@ -667,6 +668,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
|
||||
@@ -693,6 +695,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
|
||||
|
||||
/* Draw */
|
||||
void OBJECT_collection_settings_create(struct IDProperty *properties) RET_NONE
|
||||
|
||||
@@ -994,8 +994,8 @@ void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat,
|
||||
}
|
||||
|
||||
bool negX = (scale[0] < 0.0f);
|
||||
bool negY = (scale[0] < 0.0f);
|
||||
bool negZ = (scale[0] < 0.0f);
|
||||
bool negY = (scale[1] < 0.0f);
|
||||
bool negZ = (scale[2] < 0.0f);
|
||||
if (negX || negY || negZ) {
|
||||
m_viewmatrix.tscale((negX)?-1.0f:1.0f, (negY)?-1.0f:1.0f, (negZ)?-1.0f:1.0f, 1.0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user