Gelöst: [OpenGL] glDrawElements mit VAO, VBO und EBO

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
pexxll
Beiträge: 6
Registriert: 29.01.2019 14:54

Gelöst: [OpenGL] glDrawElements mit VAO, VBO und EBO

Beitrag von pexxll »

Hallo,

um PureBasic mit modernem OpenGL zu lernen, hatte ich begonnen, mich anhand des von Luis empfohlenen Tutorials für OpenGL 3.3+ Schritt für Schritt entlang zu hangeln und das Beispiel 1 zu 1 in Purebasic nachzubauen. Dank vieler guter Beispiele und Anleitungen im deutschen und englischen Forum konnte ich bereits so manche Hürden nehmen.

Tutorial: https://learnopengl.com/Getting-started/Hello-Triangle

Ich hatte es geschafft, mittels Vertex Array Object und Vertex Buffer Object sowie den benötigten Shadern 2 farbige (an der Längsseite deckungsgleiche) Dreiecke darzustellen.

Bild

Um doppeltes Rendern der überlappenden Vertices zu vermeiden, wird daraufhin im Tutorial die Anzahl Vertices um die Doppelten reduziert und ein weiterer Array angelegt, der angibt, aus welchen Vertices die Dreiecke sich jeweils zusammen setzen. Dieser Index-Array wird ans Element Buffer Object gebunden. Hier stoße ich leider an meine Grenzen.
Werden die Dreiecke mit glDrawArrays gezeichnet, ergibt sich folgendes Bild:

Bild

