2

私は C++ を初めて使用しますが、この言語は私には問題ないようです。学習プロジェクトとして、マイナーな 2D グラフィック エンジンを作成することにしました。難しいプロジェクトのように思えるかもしれませんが、先に進む方法はよくわかります。

私はまだ実際に始めていませんが、この問題に遭遇したとき、頭の中で物事を形成しています。ある時点で、画面に円を描く関数を作成する必要があります。現時点での私のアプローチは次のようになります。

in a square with sides from (x-r) to (x+r) loop through x and y,
if at each point, the current distance sqr(x^2+y^2) is less than or equal to r
, then draw a pixel at that point.

これは機能しますが、そうでない場合は、気にしないでください。解決します。x+r & y+r が画面上にある場合にのみ、この円を描画します。

問題は、ときどき本当に大きな円を描く必要があることです。たとえば、半径 5000 の円を描く必要がある場合、(ピクセル ループ計算で合計 10000^2 回ループする必要がある場合)。したがって、2Ghz のプロセッサでは、この 1 つの円は 2Ghz/(10000^2) しかレンダリングできません。これは、コア全体を占有しながら、毎秒 22 回です (ピクセルごとに 1 回の計算しか必要としないと考えてください)。真実)。

現在、どのアプローチが正しいですか?これらの単純な計算にGFXを使用していることに関係があると思います. もしそうなら、これに C++ 用の OpenGL を使用できますか? 私もそれを学びたいです:)

4

4 に答える 4

2

画面にピクセルを手動で描画してグラフィックスを作成するのではなく、狂気があります。

使用したいのはDirectXまたはOpenGLのいずれかです。私はあなたがグーグルを開いて読んで行くことを提案します、そこに読むべきことがたくさんあります。

ライブラリをダウンロードしたら、確認するサンプルプロジェクトがたくさんあり、それらを使用して開始できます。

この時点で2つのアプローチがあります。非常に多数の辺を持つ形状を表すベクトルを数学的に計算する方法があります(つまり、円のように見えます)。または、アルファチャネルを使用して円のテクスチャ(つまり画像)を画面に描画して、残りのテクスチャを透明にする「不正行為」方法があります。(不正行為の方法は、柔軟性は劣りますが、コーディングが簡単で、実行が速く、より良い結果が得られます)。

数学的に行いたい場合は、これらのライブラリの両方で画面に線を引くことができるため、個々のピクセルではなく、各線の始点と終点の観点からアプローチを開始する必要があります。つまり、ベクターグラフィックが必要です。

現在、重い計算を行うことはできませんが、ベクトルアプローチは次のようになります(sudo-code):

in-param: num_of_sides, length_of_side;
float angle = 360 / num_of_sides;
float start_x = 0;
float start_y = 0;

x = startX;
y = startX;
for(int i(0); i < num_of_sides; ++i)
{
  float endX, endY;
  rotateOffsetByAngle(x, y, x + lenth_of_side, y, angle * i, endX, endY);
  drawline(x, y, endX, endY);
  x = endX;
  y = endY;
}


drawline(float startX, startY, endX, endY)
{
  //does code that draws line between the start and end coordinates;
}

rotateOffsetByAngle(float startX, startY, endX, endY, angle, &outX, &outY)
{
  //the in-parameters startX, startY and endX, endY describe a line
  //we treat this line as the offset from the starting point

  //do code that rotates this line around the point startX, startY, by the angle.
  //after this rotation is done endX and endY are now at the same
  //distance from startX and startY that they were, but rotated.

  outX = endX;
  outY = endY; //pass these new coordinates back out by reference;

}

上記のコードでは、円の外側を移動して、外側の周りに個々の線を1つずつ描画します。始点とオフセットがある各線について、オフセットをある角度だけ回転させます(この角度は円の周りを移動するにつれて増加します)。次に、始点からオフセット点まで線を引きます。次の反復を開始する前に、開始点をオフセット点に移動して、次の行が最後の行の終わりから開始するようにします。

