PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : OpenGL && 2D


Unregistered
2002-08-28, 17:53:13
Hi,

klar warum OpenGL und 2D, ganz einfach. Ich habe jetzt mit ein paar Freunden ein Team gebildet und wir wollen zusammen ein wenig programmieren. Jetzt wollen wir klein einsteigen und erstmal was au der 2D Ebene programmieren. Mit den Grundlagen, was die Projektionsarten betrifft, kenn ich mich aus, aber mir fehlen ein paar zusätzliche Informationen.

Wenn ich ein Bild lade und es anzeige, geht das auch ohne Texture Mapping?
Kann ich da nur für eine bestimmte Farbe den Alphawert auf 0 setzen und wenn, wie?
Kann man die Bilder um beliebige Grad drehen? Also kann ich die Bilder im Kreis um alle 360° Positionen ausrichten lassen? Wenn auch das dann wäre es cool wenn mir einer sagen könnte wie?

Und vielleicht kann mir jemand sonst noch irgendwelche Tips geben, da ich nur mit DirectDraw im 2D Bereich gearbeitet habe.

Für alle Antworten schon mal Danke im Vorraus


MFG Einfachkrank

Einfachkrank
2002-08-28, 18:07:02
kommt jetzt blöde, aber das da oben ist mein Thread, hab vergessen meinen Namen ein zu geben. :D :D :D

zeckensack
2002-08-28, 19:01:37
Originally posted by Unregistered
Wenn ich ein Bild lade und es anzeige, geht das auch ohne Texture Mapping?Das geht schon, und zwar mit glDrawPixels(...). Gewußt wie, performt es auch ganz ordentlich, wenn auch nicht großartig (ca 60 fps 800x600x32 fullscreen-blits sind machbar).
Verbietet sich aber bei dir, weil man mit DrawPixels nicht rotieren kann.
Kann ich da nur für eine bestimmte Farbe den Alphawert auf 0 setzen und wenn, wie?OpenGL kennt kein echtes 'Color Keying', es ist nur mit erheblichem Aufwand (Pixel Shader+Alpha Test) nachbildbar.
Besser (weil wesentlich einfacher) ist es, einfach 'zu Fuß' Löcher in die Bilder einzufügen, indem man Texturen mit Alpha-Kanal benutzt. Dann kann man entweder mit Alpha-Test oder mit Blending die gewünschten Stellen unsichtbar machen.
Vorsicht: Blending verhindert nicht, daß an 'unsichtbaren' Stellen der Z-Buffer (+Stencil) geschrieben wird. Dafür braucht es Alpha Test, man kann aber auch beides kombinieren.
Kann man die Bilder um beliebige Grad drehen? Also kann ich die Bilder im Kreis um alle 360° Positionen ausrichten lassen? Wenn auch das dann wäre es cool wenn mir einer sagen könnte wie?Du pappst deine Bilder als Texturen auf 'Primitives' (=Dreiecke/Vierecke/Strips/Fans; wir müssen hier so langsam mal korrekte OGL-Sprache einführen ;) ). Wenn du die Primitives drehst (mittels Matrixoperationen), dreht sich die Textur natürlich mit :)
Und vielleicht kann mir jemand sonst noch irgendwelche Tips geben, da ich nur mit DirectDraw im 2D Bereich gearbeitet habe.Für Texturen und einfache Animation/Effekte, kann ich wieder nur empfehlen, dir die ersten fünf bis zehn Tutorials auf NeHe-GL (http://nehe.gamedev.net/) reinzuziehen ;)

Einfachkrank
2002-08-28, 19:30:56
OpenGL kennt kein echtes 'Color Keying', es ist nur mit erheblichem Aufwand (Pixel Shader+Alpha Test) nachbildbar.
Besser (weil wesentlich einfacher) ist es, einfach 'zu Fuß' Löcher in die Bilder einzufügen, indem man Texturen mit Alpha-Kanal benutzt. Dann kann man entweder mit Alpha-Test oder mit Blending die gewünschten Stellen unsichtbar machen.
Vorsicht: Blending verhindert nicht, daß an 'unsichtbaren' Stellen der Z-Buffer (+Stencil) geschrieben wird. Dafür braucht es Alpha Test, man kann aber auch beides kombinieren.Ist der Alpha- Kanal bei den *.tga files dabei? Weil wie ich die lade, weiß ich auch. Oder was gibts da noch für Bildformat mit Alpha Kanal?
Gibt es dafür ein bestimmtes kleines Tutorial?

MeLLe
2002-08-28, 19:57:06
AFAIK besitzen TGA-Files einen Alpha-Kanal. Ja.
Was weiter Bildformate mit Alpha-Bits angeht habe ich k.A. ;)

