Materials and lighting

Friflex. In this article series, I share my experience with Blender (we use Blender to work on our sports digitization projects). In previous articles we talked about work with objects and with cameras: learned how to point the lens at objects, change the focal length and much more. In this article, we will talk about how to make the scene more realistic: we will set up lighting, add shadows, create a texture for an object, the properties of which will be changed through the API.

Content:

materials

We will not go into creating complex textures – this is a whole art, which can be devoted to a separate series of articles. On the contrary, we will create a simple material and focus on how to work with it through the API.

Materials in Blender allow you to influence the appearance of objects. For example, we can change the color, transparency, roughness, etc. In this article, we will look at how to work with these properties through the API.

This is a gif.  To view, click on the image
This is a gif. To view, click on the image

We have just moved to the material editing section – “shading”. Now let’s create a simple material called “custom material” and install it on our cube.

This is a gif.  To view, click on the image
This is a gif. To view, click on the image

Let’s try to change the color of the new material.

This is a gif.  To view, click on the image
This is a gif. To view, click on the image

Excellent! Our cube has acquired a purple color. But now let’s figure out how to access stuff through the API.

material = bpy.data.materials['custom material']

Before moving on, let’s take a look at what the material is.

The material is made up of knots that affect the appearance. This creates a slight complication: we need to access not the material itself, but the specific node whose property we want to change. But there is a way to avoid this confusion. To do this, we need to consider “custom properties” (aka. custom properties) and “drivers”.

Custom properties

AT first part we worked with basic object properties: location, scale, etc.

cube = bpy.data.objects[‘Cube’]
cube.scale.x = 2

Lucky for us, Blender provides the ability to create custom properties that can be accessed in a similar way.

This is a gif.  To view, click on the image
This is a gif. To view, click on the image

We have just created a property that will be responsible for changing the color of the object. Let’s try to access it.

cube = bpy.data.objects[‘Cube’]
list(cube[‘color’]) # Получим [0, 0, 0]

However, if we now try to change the color, nothing will happen. We haven’t told blender what it should do when we change a property.

Drivers

In Blender, drivers allow you to create relationships between two or more properties. We can now bind the color (material property) to the custom cube property we created in the previous block. First of all, we need to get the path of the property to which the binding will occur.

This is a gif.  To view, click on the image
This is a gif. To view, click on the image

Now let’s move on to the property that we will bind, create a driver for it and open the driver editor.

This is a gif.  To view, click on the image
This is a gif. To view, click on the image

In the editor, we will carry out a simple binding of one property to another. For a better understanding of the drivers, I advise you to read this article.

This is a gif.  To view, click on the image
This is a gif. To view, click on the image

Now, when we change the custom cube property, the bound material property will automatically change along with it. Just note that the color property consists of three values: red, green, blue. At the moment, we have tied only the r-channel. g and b channels can be linked in a similar way.

cube = bpy.data.objects[‘Cube’]
cube[‘color’] = 0.5

It is important that if you try to apply the code from the example above in the Blender console, then outwardly nothing will happen. The changes will be visible on the image after rendering.

Lighting

Let’s move on to an equally interesting topic – light sources. There are four types of emitters in Blender: “Spot”, “Point”, “Area”, “Sun”. To get an idea of ​​how each of them works, I suggest you look at this video. We will move on to their consideration from the point of view of the API. And first of all, we will get access to the light source.

light = bpy.data.lights['Light']

color

By default, any light source uses white light. With the help of the color property, we can change this. For example, let’s make the color of the lamp glow more purple.

light = bpy.data.lights['Light']
light.color = (0.33, 0.01, 1.0)

Energy

This property is responsible for the power of the emitter. The unit of measure is watt.

light = bpy.data.lights['Light']
light.energy = 100

Procedural generation of emitters

Blender provides the ability to create new objects through an API. Let’s try to create a new conical light source.

spot = bpy.data.objects.new(
    'SpotLight',
    bpy.data.lights.new('SpotLight', 'SPOT')
    )

In the example above, we created an object of type bpy.types.Object called SpotLight and placed in it (in the data property) a light source with a similar name and type bpy.types.SpotLight

However, if we now look at the list of objects located on the stage, it turns out that our object does not exist. In Blender, you can’t just take and create an object, you still need to place it in some kind of collection in order for it to be added to the stage.

collection = bpy.context.scene.collection
collection.objects.link(spot)

Thus, we have added our lamp to the main collection of the scene and now we can interact with it.

rotation

To change the direction of the glow, just turn the emitter on the stage. To do this, we will use the standard property of objects – “rotation_euler”.

spot = bpy.data.objects['SpotLight']
spot.rotation_euler = (1, 1, 1)
This is a gif.  To view, click on the image
This is a gif. To view, click on the image

Targeting an object

Let’s say we want to point the lamp created in the previous step at our cube. To do this, we can use the function discussed in article about working with cameras.

 def point_ligth_at(
        ligth: bpy.types.Object,
        target: mathutils.Vector,
        track_axis: str="Z",
        up_axis: str="Y"
        ):
    vector = ligth.location - target
    ligth.rotation_euler = vector.to_track_quat(
        track_axis,
        up_axis
        ).to_euler()

light = bpy.data.objects['Light']
cube = bpy.data.objects['Cube']
point_ligth_at(light, cube.location)

The end

If you have worked with blender and want to discuss what you read or share your experience and knowledge, I am waiting for you in the comments! Let’s make the article more complete and useful for beginners.

Similar Posts

Leave a Reply