Multiple textures for Sprite

Guys, in Materials documentation there is for Sprites Samplers:

“If you need multiple textures in a shader, you can use render.enable_texture() and set texture samplers manually from your render script.”

If I want to have such second texture available - and I want it to be drew on one texture in form of one tilesource. For example I have one frame/sprite in tilesource as tile 1, and below it I duplicate the same image, but with different colors (e.g. normal map) - this second image is in tile 2. By default I would use this tilesource as Texture for Sprite and a “tile 1” animation from it as Animation Property for Sprite.

Example visualization of such tilesource:


The upper part is tile 1 (with albedo/Diffuse data) and below is corresponding tile 2 (with normal data)

So in such sprite’s fragment program I have Sampler2D, which contains only information about colors (diffuse/albedo) and How could I access second information - normal map, from tile below?

I think I can:
To first render target draw the sprite with usual, default material, that will output color as usual.

To second render target, I will somehow enable other material for such sprite (:question:) - this material’s fragment program will instead of drawing usual color, offset the Sampler2D by the height of a tile and take data from row below, namely from normal map and save it as output color, right?

Then I could proceed with magic with such 2 render targets, right?

I intended to put (:question:) mark between my understanding, because I’m missing this piece - how can I change material for Sprite in render pipeline? Like I do when I set material for quad? A material from render’s list of Materials?

Will the above still work if I put more frames into tilesource? What when I switch animation to tile next to tile 1 in upper row? If I offset this tile to lookup normal data from a frame that is below, in second row, will it works (or simply speaking, won’t it mess up coords if I move to the right in tileource? :sweat_smile:)

Or should I totally change approach and make second texture with normal data in somehow different way attached to sprite? Atlas approach? (I don’t want to go with Model approach to which I actually can attach multiple textures)

(I originally posted it on Discord, but I think it’s worth noting on forum, as at some point someone might be at the same stage as me rn :grin:)

1 Like

Not sure I understand exactly what you want to achieve (normal mapping for sprites?), but in any case. If you want to use both albedo and normal info in the same shader you can do this by offsetting the UVs as you said, so your fragment shader would contain something like:

varying vec2 var_texcoord0;
uniform sampler2D tilesource;

void main()
{
    // sample the texture from two texture coordinates
    vec4 albedo = texture2D(tilesource, var_texcoord0);
    vec2 offset = vec2(...)
    vec4 normal = texture2D(tilesource, var_texcoord0 + offset);
   // rest of shader
}

Or alternatively if you want to go the route of using separate material you can do that as well for any render component. Render scripts doesn’t know anything about the GO world, so a sprite in this sense is nothing different from any other rendering construct (not 100% the truth, fonts have their own rendering that sets a special uniform but it’s easier to think of it with this simplification).

To direct the rendering you can add a material in the render list, enable it by render.enable_material(id) before issuing the render.draw with your sprite predicate. This will override the material you set on your sprite to use a different material.

But maybe if you describe a bit more of what you want to do I can perhaps come up with some other approaches :slight_smile:

2 Likes

Okay. I assume the tiles should be from a tilesource and not an atlas since atlases aren’t really offset friendly?

1 Like

Hmmm, doesn’t work the way I expect. Maybe an example would be nice.

What part didn’t work?
How did you layout the albedo vs normal tiles in the tile source?
In what units is your offset?

Okay, this is my tile source. Each tile is 512x512.

If I set
vec2 offset = vec2(512, 512) gl_FragColor = texture2D(texture_sampler, var_texcoord0 + offset);
Shader still uses the very first image in the tilesource that the sprite is assigned. Full image.

If I set
vec2 offset = vec2(2,1) gl_FragColor = texture2D(texture_sampler, var_texcoord0 * offset);
Then I get the other image. But I thought it would produce the image on the right side only as if changing the sprite’s animation to tile 2.

I was actually playing around with this, and I’m not completely sure but I noticed in a situation where you have a sprite with a tilemap source, the offset you have to add is a vec2( tilesize/100 ). For example, in your case, you would have to set offset to vec2(0, -0.512) to get the tile right below that one. This does explain why in @Pawel 's example of making nomal maps for sprites, their offset value was decimal, which I was so confused about but now I (sort of) understand. Though I am confused why the textures they used were 16x48 but the offset was -0.25 rather than -0.16

1 Like

Ok, seems like its not a set rule. I tried doing it with a 667*3600 texture split into 3 rows (1 column), each texture being 1200 in height, but I had to get the offset to -0.293 for it to work. I can’t wait till sprites can take multiple textures

1 Like

I have since gotten this to work with tilesources, but not atlases. I forgot to return here and state that, sorry.