Auf jeden Fall solltest Du Dich für ...

Masking: http://nehe.gamedev.net/tutorials/lesson.asp?l=20
und
TGA Loading: http://nehe.gamedev.net/tutorials/lesson.asp?l=33

an den angegebenen Stellen informieren ;)

Einfachkrank
2002-08-29, 16:15:27
Hi,

jetzt hab ich so viel mit meinem 3D Würfel herumexperimentiert, dass ich nicht mehr in der Lage bin eine ganz normale 2D Perspektive zu erzeugen :bonk: . Hab versucht die glOrtho2D() zu benutzen und dann einfach erstmal wieder ein paar Primitves zu rendern, aber meine Bildschirm bleibt einfach nur schwarz :(
Muss ich bei der 2D Perspektive auf was spezielles achten?

MFG Einfachkrank

zeckensack
2002-08-29, 18:50:06
Auch eine 2D-Projektion hat (normalerweise) einen Z-Buffer und (immer!) ein dazugehöriges Clip-Volumen.

Du mußt 'near' und 'far' auf sinnvolle Werte setzen (zumindest mal auf unterschiedliche Werte), und deine Primitives müssen von der Tiefe her in dieses Volumen reinfallen, sonst werden sie nicht dargestellt.

Bsp1:
Near=1.0
Far=100.0

Alle Z-Werte des Dreiecks sind 0 (zB Default, wenn man glVertex2f(x,y) benutzt) -> Dreieck wird nicht dargestellt.

Bsp2:
Near=-1.0
Far=1.0

Dreiecke mit Z=0 werden dargestellt.

Das ist völlig unabhängig davon, ob du Z-Buffer und Z-Test aktiviert hast!

Einfachkrank
2002-08-29, 20:40:37
Hi,

also ich habe die glOrtho() Funktion genutzt um meine Projektionsart einzustellen. Die Near und Far Clipping Planes habe ich auf 1 und -1 stehen und meine Polygone haben einen Z-Wert von 0, sehe aber trotzdem keine. :(

Einfachkrank
2002-08-30, 16:04:58
Kann man in DirectDraw, Bilder drehen? Also um alle 360° Positionen ? Wenn ja, kann mir es vielleicht jemand erklären?

zeckensack
2002-08-30, 16:21:11
Originally posted by Einfachkrank
Hi,

also ich habe die glOrtho() Funktion genutzt um meine Projektionsart einzustellen. Die Near und Far Clipping Planes habe ich auf 1 und -1 stehen und meine Polygone haben einen Z-Wert von 0, sehe aber trotzdem keine. :( Zeig mal Code :bäh:

Einfachkrank
2002-08-30, 18:04:35
# include <windows.h>
# include <gl/gl.h>
# include <gl/glu.h>
# include <stdio.h>

# define WIN32_LEAN_AND_MEAN
# define BITMAP_ID 0x4D42


HWND hwnd = NULL;
HDC hdc = NULL;
HGLRC hrc = NULL;
BOOL isDone = TRUE, isFullscreen = TRUE;
int bits = 16, height = 768, width = 1024;
char classname[] = "OpenGL by Einfachkrank";

BITMAPINFOHEADER bitmapInfoHeader;
unsigned char* bitmapData;
unsigned int texture;

float angle = 0.0f;


/* ****************************************************************** */

LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
switch(message)
{
case WM_KEYDOWN:
{
switch(wparam)
{
case VK_ESCAPE:
{
isDone = TRUE;
return 0;
} break;
default: break;
}
}
default: break;
}

return (DefWindowProc(hwnd, message, wparam, lparam));
} // Callback

/* ****************************************************************** */

void SetupPixelFormat(HDC hDC)
{
int nPixelFormat;

static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
bits,
0, 0, 0, 0, 0, 0,
0, 0, 0,
0, 0, 0, 0,
bits,
0, 0,
PFD_MAIN_PLANE,
0, 0, 0, 0 };

nPixelFormat = ChoosePixelFormat(hDC, &pfd);

SetPixelFormat(hDC, nPixelFormat, &pfd);
} // SetupPixelFormat

/* ****************************************************************** */

unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
{
FILE *filePtr;
BITMAPFILEHEADER bitmapFileHeader;
unsigned char *bitmapImage;
int imageIdx = 0;
unsigned char tempRGB;

filePtr = fopen(filename, "rb");
if (filePtr == NULL)
return NULL;

fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);

if (bitmapFileHeader.bfType != BITMAP_ID)
{
fclose(filePtr);
return NULL;
}

fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);

fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);

bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);

if (!bitmapImage)
{
free(bitmapImage);
fclose(filePtr);
return NULL;
}

fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);

if (bitmapImage == NULL)
{
fclose(filePtr);
return NULL;
}

for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx+=3)
{
tempRGB = bitmapImage[imageIdx];
bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
bitmapImage[imageIdx + 2] = tempRGB;
}

fclose(filePtr);
return bitmapImage;
}

/* ****************************************************************** */

void Initialize(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);

bitmapData = LoadBitmapFile("Textur.bmp", &bitmapInfoHeader);

glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmapInfoHeader.biWidth,
bitmapInfoHeader.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmapData);
} // Initialize

/* ****************************************************************** */

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprevinst, LPSTR lpcmdline, int nshowcmd)
{
WNDCLASSEX winclass;
MSG message;
DWORD dwStyle, dwExStyle;
RECT windowRect;

winclass.cbSize = sizeof(WNDCLASSEX);
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hbrBackground = NULL;
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
winclass.hInstance = hinst;
winclass.lpfnWndProc = WindowProc;
winclass.lpszClassName = classname;
winclass.lpszMenuName = NULL;
winclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;

if(!RegisterClassEx(&winclass))
{
MessageBox(NULL, "RegisterClassEx FAILED", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return 0;
}

windowRect.left = (long)0;
windowRect.right = (long)width;
windowRect.top = (long)0;
windowRect.bottom = (long)height;

if(isFullscreen)
{
DEVMODE dmScreenSettings;
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = width;
dmScreenSettings.dmPelsHeight = height;
dmScreenSettings.dmBitsPerPel = bits;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
MessageBox(NULL, "ChangeDisplaySettings FAILED", "ERROR", MB_OK | MB_ICONEXCLAMATION);
isFullscreen = FALSE;
}

dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP;
ShowCursor(FALSE);
}
else
{
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle = WS_OVERLAPPEDWINDOW;
}

AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);

hwnd = CreateWindowEx(NULL, classname, classname, dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0,0, width, height, NULL, NULL, hinst, NULL);

if(!hwnd)
{
MessageBox(NULL, "HWND FAILED", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return 0;
}

hdc = GetDC(hwnd);
SetupPixelFormat(hdc);

hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc, hrc);

ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);

isDone = FALSE;

glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glOrtho((double)0,(double)width,(double)0,(double)height,(double)1,(double)-1);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();


while(!isDone)
{
while(PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&message);
DispatchMessage(&message);
}

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

angle += 0.1f;
if(angle >= 360.0f)
angle = 0.0f;

glTranslatef(0.0f, 0.0f, 0.0f);
glRotatef(angle, 0.0f, 0.0f, 1.0f);

glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5f, -0.5f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0.5f, -0.5f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-0.5f, 0.5f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(0.5f, 0.5f, 0.0f);
glEnd();

glFlush();
SwapBuffers(hdc);
}

if(isFullscreen)
{
ShowCursor(TRUE);
ChangeDisplaySettings(NULL, 0);
}

wglMakeCurrent(hdc, hrc);
wglDeleteContext(hrc);
ReleaseDC(hwnd, hdc);

return message.wParam;
} // WinMain

/* ****************************************************************** */
Das war jetzt alles

Xmas
2002-08-30, 20:06:14
Also entweder machst du die Zeile mit glOrtho ganz weg (dann funzts nämlich ;)) oder du passt deine Vertex-Koordinaten an.

Das
glOrtho(0, (double)width, 0, (double)height, 1, -1);
bedeutet nämlich, dass die auf dem Bildschirm sichtbaren Koordinaten zwischen [0,0](unten links) und [width,height](oben rechts) liegen. Und nicht zwischen -1 und 1, das tun sie mit Identity-Matrix.

Außerdem renderst du den Quad falsch, tausche mal den 3. und den 4. Eckpunkt.

Was mir auch aufgefallen ist, wieso rufst du AdjustWindowRectEx auf, wenn du dann windowRect gar nicht benutzt?

Xmas
2002-08-30, 21:09:01
Weitere Fehler:

Initialize() wird gar nicht aufgerufen.
Der Speicher für das Bitmap wird nicht mehr freigegeben.
Du musst unbedingt den Minification-Filter auf GL_LINEAR oder GL_NEAREST setzen, weil du keine Mipmaps hast, also:
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Sonst wird die Textur nicht verwendet.

Einfachkrank
2002-09-01, 12:15:44
Hi,