Im Tutorial wird nun allerdings glDrawElements verwendet.
Mit glDrawElements(#TRIANGLES...) bekomme ich folgendes Ergebnis:

Bild

Mit glDrawElements(#TRIANGLE_STRIP...):

Bild

Trotz Orientierung an funktionierenden Beispielen mit VBO und EBO wie diesem hier
https://www.purebasic.fr/english/viewto ... lit=openGL
weiß ich nicht, was ich falsch mache. Über Hilfestellung würde ich mich freuen.

Hier der Code:

Code: Alles auswählen

#GL_ARRAY_BUFFER = $8892
#GL_STATIC_DRAW = $88E4
#GL_VERTEX_SHADER = $8B31
#GL_FRAGMENT_SHADER = $8B30
#GL_ELEMENT_ARRAY_BUFFER = $8893
;#GL_UNSIGNED_INT = 5125
;#GL_FRONT_AND_BACK = 1032



;wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
; Koordinaten für Vertices (Struktur und Array)
;wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
Global points_vbo.i, colors_vbo.i, vao.i, ebo.i
        
Structure Tvertex
  x.f
  y.f
  z.f
EndStructure

Structure Tindex
  a.i
  b.i
  c.i
EndStructure



Global Dim Vertex.Tvertex(6)

;wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
;Original-Array der Vertices für 2 Dreiecke 
;wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

;!!!!!!!!!!! 2 Dreiecke teilen sich 2 Vertizes - schlechte Performance -> deshalb EBO verwenden !!!!!!!!!!!!!!!!
; ;// first triangle
; Vertex(0)\x = 0.5  : Vertex(0)\y = 0.5  : Vertex(0)\z = 0     ; // top right
; Vertex(1)\x = 0.5   : Vertex(1)\y = -0.5  : Vertex(1)\z = 0   ; // bottom right
; Vertex(2)\x = -0.5   : Vertex(2)\y = 0.5 : Vertex(2)\z = 0    ; // top left 
; 
; ; ;// second triangle
; Vertex(3)\x = 0.5  : Vertex(3)\y = -0.5  : Vertex(3)\z = 0     ; // top right
; Vertex(4)\x = -0.5   : Vertex(4)\y = -0.5  : Vertex(4)\z = 0   ; // bottom left
; Vertex(5)\x = -0.5   : Vertex(5)\y = 0.5 : Vertex(5)\z = 0    ; // top left 

;wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
;reduzierter Array der Vertices für 2 Dreiecke und Index-Array für EBO
;wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

Vertex(0)\x = 0.5  : Vertex(0)\y = 0.5  : Vertex(0)\z = 0     ; // top right
Vertex(1)\x = 0.5   : Vertex(1)\y = -0.5  : Vertex(1)\z = 0   ; // bottom right
Vertex(2)\x = -0.5   : Vertex(2)\y = -0.5 : Vertex(2)\z = 0   ; // bottom left 
Vertex(3)\x = -0.5   : Vertex(3)\y = 0.5 : Vertex(3)\z = 0    ; // top left 

Global Dim Index.Tindex(2)

Index(0)\a = 0  : Index(0)\b = 1  : Index(0)\c = 3     ; // first triangle
Index(1)\a = 1  : Index(1)\b = 2  : Index(1)\c = 3     ; // second triangle


;wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

;!!!!! stehen diese Zeilen hinter der include-Datei gibt es bei glcreateShader einen Invalid Memory access-Fehler
OpenWindow(0, 0, 0, 800, 600, "Tutorial Phase 3 - VertexShader ")
OpenGLGadget(0, 10, 10, WindowWidth(0) , WindowHeight(0) , #PB_OpenGL_Keyboard)
glClearColor_(0.5, 0.5, 0.3, 1.0)
glViewport_(0, 0, WindowWidth(0), WindowHeight(0))
glPolygonMode_(#GL_FRONT_AND_BACK, #GL_LINE)


IncludeFile "d:\OpenGL\OpenGL_INCLUDE\MoreFunctions.pbi" 


glGenVertexArrays (1, @vao)   ; Vertex Array Object
glBindVertexArray(vao)

;2. copy our vertices Array in a buffer For OpenGL To use
glGenBuffers(1, @points_vbo ) ; Vertex Buffer Object
glBindBuffer(#GL_ARRAY_BUFFER, points_vbo);
;!!!!!!!!!!!!!!!!! mit glBufferData(#GL_ARRAY_BUFFER,12 * SizeOf(float),@Vertex(0), #GL_STATIC_DRAW) wird nur eines von 2 kompletten Dreiecken angezeigt !!!!!!!!!!!!
glBufferData(#GL_ARRAY_BUFFER,12 * ArraySize(Vertex()),@Vertex(0), #GL_STATIC_DRAW)  

;3. copy our index Array in a element buffer For OpenGL To use
glGenBuffers(1, @ebo)         ;Element Buffer Object
glBindBuffer(#GL_ELEMENT_ARRAY_BUFFER, ebo) 
glBufferData(#GL_ELEMENT_ARRAY_BUFFER, 12*ArraySize(Index()), @Index(0), #GL_STATIC_DRAW);


;// 4. then set our vertex attributes pointers
glVertexAttribPointer(0, 3, #GL_FLOAT, #GL_FALSE, 3 * SizeOf(float), 0)
glEnableVertexAttribArray(0);

glEnable_(#GL_DEPTH_TEST); // enable depth-testing


;wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
; Shader anlegen
;wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

Define vertex_shader.s
Define fragment_shader.s
Define *fbuff
Define *vbuff


vertex_shader = "#version 330 core"+#CRLF$
vertex_shader + "layout(location = 0) in vec3 aPos;"+#CRLF$
vertex_shader + "void main() {"+#CRLF$
vertex_shader + "gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);"+#CRLF$
vertex_shader + "}"



fragment_shader = "#version 330 core"+#CRLF$
fragment_shader + "out vec4 FragColor;"+#CRLF$
fragment_shader + "void main()"+#CRLF$
fragment_shader + "{"+#CRLF$
fragment_shader + "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);"+#CRLF$
fragment_shader + "}"+#CRLF$



*vbuff = Ascii(vertex_shader)
*fbuff = Ascii(fragment_shader)



Global vs = glCreateShader(#GL_VERTEX_SHADER);
glShaderSource(vs, 1, @*vbuff, #Null) ;
glCompileShader(vs)

Global fs = glCreateShader(#GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, @*fbuff, #Null);
glCompileShader(fs)  




;wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
; Shader zu Programm zusammenfügen
;wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

Global shader_programme = glCreateProgram();
glAttachShader(shader_programme, vs);
glAttachShader(shader_programme, fs);
glLinkProgram(shader_programme)     ;

; nicht mehr benötigte Shader werden gelöscht
glDeleteShader(vs)
glDeleteShader(fs)


;wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
;Drawing (in render loop)
;wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
    
SetActiveGadget(0)

   Repeat
   
     Event = WaitWindowEvent()
     If Event = #PB_Event_Gadget And EventGadget() = 0
        If EventType() = #PB_EventType_KeyDown
     
            key = GetGadgetAttribute(0,#PB_OpenGL_Key )
            If key = #PB_Shortcut_Up               
            ElseIf key = #PB_Shortcut_Escape ;  Esc key to exit

             quit = 1
            EndIf
        EndIf
      EndIf

  glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)
  glViewport_(0, 0, 800, 600)                          
  glUseProgram(shader_programme)
  
; glEnableClientState_(#GL_VERTEX_ARRAY )
  glBindVertexArray(vao)
  
  ;draw points 0-6 from the currently bound VAO With current in-use shader
  ;glDrawArrays_(#GL_TRIANGLES, 0, 6)
  
   glDrawElements_(#GL_TRIANGLES, 6, #GL_UNSIGNED_INT, 0 )
  ;glDrawElements_(#GL_TRIANGLE_STRIP, 6, #GL_UNSIGNED_INT, 0 )
   
   glBindVertexArray(0)                                  
   SetGadgetAttribute(0, #PB_OpenGL_FlipBuffers, #True)
  Delay(16)
 
Until Event = #PB_Event_CloseWindow Or quit = 1
Vielen Dank und Gruß
pexxll
Zuletzt geändert von pexxll am 31.01.2019 19:57, insgesamt 3-mal geändert.
Benutzeravatar
man-in-black
Beiträge: 362
Registriert: 21.08.2006 17:39

Re: [OpenGL] glDrawElements mit VAO, VBO und EBO

Beitrag von man-in-black »

Hi,

gucke dir die Reihenfolge der Punkte im Array an. Die Dreiecke werden meines Wissens immer aus den letzten 3 Punkten gebildet (bezüglich eines Zeigers von Element 3 bis n). Deine Folge müsste also wie folgt aussehen: rechts-oben > rechts-unten > links-oben > links-unten. Die Reihenfolge hat später auch einen Einfluss auf die Flächennormalen und damit u.a. die Füllung der Dreiecke.

MFG
MIB
(hab alles, kann alles, weiß alles!!^^)

Bild
pexxll
Beiträge: 6
Registriert: 29.01.2019 14:54

Re: [OpenGL] glDrawElements mit VAO, VBO und EBO

Beitrag von pexxll »

Hallo man-in-black,

danke für deinen Hinweis! Ich habe die Reihenfolge wie folgt geändert, und sehe nun zumindest das erste Dreieck mit glDrawElements(#TRIANGLES...) vollständig.

Code: Alles auswählen

Vertex(0)\x = 0.5  : Vertex(0)\y = 0.5  : Vertex(0)\z = 0     ; // top right
Vertex(1)\x = 0.5   : Vertex(1)\y = -0.5  : Vertex(1)\z = 0   ; // bottom right
Vertex(2)\x = -0.5   : Vertex(2)\y = 0.5 : Vertex(2)\z = 0    ; // top left 
Vertex(3)\x = -0.5   : Vertex(3)\y = -0.5 : Vertex(3)\z = 0   ; // bottom left 


Global Dim Index.Tindex(2)

Index(0)\a = 2  : Index(0)\b = 1  : Index(0)\c = 0     ; // first triangle
Index(1)\a = 3  : Index(1)\b = 2  : Index(1)\c = 1     ; // second triangle
Ich probier mal weiter.

mfg
pexxll
Benutzeravatar
man-in-black
Beiträge: 362
Registriert: 21.08.2006 17:39

Re: [OpenGL] glDrawElements mit VAO, VBO und EBO

Beitrag von man-in-black »

Hi,

bin eben extra an den PC, um dein Beispiel genauer anzugucken. Leider fehlt die eine Include ...
Daher nur eine halbgare Lösung/ vielmehr mein händischer debugger :lol: :

Was mir jetzt aufgefallen ist:
Deine neuen Punkte werden wie folgt vorgegeben:

Code: Alles auswählen

T1:
1       3
                        gegen Uhrzeigersinn (ccw)
        2

T2:
2
                         Uhrzeigersinn (cw)
1        3
Das bewirkt im Code unterschiedlich gerichtete Flächennormalen (+-z). Normalerweise wird in OpenGL entweder +z oder -z verborgen.
Das könnte der Grund für das Nicht-Anzeigen sein.

---
Zu deinem ersten Post:
glDrawArrays nutzt meines Wissens nur den Array und nicht die Indice.
Daher kommt folgendes Bild heraus:

Code: Alles auswählen

T1:
           1
                         Uhrzeigersinn (cw)
3          2

T2:
1
     0                   Strich, da Element [5-6] = 0

wenn du glDrawElements nutzt:
Die Linien passen. Weshalb der Rest nicht stimmt, kann ich ohne Probieren nicht sagen:

Code: Alles auswählen

T1:
3         1
                         Uhrzeigersinn (cw)
          2

T2:
3
                         Uhrzeigersinn (cw)
2         1
und mit dem _Strip kommt folgende Reihenfolge:

Code: Alles auswählen

T1:
3,6        1
                         2-3-4 = Linie;  3-4-5 = Dreieck (cw); 4-5-6 = Dreieck (cw)
5         2,4

MFG
MIB
(hab alles, kann alles, weiß alles!!^^)

Bild
pexxll
Beiträge: 6
Registriert: 29.01.2019 14:54

Re: [OpenGL] glDrawElements mit VAO, VBO und EBO

Beitrag von pexxll »

Hallo man-in-black,

während ich jetzt deine Angaben genauer unter die Lupe nehme, vielen Dank dafür, hier der Vollständigkeit halber die Include-Datei MoreFunctions.pbi:

Code: Alles auswählen

CompilerIf (#PB_Compiler_Processor = #PB_Processor_x86)
Import "Opengl32.lib" 
 wglGetProcAddress_(s.p-ascii) As "_wglGetProcAddress@4"
EndImport
 CompilerElse   
Import "Opengl32.lib" 
 wglGetProcAddress_(s.p-ascii) As "wglGetProcAddress"
EndImport
CompilerEndIf

Prototype PFNGLGENBUFFERSPROC ( n.i, *buffers)
Global glGenBuffers.PFNGLGENBUFFERSPROC
glGenBuffers = wglGetProcAddress_( "glGenBuffers" )
Prototype PFNGLBINDBUFFERPROC ( target.l, buffer.i)
Global glBindBuffer.PFNGLBINDBUFFERPROC
glBindBuffer = wglGetProcAddress_( "glBindBuffer" )
Prototype PFNGLBUFFERDATAPROC ( target.l, size.i, *Data_, usage.l)
Global glBufferData.PFNGLBUFFERDATAPROC
glBufferData = wglGetProcAddress_( "glBufferData" )

Prototype PFNGLGENVERTEXARRAYSPROC (n.i, *arrays)
Global glGenVertexArrays.PFNGLGENVERTEXARRAYSPROC
glGenVertexArrays = wglGetProcAddress_( "glGenVertexArrays" )

Prototype PFNGLBINDVERTEXARRAYPROC(n.i)
Global glBindVertexArray.PFNGLBINDVERTEXARRAYPROC
glBindVertexArray = wglGetProcAddress_( "glBindVertexArray" )

Prototype PFNGLENABLEVERTEXATTRIBARRAYPROC ( index.i )
Global glEnableVertexAttribArray.PFNGLENABLEVERTEXATTRIBARRAYPROC
glEnableVertexAttribArray = wglGetProcAddress_( "glEnableVertexAttribArray" )

Prototype PFNGLVERTEXATTRIBPOINTERPROC ( index.i, size.i, type.l, normalized.b, stride.i, *pointer )
Global glVertexAttribPointer.PFNGLVERTEXATTRIBPOINTERPROC
glVertexAttribPointer = wglGetProcAddress_( "glVertexAttribPointer" )

Prototype.i PFNGLCREATESHADERPROC ( type.l )
Global glCreateShader.PFNGLCREATESHADERPROC
glCreateShader = wglGetProcAddress_( "glCreateShader" )

Prototype PFNGLSHADERSOURCEPROC ( shader.i, count.i, *stringBuffer, *length )
Global glShaderSource.PFNGLSHADERSOURCEPROC
glShaderSource = wglGetProcAddress_( "glShaderSource" )

Prototype PFNGLCOMPILESHADERPROC ( shader.i )
Global glCompileShader.PFNGLCOMPILESHADERPROC
glCompileShader = wglGetProcAddress_( "glCompileShader" )

Prototype PFNGLATTACHSHADERPROC ( program.i, shader.i )
Global glAttachShader.PFNGLATTACHSHADERPROC
glAttachShader = wglGetProcAddress_( "glAttachShader" )

Prototype PFNGLLINKPROGRAMPROC ( program.i )
Global glLinkProgram.PFNGLLINKPROGRAMPROC
glLinkProgram = wglGetProcAddress_( "glLinkProgram" )

Prototype.i PFNGLCREATEPROGRAMPROC ( )
Global glCreateProgram.PFNGLCREATEPROGRAMPROC
glCreateProgram = wglGetProcAddress_( "glCreateProgram" )

Prototype PFNGLUSEPROGRAMPROC ( program.i )
Global glUseProgram.PFNGLUSEPROGRAMPROC
glUseProgram = wglGetProcAddress_( "glUseProgram" )

; Prototype PFNGLDRAWARRAYSPROC ( mode.l, first.i, count.i )
; Global glDrawArrays.PFNGLDRAWARRAYSPROC
; glDrawArrays = wglGetProcAddress_( "glDrawArrays" )

Prototype PFNGLMAPBUFFERPROC(Target.i, Access.i)
Global glMapBuffer.PFNGLMAPBUFFERPROC
glMapBuffer = wglGetProcAddress_("glMapBuffer")

Prototype PFNGLUNMAPBUFFERPROC(Target.i)
Global glUnmapBuffer.PFNGLUNMAPBUFFERPROC
glUnmapBuffer = wglGetProcAddress_("glUnmapBuffer")

Prototype PFNGLBUFFERSUBDATAPROC ( target.l, offset.i, size.i, *Data_)
Global glBufferSubData.PFNGLBUFFERSUBDATAPROC
glBufferSubData = wglGetProcAddress_( "glBufferSubData" )

;**********************************************************************************
;                                   NewFunctions
;**********************************************************************************

Prototype PFNGLGETUNIFORMLOCATIONPROC ( program.i, name.p-ascii )
Global glGetUniformLocation.PFNGLGETUNIFORMLOCATIONPROC
glGetUniformLocation = wglGetProcAddress_( "glGetUniformLocation" )

Prototype PFNGLUNIFORMMATRIX4FVPROC ( location.i, count.i, transpose.b, *value )
Global glUniformMatrix4fv.PFNGLUNIFORMMATRIX4FVPROC
glUniformMatrix4fv = wglGetProcAddress_( "glUniformMatrix4fv" )

;**********************************************************************************
;                                   MyFunctions
;**********************************************************************************

Prototype PFNGLDELETESHADERPROC (shader.i )
Global glDeleteShader.PFNGLDELETESHADERPROC
glDeleteShader = wglGetProcAddress_( "glDeleteShader" )

; Prototype PFNGLGETPROGRAMPARAMETERPROC (program.i, status.i)
; Global glGetProgramParameter.PFNGLGETPROGRAMPARAMETERPROC
; glGetProgramParameter = wglGetProcAddress_( "glGetProgramParameter" )
Danke für die Hilfe und
Grüße
pexxll
pexxll
Beiträge: 6
Registriert: 29.01.2019 14:54

Re: [OpenGL] glDrawElements mit VAO, VBO und EBO

Beitrag von pexxll »

Hallo,

beim Ausprobieren der überlappenden Dreieck-Darstellung mit VAO und EBO habe ich weiter mit den Reihenfolgen der Indices und Vertices experimentiert. Auch in Uhrzeigerrichtung oben rechts beginnend, ergibt sich kein Viereck mit Diagonale.
(eingebundene PBI siehe voriger Post)

Auch hat es den Anschein, als würde nur Index(0) in die Berechnung einbezogen, denn egal welche Werte ich in Index(1) eintrage bzw. dieses ganz auskommentiere, bleibt die Bildschirmausgabe unverändert.

Mit der Variante wie vorgeschlagen, ergibt sich Folgendes.

Code: Alles auswählen

Vertex(0)\x = 0.5  : Vertex(0)\y = 0.5  : Vertex(0)\z = 0     ; // top right
Vertex(1)\x = 0.5   : Vertex(1)\y = -0.5  : Vertex(1)\z = 0   ; // bottom right
Vertex(2)\x = -0.5   : Vertex(2)\y = 0.5 : Vertex(2)\z = 0    ; // top left 
Vertex(3)\x = -0.5   : Vertex(3)\y = -0.5 : Vertex(3)\z = 0   ; // bottom left 
Variante 1:
Bild

Code: Alles auswählen

Index(0)\a = 1  : Index(0)\b = 3  : Index(0)\c = 2     ; // erstes Dreieck in Uhrzeigerrichtung
Index(1)\a = 0  : Index(1)\b = 1  : Index(1)\c = 2     ; // zweites dreieck in Uhrzeigerrichtung
Variante 2 (Indizes 0 und 1 vertauscht):
Bild

Code: Alles auswählen

Index(0)\a = 0  : Index(0)\b = 1  : Index(0)\c = 2     ; // zweites Dreieck zuerst
Index(1)\a = 1  : Index(1)\b = 3  : Index(1)\c = 2     ; // erstes Dreieck als Zweites
Hier nochmal der Link zum C++-Codebeisspiel: https://learnopengl.com/code_viewer_gh. ... ndexed.cpp

Verwirrte Grüße
pexxll
Benutzeravatar
man-in-black
Beiträge: 362
Registriert: 21.08.2006 17:39

Re: [OpenGL] glDrawElements mit VAO, VBO und EBO

Beitrag von man-in-black »

Hi,

nutzt eu die x64 Version? Dann hast du float/4byte und int/8byte.
Die musst du berücksichtigen, wenn du die Buffergrößen übergibst.
3x 4byte = 12 x Arraysize
3x 8byte = 24 x Arraysize (s. glBufferData)

nicht getestet, aber das könnte beschriebenes Chaos der Werte verursachen. ;)

MFG
MIB
(hab alles, kann alles, weiß alles!!^^)

Bild
pexxll
Beiträge: 6
Registriert: 29.01.2019 14:54

[Gelöst] [OpenGL] glDrawElements mit VAO, VBO und EBO

Beitrag von pexxll »

Hallo man-in-black,

ja 64er-Version. Danke für den Tipp. Dessen war ich mir nicht bewusst.
Mit diesen Werten hatte ich aber testweise auch schon rumgespielt. Beide ergeben das selbe Bild:

Code: Alles auswählen

glBindBuffer(#GL_ARRAY_BUFFER, points_vbo);
glBufferData(#GL_ARRAY_BUFFER,12 * ArraySize(Vertex()),@Vertex(0), #GL_STATIC_DRAW)  

glBindBuffer(#GL_ELEMENT_ARRAY_BUFFER, ebo) 
glBufferData(#GL_ELEMENT_ARRAY_BUFFER, 12*ArraySize(Index()), @Index(0), #GL_STATIC_DRAW)
und (wie zuvor):

Code: Alles auswählen

glBindBuffer(#GL_ARRAY_BUFFER, points_vbo);
glBufferData(#GL_ARRAY_BUFFER,12 * ArraySize(Vertex()),@Vertex(0), #GL_STATIC_DRAW)  

glBindBuffer(#GL_ELEMENT_ARRAY_BUFFER, ebo) 
glBufferData(#GL_ELEMENT_ARRAY_BUFFER, 24*ArraySize(Index()), @Index(0), #GL_STATIC_DRAW)
Ich habe es aber dennoch hinbekommen. *Freudentanz*
Die Art, wie der Index-Array gestrickt war, war offensichtlich verkehrt.

Ich bin über ein ähnliches Beispiel gestolpert, wo der Index-Array eindimensional ist (beide Dreiecke werden entgegen dem Uhrzeigersinn gezeichnet).Nun klappt es auch mit den beiden Dreiecken... Mit Uhrzeigersinn vermutlich auch, also Beide...

Bild

Hier nochmal die wichtigsten Eckdaten:

Code: Alles auswählen

Structure Tvertex
  x.f
  y.f
  z.f
EndStructure

Global Dim Vertex.Tvertex(4)
Vertex(0)\x = 0.5  : Vertex(0)\y = 0.5  : Vertex(0)\z = 0     ; // top right
Vertex(1)\x = 0.5   : Vertex(1)\y = -0.5  : Vertex(1)\z = 0   ; // bottom right
Vertex(2)\x = -0.5   : Vertex(2)\y = 0.5 : Vertex(2)\z = 0    ; // top left 
Vertex(3)\x = -0.5   : Vertex(3)\y = -0.5 : Vertex(3)\z = 0   ; // bottom left 

Global Dim Index.l(5)
index(0) = 1
index(1) = 0
index(2) = 2
index(3) = 3
index(4) = 1
index(5) = 2

...

glBufferData(#GL_ARRAY_BUFFER,12 * ArraySize(Vertex()),@Vertex(0), #GL_STATIC_DRAW)  
...

glBindBuffer(#GL_ELEMENT_ARRAY_BUFFER, ebo) 
glBufferData(#GL_ELEMENT_ARRAY_BUFFER, 24*ArraySize(Index()), @Index(0), #GL_STATIC_DRAW)

....

glDrawElements_(#GL_TRIANGLES, 6, #GL_UNSIGNED_INT, 0 )

....
Vielen Dank für deine Geduld und wertvollen Hinweise!

pexxll
Benutzeravatar
man-in-black
Beiträge: 362
Registriert: 21.08.2006 17:39

Re: Gelöst: [OpenGL] glDrawElements mit VAO, VBO und EBO

Beitrag von man-in-black »

Hi,

freut mich. Aber dein Code funktioniert nur zufälligerweise richtig. ;)

Vorweg, es ist egal, ob ein Array strukturiert ist oder nur einen nativen Datentyp repräsentiert.
Im Speicher bleibt es eine lange Kette aus Elementen (gucke dir das einfach mal mit peekI(Array.Point()+x*sizeOf(integer)) mit Laufvariable x an; Elemente natürlich vorher füllen).

Wieso hat es dann bei dir nicht geklappt? Weil OpenGL den Variablentyp nicht kannte und von
dir falsch übergeben bekommen hat. Deine Struktur besteht aus Int's (x64 > 8byte) und der Verarbeitung (glDrawElements) hast du #GL_UNSIGNED_INT übergeben. Das sind aber per Definition nur 4byte (auch in 64x). Du hättest theoretisch GLINT64 nutzen müssen, wenn es das gäbe. UND du darfst signed und unsigned nicht einfach so in einen Topf schmeißen!
https://www.khronos.org/opengl/wiki/OpenGL_Type

Wieso geht das letzte Beispiel? Weil dein Index als Long (4byte) definiert ist.
Und nimm beim letzten Beispiel die 24(byte) raus. Jedes Element ist nurnoch 4(byte) groß.

Damit sollten wir dein Problem endgültig erfasst und gelöst haben. ;)

MFG
MIB
(hab alles, kann alles, weiß alles!!^^)

Bild
pexxll
Beiträge: 6
Registriert: 29.01.2019 14:54

Re: Gelöst: [OpenGL] glDrawElements mit VAO, VBO und EBO

Beitrag von pexxll »

Hallo man-in-black,

ich ahnte sowas … 8)

Dass beim letzten Beispiel die 24Byte verkehrt waren, ist mir auch schon aufgefallen, da Long-Werte ja nur 4Byte einnehmen.

Auf den Zusammenhang zwischen #GL_UNSIGNED_INT und den Byte-Werten der Array-Typen wäre ich von alleine wohl nicht gekommen. Danke für die ausführliche Erläuterung! Ich glaub, jetzt habe ichs gerafft. >:)

UND du darfst signed und unsigned nicht einfach so in einen Topf schmeißen!
Dass bei glDrawElements #GL_UNSIGNED_INT verwendet wird, ist korrekt, oder? Der Index-Array enthält ja die keys des Vertex-Arrays und somit keine Negativ-Werte.

Code: Alles auswählen

...

Structure Tvertex
  x.f
  y.f
  z.f
EndStructure

Structure Tindex
  a.l
  b.l
  c.l
EndStructure

Global Dim Vertex.Tvertex(4)
Vertex(0)\x = 0.5  : Vertex(0)\y = 0.5  : Vertex(0)\z = 0     ; // top right
Vertex(1)\x = 0.5   : Vertex(1)\y = -0.5  : Vertex(1)\z = 0   ; // bottom right
Vertex(2)\x = -0.5   : Vertex(2)\y = 0.5 : Vertex(2)\z = 0    ; // top left 
Vertex(3)\x = -0.5   : Vertex(3)\y = -0.5 : Vertex(3)\z = 0   ; // bottom left 


Global Dim Index.Tindex(2)
Index(0)\a = 0  : Index(0)\b = 1  : Index(0)\c = 2     ; // first triangle
Index(1)\a = 1  : Index(1)\b = 3  : Index(1)\c = 2     ; // second triangle

...

glBindBuffer(#GL_ARRAY_BUFFER, points_vbo);
glBufferData(#GL_ARRAY_BUFFER,12 * ArraySize(Vertex()),@Vertex(0), #GL_STATIC_DRAW)  

glBindBuffer(#GL_ELEMENT_ARRAY_BUFFER, ebo) 
glBufferData(#GL_ELEMENT_ARRAY_BUFFER, 12*ArraySize(Index()), @Index(0), #GL_STATIC_DRAW)

...

glDrawElements_(#GL_TRIANGLES, 6, #GL_UNSIGNED_INT, 0 )

Danke und Grüße
pexxll
Antworten