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=4733Infos 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 Prowieso 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.