0
$\begingroup$

When changing the background from it's default value to gray (0.5,0.5,0.5) I saw that the other object colors were effected (been brighter). I must say that I didn't use nodes to change the background color. What is the way to do it using python script? I want the background and the plane to have the same color this way the scene will look like endless horizon but without effecting the colors of the current objects.

enter image description here

$\endgroup$
2
  • $\begingroup$ You can use a transparent background for the render and add the color in the compositor. $\endgroup$
    – Robert Gützkow
    Nov 2, 2019 at 11:39
  • $\begingroup$ @rjg thank you for helping. can you read again the question I have added clearer description of the problem with an example. $\endgroup$
    – AvivSham
    Nov 2, 2019 at 12:03

2 Answers 2

3
$\begingroup$

As mentioned by @rjg, you will need to add the color in compositor. The reason, why the colors of other objects change, when you change background color is beacause the way light works. (And the fact that background is not just a color).

Now the way how to achieve what @rjg has mentioned is following.

Go to Propetries panel > Render > Film and tick the Transparent box.

Go to Compositor (Compositing workspace), tick Use nodes, add a Mix node and route RenderLayers Image output into the bottom Image input of Mix node and Alpha otput of RenderLayers into Fac input of Mix node. Set the desired color of the background on the first Image input of Mix node and finally route the output of Mix node to Image input of Composite node.

Compositor node setup You can precisely set the color of the background by checking the color of a rendered image (right click on rendered image to see RGB values), or kind-of automatically (below).

Result render You will notice the border line, where the plane ends, which is probably undesired and can be fixed by further utilization of the Compositor.

In the compositor you will need to apply a Feather (Dilatate/Erode - mode: Feather) filter to the alpha channel, before plugging it into the Mix node. Compositor node setup with Feather filter Feel free to adjust the Distance value (Note that it can be both positive and negative).

Here is a visualisation of what the Feather filter does to the alpha channel: Compositor node setup with Feather filter And the result: Compositor node setup with Feather filter Now each time you render, the background will be this color. Note however that the color of the plane might change if you add a light source or even an object (again due to the way light works).

Now for the last question, how to do this in python (I assume to automate this). You could actually do this in python so that python script sets the color.

You would need to look at the rendered image, the way is described here, and determine what the background color is, then set the color on the Mix node to that value.

You can get very close to this behavior without using Python with this node setup: Node setup for automatic background color You basically use the Translate node to move the pixel of the image, that you want to grab the background color from, to the middle of the screen. Then you scale the image by large amount (so that the whole image is made up of this one pixel) and you plug that into the first Image input of the Mix node.

Now the background color will adjust automatically.

Edit: I found a way to setup the whole thing with Python and was eager to try it out, so here is the code.

import bpy



#select the point in pixels from which the background color will be selected
#note that it is not necessarily exact so it may be about +-4px (too lazy to do the math correctly)
target_x = 20
target_y = 50



render_p = bpy.context.scene.render.resolution_percentage/100.0
render_w = bpy.context.scene.render.resolution_x * render_p
render_h = bpy.context.scene.render.resolution_y * render_p




bpy.context.scene.render.film_transparent = True

#bpy.ops.node.add_node(type="CompositorNodeMixRGB", use_transform=True)
#bpy.ops.node.translate_attach_remove_on_cancel(TRANSFORM_OT_translate={"value":(-121.875, 273.423, 0), "orient_type":'GLOBAL', "orient_matrix":((1, 0, 0), (0, 1, 0), (0, 0, 1)), "orient_matrix_type":'GLOBAL', "constraint_axis":(False, False, False), "mirror":True, "use_proportional_edit":False, "proportional_edit_falloff":'SMOOTH', "proportional_size":1, "use_proportional_connected":False, "use_proportional_projected":False, "snap":False, "snap_target":'CLOSEST', "snap_point":(0, 0, 0), "snap_align":False, "snap_normal":(0, 0, 0), "gpencil_strokes":False, "cursor_transform":False, "texture_space":False, "remove_on_cancel":True, "release_confirm":True, "use_accurate":False}, NODE_OT_attach={}, NODE_OT_insert_offset={})

# switch on nodes and get reference
bpy.context.scene.use_nodes = True
tree = bpy.context.scene.node_tree

# clear default nodes
for node in tree.nodes:
    tree.nodes.remove(node)

# create input image node
in_node = tree.nodes.new(type='CompositorNodeRLayers')
in_node.location = -400,0

#create mix node
mix_node = tree.nodes.new(type='CompositorNodeMixRGB')
mix_node.location = 400,0

