[SOLVED] Off-by-one-error in SDL_RenderGeometry()?

Not sure if this is a mathematical problem or a problem in SDL, but the following program renders a red triangle, draws a green edge and marks every point of the triangle with blue:

#include <stdio.h>
#include "SDL.h"

int main(void)
{
  if (SDL_Init(SDL_INIT_EVERYTHING)) {
    printf("Error initializing SDL: %s.\n", SDL_GetError());
    exit(1);
  }
  SDL_Window *window = SDL_CreateWindow("drawtriangle", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 400, 0);
  if (window == NULL) {
    printf("Could not create window: %s.\n", SDL_GetError());
    exit(1);
  }
  SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
  if (renderer == NULL) {
    printf("Could not create renderer: %s.\n", SDL_GetError());
    exit(1);
  }
  SDL_bool quit = SDL_FALSE;
  while (!quit) {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
      if (event.type == SDL_KEYDOWN) {
	if (event.key.keysym.sym == SDLK_ESCAPE) {
	  quit = SDL_TRUE;
	}
      } else if (event.type == SDL_QUIT) {
	quit = SDL_TRUE;
      }
    }
    SDL_SetRenderDrawColor(renderer, 128, 128, 128, 0);
    if (SDL_RenderClear(renderer) < 0) {
      printf("Could not clear renderer: %s.\n", SDL_GetError());
      exit(1);
    }
    SDL_Point points[] = {
      {100, 300},
      {350, 50},
      {600, 300}
    };
    SDL_Vertex vertices[] = {
      {{points[0].x, points[0].y}, {255, 0, 0, 255}, {1, 1}
       },
      {{points[1].x, points[1].y}, {255, 0, 0, 255}, {1, 1}
       },
      {{points[2].x, points[2].y}, {255, 0, 0, 255}, {1, 1}
       }
    };
    SDL_SetRenderDrawColor(renderer, 255, 0, 0, 0);
    SDL_RenderGeometry(renderer, NULL, vertices, 3, NULL, 0);
    SDL_SetRenderDrawColor(renderer, 0, 255, 0, 0);
    SDL_RenderDrawLine(renderer, points[0].x, points[0].y, points[1].x, points[1].y);
    SDL_RenderDrawLine(renderer, points[1].x, points[1].y, points[2].x, points[2].y);
    SDL_RenderDrawLine(renderer, points[2].x, points[2].y, points[0].x, points[0].y);
    SDL_SetRenderDrawColor(renderer, 0, 0, 255, 0);
    SDL_RenderDrawPoint(renderer, points[0].x, points[0].y);
    SDL_RenderDrawPoint(renderer, points[1].x, points[1].y);
    SDL_RenderDrawPoint(renderer, points[2].x, points[2].y);
    SDL_RenderPresent(renderer);
  }
  SDL_DestroyRenderer(renderer);
  renderer = NULL;
  SDL_DestroyWindow(window);
  window = NULL;
  SDL_Quit();
}

Compile with

cc main.c `sdl2-config --cflags --libs` -Wall

Press ESCAPE to quit.

When you look very close or scale the triangle up like this (400% zoom):

… you will see a thin red line left of the green edge on the left. The blue points match the triangle points exactly.

So, for me it looks like SDL_RenderGeometry() does not exactly match the points of the triangle I gave to the function. What am I getting wrong?

System info:

uname -a: Linux bb-ubuntu 5.19.0-45-generic #46~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Wed Jun 7 15:06:04 UTC 20 x86_64 x86_64 x86_64 GNU/Linux

sdl2-config --version: 2.27.1

So the probable cause is a difference between the GPU’s rasterization of the triangle and SDL’s line drawing.

Try the different line drawing hints and see which one works best for your program. Take a look at SDL_hints.h to see what’s available. The one that uses SDL_RenderGeometry() under the hood will probably most closely match your other uses of SDL_RenderGeometry()

You could also try offsetting your points by a half a pixel.

1 Like

Nice:

SDL_SetHint(SDL_HINT_RENDER_LINE_METHOD, "3");  

seems to do the trick:

[Although points aren’t rendered as exactly into the edges as before. But doesn’t matter.]

Thank you very much, @sjr!

[Created a pull request for a wiki page for this hint (not sure why there didn’t exist an entry for this hint - did I miss sth?). Copied it from from it’s commit. Hope this is okay.]

No problem, glad it worked out!

1 Like