jetzt habe ich es durch sämtliche Fehlerbeseitigungen hinbekommen, dass mein angebliches Quad mit Textur zu sehen ist, aber es ist eben kein richtiges Viereck, sondern ein Fünfeck mit Einschnitt zur Mitte. An was leigt denn das jetzt, wie bekomme ich es denn hin, dass das Viereck richtig zu sehen ist? Und noch was zu den Texturen, müssen das auch ganz bestimmte sein, weil ich manche Bitmaps laden kann und bei manchen hängt sich der Rechner auf :( ?

MFG Einfachkrank

Xmas
2002-09-01, 14:11:14
Originally posted by Xmas
Außerdem renderst du den Quad falsch, tausche mal den 3. und den 4. Eckpunkt.

Wenn du Quads (GL_QUADS) renderst, musst du die Eckpunkte rundum übergeben. Du nimmst aber stattdessen eine Z-Form. Da die Hardware nur Dreiecke rendern kann, wird automatisch zerlegt, und zwar in zwei Dreiecke mit den Eckpunkten (1 2 3) und (1 3 4). Also ist die Kante zwischen 1 und 3 die geteilte Kante.

Dies trifft nicht für Quadstrips zu!

Quad:
1_2
| \ |
4_3

5_6
| \ |
8_7

Quadstrip:
1_2
| / |
3_4
| / |
5_6
| / |
7_8
...


Die Texturen müssen in deinem Fall 24-Bit BMPs sein deren Höhe und Breite eine Zweierpotenz ist (muss nicht gleich sein). Um andere Werte als Zweierpotenzen verwenden zu können, musst du die Extension NV_texture_rectangle verwenden (die aber NVidia-Spezifisch ist).

Welche Entwicklungsumgebung verwendest du? Ich empfehle dir unbedingt, dich mal mit dem Debugger auseinanderzusetzen, damit du schnell und einfach eingrenzen kannst, wo ein Fehler auftritt.

Einfachkrank
2002-09-01, 14:46:26
@ Xmas
Ich arbeite in WinMe mit Visual C++ 6.0 Standart.

Noch eine Frage: Wie kann es eigentlich sein, dass einfache OpenGL Anwendungen bei mir perfekt laufen und auf noch besseren Rechnern schlechter?

Einfachkrank
2002-09-01, 20:01:33
Hey,

jetzt funzt es endlich und auch mit der gluOrtho2D(). Jetzt werde ich mir noch das mit dem Masking ansehen und dann geht es doch langsam :)

Nur wie schon mal gefragt: Einfache Anwendungen wie diese hier, funzen bei mir einfach super, aber bei anderen Leuten die viel schnellere Rechner und neuere Grakas und auch noch mehr Arbeitsspeicher haben ???

MFG Einfachkrank

zeckensack
2002-09-02, 00:27:31
Originally posted by Einfachkrank
Nur wie schon mal gefragt: Einfache Anwendungen wie diese hier, funzen bei mir einfach super, aber bei anderen Leuten die viel schnellere Rechner und neuere Grakas und auch noch mehr Arbeitsspeicher haben ???

MFG Einfachkrank Könnte daran liegen, daß du gezielt einen 16bittigen OpenGL-Context erzeugst (in deinem PFD ist bits=16). Wenn man jetzt eine Desktop-Farbtiefe von 32bit eingestellt hat, gibt es zwei Möglichkeiten:
1)Der GL-Treiber geht mit etwas Ignoranz an die Sache heran und gibt dir einen 32bittiges Context, dafür mit HW-Beschleunigung
2)Der GL-Treiber hält sich strikt an deine Vorgabe von 16 Bit, dafür geht aber die HW-Beschleunigung flöten -> lahmes Software-Rendering

Wenn du es dir einfach machen willst, fordere einfach 0 Bits an, das bedeutet 'Lieber Treiber, nimm einfach irgendwas', und in der Regel klappt's dann auch mit der Hardwarebeschleunigung. :)

Vorsicht!
Manche Treiber (vornehmlich bei echten Profikarten) können unter diesen Umständen auch schon mal einen Context ohne Z-Buffer erzeugen.
Die wirklich endgültige Lösung ist, vor dem Erzeugen des Contexts die aktuelle Bildschirmfarbtiefe abzufragen (AFAIR mit der GDI-Funktion GetSystemMetrics), und das dann als Farb- und Z-Buffertiefe in den pfd einzutragen.

Oder aber du schaltest vorher eigenhändig die Bildschirmauflösung in einen verträglichen Modus um, was man aber bei nicht-Fullscreen-Anwendungen bleiben lassen sollte.