四角形の描画

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
lbfuvab

四角形の描画

#1

投稿記事 by lbfuvab » 15年前

環境はXP SP3 + DxLibです。
水面の波の干渉(定常波?)のプログラムを組んでいて、
細かく濃淡をつける必要あったので4x4の大きさの正方形を160x120個書いているのですが(プログラム添付済み
これを2x2の正方形を320x240個にするとガタガタに処理落ちしてしまいます。
調べてみると描画部分が時間を食っていました。

本題に入りますが、どうすれば正方形の描画スピードが上がるのでしょうか、教えてください。
また、目立たないように描画時にぼかしたり出来るのでしょうか?

現在はDrawBoxを使っています。

lbfuvab

Re:四角形の描画

#2

投稿記事 by lbfuvab » 15年前

ファイルの場所は
http://www1.axfc.net/uploader/Sc/so/62775.zip
です。

kazuoni

Re:四角形の描画

#3

投稿記事 by kazuoni » 15年前

描写速度には詳しくないですが・・・
対称性から、半分描写して、それを左右反転したものをもう片方に張り付ける・・・
なんてのはだめですかね^^;

だめですよねorz

lbfuvab

Re:四角形の描画

#4

投稿記事 by lbfuvab » 15年前

>>kazuoniさん
真ん中が自由端と考えて反射ってことですか?
・・・すいません、数学的にどうしたらよいのか思いつきません。

それとも一部を出力してそれを対称性をつかって貼り付けるってことですか?

kazuoni

Re:四角形の描画

#5

投稿記事 by kazuoni » 15年前

> それとも一部を出力してそれを対称性をつかって貼り付けるってことですか?

そっちです。

lbfuvab

Re:四角形の描画

#6

投稿記事 by lbfuvab » 15年前

>>kazuoniさん
できたのですが、
裏画面に1/4だけ書く

MakeGraphでつくった画像(以下a)にコピー

aを反転させながら裏画面に描画

としたのですが、これでは無駄が出るので(逆に遅くなる)

aに描画

aを反転させながら裏画面に描画

としたいのですが、描画先の変更はSetDrawScreen(a);では無理なようです。
どうすれば良いのでしょうか?

kazuoni

Re:四角形の描画

#7

投稿記事 by kazuoni » 15年前

一応作ってみました。
BOX_SIZEを変えれば正方形のサイズが変わります。(2~)

うちの環境では全く処理落ちはしませんが・・・
これ以上効率のいい描写は自分にはわからないです。。すみません。

一応自分のPCのスペック書いときます
Intel(R) Core(TM)2 Duo CPU E6850 @ 3.00GHz (2 CPUs), ~3.0GHz
2046MB RAM
GeForce 8600 GT


#追記
波ではなく、ただ、用意したカラー配列をランダムの色でDrawBoxしているだけです^^;

kazuoni

Re:四角形の描画

#8

投稿記事 by kazuoni » 15年前

×DrawBox(x,y,x+BOX_SIZE-1,y+BOX_SIZE-1,color[rand],true);
○DrawBox(x,y,x+BOX_SIZE,y+BOX_SIZE,color[rand],true);
意味のないことやってました^^;
これでBOX_SIZEは1~になりますね。。

#メリクリ画像のおかげか、新鮮味があり、妙に落ち着かない・・・w

Justy

Re:四角形の描画

#9

投稿記事 by Justy » 15年前


> aに描画

 レンダリング可能なテクスチャは MakeScreenで作ることができます。
 ついでに描画するのはボックスじゃなくて点にして、
最適化して(Releaseで)ビルドすればもっと高速になりそうです。

 実際に早くなったのかどうかはわかりませんが、簡単なサンプルを作ってみました。
 点を一気に描いているので少しは早くなっているかと思いますが、どうですかね?

[color=#d0d0ff" face="monospace]
#include "DxLib.h"
#include <time.h>
#include <stdlib.h>

// 基本値
const int WindowWidth = 640;
const int WindowHeight = 480;
const int BoxSize = 2; // 0~16くらいで


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )
{
srand((unsigned)time(0));

ChangeWindowMode(TRUE);
if(DxLib_Init() == -1) return 0;
SetDrawMode(DX_DRAWMODE_BILINEAR);

const int color_max_num = 128 / BoxSize;
int color[color_max_num];
for(int i=0 ; i<color_max_num ; ++i )
color = GetColor(rand()%255 , rand()%255, rand()%255);

// 仮想画面(レンダーテクスチャ)を作成
const int virtualScreenTexWidth = WindowWidth/BoxSize;
const int virtualScreenTexHeight = WindowHeight/BoxSize;
int virtualScreenTex = MakeScreen(virtualScreenTexWidth, virtualScreenTexHeight);

// 頂点情報
POINTDATA *points = (POINTDATA *)malloc(sizeof(POINTDATA) * (virtualScreenTexWidth * virtualScreenTexHeight));

int count = 0;
char key[256];
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll(key) && !key[KEY_INPUT_ESCAPE])
{
// 仮想画面を描画先に
SetDrawScreen(virtualScreenTex);

// 点を描く
for(int y=0; y<virtualScreenTexHeight; ++y)
{
for(int x=0 ; x<virtualScreenTexWidth; ++x)
{
int pos = x + y * virtualScreenTexWidth;
POINTDATA *p = &points[pos];
p->x = x; p->y = y;
p->color = color[(pos + x * y + count) % color_max_num];
p->pal = 0;
}
}
DrawPixelSet(points, virtualScreenTexWidth * virtualScreenTexHeight);
++count;

// 描画先を裏画面に
SetDrawScreen(DX_SCREEN_BACK);

// 全画面に表示
DrawExtendGraph(0, 0, WindowWidth, WindowHeight, virtualScreenTex, FALSE);

ScreenFlip();
}

free(points);
DeleteGraph(virtualScreenTex);

DxLib_End();
return 0;
}
[/color]

