1
\$\begingroup\$

I'm trying to animate 2d sprites using glDrawArraysInstanced(), and I'm having trouble separating for each "cycle" ran through the pipeline.

according to one of the tutorials I'm reading, it says:

"Send the age of each particle along with the position, and in the shaders, compute the UVs"

But without clarifying exactly how to do so. This is what my vert shader looks like atm:

#version 400 core
layout ( location = 0 ) in vec3 vertex_position; //vertices, 1 box
layout ( location = 1 ) in vec2 tex_cord; //1 tex cord
layout ( location = 2 ) in vec4 color_vec4; //1 vec4 color per texture
layout ( location = 3 ) in mat4 in_mat; //4 vec4 to make 1 mat4

//flat out int InstanceID; //use but how?

out vec2 UV;
out vec4 color4;

void main()
{
    gl_Position=in_mat*vec4(vertex_position,1.0);

    color4=color_vec4;
    UV=tex_cord;
}

And my frag shader:

#version 400 core
in vec2 UV;
in vec4 color4;

uniform sampler2D png_tex;  //texture atlas

void main()
{
    gl_FragColor=texture(png_tex,UV)*color4;
}

Does anyone know how to get the vec2-uv coordinate to change/cycle, when using instanced drawing?

Solution:

adding this to my vert shader:

UV=vec2
(
(tex_cord.x/info_vec4.z)+(1.0/info_vec4.z*info_vec4.x),
(tex_cord.y/info_vec4.w)+(1.0/info_vec4.w*info_vec4.y)
);

I know this can be done cleaner, but I'm not sure exactly how atm. This works however, and its alot faster than having to pass a new png/texture per update. The explanation for it is: info_vec4 is an ivec that I pass as an attribute with information of the current primitive/triangle. It holds: x=xcord (1-5), y=ycord (only 1), z=number of x frames total, and w=number of y total. The trick was figuring out how to iron out UV.x=0, basically by adding 1*somevalue to 0.

\$\endgroup\$
1
\$\begingroup\$

As the tutorial suggests you should send the age or the frame number along with the instanced position.

On top of that you'll want to set 2 parameters one for how many frames you have horizontally and one for how many you have vertically.

Then you simply do:

uv.X = (frameNum % horiontalFrames)/horizontalFrames;
uv.Y = floor(frameNum/horizontalFrames)/verticalFrames;

This assumes of course that your animation frames are evenly spaced inside a texture and don't have any offset to the edges etc.

\$\endgroup\$
  • \$\begingroup\$ inside the shader? Each pass eats up a vec2, but I cant generate 3 vec2's and differentiate between them that way. Do I really need to use a vertex id and hardcode the uv kord for each vertice? I dont feel like passing texture coords for each triangle/primitive \$\endgroup\$ – Charlie Aug 7 '16 at 2:34
  • \$\begingroup\$ No idea what you are asking me. You know how you are passing data for every instance? Pass extra data like a frame number for that instance. You are not setting vertex data, you are setting instance data. \$\endgroup\$ – Nils Ole Timm Aug 7 '16 at 18:01
  • \$\begingroup\$ Im working on the solution, you put me on the right track. Ill give you the accepted answer once this works (something about understanding how the GPU runs through the attributes per vert and per primitive) \$\endgroup\$ – Charlie Aug 7 '16 at 19:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.