I wrote this piece of code in order to send some floats to a shader:

data = [ float(x),float(y),float(z)]
	var byte_array = PoolByteArray(data)
	var img = Image.new()
	img.create_from_data(3, 1, false, Image.FORMAT_RF , byte_array)
	var texture = ImageTexture.new()
	texture.create_from_image(img, 0)

But I get the error:

Expected data size of 12 bytes in Image::create(), got instead 3 bytes

So clearly I am missing some step.

  • Okay, this is a hack, but it looks like it works.

    func _ready():
    	var data_array = [ 1.17, 2.05, 3.14 ]
    	var img = Image.new()
    	img.create(data_array.size(), 1, false, Image.FORMAT_RF)
    	img.lock()
    	for i in range(data_array.size()):
    		img.set_pixel(i, 0, Color(data_array[i], 0.0, 0.0))
    	img.unlock()
    	var texture = ImageTexture.new()
    	texture.create_from_image(img, 0)
    	# test to make sure it works
    	img.lock()
    	for i in range(data_array.size()):
    		print("pixel ", i, ": ", img.get_pixel(i, 0))
    	img.unlock()
    	print("texture width: ", texture.get_width(), ", height: ", texture.get_height())

I believe you want to use FORMAT_RGBF for 3 components. FORMAT_RF is for 1 float.

    cybereality I want 1 float. My example is misleading because I used x, y and z. But really, the actual array will have an arbitrary number of floats and RF will be more convenient to use.

    Okay, I understand. A PoolByteArray stores data on individual bytes. A floating-point number is 4 bytes, so 3 should be 12 bytes total. You get the error message because the Image create_from_data() line is correct, but is expecting a byte array of 12 (4 bytes * 3), but that byte_array must not be initialized correctly. So the problem is on the first line. You likely need to use the function var2bytes(). So it may look like this:

    var data_array = [x, y, z]
    var byte_array = var2bytes(data_array)
    # rest of code should work

      cybereality Oooh! we're getting warm here! now the error message is

      Expected data size of 12 bytes in Image::create(), got instead 32 bytes.

      Still not working but for the first time in a while I think we're on the right path.

      Okay, this is a hack, but it looks like it works.

      func _ready():
      	var data_array = [ 1.17, 2.05, 3.14 ]
      	var img = Image.new()
      	img.create(data_array.size(), 1, false, Image.FORMAT_RF)
      	img.lock()
      	for i in range(data_array.size()):
      		img.set_pixel(i, 0, Color(data_array[i], 0.0, 0.0))
      	img.unlock()
      	var texture = ImageTexture.new()
      	texture.create_from_image(img, 0)
      	# test to make sure it works
      	img.lock()
      	for i in range(data_array.size()):
      		print("pixel ", i, ": ", img.get_pixel(i, 0))
      	img.unlock()
      	print("texture width: ", texture.get_width(), ", height: ", texture.get_height())

        cybereality Good lord 😅
        I'm marking this as the best answer, but I hope to find something less hacky. I tried something similar but using Vector2, because I know each component is stored as 32 bit floats.

        Right now I am trying to understand what exactly is var2bytes doing. Because when I print out each byte it's always something weird and unintuitive. I think it's converting to byte some extra information I don't need. So once I figure out what it is exactly I might be able to exclude some elements from it or something. But that's for tomorrow's brain. Today's brain is tired.

        I really appreciate the help, by the way! thank you.