Можно ли оптимизировать этот алгоритм рисования линий? - SDL
Для проекта, над которым я работал, возможность рисовать линии с градиентом (т.е. они меняют цвет в течение интервала, который они рисуют) была бы очень полезна. У меня есть алгоритм для этого, как я вставлю ниже, но он оказывается УЖАСНО медленным. Я использую алгоритм Брезенхэма, чтобы найти каждую точку, но боюсь, что я достиг пределов программного рендеринга. До сих пор я использовал SDL2, и мой алгоритм рисования линий выглядит в 200 раз медленнее, чемSDL_RenderDrawLine
, Это приблизительная оценка, полученная из сравнения времен двух функций, чтобы нарисовать 10000 линий. Моя функция займет около 500 мс, иSDL_RenderDrawLine
сделал это за 2-3мс на моей машине. Я даже протестировал функции с горизонтальными линиями, чтобы убедиться, что это не просто неуклюжий алгоритм Брезенхэма, и заштрихована похожая медленность. К сожалению, SDL не имеет API для рисования линий с градиентом (или, если он есть, я слепой). Я знал, что любой программный рендеринг будет значительно медленнее, чем аппаратный, но сдвиговая величина медлительности застала меня врасплох. Есть ли способ, который можно использовать для ускорения этого? Я только что испортил систему рисования без причины? Я подумал о том, чтобы сохранить массив пикселей, которые я хочу нарисовать, и затем сразу же перенести их на экран, но я не знаю, как это сделать с SDL2, и я не могу найти API в вики. или документация, которая позволяет это. Будет ли это даже быстрее?
Спасибо за внимание!
void DRW_LineGradient(SDL_Renderer* rend, SDL_Color c1, int x1, int y1, SDL_Color c2, int x2, int y2){
Uint8 tmpr, tmpg, tmpb, tmpa;
SDL_GetRenderDrawColor(rend, &tmpr, &tmpg, &tmpb, &tmpa);
int dy = y2 - y1;
int dx = x2 - x1;
/* Use doubles for a simple gradient */
double d = (abs(x1 - x2) > abs(y1 - y2) ? abs(x1 - x2) : abs(y1 - y2));
double dr = (c2.r - c1.r) / d;
double dg = (c2.g - c1.g) / d;
double db = (c2.b - c1.b) / d;
double da = (c2.a - c1.a) / d;
double r = c1.r, g = c1.g, b = c1.b, a = c1.a;
/* The line is vertical */
if (dx == 0) {
int y;
if (y2 >= y1) {
for (y = y1; y <= y2; y++) {
SDL_SetRenderDrawColor(rend, r, g, b, a);
SDL_RenderDrawPoint(rend, x1, y);
r += dr;
g += dg;
b += db;
a += da;
}
return;
}
else{
for (y = y1; y >= y2; y--) {
SDL_SetRenderDrawColor(rend, r, g, b, a);
SDL_RenderDrawPoint(rend, x1, y);
r += dr;
g += dg;
b += db;
a += da;
}
return;
}
}
/* The line is horizontal */
if (dy == 0) {
int x;
if (x2 >= x1) {
for (x = x1; x <= x2; x++) {
SDL_SetRenderDrawColor(rend, r, g, b, a);
SDL_RenderDrawPoint(rend, x, y1);
r += dr;
g += dg;
b += db;
a += da;
}
return;
}
else{
for (x = x1; x >= x2; x--) {
SDL_SetRenderDrawColor(rend, r, g, b, a);
SDL_RenderDrawPoint(rend, x, y1);
r += dr;
g += dg;
b += db;
a += da;
}
return;
}
}
/* The line has a slope of 1 or -1 */
if (abs(dy) == abs(dx)) {
int xmult = 1, ymult = 1;
if (dx < 0) {
xmult = -1;
}
if (dy < 0) {
ymult = -1;
}
int x = x1, y = y1;
do {
SDL_SetRenderDrawColor(rend, r, g, b, a);
SDL_RenderDrawPoint(rend, x, y);
x += xmult;
y += ymult;
r += dr;
g += dg;
b += db;
a += da;
} while (x != x2);
return;
}
/* Use bresenham's algorithm to render the line */
int checky = dx >> 1;
int octant = findOctant((Line){x1, y1, x2, y2, dx, dy});
dy = abs(dy);
dx = abs(dx);
x2 = abs(x2 - x1) + x1;
y2 = abs(y2 - y1) + y1;
if (octant == 1 || octant == 2 || octant == 5 || octant == 6) {
int tmp = dy;
dy = dx;
dx = tmp;
}
int x, y = 0;
for (x = 0; x <= dx; x++) {
SDL_SetRenderDrawColor(rend, r, g, b, a);
switch (octant) {
case 0:
SDL_RenderDrawPoint(rend, x + x1, y + y1);
break;
case 1:
SDL_RenderDrawPoint(rend, y + x1, x + y1);
break;
case 2:
SDL_RenderDrawPoint(rend, -y + x1, x + y1);
break;
case 3:
SDL_RenderDrawPoint(rend, -x + x1, y + y1);
break;
case 4:
SDL_RenderDrawPoint(rend, -x + x1, -y + y1);
break;
case 5:
SDL_RenderDrawPoint(rend, -y + x1, -x + y1);
break;
case 6:
SDL_RenderDrawPoint(rend, y + x1, -x + y1);
break;
case 7:
SDL_RenderDrawPoint(rend, x + x1, -y + y1);
break;
default:
break;
}
checky += dy;
if (checky >= dx) {
checky -= dx;
y++;
}
r += dr;
g += dg;
b += db;
a += da;
}
SDL_SetRenderDrawColor(rend, tmpr, tmpg, tmpb, tmpa);
}
ПРИМЕЧАНИЕ:
Я неохотно просто перехожу к использованию OpenGL 3.0+ (который, как я слышал, поддерживает SDL2), потому что я не знаю, как его использовать. Большинство учебных пособий, которые я нашел, объясняли процесс настройки контекстов с помощью SDL, а затем окрашивали экран одним сплошным цветом, но затем остановились, прежде чем объяснять, как рисовать фигуры и тому подобное. Если бы кто-то мог предложить хорошее место, чтобы начать узнавать об этом, это также было бы чрезвычайно полезно.