#create alpha filter node
af_node = tree.nodes.new(type='CompositorNodeDilateErode')
af_node.mode = 'FEATHER'
af_node.distance = -50
af_node.location = 0,-200

#create translate node
t_node = tree.nodes.new(type='CompositorNodeTranslate')
t_node.inputs[1].default_value = render_w/2 - target_x
t_node.inputs[2].default_value = render_h/2 - target_y
t_node.location = 0,200

#create viewer
v_node = tree.nodes.new(type='CompositorNodeViewer')
v_node.location = 200,400


#create scale node
s_node = tree.nodes.new(type='CompositorNodeScale')
s_node.inputs[1].default_value = render_w
s_node.inputs[2].default_value = render_h
s_node.location = 200,200

# create output node
out_node = tree.nodes.new('CompositorNodeComposite')   
out_node.location = 800,0

# link nodes
tree.links.new(in_node.outputs[0], mix_node.inputs[2])
tree.links.new(mix_node.outputs[0], out_node.inputs[0])
tree.links.new(in_node.outputs[1], af_node.inputs[0])
tree.links.new(af_node.outputs[0], mix_node.inputs[0])
tree.links.new(in_node.outputs[0], t_node.inputs[0])
tree.links.new(t_node.outputs[0], s_node.inputs[0])
tree.links.new(s_node.outputs[0], mix_node.inputs[1])
tree.links.new(t_node.outputs[0], v_node.inputs[0])

target_x and target_y is used to select the pixel from which a color for the background is picked. It isn't necessarily pixel precise so choose a general area.

I have also added a Viewer node. If you click it in the Compositor (and you have backdrop enabled and you have rendered the image already) you will see a cross on the screen, pointing to the selected pixel in the backdrop. At this moment, you can adjust the Translate parameters manually to select a different pixel (Alt+V and V to zoom the backdrop in and out). Python generated node setup So just paste the script into Blender and run it.

A tip: If you are having a problem with anything, it never hurts to try things on a new blank file and get a feel for how a thing behaves. When you encounter problem in your file then, you will notice the moment when it went wrong with more ease and find solutions faster.

$\endgroup$
6
  • $\begingroup$ Thank you very much for your response! this indeed look good (although I thought the solution would be easier). How can it be done using script? $\endgroup$
    – AvivSham
    Nov 2, 2019 at 17:35
  • $\begingroup$ I followed your steps using blender's UI but when I entered the composition tab and added the Render layers I didn't see the image of the scene as in your example but I kept going and nothing happend the background stull was the default checkerboard $\endgroup$
    – AvivSham
    Nov 2, 2019 at 17:52
  • $\begingroup$ When you go to Composition and tick Use nodes a basic node setup (Render Layers going into Composite) should appear. Then it's just adding things in between. It is easier to start small - first the mix node with Factor set to 1 and then build up. If you copied the final setup and the Translate node landed you on a transparent pixel, then the behavior is weird. $\endgroup$
    – IsawU
    Nov 2, 2019 at 19:18
  • $\begingroup$ I have edited the answer to include Python script to set it all up, but have a look at the answer by @kremlas - it is actually smart and so simple. $\endgroup$
    – IsawU
    Nov 2, 2019 at 20:21
  • $\begingroup$ I will try it out and let you know thanks! BTW, if I have a moving camera won't it be a problem? since I see some of the parameters are hard coded specially traget_x/y. $\endgroup$
    – AvivSham
    Nov 3, 2019 at 8:05
1
$\begingroup$

If you don't mind me coming up with a 'somehow dirty' solution, I had to deal with the same situation a while back and this is what I used:

Basically every time you change the background color it also changes the global or ambient illumination of the scene (as was mentioned before). One of the solutions sure is to compose it later in the compositor, but I came with an idea (or maybe I've read or seen it somewhere and just passing it along) to divide illumination between foreground and background in the scene itself. In the node editor set your world nodes like this:

enter image description here

The shader above divides the background into two parts - the part that is shown in the viewport and the part that illuminates the foreground (the reason why this works is because the background would illuminate only the parts of objects that are not seen at that precise moment).

That way you can use two different colors or pictures to create and illuminate the scene (notice different colors on the World properties).

enter image description here

enter image description here

enter image description here

I must admit, though, that I haven't tested it with transparency/translucency, in which way the results may differ and would have to be tweaked. But this should work for your scenario as I believe you are working with solid materials. Anyway, thought I would chip in with my two cents.

Cheers, Martin

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .