Cookies op Tweakers

Tweakers is onderdeel van DPG Media en maakt gebruik van cookies, JavaScript en vergelijkbare technologie om je onder andere een optimale gebruikerservaring te bieden. Ook kan Tweakers hierdoor het gedrag van bezoekers vastleggen en analyseren. Door gebruik te maken van deze website, of door op 'Cookies accepteren' te klikken, geef je toestemming voor het gebruik van cookies. Wil je meer informatie over cookies en hoe ze worden gebruikt? Bekijk dan ons cookiebeleid.

Meer informatie
Toon posts:

[OpenGL] Renderen naar Texture via FrameBuffer lukt niet

Pagina: 1
Acties:

Vraag


Acties:
  • 0Henk 'm!

  • BoAC
  • Registratie: februari 2003
  • Nu online

BoAC

Memento mori

Topicstarter
Ik ben bezig met een hobby projectje waarbij ik ProjectM wil gebruiken om animaties weer te geven voor muziek.
ProjectM is een library die met behulp van OpenGL animaties weergeeft gebaseerd op sample data die je geeft via een callback-methode.

Ontwikkelomgeving: Ubuntu 20.04
OpenGL Libraries: Standaard meegeleverde Mesa library
X11 voor het aanmaken van de Windows

Nu gaat het weergeven van de animatie direct via OpenGL prima:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// relevante includes
..
#include <X11/X.h>
#include <X11/Xlib.h>

#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
..

// Init
    egl_display = eglGetDisplay((EGLNativeDisplayType)m_pWindow->getDisplay());
    if (egl_display == EGL_NO_DISPLAY) {
        return;
    }
    if (!eglInitialize(egl_display, NULL, NULL)) {
        return;
    }

    EGLint attr[] = {       // some attributes to set up our egl-interface
        EGL_BUFFER_SIZE, 16,
        EGL_RENDERABLE_TYPE,
        EGL_OPENGL_ES2_BIT,
        EGL_NONE
    };
   
    EGLint attributes[] = {
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_NONE};
   
 
    EGLConfig  ecfg;
    EGLint num_config;
    if ( !eglChooseConfig(egl_display, attr, &ecfg, 1, &num_config)) {
        return;
    }
 
    if (num_config != 1) {
        return;
    }
    
    if (!eglBindAPI(EGL_OPENGL_API)) {
        fprintf(stderr, "failed to bind EGL_OPENGL_API\n");
        return;
    }
 
    egl_surface = eglCreateWindowSurface (egl_display, ecfg, m_pWindow->getWindow(), NULL);
    if (egl_surface == EGL_NO_SURFACE) {
        return;
    }
 
    // egl-contexts collect all state descriptions needed required for operation
    EGLint ctxattr[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
    };

    egl_context = eglCreateContext (egl_display, ecfg, EGL_NO_CONTEXT, ctxattr);
    if (egl_context == EGL_NO_CONTEXT) {
        return;
    }
 
    // associate the egl-context with the egl-surface
    eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
..

// OpenGL init is verder niet nodig

// ProjectM init
    m_pGlobalPM = new projectM("/home/aalderd/.projectM/config.inp");
    m_pGlobalPM->projectM_resetGL(iWidth, iHeight);


// GL render
    glClearColor(0, 0, 0, 0);
    glViewport(0, 0, width, height);

    glEnable(GL_BLEND); 

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    m_pGlobalPM->renderFrame();

Dit werkt allemaal prima en levert het volgende beeld op:


Nu wil ik eigenlijk dit beeld op een texture renderen zodat ik dat ergens anders op kan 'plakken'. Dit lukt mij echter niet goed en levert mij het volgende beeld op:


Ik probeer dat als volgt te doen. De Init blijft hetzelfde als in de vorige snipped.
Voor OpenGL maak ik echter een Framebuffer aan met een Texture daaraan gekoppeld. Dat Framebuffer bind ik voordat ik ProjectM initialiseer en voordat ik ProjectM laat renderen:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    glGenFramebuffers(1, &m_Videoframebuffername);
    glBindFramebuffer(GL_FRAMEBUFFER, m_Videoframebuffername);

    glGenTextures(1, &m_VideoTexture);

    glBindTexture(GL_TEXTURE_2D, m_VideoTexture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, iWidth, iHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_VideoTexture, 0);

    glGenRenderbuffers(1, &m_RenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, m_RenderBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, iWidth, iHeight);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_RenderBuffer);

    m_pGlobalPM = new projectM("/path/to/config.inp");
    m_pGlobalPM->projectM_resetGL(iWidth, iHeight);
    
    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        printf("Failed to create framebuffer\n");
    }

    glBindRenderbuffer(GL_RENDERBUFFER, 0);
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

