I have referred to https://blenderartists.org/t/how-to-modify-rgb-curve-nodes-in-compositor/503936 hoping the technique would be same or similar for shader nodes. I have also checked Is there a way of keyframing RGB curves? and How to make preset for RGB curves in compositor

-- where, in passing, the high-voted answer needs a typo correcting, from: (RGB_Curves_Node).mapping.curves[0].points[id].location_x to: (RGB_Curves_Node).mapping.curves[0].points[id].location.x and same for y.

In this, "id is used to access which point you want the property from. Also, the 'R', 'G', 'B' and 'C' curves are separated by id 0, 1, 2, 3 respectively."

Therefore I script:

rgbC = nodes.new(type='ShaderNodeRGBCurve')
rgbC.mapping.curves[2].points[0].location = (0,0)
rgbC.mapping.curves[2].points[1].location = (0.48,0.675)

But, although 'points[1]' is set correctly, the curve does not bend, and a straight line then goes from an existing end point through the new one -- having lost its 'other end' anchor (that presumably would have made it bend?). If I try and anchor both ends (0,0) and (1,1), then when adding the 3rd point so:

rgbC.mapping.curves[2].points[2].location = (1,1)

I get an 'index out of range' error.

Any help on properly adding and setting points would be much appreciated, thanks.


1 Answer 1


I spent the day looking for the same answer and had given up already because it's nowhere to be found, may it be in the documentation, StackExchange or specialized forums.

It was when I decided to replace the RGB Curves node with a ColorRamp that I figured it out, and it's ridiculously simple! If only it were documented anywhere.

You add points to a RGB Curve with the same method used to add points to a ColorRamp: new()

In your case, I'd leave point 1 alone and add this at the end, removing the redundant update() line:


curves.new() explained

When you add a point update() is trigged, resetting the points' index based on their x location.

Example Issue: You always start with curve[n].points[0] at (0,0) and curve[n].points[1] at (1,1). If you create a point at (.5,.5) it won't be curve[n].points[2] because it'll be situated between [0] and [1]. The new point will become [1], and the previous point[1] becomes [2].

It makes easy to lose track of your points when you're also manipulating them. To avoid this, you can add all new points at (1,1), reposition them and do whatever you need; then execute update() at the end so they're reindexed in the new order.

This way your new points will always have a higher index than your existing points while you're working on them.

Here follows a sample script to add an RGB Curve node to the active material, add three new points and reposition them:

import bpy
NODES = bpy.context.active_object.active_material.node_tree.nodes
# Create node
rgbC = NODES.new("ShaderNodeRGBCurve")
# Select "C" curve
curve_c = rgbC.mapping.curves[3]

# Add three points at (1,1) so they're created with [2],[3] and [4] indexes

# Move the new points to desired (x,y) locations
curve_c.points[2].location = (.2, .1)
curve_c.points[3].location = (.44, .44)
curve_c.points[4].location = (.6, .9)

# Update curve. Now new points are [1],[2],[3] and last one is [4]

And the short version if you're sure you don't need to preserve indexes:

import bpy
NODES = bpy.context.active_object.active_material.node_tree.nodes
rgbC = NODES.new("ShaderNodeRGBCurve")
curve_c = rgbC.mapping.curves[3]

# Add new points at (x,y). No need to update() at the end


RGB Curve node generated through python script


You must log in to answer this question.

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