Problem rendering a textured rect with SDL_RenderGeometryRaw

I’m trying to create a spritesheet that generates two-triangle textured rects based on the sprite test in SDL. I decided not to use SDL_Vertex or SDL_RenderGeometry and just use SDL_RenderGeometryRaw with a single array of floats interleaving x,y and u,v values. I’m currently just trying to render a single rect but despite everything looking correct, nothing at all renders. I know the texture is loaded because it renders with SDL_RenderCopy.

I’m posting asking if someone more familiar with this can tell me what I’ve gotten wrong here. Unfortunately, Google doesn’t really help. I’ve deleted irrelevant stuff like allocation/reallocation etc.

typedef struct Spritesheet {
	int num_vertices, topindex;
	float* vertices; // interleaved x,u,y,v
} Spritesheet;

static void PushSprite(Spritesheet* s, SDL_FRect* dstrect)
{
	
	/*
	 *   0--1
	 *   |\ |
	 *   | \|
	 *   3--2
	 */

	//0
	s->vertices[s->topindex++] = dstrect->x;
	s->vertices[s->topindex++] = dstrect->y;
	s->vertices[s->topindex++] = 0.0f;
	s->vertices[s->topindex++] = 0.0f;

	//1
	s->vertices[s->topindex++] = dstrect->x + dstrect->w;
	s->vertices[s->topindex++] = dstrect->y;
	s->vertices[s->topindex++] = 1.0f;
	s->vertices[s->topindex++] = 0.0f;

	//2
	s->vertices[s->topindex++] = dstrect->x + dstrect->w;
	s->vertices[s->topindex++] = dstrect->y + dstrect->h;
	s->vertices[s->topindex++] = 1.0f;
	s->vertices[s->topindex++] = 1.0f;

	//0
	s->vertices[s->topindex++] = dstrect->x;
	s->vertices[s->topindex++] = dstrect->y;
	s->vertices[s->topindex++] = 0.0f;
	s->vertices[s->topindex++] = 0.0f;

	//2
	s->vertices[s->topindex++] = dstrect->x + dstrect->w;
	s->vertices[s->topindex++] = dstrect->y + dstrect->h;
	s->vertices[s->topindex++] = 1.0f;
	s->vertices[s->topindex++] = 1.0f;

	//3
	s->vertices[s->topindex++] = dstrect->x;
	s->vertices[s->topindex++] = dstrect->y + dstrect->h;
	s->vertices[s->topindex++] = 0.0f;
	s->vertices[s->topindex++] = 1.0f;
}

static void RenderSprites(SDL_Renderer* ren, Spritesheet* s, SDL_Texture* tex)
{
	SDL_Color color;
	int stride = sizeof(float) * 4;
	SDL_GetRenderDrawColor(ren, &color.r, &color.g, &color.b, &color.a);
	SDL_RenderGeometryRaw(ren, tex, &s->vertices, stride, &color, 0, &s->vertices[2], stride, s->topindex, NULL, 0, 0);
}

edit: I kept getting uv errors so I looked at the source for SDL_RenderGeometryRaw, and it looks like it expects those values to be adjacent, so I rewrote the interleaving and the updated code is replaced above.

However, now I get the following: Values of ‘uv’ out of bounds 0.000000 0.000000 at 9/24, but that shouldn’t be out of bounds?

First, using topindex as the number of vertices in your SDL_RenderGeometryRaw() call will be wrong. You only have 6, yet by the time you get to the actual draw call it’ll be 24 (because you have 24 s->vertices[s->topindex++] lines). So you’re telling SDL to draw 24 vertices, yet you don’t have 24 vertices in your array, so whatever junk data happens to be in memory past vertex #6 blows up SDL’s sanity checks.

Second, it may not like vertex position and texcoord being interleaved but color being separate.

1 Like

Thanks, that turned out to be one of several issues. I just managed to get it working:


typedef struct Spritesheet
{
	SDL_Texture* tex;
	SDL_Color color;
	int vert_cap, topvertex;
	float* vertices;
} Spritesheet;

static void PushSprite(Spritesheet* s, SDL_FRect* dstrect)
{
	float
		x = dstrect->x,
		y = dstrect->y,
		w = x + dstrect->w,
		h = y + dstrect->h;
	
	SDL_memcpy(&s->vertices[s->topvertex], (float[24]) {
		x, h, 0, 0,
		w, h, 1, 0,
		w, y, 1, 1,
		x, h, 0, 0,
		w, y, 1, 1,
		x, y, 0, 1
	}, sizeof(float) * 24);
	
	s->topvertex += 24;
	
}

static void RenderSprites(SDL_Renderer* ren, Spritesheet* s)
{
	
	int stride = sizeof(float) * 4;
	int num_vertices = s->topvertex / 4;
	int code;
	if ((code = SDL_RenderGeometryRaw(ren, s->tex, s->vertices, stride, &s->color, 0, &s->vertices[2], stride, num_vertices, NULL, 0,0)) != 0)
	{
		SDL_Log("Error rendering geometry: %s", SDL_GetError());
		exit(code);
	}
}

:grinning: