just change the texture image with Python script and render it

I want just change the texture image and render it with Python scripts

lux.importFile(“C:/sample/sample_001.bip”)
width = 100
height = 100
opts = lux.getRenderOptions()
opts.setMaxSamplesRendering(1)
opts.setMaxTimeRendering(1)


texture_file = "C:/sample/texture_001.png"

Load textured images from here and apply them

Set? Load? Import?


lux.renderImage(path=“C:/sample/rendering_001.png”, width=width, height=height, opts=opts, format=lux.RENDER_OUTPUT_PNG)

I think this…
Help me!
Thank you!


AH!!! I used keyshot_headless script~

I wonder if it’s possible, I know you can change materials by replacing it with a material from the library but not sure if you can change a texture using scripting. If you have a multi material you could also switch those using scripts and make a certain sub material active.

Maybe @morten.kristensen.1 has some tips, I’ve little experience, I just looked at the manual.

1 Like

Thank you!!!
I asked him(@morten.kristensen.1) help.

Ah!! I used keyshot_headless script.

Hi @cheon.cheon. I urge you to search the forum for previous questions, and read our scripting section of our manual that includes a number of quick start examples about scripting.

From what I can gather, you want to change the texture used by some material on some node in the scene tree (right?). To employ a material that uses your texture in question, there are generally two approaches via scripting:

1. Apply preexisting material

First, find the node in your scene that you want to apply the preexisting material to. Read our Accessing Scene Nodes quick start guide about how to do that.

Second, apply your material (by name) on the node:

node.setMaterial("texture_001")

Note that this assumes that you have already imported your texture into our texture library.
You can access all the known textures via:

lux.getLibraryTextures()  # List of all the names of known textures.

2. Use the Material Graph to apply the specific texture

This is an advanced feature. I recommend that you try the other approach first. However, if you look into it, read our Material Graph quick start guide before proceeding.

Let’s assume you had a scene with a simple cube, and you wanted to change the texture used by its material. You’d first need to figure out the name of the material:

root = lux.getSceneTree()

# It is known that the name of the cube group node is "Cube".
nodes = root.find(name="Cube", types=[lux.NODE_TYPE_GROUP])
assert len(nodes) == 1     # And that there is only one.
node = nodes[0]
>>> node.getMaterial()
'Cube Material'  # In this case.

Get a material graph representation of that material:

graph = lux.getMaterialGraph("Cube Material")

Figure out what the shader graph consists of:

>>> graph.getNodes()  # might return:
(<lux.ShaderNode | Root, ID: 6>, <lux.ShaderNode | Diffuse, ID: 7>)

It is thus the diffuse shader that should be looked at in this case with ID=7.

diffuse_node = graph.getNodeFromID(7)

Investigating its in- and outgoing edges, we might find:

>>> diffuse_node.getInputEdges()
()  # No input edges.
>>> diffuse_node.getOutputEdges()
(<lux.ShaderEdge | ID: 5,
  source: <lux.ShaderNode | Diffuse, ID: 7>,
  target: <lux.ShaderNode | Root, ID: 6>,
  parameter: "surface">,)

At this point, we need to create a texture map node using some texture and attaching it to the diffuse node, i.e., adding an edge.

Create the texture map node:

tex_node = graph.newNode(lux.SHADER_TYPE_TEXTURE_MAP)

It now exists but it isn’t connected to anything:

>>> graph.getNodes()
(<lux.ShaderNode | Root, ID: 6>,
 <lux.ShaderNode | Diffuse, ID: 7>,
 <lux.ShaderNode | Texture Map, ID: 8>)
>>> tex_node.getInputEdges()
()
>>> tex_node.getOutputEdges()
()

For the sake of testing, let’s find a walnut texture:

>>> for tex in lux.getLibraryTextures():
      if "walnut" in tex:
        print(tex)
/Library/Application Support/KeyShot12/Textures/Wood/black_walnut.jpg
/Library/Application Support/KeyShot12/Textures/Wood/walnut.jpg

These paths are from my macOS machine and can be different on other computers.

Then it can be applied to the “texture” parameter of the texture map shader node:

tex_parm = tex_node.getParameter("texture")

# Before:
>>> tex_parm
<lux.ShaderParameter | name: "texture" (Texture), type: String>

# Set the texture:
>>> tex_parm.setValue("/Library/Application Support/KeyShot12/Textures/Wood/walnut.jpg")
True

# After:
>>> tex_parm
<lux.ShaderParameter | name: "texture" (Texture), type: String>
/Library/Application Support/KeyShot12/Textures/Wood/walnut.jpg

Now we attach the texture map shader node to the diffuse shader node via an edge:

graph.newEdge(source=tex_node, target=diffuse_node, param="diffuse")

The texture will now be applied and will appear in renderings or in the realtime rendering window.

Further investigation also shows the new connection in the graph:

# The texture shader node points to the diffuse shader node.
>>> tex_node.getInputEdges()
()
>>> tex_node.getOutputEdges()
(<lux.ShaderEdge | ID: 6,
 source: <lux.ShaderNode | Texture Map, ID: 8>,
 target: <lux.ShaderNode | Diffuse, ID: 7>,
 parameter: "diffuse">,)

# The diffuse shader node is pointed to by the texture shader node and
# points to the root of the material graph of the "Cube Material"
# material.
>>> diffuse_node.getInputEdges()
(<lux.ShaderEdge | ID: 6,
 source: <lux.ShaderNode | Texture Map, ID: 8>,
 target: <lux.ShaderNode | Diffuse, ID: 7>,
 parameter: "diffuse">,)
>>> diffuse_node.getOutputEdges()
(<lux.ShaderEdge | ID: 5,
 source: <lux.ShaderNode | Diffuse, ID: 7>,
 target: <lux.ShaderNode | Root, ID: 6>,
 parameter: "surface">,)

I hope this helps.
/Morten

2 Likes

@morten.kristensen.1
Thank you. Thank you. Thank you very much~~
I’ll apply it and reply to you

ah…
Set Material is only Material. Texture has an error…
Exception: Unknown material!

However, the material works well.

Let me check the second way.

GooooooooooooooooD!!!

graph = lux.getMaterialGraph(“texture #1”)
texture_node = graph.getNodeFromID(20)
temp_getParameter = texture_node.getParameter(“texture”)
temp_getParameter.setValue(“C:/map/test_texture_01.jpg”)
renderImage…

Mission complete~~~!!!
Thank you!!!


texture_node = graph.getNodeFromID(20)

This part is a bit confusing.
When I work on something, the ID changes.
Even if I copy the bip file, it changes.
If there are more than one texture, you must check it manually

2 Likes

Well done, @cheon.cheon! Happy to help.