Nu heeft ProjectM zelf ook de mogelijkheid om naar een Texture te renderen maar dat levert hetzelfde beeld op:
C++:
1
    m_VideoTexture = m_pGlobalPM->initRenderToTexture();

De initRenderToTexture moet uitgevoerd worden na resetGL(width, height);
Ik hoef dan zelf geen Framebuffer te maken met een texture eraan, maar moet de geleverde texture (m_VideoTexture) wel zelf renderen :)

Het renderen van de texture doe ik als volgt:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    glClearColor (0.5, 0.5, 0.5, 0.5);
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    glViewport(0, 0, width, height);

    glUseProgram(shader);

    positionParam = glGetAttribLocation(shader, "position");
    texturepositionParam = glGetAttribLocation(shader, "textureposition");
    radiansParam = glGetAttribLocation(shader, "radians");
    
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_VideoTexture);
    glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
    glVertexAttribPointer(positionParam, 2, GL_FLOAT, GL_FALSE, stride, (void*)(0));
    glVertexAttribPointer(texturepositionParam, 2, GL_FLOAT, GL_FALSE, stride, (void*)(3 * sizeof(float)));
    glVertexAttribPointer(radiansParam, 1, GL_FLOAT, GL_FALSE, stride, (void*)(5 * sizeof(float)));
    glEnableVertexAttribArray(positionParam);
    glEnableVertexAttribArray(texturepositionParam);
    glEnableVertexAttribArray(radiansParam);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisableVertexAttribArray(positionParam);
    glDisableVertexAttribArray(texturepositionParam);
    glDisableVertexAttribArray(radiansParam);

    glBindTexture(GL_TEXTURE_2D, 0);
    
    glUseProgram(0);

De buffers/shaders enz laat ik even achterwege omdat het renderen van een texture verder prima gaat. Mijn vermoeden is dat het fout gaat met de extra FBO die ik aanmaak.

Nu heb ik zelf niet veel ervaring met OpenGL (ben net begonnen ;)) en zal vast wel wat versies door elkaar halen.

Het voorbeeld voor het renderen naar Texture met behulp van een Framebuffer heb ik hier vandaan gehaald:
http://www.opengl-tutoria...ial-14-render-to-texture/

Overigens heb ik het renderen naar Textures wel correct voor elkaar gekregen met MPV voor het afspelen van video's met behulp van OpenGL.

Mijn uiteindelijke doel is (nog) niet volledig 3d maar 2d voor afspelen van video's, geluids animaties en weergeven van foto's met evt wat effecten :)

Mijn vraag is nu, wie helpt mij de goede richting op zodat ik de render wel correct krijg in mijn test programma :P

Alle reacties


Acties:
  • 0Henk 'm!

  • DroogKloot
  • Registratie: februari 2001
  • Niet online

DroogKloot

depenisvanjezus

quote: BoAC
C++:
1
2
3
    glVertexAttribPointer(positionParam, 2, GL_FLOAT, GL_FALSE, stride, (void*)(0));
    glVertexAttribPointer(texturepositionParam, 2, GL_FLOAT, GL_FALSE, stride, (void*)(3 * sizeof(float)));
    glVertexAttribPointer(radiansParam, 1, GL_FLOAT, GL_FALSE, stride, (void*)(5 * sizeof(float)));
Weet je zeker dat dit klopt? Als elke position een vec2f (2 * sizeof(float) = 8 bytes) attribute is, waarom begint texturepositionParam dan op een offset van 3 * sizeof(float) = 12 bytes in je vertex buffer?

[Voor 189% gewijzigd door DroogKloot op 06-07-2020 23:15]


Acties:
  • 0Henk 'm!

  • BoAC
  • Registratie: februari 2003
  • Nu online

BoAC

Memento mori

Topicstarter
DroogKloot schreef op maandag 6 juli 2020 @ 23:04:
[...]


Weet je zeker dat dit klopt? Als elke position een vec2f (2 * sizeof(float) = 8 bytes) attribute is, waarom begint texturepositionParam dan op een offset van 3 * sizeof(float) = 12 bytes in je vertex buffer?
Omdat ik in mijn vertexbuffer ook een z positie meegeef die nu altijd 0.0f is. Maakt volgens mij niets uit voor het probleem wat ik heb met het weergeven. Andere textures worden correct weergegeven :)


Apple iPad Pro (2021) 11" Wi-Fi, 8GB ram Microsoft Xbox Series X LG CX Google Pixel 5a 5G Sony XH90 / XH92 Samsung Galaxy S21 5G Sony PlayStation 5 Nintendo Switch Lite

Tweakers vormt samen met Hardware Info, AutoTrack, Gaspedaal.nl, Nationale Vacaturebank, Intermediair en Independer DPG Online Services B.V.
Alle rechten voorbehouden © 1998 - 2021 Hosting door True