私が取り組んでいるプロジェクトでは、グラデーションを使用して線を描画する機能 (つまり、描画される間隔で色が変わる) は非常に便利です。以下に貼り付けるように、これにはアルゴリズムがありますが、非常に遅いことが判明しました。Bresenham アルゴリズムを使用して各点を見つけていますが、ソフトウェア レンダリングの限界に達したのではないかと心配しています。これまで SDL2 を使用してきましたが、私の線画アルゴリズムは より 200 倍遅く見えますSDL_RenderDrawLine
。これは概算であり、2 つの関数が 10,000 行を描画する時間を比較して算出したものです。私の関数は500ミリ秒近くかかり、SDL_RenderDrawLine
私のマシンでは2〜3ミリ秒でそれを行いました。私は水平線を使って関数をテストし、ブレゼンハム アルゴリズムが失敗しただけではなく、同様の速度低下が発生したことを確認しました。残念ながら、SDL にはグラデーションを使用して線を描画するための API がありません (あるとしても、私は盲目です)。ソフトウェアのレンダリングはハードウェアよりも大幅に遅くなることはわかっていましたが、その遅さの圧倒的な大きさに驚かされました。これを高速化するために使用できる方法はありますか? 理由を超えて描画システムを台無しにしてしまったのでしょうか? 描画したいピクセルの配列を保存してから、それらを一度に画面に表示することを検討しましたが、SDL2 でこれを行う方法がわからず、wiki で 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 を使用してコンテキストを設定し、画面を単色で着色するプロセスについて説明していましたが、図形の描画方法などを説明する前に停止します。誰かがこれについて学び始めるのに適した場所を提供できれば、それも非常に役に立ちます.