kazuoni

Re:四角形の描画

#10

投稿記事 by kazuoni » 15年前

あ、やっぱりその方法のが高速ですよね^^;
自分もPixelSetのが早いのでは?っと思いながらプログラム組んでいましたが、
そんな関数があるとは・・・。いやはや、DXライブラリ関数を把握せねば。。

#じっくり見ると、細胞みたいで気持ち悪い・・・

Tatu

Re:四角形の描画

#11

投稿記事 by Tatu » 15年前

描画速度を速くする方法はわかりませんが、
私も水面を伝わる波を320*320の範囲内で描画するプログラム
を書いてみました。
止めるときはエスケープキーを押してください。

Rキーではじめの状態に戻します。

波の内容はwave.txtを変更することで変えられます。

描ける波は10個までで、
始点のx座標,始点のy座標,振幅,周期,波長
の値を整数で入れてください。

wave.txtの例

80,160,30,1,4
240,160,30,1,4
160,240,30,2,10
160,80,30,2,10
80,80,10,5,20
240,80,10,5,20
80,240,10,5,20
240,240,10,5,20
160,160,5,10,40
0,0,0,0,0


#include "DxLib.h"
#include <math.h>

#define SIZE_X 320        //横の長さ
#define SIZE_Y 320        //縦の長さ
#define PI 3.14159265    //円周率

char key[256];

//波の情報構造体
typedef struct{
    int x,y;//始点の座標
    int a;//振幅
    int t;//周期
    int l;//波長
}wave_t;

wave_t wave[10];//10個まで