それが理解できることを願っています。

于 2012-10-29T11:41:08.180 に答える
1

これは、塗りつぶされた円を描く 1 つの方法です。ご覧のとおり、パフォーマンスは非常に遅くなります。

最新のグラフィックスは、最適化できるように低レベルのものを抽象化することに基づいています。開発者は drawCircle(x,y,r) を記述し、グラフィックス ライブラリ + ドライバーはそれをチップに渡すことができ、チップは適切なピクセルを埋めることができます。

C++ で書いていますが、グラフィックス ドライバーを使用しない限り、コアに最も近いデータを操作していません。setPixelColour レベルのメソッドとネットワーク上で渡される実際のバイナリ値の間にさえ、サブルーチン呼び出しの層があります。ほとんどすべてのレイヤーでチェックが行われ、追加の計算とルーチンが実行されます。したがって、グラフィックスを高速化する秘訣は、これらの呼び出しの回数を減らすことです。コマンド drawCircle をグラフィック チップまで取得できる場合は、それを行います。通常の形状を描画するのと同じくらい平凡な場合は、1 つのピクセルの呼び出しを無駄にしないでください。

最新の OS では、グラフィックス処理のレイヤーがあり、ユーザーのような個々のアプリケーションの要求を受け取り、それらをウィンドウ処理、合成、およびその他の効果と組み合わせます。したがって、「画面に描画」するコマンドは、すでにいくつかのレイヤーによって仲介されています。CPU に提供する必要があるのは、計算をグラフィックス サブシステムにオフロードするために必要な最小限の情報です。

開発サイクルは簡単で比較的痛みが少ないので、画面に何かを描く方法を学びたい場合は、canvas と js で遊んでください。C++ を学習したい場合は、プロジェクト Euler を試すか、既存のグラフィック ライブラリを使用して描画してください。2D グラフィックス ライブラリを作成する場合は、DirectX や OpenGL などの基礎となるグラフィックス テクノロジを学習してください。これらは実際にグラフィックスを作成する方法であるためです。しかし、それらは非常に複雑に見えますね。次に、最初に C++ をさらに学習する必要があります。結果が複雑であっても、いくつかの非常に正当な理由があります。

于 2012-10-29T11:59:46.787 に答える
1

最初の答えが言うように、深刻な作業のためにこれを自分で行うべきではありません。しかし、例としてこれを行いたい場合は、次のようにすることもできます: 最初に、画面に線分を描画するための関数を定義します:

void draw_line(int x1, int y1, int x2, int y2);

これは比較的簡単に実装できます。最も速く変化する方向を見つけて、整数ロジックを使用しながらその方向を反復処理して、他の次元がどれだけ変化するかを調べます。つまり、x がより速く変化している場合、y = (x-x1)*(y2-y1)/(x2-x1).

次に、この関数を使用して円を区分線要素として実装します。

void draw_circle(int x, int y, int r)
{
    double dtheta = 2*M_PI/8/r;
    int x1 = x+r, x2, y1 = y, y2;
    int n = 2*M_PI/dtheta;
    for(int i = 1; i < n; i++)
    {
        double theta = i*dtheta;
        x2 = int(x+r*cos(theta)); y2 = int(y+r*sin(theta));
        draw_line(x1, y1, x2, y2);
        x1 = x2; y1 = y2;
    }
}

これは、浮動小数点論理と三角関数を使用して、どの線要素が最も円に近いかを判断します。これはやや大雑把な実装ですが、非常に大規模なサークルに対して効率的な実装を行うには、このようなことを行う必要があると思います。

整数ロジックの使用のみが許可されている場合、最初に低解像度の整数円を描画し、次に選択した各ピクセルをより小さなピクセルに分割し、そこに必要なサブピクセルを選択するという 1 つの方法が考えられます。これは N log N としてスケーリングされるため、上記のアプローチよりもさらに遅くなります。しかし、あなたはsinとcosを避けることができるでしょう。

于 2012-10-29T11:59:57.250 に答える