Godot: Shader language: implement arrays support

Created on 29 Aug 2017  路  20Comments  路  Source: godotengine/godot

as i understand there is no way right now to declare and use any arrays inside shaders like float arr[] = float[] (1,2,3,4);
would be even more better to be able to declare them as uniforms or varying. and even better ( 馃檮 ) to have multidimensional arrays.

archived feature proposal shaders

Most helpful comment

For those wondering, here is a workaround using texture uniforms for the time being.
It might be useful depending on your case (better examples are also welcome :) )

gdscript

extends ColorRect

# ColorRect is the Node on which I have my shader material attached

func _ready():
    # The array I want to send to my shader
    var array = [1, 1, 1, 0, 2, 2, 2, 0, 0, 3]

    # You'll have to get thoose the way you want
    var array_width = 10
    var array_heigh = 1

    # The following is used to convert the array into a Texture
    var byte_array = PoolByteArray(array)
    var img = Image.new()

    # I don't want any mipmaps generated : use_mipmaps = false
    # I'm only interested with 1 component per pixel (the corresponding array value) : Format = Image.FORMAT_R8
    img.create_from_data(array_width, array_heigh, false, Image.FORMAT_R8, byte_array)

    var texture = ImageTexture.new()

    # Override the default flag with 0 since I don't want texture repeat/filtering/mipmaps/etc
    texture.create_from_image(img, 0)

    # Upload the texture to my shader
    material.set_shader_param("my_array", texture)

Shader

uniform sampler2D my_array;

int get_array_value(ivec2 coord)
{
    // retrieve r component on the desired array position
    float texture_value = texelFetch(my_array, coord, 0).r;
    // the resulting value is in srgb space, so convert it back to linear space
    texture_value *= 255.;
    return int(texture_value);  
}

All 20 comments

makes sense but not for now, kicking to 3.1

Was asked in a Q&A thread: https://godotengine.org/qa/27228/array-godot-shader
It would be a nice way to avoid additional textures if they are just small data containers, because texture fetchs are expensive... not necessarily in processing time, but in how many you can have: https://github.com/Zylann/godot_heightmap_native_plugin/issues/22

Hi, I'm throwing in my support for this feature. Currently trying to implement a simple 1d LUT for palette shifting and finding it difficult to work with my data since it's in an integer array format and not textures due to the relatively lopsided amount of outputs I need for a given input. Having arrays in-language would help a lot to avoid converting the tables I already have to sparse textures.

I assume this is still being worked on for 3.1? Trying to implement a particle system that can reverse speed and go backward in time (like Prince of Persia rewind), but seeing how I can only access the individual particle data through a particle shader it'd be useful to store them in a uniform array to access by gdScript.

bumping this because I need an array of arrays for an 8-bit mask to perform some autotiling functions now and I'm not sure of another way to work around this. Arrays are really sorely missing from the shading language....

edit: (and I'm not sure if even shader model 3 would be very happy with a 256-way branching function..)

My water shader uses lots of copies of similar variables because array support is lacking right now. Would really need such a feature to make code neat.

I started working on this.
I got some basic types to work for uniforms (float[], int[], uint[]). There's still a long way to go, and I'm still getting the hang of godot so it might take a while.

Apparently @arkinsamedi finished adding arrays in this commit? , can he confirm that its done and ready to merge?

I really hope this is going to be in 3.2.

It will be in 3.1 they said, it's all fine they said... +bump this is a very fundamental feature for any kind of logic system. I would very much appreciate if this is in 3.2

For those wondering, here is a workaround using texture uniforms for the time being.
It might be useful depending on your case (better examples are also welcome :) )

gdscript

extends ColorRect

# ColorRect is the Node on which I have my shader material attached

func _ready():
    # The array I want to send to my shader
    var array = [1, 1, 1, 0, 2, 2, 2, 0, 0, 3]

    # You'll have to get thoose the way you want
    var array_width = 10
    var array_heigh = 1

    # The following is used to convert the array into a Texture
    var byte_array = PoolByteArray(array)
    var img = Image.new()

    # I don't want any mipmaps generated : use_mipmaps = false
    # I'm only interested with 1 component per pixel (the corresponding array value) : Format = Image.FORMAT_R8
    img.create_from_data(array_width, array_heigh, false, Image.FORMAT_R8, byte_array)

    var texture = ImageTexture.new()

    # Override the default flag with 0 since I don't want texture repeat/filtering/mipmaps/etc
    texture.create_from_image(img, 0)

    # Upload the texture to my shader
    material.set_shader_param("my_array", texture)

Shader

uniform sampler2D my_array;

int get_array_value(ivec2 coord)
{
    // retrieve r component on the desired array position
    float texture_value = texelFetch(my_array, coord, 0).r;
    // the resulting value is in srgb space, so convert it back to linear space
    texture_value *= 255.;
    return int(texture_value);  
}

sampler arrays would be nice to have, you can't use a texture as a texture array after all.

I see a 4.0 milestone. Sooo close... I'll settle for any type of uniform array support tbh 馃榿

3.2 has some array support! http://docs.godotengine.org/en/latest/tutorials/shading/shading_reference/shading_language.html#arrays

Quite a number of people are still holding out specifically for uniform support, since transport seems to be what's necessitating the use case for most as compared to internal processing.

Better if @reduz implements uniform arrays himself since I'm stuck with them hardly...

Hi guys, currently working on a ray marching shader, hoping to dynamically create/modify shapes.
I have absolutely no other option but to use textures for data, and you can imagine the butchery.

Just to remind that this feature is really important in the eyes of some.

Feature and improvement proposals for the Godot Engine are now being discussed and reviewed in a dedicated Godot Improvement Proposals (GIP) (godotengine/godot-proposals) issue tracker. The GIP tracker has a detailed issue template designed so that proposals include all the relevant information to start a productive discussion and help the community assess the validity of the proposal for the engine.

The main (godotengine/godot) tracker is now solely dedicated to bug reports and Pull Requests, enabling contributors to have a better focus on bug fixing work. Therefore, we are now closing all older feature proposals on the main issue tracker.

If you are interested in this feature proposal, please open a new proposal on the GIP tracker following the given issue template (after checking that it doesn't exist already). Be sure to reference this closed issue if it includes any relevant discussion (which you are also encouraged to summarize in the new proposal). Thanks in advance!

Hi guys, currently working on a ray marching shader, hoping to dynamically create/modify shapes.
I have absolutely no other option but to use textures for data, and you can imagine the butchery.

Just to remind that this feature is really important in the eyes of some.

I 100% agree with you :)

@panicq Please don't bump issues without contributing significant new information. Use the :+1: reaction button on the first post instead.

Was this page helpful?
0 / 5 - 0 ratings