int ProcessLoop(){
    if(ProcessMessage()!=0)return -1;
    if(ClearDrawScreen()!=0)return -1;
    GetHitKeyStateAll(key);
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstatnce,HINSTANCE hPrevInstatnce,LPSTR lpCmdLine,int nCmdShow){
    ChangeWindowMode(TRUE);//
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;

    //初期化
    int i;

    char c[8];            //文字列格納
    int l=0,m=0,n=0;    //行、列、文字の番号

    int x,y;//それぞれのピクセルの座標
    double dx,dy;//ピクセルと波の始点の座標の差
    double r;//ピクセルと始点の距離
    int cnt=0;//描画を始めてからの時間
    double cnt2;//描画を始めてからの時間-始点からピクセルに波が伝わる時間
    double z;//変位 大きいほど白くなる
    int brt;//明るさ

    //白から黒まで256色用意
    int color[256];
    for(i=0;i<256;i++){
        color=GetColor(i,i,i);
    }

    //ファイル読み込み
    FILE* fp;
    fp=fopen("wave.txt","r");
    if(fp == NULL){
        return 0;
    }
    while(l<10){
        for(n=0;n<8;n++){
            c[n]=fgetc(fp);

            if(c[n]==',' || c[n]=='\n'){
                c[n]='\0';
                break;
            }
            if(c[n]==EOF) goto EXFILE;
        }

        switch(m){
            case 0:
                wave[[/url].x=atoi(c);
                break;
            case 1:
                wave[[/url].y=atoi(c);
                break;
            case 2:
                wave[[/url].a=atoi(c);
                break;
            case 3:
                wave[[/url].t=atoi(c);
                break;
            case 4:
                wave[[/url].l=atoi(c);
                break;
        }
        m++;
        if(m==5){
            m=0;
            l++;
        }

    }
EXFILE:
    fclose(fp);
            
    while(ProcessLoop()==0){

        //それぞれのピクセルで計算・描画
        for(y=0;y<SIZE_Y;y++){
            for(x=0;x<SIZE_X;x++){
                z=0;
                //それぞれの波による変位を計算し、足し合わせる
                for(i=0;i<10;i++){
                    //0で割ることを回避
                    //情報のないものを計算しない
                    if(wave.t!=0){
                        dx=x-wave.x;
                        dy=y-wave.y;
                        r=sqrt(dx*dx+dy*dy);
                        //波長/周期=速度
                        cnt2=cnt - r / (wave.l / wave.t );
                        //波がそのピクセルに伝わる時間をこえていたら
                        if(cnt2>0){
                            z+=wave.a * sin(PI*2 / wave.t * cnt2 );
                        }
                    }
                }
                brt=(int)(127+z);
                //ポインタエラー回避
                if(brt<0) brt=0;
                if(brt>255) brt=255;
                DrawPixel(x,y,color[brt]);
            }
        }
        DrawFormatString(0,320,color[255],"cnt=%d",cnt);
        cnt++;//時間経過

        //プログラムを止める
        if(key[KEY_INPUT_ESCAPE]==1) break;
        //最初からやりなおす
        if(key[KEY_INPUT_[/url]==1) cnt=0;

        ScreenFlip();
    }
    DxLib_End();
    return 0;
}

lbfuvab

Re:四角形の描画

#12

投稿記事 by lbfuvab » 15年前

DrawPixelSet使ってプログラム組みなおしたらやや速くなりました(^0^)/
Justyさん有難うございます。
今回はソースも添付しました。
サイズ的に添付できなかったのでアップローダを使ってます。
http://www1.axfc.net/uploader/Sc/so/641 ... tatic_wave

追記:出来たらどれくらいのFPSで動くか教えてください。

kazuoni

Re:四角形の描画

#13

投稿記事 by kazuoni » 15年前

> やや速くなりました

うちの環境では59,60の間をうろうろします。なので、我が家ではほぼ問題なしです。

・・・我が家はですが・・・^^;

Justy

Re:四角形の描画

#14

投稿記事 by Justy » 15年前


> 出来たらどれくらいのFPSで動くか教えてください

 実はうちの環境では最初のものも後のものもさほど変わりませんでした。
 最初のは 58~62、後のは 57~59です。


 あともう十分だとは思いますが折角なので、もちっと高速に描画できる
かもしれない方法も載せておきます。
 SoftImage系を使って点を描画し、最終的にDXライブラリのテクスチャに変換・表示を
しています。

 うちの計測では BoxSize=2で MakeScreen形式だと 2ms~3ms、この方法だと 1msほど、
BoxSize=1で MakeScreen形式だと 10ms~11ms、この方法だと 3~4msほどとなります。


[color=#d0d0ff" face="monospace]#include "DxLib.h"

// 基本値
const int WindowWidth = 640;
const int WindowHeight = 480;
const int BoxSize = 2; // 0~16くらいで


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )
{
ChangeWindowMode(TRUE);
if(DxLib_Init() == -1) return 0;
SetDrawScreen(DX_SCREEN_BACK);

// ソフトイメージを作成
const int softImageWidth = WindowWidth/BoxSize;
const int softImagHeight = WindowHeight/BoxSize;
int memImage = MakePAL8ColorSoftImage(softImageWidth, softImagHeight);

// ソフトイメージ用パレット作成
for(int pal=0; pal<256; ++pal)
SetPaletteSoftImage(memImage, pal, pal, pal, pal, 255);
int tex = CreateGraphFromSoftImage(memImage);

int count = 0;
char key[256];
int fontColor = GetColor(25, 255, 255);

while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll(key) && !key[KEY_INPUT_ESCAPE])
{
// 開始時間
int start = GetNowCount();

// ソフトイメージ上に点を描く
for(int y=0; y<softImagHeight; ++y)
{
for(int x=0 ; x<softImageWidth; ++x)
DrawPixelPalCodeSoftImage(memImage, x, y, (x + y * softImageWidth + x * y + count) % 255);
}
++count;

// テクスチャに変換
ReCreateGraphFromSoftImage(memImage, tex);

// 全画面に表示
DrawExtendGraph(0, 0, WindowWidth, WindowHeight, tex, FALSE);

// 実行時間表示
DrawFormatString(0, 0, fontColor,"%dms", GetNowCount() - start);

ScreenFlip();
}
DeleteSoftImage(memImage);
DeleteGraph(tex);

DxLib_End();
return 0;
}
[/color]

lbfuvab

Re:四角形の描画

#15

投稿記事 by lbfuvab » 15年前

>>Justyさん
有難うございます!
家の古いほうのPC(Pen4 + オンボードのグラボ)でもサクサク動くようになりました。

閉鎖

“C言語何でも質問掲示板” へ戻る