Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Saving Texture3D resource through script does not work in Godot 4 #72993

Closed
Kwu564 opened this issue Feb 9, 2023 · 12 comments
Closed

Saving Texture3D resource through script does not work in Godot 4 #72993

Kwu564 opened this issue Feb 9, 2023 · 12 comments

Comments

@Kwu564
Copy link

Kwu564 commented Feb 9, 2023

Godot version

4.0.beta.3

System information

Vulkan, Windows 10 GTX970m

Issue description

Saving Texture3Ds from script is does not work in Godot 4. Someone apparently already fixed it but there's no pr of it yet it seems: Game3DEE@68bb829

Edit: Turns out there's already a pr here: #66558 but it's not merged yet.

Steps to reproduce

First declare an array of type Image to hold each layer of the 3D Texture.

Initialize the Image array in a triple nested for loop where the outermost loop iterates through each each Image creating a new Image for the current layer, and the two inner loops iterate through each Image's x and y pixel coordinates setting the pixel at those coordinates.

Then, create an ImageTexture3D by first declaring ImageTexture3D.new() and then initializing it with ImageTexture3D.create() setting the format to Image.FORMAT_RGBA_8, its dimensions and passing in the image layer array to it.

Finally save the 3D texture using ResourceSaver.save(). Saving as tres outputs a 1x1x1 pink texture and saving as png or tga causes the saver to not write anything to the disk.

Minimal reproduction project

Create a new empty project and follow the steps to to reproduce.

@Zireael07
Copy link
Contributor

Beta 3, really? There's an RC already out, double check if the issue still exists.

@Kwu564
Copy link
Author

Kwu564 commented Feb 10, 2023

It's still not working on the latest snapshot beta 17.

@AThousandShips
Copy link
Member

Do you mean PR #71394?

@Kwu564
Copy link
Author

Kwu564 commented Feb 10, 2023

Yes that's it.

Edit: Also this one: #70212

@Calinou
Copy link
Member

Calinou commented Feb 10, 2023

Duplicate of #66558.

@Calinou Calinou closed this as not planned Won't fix, can't repro, duplicate, stale Feb 10, 2023
@PGComai
Copy link

PGComai commented Apr 15, 2023

I'm trying to understand the process of creating the data array for the image.

First declare an array of type Image to hold each layer of the 3D Texture.

Initialize the Image array in a triple nested for loop where the outermost loop iterates through each each Image creating a new Image for the current layer, and the two inner loops iterate through each Image's x and y pixel coordinates setting the pixel at those coordinates.

Could someone help me with this part? Before reading this, my code looked like this:

var arr = []
	for x in range(-bounds,bounds):
		arr.append([])
		for y in range(-bounds,bounds):
			arr[x+bounds].append([])
			for z in range(-bounds,bounds):
				var loc = Vector3(x,y,z)
				var item = get_cell_item(loc)
				if item == 0:
					# cell is full
					arr[x+bounds][y+bounds].append(Color(1,1,1,1))
				elif item == -1:
					arr[x+bounds][y+bounds].append(Color(0,0,0,1))

How do I create an array of type image? And is this the correct loop arrangement?

@Kwu564
Copy link
Author

Kwu564 commented Apr 15, 2023

A Texture3D is just an array of 2d images. The array should be used to store individual images. The outer most loop appends a new image to the image array. Then an inner loop iterates through each row of the current image and then the innermost loop iterates through each column of that current row setting each pixel of that image. Once done you can create a new Texture3D passing along the array of images to it.

@PGComai
Copy link

PGComai commented Apr 15, 2023

A Texture3D is just an array of 2d images. The array should be used to store individual images. The outer most loop appends a new image to the image array. Then an inner loop iterates through each row of the current image and then the innermost loop iterates through each column of that current row setting each pixel of that image. Once done you can create a new Texture3D passing along the array of images to it.

Thank you! This solved my problem, here is the new code:

func make_array_from_gm():
	var arr = []
	for z in range(-bounds,bounds):
		var arrimg = Image.create(2*bounds, 2*bounds, false, Image.FORMAT_L8)
		for x in range(-bounds,bounds):
			for y in range(-bounds,bounds):
				var loc = Vector3(x,y,z)
				var item = get_cell_item(loc)
				if item == 0:
					# cell is full
					arrimg.set_pixelv(Vector2i(x+bounds,y+bounds), Color.WHITE)
				elif item == -1:
					arrimg.set_pixelv(Vector2i(x+bounds,y+bounds), Color.BLACK)
		arr.append(arrimg)
	return arr

@DrLutzi
Copy link

DrLutzi commented Aug 16, 2023

I believe this issue deserves re-opening, as PR #71394 does not fix the problem for ImageTexture3D in 4.1.1 (a278c1b)

The following code should produce a tres file containing the data. Instead, it produces an tres file without data:

var i := Image.create(1, 1, false, Image.FORMAT_RGB8)
i.set_pixel(0,0, Color(1,0,0))
var l := ImageTexture3D.new()
l.create(Image.FORMAT_RGB8, 1, 1, 1, false, [ i ])
ResourceSaver.save(l, "res://texture3d.tres")

The equivalent for Texture2DArray works fine:

var i := Image.create(1, 1, false, Image.FORMAT_RGB8)
i.set_pixel(0,0, Color(1,0,0))
var l := Texture2DArray.new()
l.create_from_images([ i ])
ResourceSaver.save(l, "res://layered.tres")

I'm not sure if this is really how I'm meant to save as I am still fairly unfamiliar with godot, but it does feel like there is an issue there.

@Kwu564
Copy link
Author

Kwu564 commented Aug 16, 2023

Yeah, I agree. I'm thinking of contributing a fix if no one gets to it yet.

@q8f13
Copy link

q8f13 commented Sep 21, 2023

Can confirm that ImageTexture3D instance generated from code can't be saved into tres file

I believe this issue deserves re-opening, as PR #71394 does not fix the problem for ImageTexture3D in 4.1.1 (a278c1b)

The following code should produce a tres file containing the data. Instead, it produces an tres file without data:

var i := Image.create(1, 1, false, Image.FORMAT_RGB8)
i.set_pixel(0,0, Color(1,0,0))
var l := ImageTexture3D.new()
l.create(Image.FORMAT_RGB8, 1, 1, 1, false, [ i ])
ResourceSaver.save(l, "res://texture3d.tres")

The equivalent for Texture2DArray works fine:

var i := Image.create(1, 1, false, Image.FORMAT_RGB8)
i.set_pixel(0,0, Color(1,0,0))
var l := Texture2DArray.new()
l.create_from_images([ i ])
ResourceSaver.save(l, "res://layered.tres")

I'm not sure if this is really how I'm meant to save as I am still fairly unfamiliar with godot, but it does feel like there is an issue there.

Can confirm that ImageTexture3D generated from code can't be saved into valid tres/res file.
File generated as tres just be like:

[gd_resource type="ImageTexture3D" format=3 uid="uid://1brwgfcw8yvu"]

[resource]

Using godot 4.1.1 bd6af8e

@AThousandShips
Copy link
Member

This is a duplicate, please see:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants