0 votes

I need this for my 3D plane. I have a single png file containing several sprites and I want to show a certain sprite onto my 3D plane mesh using shadermaterial with params such as vframes(number of frames vertical), hframes(number of frames horizontally), frames(current shown frame), and texture. Basically I want a shadermaterial that works just like the 2D Sprite node's animation properties.

I could just use a viewport and sprites to draw the spite I want and return the viewport's texture to my 3d mesh material or manually separate the large png file into several smaller files. But that would make the game I am making run a tad bit slower. I want to use a single large png file for all my sprites so that the file will be cached during gameplay allowing better performance compared to loading many different files.

I've been reading the docs on shading language but I can't seem to get an idea on how to specifically show only a part of the large png file using shaders. Please guide me senpais.

in Engine by (271 points)

1 Answer

+1 vote
Best answer

here you have a variant with texture interpolation ... have'nt tested, but this is the way to go.

frameSize = vec2(0.2,0.2); // the frame size in frations ... this is a a frameset 5 x 5
frameOffset = vec2(0.4,0.2); // the frame 3rd row 2nd column
uv_to_frame = uv * frameSize; //scale uv down to frame size
uv_to_frame = mod(uv_to_frame,frameSize); //modulo uv to handle repetition
uv_to_frame += frameOffset; //shift uv to frame
vec4 texelColor = texture ( textureSampler, uv_to_frame );

// for unfiltered pixels you have to do this
uv_to_frame *= textureSize(textureSampler,0 )
vec4 texelColor = texelFetch( textureSampler, uv_to_frame,0 );
by (4,084 points)
selected by

Thank you! I was able to make it thanks to your guidance :D
my code looks like this:

uniform int hframe : hint_range(1,128);
uniform int vframe : hint_range(1,128);
uniform vec2 current_frame = vec2(0,0);

void fragment() {
    vec2 base_uv = (UV / vec2(float(hframe),float(vframe)));
    base_uv += current_frame/vec2(float(hframe),float(vframe));
    vec4 albedo_tex = texture(texture_albedo,base_uv);

It works, thank you so much klaas.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.