|
Post by scalion on Sept 3, 2019 11:50:48 GMT 1
[FR] J'ai eu beaucoup de mal à faire mes premiers pas en OpenGL, il y avait trop de documentations et peu d'exemple simples. Aujourd'hui je suis plutôt à l'aise avec OpenGL et j'ai envie de fournir un exemple simple qui m'a beaucoup manqué au début. J'espère qu'il aidera quelqu'un à démarrer sur une bonne base pour approfondir ensuite ses connaissances en OpenGL
Voici donc le programme le plus minimaliste que j'ai pu faire en OpenGL, il affiche simplement 2 triangle en 2D avec un peu de transparence.
[US]I had a hard time making my first steps in OpenGL, there were too many documentations and too few simple examples. Today I am rather comfortable with OpenGL and I want to provide a simple example that I missed a lot at the beginning. I hope it will help someone get started on a good foundation and then deepen their knowledge of OpenGL
Here is the most minimalist program I could do in OpenGL, it just displays 2 triangle in 2D with a little transparency.
$Library "OpenGL.inc"
Global Long OpenGL_DC, OpenGL_RDC Global PFD As PIXELFORMATDESCRIPTOR
Form OpenGLWin Me.FullW
PFD.nSize = SizeOf(PFD) PFD.nVersion = 1 PFD.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW
OpenGL_DC = Me.hDC
Void SetPixelFormat(OpenGL_DC, ChoosePixelFormat(OpenGL_DC, PFD), PFD) OpenGL_RDC = wglCreateContext(OpenGL_DC) If !wglMakeCurrent(OpenGL_DC, OpenGL_RDC) Message"OpenGL Initialisation error. :(" : End
glMatrixMode(GL_PROJECTION) glOrtho(0, _X, _Y, 0, -1, 2000) glClearColor(0, 0, 0, 0) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
Global Double a
Do glClear(GL_COLOR_BUFFER_BIT) glBegin(GL_TRIANGLES) glColor4f(1, 1, 0, 1) : glVertex3d(MouseX - 115, MouseY + 100, 0) glColor4f(0, 1, 1, 1) : glVertex3d(MouseX, MouseY - 100, 0) glColor4f(1, 0, 1, 1) : glVertex3d(MouseX + 115, MouseY + 100, 0) a = Frac(-Timer / 60) * 2 * PI glColor4f(1, 0, 0, 0.5) : glVertex3d(_X / 2 + Sin(a) * 200, _Y / 2 + Cos(a) * 200, 0) glColor4f(0, 1, 0, 0.5) : glVertex3d(_X / 2 + Sin(a + 2.094) * 200, _Y / 2 + Cos(a + 2.094) * 200, 0) glColor4f(0, 0, 1, 0.5) : glVertex3d(_X / 2 + Sin(a + 4.188) * 200, _Y / 2 + Cos(a + 4.188) * 200, 0) glEnd() SwapBuffers(OpenGL_DC) PeekEvent Loop Until Me Is Nothing
wglDeleteContext(OpenGL_RDC)
|
|
|
Post by scalion on Sept 3, 2019 12:28:25 GMT 1
You dont have the same OpenGL library. Maybe PIXEL_FORMAT_DESCRIPTOR work, take a look in your import tab if that appear, else try to replace $Library "OpenGL.inc" by this code : Global Const GL_PROJECTION = 5889 Global Const GL_TEXTURE_2D = 3553 Global Const GL_TRIANGLES = &h0004 Global Const GL_COLOR_BUFFER_BIT = 16384 Global Const GL_ALPHA_TEST = &h0BC0 Global Const GL_COLOR_MATERIAL = &h0B57 Global Const GL_BLEND = &h0BE2 Global Const GL_SRC_ALPHA = &h0302 Global Const GL_ONE_MINUS_SRC_ALPHA = &h0303 Global Const GL_GREATER = 516 Global Const PFD_SUPPORT_OPENGL = 32 Global Const PFD_DOUBLEBUFFER = 1 Global Const PFD_DRAW_TO_WINDOW = 4 Global Const PFD_MAIN_PLANE = 0 Global Const PFD_TYPE_RGBA = 0 Declare Sub glAlphaFunc Lib "opengl32" Alias "glAlphaFunc" (ByVal func As Integer, ByVal ref As Single) Declare Function ChoosePixelFormat Lib "gdi32" (ByVal dc As Integer, ByRef pfd As PIXEL_FORMAT_DESCRIPTOR) As Integer Declare Function SetPixelFormat Lib "gdi32" (ByVal dc As Integer, ByVal iFmt As Integer, ByRef pfd As PIXEL_FORMAT_DESCRIPTOR) As Integer Declare Function SwapBuffers Lib "gdi32" (ByVal dc As Integer) As Integer Declare Function wglCreateContext Lib "opengl32" Alias "wglCreateContext" (ByVal dc As Integer) As Integer Declare Function wglMakeCurrent Lib "opengl32" Alias "wglMakeCurrent" (ByVal dc As Integer, ByVal rc As Integer) As Integer Declare Sub glEnable Lib "opengl32" Alias "glEnable" (ByVal cap As Integer) Declare Sub glMatrixMode Lib "opengl32" Alias "glMatrixMode" (ByVal mode As Integer) Declare Sub glOrtho Lib "opengl32" Alias "glOrtho" (ByVal l As Double , ByVal r As Double , ByVal b As Double , ByVal t As Double, ByVal n As Double, ByVal f As Double) Declare Sub glBegin Lib "opengl32" Alias "glBegin" (ByVal mode As Integer) Declare Sub glEnd Lib "opengl32" Alias "glEnd" () Declare Sub glColor4f Lib "opengl32" Alias "glColor4f" (ByVal r As Single , ByVal g As Single , ByVal b As Single , ByVal a As Single) Declare Sub glClearColor Lib "opengl32" Alias "glClearColor" (ByVal r As Single, ByVal g As Single, ByVal b As Single, ByVal a As Single) Declare Sub glVertex3d Lib "opengl32" Alias "glVertex3d" (ByVal x As Double , ByVal y As Double , ByVal z As Double) Declare Sub glClear Lib "opengl32" Alias "glClear" (ByVal mask As Integer) Declare Sub glBlendFunc Lib "opengl32" Alias "glBlendFunc" (ByVal src As Integer, ByVal dst As Integer) Type PIXELFORMATDESCRIPTOR - Short nSize, nVersion - Integer dwFlags - Byte iPixelType - Byte cColorBits - Byte cRedBits, cRedShift, cGreenBits, cGreenShift, cBlueBits, cBlueShift - Byte cAlphaBits, cAlphaShift - Byte cAccumBits, cAccumRedBits, cAccumGreenBits, cAccumBlueBits, cAccumAlphaBits - Byte cDepthBits - Byte cStencilBits - Byte cAuxBuffers - Byte iLayerType - Byte bReserved - Integer dwLayerMask - Integer dwVisibleMask - Integer dwDamageMask EndType (omg we are speed today)
That's the reason of why i dont use my library i have modified again and again...
|
|
|
Post by scalion on Sept 3, 2019 20:31:30 GMT 1
By wanting to shorten the program I was a little too fast. Oups. Sorry but I forgot something important : If missed wglDeleteContext(OpenGL_RDC). i have modified the code in first post. This function wglDeleteContext(RenderingDeviceContext) make OpenGl dispose of it.
|
|
|
Post by scalion on Sept 4, 2019 12:15:16 GMT 1
Now,To go one step further, let's combine 2D with 3D text. This time I put some comments to explain a little more detail.
$Library "OpenGL.inc"
Declare Sub glLightv Lib "opengl32" Alias "glLightfv" (ByVal light As Integer, ByVal pname As Integer, ByRef params As VECT)
Global Long OpenGL_DC, OpenGL_RDC, PixelFormat Global PFD As PIXELFORMATDESCRIPTOR
' First we open a classical window (or form like here) Form OpenGLWin Me.FullW AutoRedraw = 1
' We must define a pixel format using PIXELFORMATDESCRIPTOR. ' This structure will be used to inform GDI of what we want. ' Here we only fill in the strictly mandatory fields. PFD.nSize = SizeOf(PFD) ' Required PFD.nVersion = 1 ' nversion must be always 1
' For drawing with Opengl we must indicate how. ' For example it's possible to use PFD_DRAW_TO_BITMAP instead PFD_DRAW_TO_WINDOW ' in this case PFD_DOUBLEBUFFER not necessary PFD.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW
' Remarks : ' If we want to draw 3D graphics we must have the better z-buffer we want ' if it's 2D we have not write with PFD.cDepthBits = 32 PFD.cDepthBits = 32
' GFABASIC initialising variables to zero even typed ' It is not necessay to indicate PFD.iPixelType = PFD_TYPE_RGBA ' Because PFD_TYPE_RGBA = 0
' The ChoosePixelFormat return the most compatible index of pixel format with DC ' The pixel format work automaticaly even he's different of PFD OpenGL_DC = Me.hDC PixelFormat = ChoosePixelFormat(OpenGL_DC, PFD)
' We set the selected pixel format to the DC of window openened ' The PFD is indicated to perform logical functionnality Void SetPixelFormat(OpenGL_DC, PixelFormat, PFD)
' Now the Device Context is configured with the better pixel format we can have ' That's the window part. OpenGL need his proper specific Device Context. ' He's called "Rendering Device Context", and it will inteactive with the window DC. ' To create it simply write : OpenGL_RDC = wglCreateContext(OpenGL_DC)
' We must inform OpenGL that the actual DC is linked to the RDC created. ' If successfull OpenGL know the thread of the DC and can work now. If wglMakeCurrent(OpenGL_DC, OpenGL_RDC) Message"OpenGL Initialised" Else Message"OpenGL Initialised" End EndIf
' It's finished to initialize OpenGL
' For 2D drawing, it's simple parrallel projection ' like this : ' glMatrixMode(GL_PROJECTION) ' glOrtho(0, _X, _Y, 0, -1000, 1000)
' We set the RGBA colors used to clear screen glClearColor(0, 0, 0, 0)
' Enabling the transparancy glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
' Setting list for text rendering usind actual selected font. ' For this we need the GLYPHMETRICSFLOAT structure ' that is not implemented for this time and we must write ourself. ' Same thing for the constant WGL_FONT_POLYGONS Type GLYPHMETRICSFLOAT - Single gmfBlackBoxX - Single gmfBlackBoxY - POINTFLOAT gmpftGlyphOrigin - Single gmfCellIncX - Single gmfCellIncY End Type Type POINTFLOAT - Single x, y EndType Global Const WGL_FONT_LINES = 0 Global Const WGL_FONT_POLYGONS = 1
' The metrics are stored and can be used to centering a text for example Global GMF(90 - 32 + 1) As GLYPHMETRICSFLOAT
' Here we generete list index from 1000 ' Normaly we must use GlGenLists() in a proper code but i simplify ' the first character is 32 (space) and the last is Z (90) ' The "deviation" is zero tha mean it's the exact glyph of original font ' WGL_FONT_POLYGONS indicate it's plain polygone, not only outlines ' try to replace by WGL_FONT_LINES to see what this give ' thickness of 10 Void wglUseFontOutlines(Me.hDC, 32, 90 - 32 + 1, 1000, 0, 10, WGL_FONT_POLYGONS, V:GMF(0))
' This demonstration main loop showing 2 colored triangles usings transparancy ' and a text in 3D rotating with a static lighting
Global Double a, t = Timer, FPS Global Long FS = 0, NFPS = 0
Type VECT - Single x, y, z, w End Type
Global String Txt
Do ' Show Frames per second in window title Inc FS If Timer - t >= 1 Inc NFPS : FPS = FS / NFPS Me.Caption = "FPS = " & FPS FPS = 0 : t = Timer EndIf ' The part of the screen where opengl send the drawing to gdi glViewport(0, 0, Max(1, _X), Max(1, _Y)) ' Clearing the screen color and the z-buffer in back buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ' Drawing 3D part **************************************************************** ' Enabling depth test to have hidden faces, otherwise all is drawed in order glEnable(GL_DEPTH_TEST) ' Enabling coloring (yes it's strange) glEnable(GL_COLOR_MATERIAL) ' LoadIdentity set the matrix to default value glLoadIdentity() glMatrixMode(GL_PROJECTION) glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 84) glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glLightv(GL_LIGHT0, GL_AMBIENT , NewVector(0.5, 0.5, 0.5, 1)) glLightv(GL_LIGHT0, GL_DIFFUSE , NewVector(1, 1, 0.5, 0.9)) glLightv(GL_LIGHT0, GL_SPECULAR, NewVector(0.5, 0.5, 1, 0.9)) ' Define angle of view of 45 the aspect ratio according the screen ' and depth z min=0.1 and max=1000 clipping gluPerspective(45, Max(1, _X) / Max(1, _Y), 0.1, 1000) ' Positioning the camera ' gluLookAt set matrix transformation ' instead gluLookat we can ourself use functions like glRotate() and glTranslate() gluLookAt(0, 0, -500, 0, 0, 0, 0, 1, 0) ' Positioning the light is little complicated ' Because the matrix is applied to the light ' That mean for ech matrix transformation we must ' calculate the opposite position ' or in other words We must inverse manually the matrix. ' There are plenty of ways to do this. glMatrixMode(GL_MODELVIEW) glPushMatrix() a = Frac(Timer / 10) * 360 glRotated(-a, 0, 1, 0) glTranslated(120, 0, 0) glLightv(GL_LIGHT0, GL_POSITION, NewVector(-500, 0, 0, 0)) glPopMatrix() glMatrixMode(GL_PROJECTION) glRotated(Frac(Timer / 10) * 360, 0, 1, 0) glRotated(Sin(Frac(Timer / 15) * 2 * PI) * 50, 1, 1, 0) glTranslated(-240, 0, 0) glScaled(80, 80, 1) glListBase(1000 - 32) ' Drawing text "GFABASIC 32" ' note we always must encapsuling glCallLists() by glPushMatrix() and glPopMatrix() ' because the lists generated by wglUseFontOutlines contain also translate() calls glPushMatrix() Txt = "GFABASIC" glColor4f(1, 0.5, 0.2, 1) glCallLists(Len(Txt), GL_UNSIGNED_BYTE, V:Txt) Txt = " 32" glColor4f(1, 0, 0, 0.5) glCallLists(Len(Txt), GL_UNSIGNED_BYTE, V:Txt) glPopMatrix() ' Drawing text of current time glPushMatrix() Txt = Time$ glColor4f(0, 1, 1, 1) glTranslated(1, -1, 0) glCallLists(Len(Txt), GL_UNSIGNED_BYTE, V:Txt) glDisable(GL_DEPTH_TEST) glDisable(GL_LIGHTING) glPopMatrix() ' Drawing in 2D ************************************************************************** glLoadIdentity() glMatrixMode(GL_PROJECTION) glOrtho(0, _X, _Y, 0, -1, 1) glBegin(GL_TRIANGLES) glColor4f(1, 1, 0, 1) : glVertex2d(MouseX - 115, MouseY + 100) glColor4f(0, 1, 1, 1) : glVertex2d(MouseX, MouseY - 100) glColor4f(1, 0, 1, 1) : glVertex2d(MouseX + 115, MouseY + 100) glEnd() glTranslated(_X / 2, _Y / 2, 0) glRotated(Frac(Timer / 2) * 360, 0, 0, 1) glBegin(GL_TRIANGLES) glColor4f(1, 0, 0, 0.75) : glVertex2d(0, - 134) glColor4f(0, 1, 0, 0.75) : glVertex2d(-115.47, 66) glColor4f(0, 0, 1, 0.75) : glVertex2d(115.47 , 66) glEnd() SwapBuffers(OpenGL_DC) PeekEvent Loop Until Me Is Nothing
wglDeleteContext(OpenGL_RDC)
Function NewVector(x#, y#, z#, w#) As VECT NewVector.x = x NewVector.y = y NewVector.z = z NewVector.w = w End Function
|
|
|
Post by scalion on Sept 4, 2019 21:01:30 GMT 1
Regardes si tu as bien cette ligne dans on OpenGL.inc.g32 : Declare Function wglUseFontOutlines Lib "OPENGL32.DLL" Alias "wglUseFontOutlinesA" (ByVal hdc%, ByVal dFirst%, ByVal dCount%, ByVal dListBase%, ByVal deviation!, ByVal extrusion!, ByVal iFormat%, ByVal lpgmf%) As Int
il manque certainement l'alias "wglUseFontOutlinesA"
Il se pourrait que nous n'ayons pas le même fichier include parce-que j'utilise une version beta-test du GFA-Basic.
En attendant tu peux écrire sans que cela interfère avec la déclaration dans le fichier include :
Declare Function UtiliserLesLignesDeFonte Lib "OPENGL32.DLL" Alias "wglUseFontOutlinesA" (ByVal hdc%, ByVal dFirst%, ByVal dCount%, ByVal dListBase%, ByVal deviation!, ByVal extrusion!, ByVal iFormat%, ByVal lpgmf%) As Int
Dès lors tu remplaces wglUseFontOutlines par ton UtiliserLesLignesDeFonte dans l'appel de la fonction.
Si malgré cela ça ne marche encore pas il faudrait que tu me dises ta version d'OpenGL (mais normalement cette fonction est très ancienne donc...)
|
|
|
Post by scalion on Sept 5, 2019 10:27:09 GMT 1
Les Textures.
Dans cet example on va créer une texture RGBA et la mapper sur un cube.
Il nous faut d'abord dessiner une texture, pour ce faire on ouvre une fenetre cachée avec l'autoredraw activée, on ajuste sa taille à la dimension désirée (ici w et h) et on dessine dedans. Ici c'est une mire alternant des rayons colorés et gris encadrée par une bordure noire et blanche avec un ront blanc au milieu.
On crée un bitmap du dessin : Get 0, 0, w - 1, h - 1, BitmapForTexture
On réserve une zone de mémoire pour transférer les données de couleurs. Pour ce qui est de la couche alpha on va simplement la remplir avec la valeur 255 (totalement opaque).
Adr = mAlloc(w * h * 4) Void GetBitmapBits(BitmapForTexture, w * h * 4, Adr) For i = Adr To Adr + w * h * 4 - 3 Step 4 LPoke i, Bswap3(LPeek(i)) | $FF000000 Next i
Ceci fait, on peut supprimer le bitmap avec FreeBmp et fermer la fenêtre (clac!).
Pour créer une texture on doit activer la gestion des textures 2D: glEnable(GL_TEXTURE_2D)
On demande à OpenGL de générer un index libre pour notre texture : glGenTextures(1, V:TextureIndex)
On lui indique qu'on l'utilise: glBindTexture(GL_TEXTURE_2D, TextureIndex)
On définit comment vont être affichés les pixels de la texture, ici on définit qu'il y aura une interpolation en cas d'agrandissement (GL_TEXTURE_MAG_FILTER) et en cas zoom arrière (GL_TEXTURE_MIN_FILTER) c'est la moyenne du pixel et des 4 pixels contigus qui est affichés :
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
Il ne reste plus qu'à envoyer les données de couleurs et de transparence RGBA dans la texture en lui indiquant la taille de l'image:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, Adr)
Et bien sûr on libère la mémoire allouée avec mFree().
A ce point la texture est créée !
Pour l'utiliser on appelle avant un glBegin() : GL_BIND(GL_TEXTURE2D,TextureIndex)
Et ensuite on définit au fur et à mesure la position des vertex dans la texture. Par exemple glTexCoord2f(0, 0) suivi d'un Vertex3f().
Les valeurs vont de 0 à 1 d'un point de vu strictement logique, mais les valeur inférieuses et supérieures peuvent tout à fait être utilisées. Il faut simplement indiquer à OpenGl comment il traite ces dépassements avec par exemple si on veut que ça se remplisse avec les pixels du bord:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
Notez aussi qu'il existe une matrice pour les texture. Vous verrez un exemple d'utilisation dans le code source.
Voilà je crois j'ai rien oublié. Bonne journée
|
|
|
Post by scalion on Sept 5, 2019 15:38:33 GMT 1
glMatrixMode(GL_TEXTURE) est bon, il s'agit de modifier la matrice de texture. GL_TEXTURE_2D ne s'applique pas ici, du coup tu as appliqué une transformation sur la matrice de projection ce qui explique que ton cube se retrouve plus haut. Avant toute opération de transformation on informe OpenGL sur quelle matrice on va travailler avec glMatrixMode(), comme GL_TEXTURE_2D n'est pas un paramètre valide il est resté sur GL_PROJECTION il y a 4 matrices différentes dans OpenGL : GL_MODELVIEW ca j'ai toujours pas compris exactement mais c'est utilisé par les glLight() GL_PROJECTION pour les positionnement des vertex() GL_TEXTURE pour glTexCoord() (par exemple faire un glScale() avec cette matrice agrandit ou réduit la texture) GL_COLOR spécifique pour des opérations comme glDrawPixel()
Merci pour le retour
|
|
|
Post by scalion on Sept 6, 2019 10:52:57 GMT 1
Ca a rien à voir mais grrrr.. J'essaie de faire un fichier d'aide pour OpenGL et... Je suis en train de me bagarrer avec HTML Help Work Shop qui est une véritable daube nauséabonde. Ca fait des mois que je l'utilise et c'est bourré de bugs ce machin. Ils ont osé distribué ça... Jette un oeil par curiosité sur la structure interne des fichiers CHM, le mec qui a pondu ça doit être complètement drogué.
|
|
|
Post by scalion on Mar 27, 2020 18:26:42 GMT 1
Hi all, I ended up finding a simple way to find out which polygon displayed in OpenGL is under the mouse (or any point on the screen actually). To reach this target i use the FeedBack Buffer.
Here the demo with explanations :
|
|
|
Post by scalion on Mar 27, 2020 20:56:26 GMT 1
J'adore ton POST JMM Maintenant je termine mon pacman 3d (surtout j'attends que tu me fasses une super librairie gl32 avec WaveOut pour y mettre du son !!!!!) ... au plus vite parce-que j'ai d'autres trucs en cours... je suis un peu taquin ^^
Coming soon :
|
|