BlitzBasic schneller als C/C++?



  • Die Überschrift klingt ein wenig provozierend. Doch ich will keine Diskussion welches schneller ist.
    Es geht darum das ich sehen wollte ob BlitzBasic wirklich so schnell ist.
    Ich habe ein Programm gefunden das eine auf DirectDraw7 basierende 3D Voxel-Landschaft zeichnet. Dieses Programm übersetzte ich in C/C++.

    Das Ergebniss

    C/C++ beim Start 60FPS
    BB    beim Start 19FPS
    

    Mein System 3.06Mhz Pentium4, Radeon 9600pro, 1024MB Ram, WinXP

    Aber nur bei mir.

    System 1500Athlon 4200Ti

    C/C++ beim Start 28FPS
    BB    beim Start 30FPS
    

    System 900Athlon 4200Ti

    C/C++ ~20-30FPS
    BB    konstant 25FPS
    

    Ich habe wirklich angenommen das C/C++ um einiges schneller ist. Was ja bei mir auch so ist. Woran könnte es liegen? Für den interessierten habe ich hier mal ein paar Infos und den Quellcode reingepackt.

    Wenn ihr hier eure Werte eintragen würdet, währe echt toll.

    Informationen

    Hier könnt ihr beide Versionen runterladen http://mitglied.lycos.de/gidxgraphic/
    (etwas runterscrollen)

    Die BB Version findet ihr hier
    http://www.blitzforum.de/viewtopic.php?t=4733

    Infos zu BlitzBasic
    http://www.blitzbasic.com/

    Achtung, ich habe den ganzen Quellcode in eine Seite gepackt, es läuft trotzdem!

    ////////////////////////////////////////////////////////////////////////////
    // Dies und das
    ////////////////////////////////////////////////////////////////////////////
    #define DIRECTDRAW_VERSION   0x0700
    #define Title     "Voxelgrafik mit DirectDraw"
    #define ClassName "VOXEL"
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <stdio.h>
    #include <math.h>
    
    #pragma comment(lib,"dxguid.lib")
    #pragma comment(lib,"ddraw.lib")
    #pragma comment(lib,"winmm.lib")
    
    #include <mmsystem.h>
    #include <stdio.h>
    #include <ddraw.h>
    
    #define UTIL_DELETE(p) {if(p){delete[](p);(p)=NULL;}}
    #define UTIL_DELETE_ARRAY(p) {if(p){delete[](p);(p)=NULL;}}
    
    ////////////////////////////////////////////////////////////////////////////
    // GRAFIK KLASSE
    ////////////////////////////////////////////////////////////////////////////
    class CGraphic
    {
    private:
    	int						m_iLength;
    	int						m_dwBPP;
    	int						m_dwX;
    	int						m_dwY;
    	WORD					*m_Vram;
    	DWORD					m_dwMaskRed;
    	DWORD					m_dwMaskGreen;
    	DWORD					m_dwMaskBlue;
    	HRESULT					m_ddrval;
        DDSURFACEDESC2			m_ddsd;
    	LPDIRECTDRAW7			m_lpDD;
    	LPDIRECTDRAWSURFACE7	m_lpDDSPrimary;
    	LPDIRECTDRAWSURFACE7	m_lpDDSBack;
    public:
    	CGraphic();
    	virtual ~CGraphic();
    	bool initDirectDraw(HWND hwnd,int x,int y);
    	bool clearBackBuffer(WORD color);
    	bool lockBackbuffer();
    	bool putPixel(int x, int y, DWORD color);
    	bool unlockBackbuffer();
    	bool flip();
    	void print(int x, int y, char* text);
    	DWORD color(int red, int green, int blue);
    };
    
    CGraphic::CGraphic()
    {
    	m_dwBPP			=16;  //Auflösung auf 16 Bit festlegen
    	m_lpDD			=NULL;
    	m_lpDDSPrimary  =NULL; 
    	m_lpDDSBack     =NULL; 
    }
    
    CGraphic::~CGraphic()
    {
    	if(m_lpDD != NULL)
        {
    		if(m_lpDDSPrimary != NULL) 
    		{ 
    			m_lpDDSPrimary->Release();
    			m_lpDDSPrimary = NULL;
    			m_lpDDSBack    = NULL;
    		} 
    		m_lpDD->Release();
    		m_lpDD = NULL;
         }
    }
    
    bool
    CGraphic::initDirectDraw(HWND hwnd,int xoffset,int yoffset)
    {	
    	m_dwX=xoffset;
    	m_dwY=yoffset;
    
    	DDSURFACEDESC2			ddsd;       
        DDSCAPS2				ddscaps;
    
    	m_ddrval = DirectDrawCreateEx(NULL, (VOID **)&m_lpDD, IID_IDirectDraw7, NULL); 
    	if(m_ddrval == DD_OK) 
    		m_ddrval =m_lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN );
    		if(m_ddrval == DD_OK) 
    			m_ddrval = m_lpDD->SetDisplayMode(xoffset, yoffset, m_dwBPP, 0, 0);
    			if(m_ddrval == DD_OK) 
    				ZeroMemory(&ddsd, sizeof(ddsd));
    				ddsd.dwSize = sizeof(ddsd); 
    				ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; 
    				ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | 
    						              DDSCAPS_COMPLEX;
    				ddsd.dwBackBufferCount = 1;
    				m_ddrval = m_lpDD->CreateSurface(&ddsd, &m_lpDDSPrimary, NULL);
    				if(m_ddrval == DD_OK) 
    					ZeroMemory(&ddscaps, sizeof(ddscaps));
    					ddscaps.dwCaps = DDSCAPS_BACKBUFFER; 
    					m_ddrval = m_lpDDSPrimary->GetAttachedSurface(&ddscaps, &m_lpDDSBack);
    					if(m_ddrval == DD_OK) 
    						ZeroMemory(&ddsd, sizeof(ddsd));
    						ddsd.dwSize=sizeof(ddsd);
    						m_ddrval = m_lpDD->GetDisplayMode(&ddsd);
    						if(m_ddrval == DD_OK)
    							m_dwMaskRed  = ddsd.ddpfPixelFormat.dwRBitMask;
    							m_dwMaskGreen= ddsd.ddpfPixelFormat.dwGBitMask;
    							m_dwMaskBlue = ddsd.ddpfPixelFormat.dwBBitMask;
    							return true;
    	return false;
    }//InitDirectDraw
    
    bool 
    CGraphic::clearBackBuffer(WORD color)
    {
    	RECT	rect;
    	DDBLTFX	ddbltfx;
    	ddbltfx.dwSize=sizeof(DDBLTFX);
    	ddbltfx.dwFillColor=color;  
    	SetRect(&rect,0,0,m_dwX,m_dwY);
    
    	m_ddrval=m_lpDDSBack->Blt(&rect,NULL,&rect,DDBLT_COLORFILL|DDBLT_WAIT,&ddbltfx);
    	if(m_ddrval != DD_OK)
    		return false;
    
    	return true;
    }//SetFtColor
    
    bool
    CGraphic::lockBackbuffer()
    { 	
        ZeroMemory(&m_ddsd, sizeof(m_ddsd));
        m_ddsd.dwSize = sizeof(m_ddsd);
        m_ddrval=m_lpDDSBack->Lock(NULL, &m_ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
    	if(m_ddrval != DD_OK)
    		return false;
    	return true;
    }//Lock
    
    bool
    CGraphic::unlockBackbuffer()
    {
        m_ddrval=m_lpDDSBack->Unlock(NULL);
    	if(m_ddrval!= DD_OK)
    		return false;
    	return true;
    }//Unlock
    
    bool  
    CGraphic::putPixel(int x, int y, DWORD color)
    { 
    	//Ist Pixel auserhalb des sichtbereichs...?
    	if(x<0 || x>m_dwX-1 || y<0 || y>m_dwY-1) 
    		return true;
        //...sonst Pixel setzen
        m_iLength = m_ddsd.lPitch>>1;
        m_Vram = (WORD*)m_ddsd.lpSurface;
        m_Vram[x + y*m_iLength] = (WORD)color;
    
        return true;
    }//PutPixel
    
    bool 
    CGraphic::flip()
    {
    	HRESULT ddrval;
    	ddrval=m_lpDDSPrimary->Flip(NULL,DDFLIP_WAIT);
    	if(ddrval==DD_OK) return true;
    	else if(ddrval == DDERR_SURFACELOST)
    	{
    		ddrval = m_lpDDSPrimary->Restore();
    		if(ddrval != DD_OK)
    			return false;
    
    		ddrval=m_lpDDSPrimary->Flip(NULL,DDFLIP_WAIT);
    		if(ddrval!=DD_OK)
    			return false;
    		return true;
    	}
    	return true;
    }//PageFlip
    
    DWORD 
    CGraphic::color(int rot, int gruen, int blau)
    {	 
    	return(((DWORD)(m_dwMaskRed  *(rot/2.55/100)))  &(DWORD)m_dwMaskRed)  +
    		  (((DWORD)(m_dwMaskGreen*(gruen/2.55/100)))&(DWORD)m_dwMaskGreen)+
    		  (((DWORD)(m_dwMaskBlue *(blau/2.55/100))) &(DWORD)m_dwMaskBlue);
    }//Color
    
    void
    CGraphic::print(int x, int y, char* text) 
    { 
    	HFONT hfont;
        HDC hdc=NULL;
    
        if(m_lpDDSBack->GetDC(&hdc)==DD_OK) 
        { 
    		hfont=CreateFont(15,0,0,0,0,0,0,0,0,0,0,0,FIXED_PITCH,0);
    		SelectObject(hdc,hfont);
            SetBkMode(hdc,TRANSPARENT); 
            SetTextColor(hdc,0x00FF00); 
            TextOut(hdc,x,y,text,lstrlen(text));
            DeleteObject(hfont);
    		m_lpDDSBack->ReleaseDC(hdc);
    		hdc=NULL;
        } 
    }//Print
    
    ////////////////////////////////////////////////////////////////////////////
    // HILFSFUNKTIONEN
    ////////////////////////////////////////////////////////////////////////////
    CGraphic *gx=new CGraphic;
    float	 *sinus;
    float	 *cosinus;
    
    void 
    util_Print(int x, int y, char* text,...)
    {  
    	char textBuffer[512];
    	va_list args;
    	va_start(args, text);
    	vsprintf(textBuffer, text, args);
    	va_end(args);
    	gx->print(x,y,textBuffer);
    }
    
    bool 
    util_LoadTexture(char *file, DWORD *array)
    {
    	FILE *dat_ein;
    	BITMAPFILEHEADER	BmFileHeader;
    	BITMAPINFOHEADER    BmInfoHeader;
    	WORD				bmHeight;
    	WORD				bmWidth;
    	DWORD			   *temp;
    	BYTE			    r,g,b;
    	BOOL                bDone  = FALSE;
    	int					EndByte=0;
    	if((dat_ein=fopen(file,"rb"))==NULL)
    	{
    		return false;
    	}
    	fread(&BmFileHeader,sizeof(BITMAPFILEHEADER),1,dat_ein);
        fread(&BmInfoHeader,sizeof(BITMAPINFOHEADER),1,dat_ein);
    	bmHeight=(WORD)BmInfoHeader.biHeight;
    	bmWidth =(WORD)BmInfoHeader.biWidth;
        if ((BmInfoHeader.biSizeImage - bmWidth * bmHeight * 3) == 0)
        {
            EndByte = 0; 
        }
        else 
        {
            EndByte = (BmFileHeader.bfSize - 54 - bmWidth * bmHeight * 3) / bmHeight; 
        }
    	temp = new DWORD[bmWidth * bmHeight];
        int count = bmWidth * bmHeight - 1;
    	while (!feof(dat_ein))
        {
            for (int i = 0; i < bmWidth; i++)
            {
                if (!feof(dat_ein))
                {
    				fread (&b, sizeof(BYTE), 1, dat_ein);
                }
                else
                {
                    bDone = TRUE;
                    break;
                }
                if (!feof(dat_ein))
                {		
    
                    fread (&g, sizeof(BYTE), 1, dat_ein);
                }
                else
                {
                    bDone = TRUE;
                    break;
                }
                if (!feof(dat_ein))
                {
                    fread (&r, sizeof(BYTE), 1, dat_ein);
                }
                else
                {
                    bDone = TRUE;
                    break;
                }		
    			temp[count] = gx->color(r,g,b);
                count--; 
            }
            if (!bDone)
            { 
                fseek(dat_ein, EndByte, SEEK_CUR);
            }
            else
            {
                break;
            }
        }
    	fclose(dat_ein);
    	count=0;
        for (int y = 0; y < bmHeight; y++)
        {
            for (int x = bmWidth - 1; x > -1; x--)
            {
    			array[x*bmHeight+y]=temp[count];
                count++;	
            }		
        }
        delete [] temp;
    	return true;
    }//loadTexture
    
    void util_CreatLockUp()
    {   //LockUp Tabelle für Sinus und Cosinus Werte erstellen
    	for(long winkel=0;winkel<360;winkel++)
    	{
    		sinus[winkel]=sinf(winkel*3.141592654f/180.0f);
    		cosinus[winkel]=sinf(winkel*3.141592654f/180.0f);
    	}
    }//CreateLockUp
    
    ////////////////////////////////////////////////////////////////////////////
    // RAYCAST FUNKTION
    ////////////////////////////////////////////////////////////////////////////
    //HeightMap und Textur
    DWORD *ptextur=new DWORD[256*256];
    DWORD *phmap=new DWORD[256*256];
    
    //Raycast
    int grw=640; 
    int grh=480; 
    int grwh=grw/2; 
    int grhh=grh/2;
    int row;
    int grwh_mi;
    int h;
    int co;
    int c;
    int xpos;
    int zpos;
    float my=0; 
    float px=8.0f; 
    float pz=8.0f; 
    float a=0; 
    double rayx;
    double rayz;
    double s1,s2;
    double *stepx=&s1;
    double *stepz=&s2;
    
    //Strahlenfunktion. Zeichnet die Landschaft
    inline 
    void raycast()
    {
    	gx->lockBackbuffer();
    	for(int i=-grwh; i<=grwh; i+=1)//step
    	{
    		row=grh+1;
    		grwh_mi=grwh-i;
    		rayx=px;
    		rayz=pz;
    		*stepx=sin(a+0.002*i); 
    		*stepz=cos(a+0.002*i);
    		for(int count=1; count<199; count++)
    		{
    			rayx+=*stepx; 
    			rayz+=*stepz;
    			if(rayx>-127 && rayx<127)
    			{			
    				xpos=(int)rayx;				
    				if(rayz>-127 && rayz<127)
    				{	
    					zpos=(int)rayz;
    					c=(phmap[(xpos+127)*256+zpos+127]);
                        h=(int)( (15000-my*100)-((0.1*my+30)*c) )/count;
    					if(h<row)
    					{
    						if(c<1)
    							co=0x465DFF;
    						else
    							co=(ptextur[(xpos+127)*256+zpos+127]);
    
    						for(int ii=h; ii<row; ii++)
    							if(grwh_mi>0 && grwh_mi<grw && ii>0 && ii<grh)
    								gx->putPixel(grwh_mi,ii,co);
    						row=h;
    					}//if(h<row)
    				}//if((rayz>-127 && rayz<127)
    			}//(rayx>-127 && rayx<127)
    		}//for(int count=1; count<250; count=count+1)
    	}//for(int i=-grwh; i<grwh-1; i++)
    	gx->unlockBackbuffer();
    }//raycast()
    
    ////////////////////////////////////////////////////////////////////////////
    // WINDOWS
    ////////////////////////////////////////////////////////////////////////////
    //Windows
    bool  bRunning;
    HWND  hwnd;
    //FPS
    unsigned long FPSTimer;
    int FPS;
    int FPSCounter;
    
    LRESULT CALLBACK 
    WinProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
    {
    	switch(message)
    	{
        case WM_KEYDOWN: 
    		switch (wparam) 
    		{
    		case (int)'A':
    			a=a+0.05f;
    			break;
    		case (int)'D':
    			a=a-0.05f;
    			break;
    		case (int)'W':
    
    			break;
    		case (int)'S':
    
    			break;
    		case VK_UP:
    
    			break;
    		case VK_DOWN:
    
    			break;
    		case VK_LEFT:
    
    			break;
    		case VK_RIGHT:
    
    			break;
    		case VK_ESCAPE: 
    			DestroyWindow(hwnd); 
    			break;
    		}
    		break; 
    	case WM_CLOSE:
    	case WM_DESTROY: 
    	{	
    		bRunning = false;
    		PostQuitMessage(0);
    		return 1;
    	}break;
    	default:break;
    	}//switch
    	return (DefWindowProc(hwnd, message, wparam, lparam));
    } // WindowProc
    
    int 
    WINAPI WinMain(	HINSTANCE hinst,HINSTANCE hprevinst,LPSTR lpcmdline,int ncmdshow)
    {
    	WNDCLASSEX	winclass;
    	MSG			message;
    
    	winclass.cbSize				= sizeof(WNDCLASSEX);
    	winclass.style				= CS_HREDRAW | CS_VREDRAW;
    	winclass.lpfnWndProc		= WinProc;
    	winclass.cbClsExtra			= 0;
    	winclass.cbWndExtra			= 0;
    	winclass.hInstance			= hinst;
    	winclass.hCursor			= LoadCursor(NULL, IDC_ARROW); 
    	winclass.hbrBackground		= (HBRUSH)GetStockObject(BLACK_BRUSH);
    	winclass.lpszMenuName		= NULL;
    	winclass.lpszClassName		= ClassName;
    	winclass.hIcon				= LoadIcon(NULL, IDI_APPLICATION);
    	winclass.hIconSm			= LoadIcon(NULL, IDI_APPLICATION);
    
    	if (!RegisterClassEx(&winclass))
    	return(0);
    
    	if (!(hwnd = CreateWindowEx(NULL,
    								ClassName,
    	   							Title,
    								WS_POPUP,
    			 					0,0,
    								320,240,
    								NULL,
    								NULL,
    								hinst,
    								NULL)))return(0);
    
    	//DirectDarw initialisieren...	
    	gx->initDirectDraw(hwnd,640,480);
    	//...die Textur und das Heightmap laden....
    	util_LoadTexture("textur.bmp",ptextur);
    	util_LoadTexture("hmap.bmp",phmap);
    	//...und von der Heightmap nur die Blauwerte extrahieren für die 
    	//Höhenberechnung...
        for (int y = 0; y < 256; y++)
        {
            for (int x = 256 - 1; x > -1; x--)
            {
    			phmap[x*256+y]=((phmap[x*256+y])& 0x00001F)<<3;	
            }		
        }
        //...das wars schon. Und weiter gehts
    
        ShowCursor(false);
    	ShowWindow(hwnd, ncmdshow);
    	UpdateWindow(hwnd);
    
    	bRunning=true;
    	while (bRunning)
    	{
    		if(PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
    		{
    			if(message.message==WM_QUIT)
    				bRunning=false;
    			TranslateMessage(&message);
    			DispatchMessage(&message);
    		}
    		else
    		{
    			gx->clearBackBuffer(0x000000);
    
    				raycast();
    
    				FPSCounter=FPSCounter+1;
    				if(timeGetTime()>FPSTimer+1000)
    				{
    					FPS=FPSCounter; 
    					FPSCounter=0;
    					FPSTimer=timeGetTime();
    				}
    				util_Print(10,10,"%d",FPS);
    
    			gx->flip();
    		}
    	}//while
    	return message.wParam;
    
    	UTIL_DELETE (gx)
    	UTIL_DELETE_ARRAY(ptextur)
    	UTIL_DELETE_ARRAY(phmap)
    
    }//WinMain()
    


  • Mit VSYNC hab' ich bei beiden ~30 fps.
    Ohne bei beiden ~40 fps.
    Bei BB kann ich die Maus benutzen, bei C++ nicht.
    Du benutzt die Autoren-Edition von Visual C++, d.h. ohne Optimierungen.
    Die BB-Version ist im Übrigen "leicht" größer... 😉



  • Mit VSYNC hab' ich bei beiden ~30 fps.Ohne bei beiden ~40 fps.

    System?

    Bei BB kann ich die Maus benutzen, bei C++ nicht.

    War zu diesem Zeitpunkt nicht wichtig.

    Du benutzt die Autoren-Edition von Visual C++, d.h. ohne Optimierungen.

    Auch ohne Compileropitmierung müsste C/C++ schneller sein.

    Die BB-Version ist im Übrigen "leicht" größer... 😉

    Ist bis jetz aber auch einziger Nachteil. 😃



  • Ich habe den Code mal in ICH++ um geschrieben, und damit auf meinem Rechner (P4-2400) eine Steigerung von 36 fps auf 44 fps erreicht. Das sind fast 25%. Anscheinend ist also nicht nur die Sprache für die Geschwindigkeit verantwortlich. (Immer bedenken, das VSYNC deaktiviert sein muss, zur Not Flip auskommentieren)

    Ich hoffe mal, das mich niemand für das seitenlange Codeposting hasst, denn es ist mindestens so unsauber wie das Original:

    //////////////////////////////////////////////////////////////////////////// 
    // Dies und das 
    //////////////////////////////////////////////////////////////////////////// 
    #define DIRECTDRAW_VERSION   0x0700 
    #define Title     "Voxelgrafik mit DirectDraw" 
    #define ClassName "VOXEL" 
    #define WIN32_LEAN_AND_MEAN 
    
    #include <windows.h> 
    //#include <stdio.h> 
    #include <cmath> 
    
    #include <fstream> 
    
    #pragma comment(lib,"dxguid.lib") 
    #pragma comment(lib,"ddraw.lib") 
    #pragma comment(lib,"winmm.lib") 
    
    #include <mmsystem.h> 
    //#include <stdio.h> 
    #include <ddraw.h> 
    
    #define UTIL_DELETE(p) {if(p){delete[](p);(p)=NULL;}} 
    #define UTIL_DELETE_ARRAY(p) {if(p){delete[](p);(p)=NULL;}} 
    
    //////////////////////////////////////////////////////////////////////////// 
    // GRAFIK KLASSE 
    //////////////////////////////////////////////////////////////////////////// 
    class CGraphic 
    { 
    private: 
    	int                        m_dwBPP; 
    	int                        m_dwX; 
    	int                        m_dwY; 
    	DWORD                    m_dwMaskRed; 
    	DWORD                    m_dwMaskGreen; 
    	DWORD                    m_dwMaskBlue; 
    	HRESULT                    m_ddrval; 
    	DDSURFACEDESC2            m_ddsd; 
    	LPDIRECTDRAW7            m_lpDD; 
    	LPDIRECTDRAWSURFACE7    m_lpDDSPrimary; 
    	LPDIRECTDRAWSURFACE7    m_lpDDSBack; 
    public: 
    	WORD                    *m_Vram; 
    	int                        m_iLength; 
    
    	CGraphic(); 
    	virtual ~CGraphic(); 
    	bool initDirectDraw(HWND hwnd,int x,int y); 
    	bool clearBackBuffer(WORD color); 
    	bool lockBackbuffer(); 
    	void putPixel(int x, int y, WORD color); 
    	bool unlockBackbuffer(); 
    	bool flip(); 
    	void print(int x, int y, char* text); 
    	WORD color(int red, int green, int blue); 
    }; 
    
    CGraphic::CGraphic() 
    { 
    	m_dwBPP            =16;  //Auflösung auf 16 Bit festlegen 
    	m_lpDD            =NULL; 
    	m_lpDDSPrimary  =NULL;  
    	m_lpDDSBack     =NULL;  
    } 
    
    CGraphic::~CGraphic() 
    { 
    	if(m_lpDD != NULL) 
    	{ 
    		if(m_lpDDSPrimary != NULL)  
    		{  
    			m_lpDDSPrimary->Release(); 
    			m_lpDDSPrimary = NULL; 
    			m_lpDDSBack    = NULL; 
    		}  
    		m_lpDD->Release(); 
    		m_lpDD = NULL; 
    	} 
    } 
    
    bool 
    CGraphic::initDirectDraw(HWND hwnd,int xoffset,int yoffset) 
    {     
    	m_dwX=xoffset; 
    	m_dwY=yoffset; 
    
    	DDSURFACEDESC2            ddsd;        
    	DDSCAPS2                ddscaps; 
    
    	m_ddrval = DirectDrawCreateEx(NULL, (VOID **)&m_lpDD, IID_IDirectDraw7, NULL);  
    	if(m_ddrval == DD_OK)  
    		m_ddrval =m_lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); 
    	if(m_ddrval == DD_OK)  
    		m_ddrval = m_lpDD->SetDisplayMode(xoffset, yoffset, m_dwBPP, 0, 0); 
    	if(m_ddrval == DD_OK)  
    		ZeroMemory(&ddsd, sizeof(ddsd)); 
    	ddsd.dwSize = sizeof(ddsd);  
    	ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;  
    	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |  
    		DDSCAPS_COMPLEX; 
    	ddsd.dwBackBufferCount = 1; 
    	m_ddrval = m_lpDD->CreateSurface(&ddsd, &m_lpDDSPrimary, NULL); 
    	if(m_ddrval == DD_OK)  
    		ZeroMemory(&ddscaps, sizeof(ddscaps)); 
    	ddscaps.dwCaps = DDSCAPS_BACKBUFFER;  
    	m_ddrval = m_lpDDSPrimary->GetAttachedSurface(&ddscaps, &m_lpDDSBack); 
    	if(m_ddrval == DD_OK)  
    		ZeroMemory(&ddsd, sizeof(ddsd)); 
    	ddsd.dwSize=sizeof(ddsd); 
    	m_ddrval = m_lpDD->GetDisplayMode(&ddsd); 
    	if(m_ddrval == DD_OK) 
    		m_dwMaskRed  = ddsd.ddpfPixelFormat.dwRBitMask; 
    	m_dwMaskGreen= ddsd.ddpfPixelFormat.dwGBitMask; 
    	m_dwMaskBlue = ddsd.ddpfPixelFormat.dwBBitMask; 
    	return true; 
    	return false; 
    }//InitDirectDraw 
    
    bool  
    CGraphic::clearBackBuffer(WORD color) 
    { 
    	RECT    rect; 
    	DDBLTFX    ddbltfx; 
    	ddbltfx.dwSize=sizeof(DDBLTFX); 
    	ddbltfx.dwFillColor=color;   
    	SetRect(&rect,0,0,m_dwX,m_dwY); 
    
    	m_ddrval=m_lpDDSBack->Blt(&rect,NULL,&rect,DDBLT_COLORFILL|DDBLT_WAIT,&ddbltfx); 
    	if(m_ddrval != DD_OK) 
    		return false; 
    
    	return true; 
    }//SetFtColor 
    
    bool 
    CGraphic::lockBackbuffer() 
    {      
    	ZeroMemory(&m_ddsd, sizeof(m_ddsd)); 
    	m_ddsd.dwSize = sizeof(m_ddsd); 
    	m_ddrval=m_lpDDSBack->Lock(NULL, &m_ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); 
    
    	m_iLength = m_ddsd.lPitch>>1; 
    	m_Vram = (WORD*)m_ddsd.lpSurface; 
    
    	if(m_ddrval != DD_OK) 
    		return false; 
    	return true; 
    }//Lock 
    
    bool 
    CGraphic::unlockBackbuffer() 
    { 
    	m_ddrval=m_lpDDSBack->Unlock(NULL); 
    	if(m_ddrval!= DD_OK) 
    		return false; 
    	return true; 
    }//Unlock 
    
    inline void 
    CGraphic::putPixel(int x, int y, WORD color) 
    {  
    	//Ist Pixel auserhalb des sichtbereichs...?  Das sollte nicht passieren
    	/*if(x<0 || x>m_dwX-1 || y<0 || y>m_dwY-1)  
    	{
    		return true; 
    	}*/
    	//...sonst Pixel setzen 
    	m_Vram[x + y * m_iLength ]= color; 
    
    	true; 
    }//PutPixel 
    
    bool  
    CGraphic::flip() 
    { 
    	HRESULT ddrval; 
    	ddrval=m_lpDDSPrimary->Flip(NULL,DDFLIP_WAIT); 
    	if(ddrval==DD_OK) return true; 
    	else if(ddrval == DDERR_SURFACELOST) 
    	{ 
    		ddrval = m_lpDDSPrimary->Restore(); 
    		if(ddrval != DD_OK) 
    			return false; 
    
    		ddrval=m_lpDDSPrimary->Flip(NULL,DDFLIP_WAIT); 
    		if(ddrval!=DD_OK) 
    			return false; 
    		return true; 
    	} 
    	return true; 
    }//PageFlip 
    
    WORD  
    CGraphic::color(int rot, int gruen, int blau) 
    {      
    	return(WORD)(
    		(((DWORD)(m_dwMaskRed  *(rot/2.55/100)))  &(DWORD)m_dwMaskRed)   |
    		(((DWORD)(m_dwMaskGreen*(gruen/2.55/100)))&(DWORD)m_dwMaskGreen) |
    		(((DWORD)(m_dwMaskBlue *(blau/2.55/100))) &(DWORD)m_dwMaskBlue)
    	);
    }//Color 
    
    void 
    CGraphic::print(int x, int y, char* text)  
    {  
    	static HFONT hfont= CreateFont(15,0,0,0,0,0,0,0,0,0,0,0,FIXED_PITCH,0);
    	//HFONT hfont; 
    	HDC hdc=NULL; 
    
    	if( m_lpDDSBack->GetDC(&hdc)==DD_OK )  
    	{  
    		HGDIOBJ oldObj= SelectObject(hdc,hfont); 
    		SetBkMode(hdc,TRANSPARENT);  
    		SetTextColor(hdc,0x00FF00);  
    		TextOut(hdc,x,y,text,lstrlen(text)); 
    		SelectObject( hdc, oldObj ); 
    		m_lpDDSBack->ReleaseDC(hdc); 
    	}  
    }//Print 
    
    //////////////////////////////////////////////////////////////////////////// 
    // HILFSFUNKTIONEN 
    //////////////////////////////////////////////////////////////////////////// 
    CGraphic *gx=new CGraphic; 
    float     *sinus; 
    float     *cosinus; 
    
    void  
    util_Print(int x, int y, char* text,...) 
    {   
    	char textBuffer[512]; 
    	va_list args; 
    	va_start(args, text); 
    	vsprintf(textBuffer, text, args); 
    	va_end(args); 
    	gx->print(x,y,textBuffer); 
    } 
    
    bool  
    util_LoadTexture(char *file, DWORD *array) 
    { 
    	FILE *dat_ein; 
    	BITMAPFILEHEADER    BmFileHeader; 
    	BITMAPINFOHEADER    BmInfoHeader; 
    	WORD                bmHeight; 
    	WORD                bmWidth; 
    	DWORD               *temp; 
    	BYTE                r,g,b; 
    	BOOL                bDone  = FALSE; 
    	int                    EndByte=0; 
    	if((dat_ein=fopen(file,"rb"))==NULL) 
    	{ 
    		return false; 
    	} 
    	fread(&BmFileHeader,sizeof(BITMAPFILEHEADER),1,dat_ein); 
    	fread(&BmInfoHeader,sizeof(BITMAPINFOHEADER),1,dat_ein); 
    	bmHeight=(WORD)BmInfoHeader.biHeight; 
    	bmWidth =(WORD)BmInfoHeader.biWidth; 
    	if ((BmInfoHeader.biSizeImage - bmWidth * bmHeight * 3) == 0) 
    	{ 
    		EndByte = 0;  
    	} 
    	else  
    	{ 
    		EndByte = (BmFileHeader.bfSize - 54 - bmWidth * bmHeight * 3) / bmHeight;  
    	} 
    	temp = new DWORD[bmWidth * bmHeight]; 
    	int count = bmWidth * bmHeight - 1; 
    	while (!feof(dat_ein)) 
    	{ 
    		for (int i = 0; i < bmWidth; i++) 
    		{ 
    			if (!feof(dat_ein)) 
    			{ 
    				fread (&b, sizeof(BYTE), 1, dat_ein); 
    			} 
    			else 
    			{ 
    				bDone = TRUE; 
    				break; 
    			} 
    			if (!feof(dat_ein)) 
    			{         
    
    				fread (&g, sizeof(BYTE), 1, dat_ein); 
    			} 
    			else 
    			{ 
    				bDone = TRUE; 
    				break; 
    			} 
    			if (!feof(dat_ein)) 
    			{ 
    				fread (&r, sizeof(BYTE), 1, dat_ein); 
    			} 
    			else 
    			{ 
    				bDone = TRUE; 
    				break; 
    			}         
    			temp[count] = gx->color(r,g,b); 
    			count--;  
    		} 
    		if (!bDone) 
    		{  
    			fseek(dat_ein, EndByte, SEEK_CUR); 
    		} 
    		else 
    		{ 
    			break; 
    		} 
    	} 
    	fclose(dat_ein); 
    	count=0; 
    	for (int y = 0; y < bmHeight; y++) 
    	{ 
    		for (int x = bmWidth - 1; x > -1; x--) 
    		{ 
    			array[x*bmHeight+y]=temp[count]; 
    			count++;     
    		}         
    	} 
    	delete [] temp; 
    	return true; 
    }//loadTexture 
    
    void util_CreatLockUp() 
    {   //LockUp Tabelle für Sinus und Cosinus Werte erstellen 
    	for(long winkel=0;winkel<360;winkel++) 
    	{ 
    		sinus[winkel]=sinf(winkel*3.141592654f/180.0f); 
    		cosinus[winkel]=sinf(winkel*3.141592654f/180.0f); 
    	} 
    }//CreateLockUp 
    
    //////////////////////////////////////////////////////////////////////////// 
    // RAYCAST FUNKTION 
    //////////////////////////////////////////////////////////////////////////// 
    //HeightMap und Textur 
    WORD *ptextur=new WORD[256*256]; 
    DWORD *phmap=new DWORD[256*256]; 
    
    //Raycast 
    int grw=640;  
    int grh=480;  
    int grwh=grw/2;  
    int grhh=grh/2; 
    int row; 
    int grwh_mi; 
    int h; 
    int co; 
    int c; 
    int xpos; 
    int zpos; 
    float my=0;  
    float px=8.0f;  
    float pz=8.0f;  
    float a=0;  
    double rayx; 
    double rayz; 
    //double s1,s2; 
    double stepx; 
    double stepz; 
    
    //Strahlenfunktion. Zeichnet die Landschaft 
    inline  
    void raycast() 
    { 
    	gx->lockBackbuffer(); 
    	int iSub= gx->m_iLength;
    
    	for(int i=-grwh; i<=grwh; i+=1)//step 
    	{ 
    		row= grh - 1; //row ist nur sinnvoll wenn < grh
    
    		grwh_mi=grwh-i; 
    
    		WORD* pwSurface= gx->m_Vram + ( grwh_mi + row * gx->m_iLength );
    
    		if( grwh_mi <= 0 || grwh_mi >= grw )
    		{
    			continue; // does this ever happen?
    		}
    
    		rayx=px; 
    		rayz=pz; 
    		stepx=sin(a+0.002*i);  
    		stepz=cos(a+0.002*i); 
    
    		int count= 0;
    		rayx+= stepx;  
    		rayz+= stepz;
    
    		//  while funktioniert für alle px,py auf der map
    		while ( rayx > -127 && rayx < 127 && rayz > -127 && rayz < 127) 
    		{ 
    			count++;
    
    			xpos=(int)rayx;                 
    			zpos= (int)rayz;
    
    			c= ( phmap[ (xpos+127)*256+zpos+127] ); 
    			h= (int)( (15000-my*100)-((0.1*my+30)*c) ) / count;
    
    			if(c<1) 
    				co=0x465DFF; 
    			else 
    				co=(ptextur[(xpos+127)*256+zpos+127]);
    
    			if( h < 0 )
    			{
    				h= 0;
    			}
    			while ( row > h ) 
    			{ 
    				// Dieser Speicherzugriff ist der Bottleneck, da non-linear
    				*pwSurface= co; 
    
    				pwSurface-= iSub;
    				row--;
    			}
    
    			rayx+= stepx;  
    			rayz+= stepz;
    
    		} // while
    	}//for(int i=-grwh; i<grwh-1; i++) 
    	gx->unlockBackbuffer(); 
    }//raycast() 
    
    //////////////////////////////////////////////////////////////////////////// 
    // WINDOWS 
    //////////////////////////////////////////////////////////////////////////// 
    //Windows 
    bool  bRunning; 
    HWND  hwnd; 
    //FPS 
    unsigned long FPSTimer; 
    int FPS; 
    int FPSCounter; 
    
    LRESULT CALLBACK  
    WinProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam) 
    { 
    	switch(message) 
    	{ 
    	case WM_KEYDOWN:  
    		switch (wparam)  
    		{ 
    		case (int)'A': 
    			a=a+0.05f; 
    			break; 
    		case (int)'D': 
    			a=a-0.05f; 
    			break; 
    		case (int)'W': 
    
    			break; 
    		case (int)'S': 
    
    			break; 
    		case VK_UP: 
    
    			break; 
    		case VK_DOWN: 
    
    			break; 
    		case VK_LEFT: 
    
    			break; 
    		case VK_RIGHT: 
    
    			break; 
    		case VK_ESCAPE:  
    			DestroyWindow(hwnd);  
    			break; 
    		} 
    		break;  
    	case WM_CLOSE: 
    	case WM_DESTROY:  
    		{     
    			bRunning = false; 
    			PostQuitMessage(0); 
    			return 1; 
    		}break; 
    	default:break; 
    	}//switch 
    	return (DefWindowProc(hwnd, message, wparam, lparam)); 
    } // WindowProc 
    
    int  
    WINAPI WinMain(    HINSTANCE hinst,HINSTANCE hprevinst,LPSTR lpcmdline,int ncmdshow) 
    { 
    	WNDCLASSEX    winclass; 
    	MSG            message; 
    
    	winclass.cbSize                = sizeof(WNDCLASSEX); 
    	winclass.style                = CS_HREDRAW | CS_VREDRAW; 
    	winclass.lpfnWndProc        = WinProc; 
    	winclass.cbClsExtra            = 0; 
    	winclass.cbWndExtra            = 0; 
    	winclass.hInstance            = hinst; 
    	winclass.hCursor            = LoadCursor(NULL, IDC_ARROW);  
    	winclass.hbrBackground        = (HBRUSH)GetStockObject(BLACK_BRUSH); 
    	winclass.lpszMenuName        = NULL; 
    	winclass.lpszClassName        = ClassName; 
    	winclass.hIcon                = LoadIcon(NULL, IDI_APPLICATION); 
    	winclass.hIconSm            = LoadIcon(NULL, IDI_APPLICATION); 
    
    	if (!RegisterClassEx(&winclass)) 
    		return(0); 
    
    	if (!(hwnd = CreateWindowEx(NULL, 
    		ClassName, 
    		Title, 
    		WS_POPUP, 
    		0,0, 
    		320,240, 
    		NULL, 
    		NULL, 
    		hinst, 
    		NULL)))return(0); 
    
    	//DirectDarw initialisieren...     
    	gx->initDirectDraw(hwnd,640,480); 
    	//...die Textur und das Heightmap laden.... 
    	util_LoadTexture("textur.bmp",phmap); 
    	//schonmal alles nach WORD
    	for (int y = 0; y < 256; y++) 
    	{ 
    		for (int x = 256 - 1; x > -1; x--) 
    		{ 
    			ptextur[x*256+y]= (WORD)((phmap[x*256+y]));     
    		}         
    	} 
    	util_LoadTexture("hmap.bmp",phmap); 
    	//...und von der Heightmap nur die Blauwerte extrahieren für die  
    	//Höhenberechnung... 
    	for (int y = 0; y < 256; y++) 
    	{ 
    		for (int x = 256 - 1; x > -1; x--) 
    		{ 
    			phmap[x*256+y]=((phmap[x*256+y])& 0x00001F)<<3;     
    		}         
    	} 
    	//...das wars schon. Und weiter gehts 
    
    	ShowCursor(false); 
    	ShowWindow(hwnd, ncmdshow); 
    	UpdateWindow(hwnd); 
    
    	bRunning=true; 
    	while (bRunning) 
    	{ 
    		if(PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) 
    		{ 
    			if(message.message==WM_QUIT) 
    				bRunning=false; 
    			TranslateMessage(&message); 
    			DispatchMessage(&message); 
    		} 
    		else 
    		{ 
    			gx->clearBackBuffer(0x000000); 
    
    			raycast(); 
    
    			FPSCounter=FPSCounter+1; 
    			if(timeGetTime()>FPSTimer+1000) 
    			{ 
    				FPS=FPSCounter;  
    				FPSCounter=0; 
    				FPSTimer=timeGetTime(); 
    			} 
    			util_Print(10,10,"%d",FPS); 
    
    			gx->flip(); 
    		} 
    	}//while 
    
    	std::ofstream ofs( "fps.txt" );
    	ofs << FPS;
    
    	UTIL_DELETE (gx) 
    	UTIL_DELETE_ARRAY(ptextur) 
    	UTIL_DELETE_ARRAY(phmap) 
    
    	return (int)message.wParam; //Code hier dahinter ist nonsene
    
    }//WinMain()
    


  • Ich hasse dich nur weil du das normale Code Tag benutzt hast und nicht das c/c++ 😃 .



  • @TGGC mehr wollte ich nicht. Ich bin froh das sich einer gefunden hat ein paar Optimierungen durchzuführen.
    Wie schnell ist bei dir die BlitzBasic Version gelaufen?

    EDIT: wenn ich diesen Teil auskommentieren:

    std::ofstream ofs( "fps.txt" ); 
         ofs << FPS;
    

    läuft bei mir das Programm mit 65FPS wenn ich es wieder einfüge steigt FPS auf 78.

    Warum?

    PS: Kann es sein das BlitzBasic für Athlon optimiert wurde? Weil es auf einem 3.06Ghz Rechner mit 20FPS und auf einem 900Mhz Athlon mit über 20 FPS läuft.
    Ist sowas möglich?



  • Huhu,

    ich habe bei der C++ Version 79 FPS und bei der BlitzBasic Version nur 41 FPS.
    System: Athlon 2400+, Radeon 9700 Pro

    wieso läuft das bei jedem völlig anders??



  • Das wollte ich auch wissen. Leider wüsste ich nicht wer eine Antwort wüsste.

    Seltsam finde ich das z.B auf einem 900 AMD die BB Version schneller ist als auf einem Pentium 4 mit 3.06Ghz.

    Ich liste mal auf was ich habe:

    Nr  Prozessor Taktung Grafikkarte     Version FPS   Version FPS
        -----------------------------------------------------------
    01  Pentium4  3.06Ghz Radeon9600Pro   C/C++   60    BB      20
    02  Pentium4  2.6Ghz  Radeon9600tx    C/C++   50    BB      18 
    03  Pentium   866MhZ  4200Ti          C/C++   15    BB      15
    04  AMD       2400+   Radeon9700Pro   C/C++   79    BB      41
    05  AMD       900mhz  4200TI          C/C++   20    BB      25 
    06  AMD       1800+   4200TI          C/C++   28    BB      30
    07  AMD       1800+   Radeon9500Pro   C/C++   30    BB      30
    

    Alle Werte beziehen sich auf die erste Version, nicht die von TGGC. Bis auf die Nr.4 Die ist glaube ich die neue Version

    Könnte es an den Grafikkarten liegen?



  • H.L.T.O schrieb:

    Mit VSYNC hab' ich bei beiden ~30 fps.Ohne bei beiden ~40 fps.

    System?

    Athlon XP 1800+ & Radeon 9500 Pro & 512 MB DDR



  • H.L.T.O schrieb:

    Könnte es an den Grafikkarten liegen?

    Möglich. Schreibe eine Version, die keine GraKa benutzt!



  • Ich wäre mir nicht sicher, ob der vsync nicht doch irgendwo von einer Win-Routine mitbenutzt wird, sodass letztlich doch sehr viel von der benutzten Vertikalfrequenz der Grafikkarte abhängig ist. Ist das eine System auch nur einen Hauch schneller, und erwischt den sync gerade noch, das andere kommt aber einen Augenblick zu spät und muss warten, dann gibt es größere Unterschiede, obwohl beides fast gleich schnell ist.
    Die nicht optimierenden Versionen des MSVC sind aber z.T. dramatisch langsamer als die optimierenden. Da kann ich mir Vorteile für Blitzbasic tatsächlich vorstellen. Gegen die optimierenden Versionen sollte es kein Land sehen, das wäre gegen jede Logik.


Anmelden zum Antworten