godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

Implement a secondary UV channel(UV2) for 2d shaders(canvas_item shader type) #7962

Open BirdmanTunes opened 11 months ago

BirdmanTunes commented 11 months ago

Describe the project you are working on

I'm working on making something like terraria, that has to paint two textures over each other for front wall and back wall on a procedurally generated mesh.

Describe the problem or limitation you are having in your project

The problem is that for procedural meshes where you need two UV channels to draw two parts of a texture on the same quad is not possible right now.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Implementing a secondary UV channel would solve this because i would simply have to assign a secondary array of UV values to the secondary UV channel.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

I am not qualified enough to propose pseudo-code, but it seems that 3d shaders already support a secondary UV channel. So that might be a good example of the implementation.

If this enhancement will not be used often, can it be worked around with a few lines of script?

I don't think this can be worked around.

Is there a reason why this should be core and not an add-on in the asset library?

This is something that is quite essential in many situations and should be part of the core.

patcorwin commented 3 weeks ago

I found this while searching to see if the feature I want has already been requested. I can't be certain but I wonder if the effect you want could be done entirely in a shader. Here's a simple example, index adjusts the lookup into the additional texture. If the existing uvs can be mapped, then you can adjust the lookup however you want. Or I might be misunderstanding your needs.

shader_type canvas_item;
uniform sampler2D vegetation: hint_default_transparent, filter_nearest;

uniform int index: hint_range(0, 3, 1) = 0;
uniform int rows = 2;
uniform int cols = 2;

void fragment() {

    vec4 base = texture(TEXTURE, UV);

    // Convert index into the top-left corner
    float y = float(index / cols) / float(rows);
    float x = fract( float(index) / float(cols) );

    // UV.x / float(cols) converts the UV of 0 to 1 into the width of the portion we want
    vec4 veg = texture(vegetation, vec2(x + UV.x / float(cols), y + UV.y / float(rows)));

    COLOR = mix(base, veg, veg.a);
}

veg result