Sign in to follow this  
Vincent Torri

OpenGL 2d with direct3d: how to display argb data in a window

Recommended Posts

Vincent Torri    122
Hey, I have a rectangle (a piece of memory) that I fill with argb data. I would like to display it in a window, using direct3d. I have 3 questions about that. 1) I've read several tutorials. One solution would be to use the sprite interface. Then create a texture, fill it with data and render it onto the surface. I have written that code:
// the variable d contains a window and d3d object, device and sprite



  d->device->Clear (0, NULL,
                    D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
                    D3DCOLOR_ARGB (0, 0, 0, 0),
                    1.0f, 0);

  d->device->BeginScene ();

 // Here is my argb surface, named 'surf'

  w = 64;
  h = 64;
  depth = 4;
  pitch = depth * w;
  surf = malloc (depth * w * h);
  if (!surf) return 0;
  ZeroMemory (surf, depth * w * h);

  tmp = (unsigned char *)surf;
  for (r = 0; r < w; r++) {
    for (g = 0; g < h; g++, tmp += depth) {
      tmp[0] = (r * 2 + foo) % 256;
      tmp[1] = (g + foo) % 256;
      tmp[2] = (w - 1 - g) * 4;
    }
  }
  foo++;

  rect.left = 0;
  rect.top = 0;
  rect.right = w;
  rect.bottom = h;

  // FIXME : other flags might speed up things
  d->sprite->Begin (0);

  d->device->CreateTexture (w, h, 0, 0,
                            D3DFMT_A8R8G8B8,
                            D3DPOOL_DEFAULT,
                            &texture, NULL);

  // I have to fill the texture with the data of surf

  d->sprite->SetTransform (&matrix);
  d->sprite->Draw (texture, &rect, NULL, NULL, D3DCOLOR_ARGB (0, 0, 0, 0));
  d->sprite->End ();

  d->device->EndScene ();
  d->device->Present (NULL, NULL, NULL, NULL);


As I mentioned in a comment of that code, I have to fill the texture with the surf data. I've looked at a lot of tutorials, sites, etc... I didn't find any code to do that. I find code to fill a texture from a file, but not from a piece of memory. So my first question is: is it possible, and if yes, how ? 2) My second question is about speed. My main cincern is speed. I've already written a code with directdraw 7. The speed is the same than a similar code on linux, using software routines. I don't know if it is normal or not. I wanted to get more speed, so I tried to do that with direct3d, in order to use hardware accelerated features of d3d. With all the doc and tutorial I've read, I found several things to speed up all that stuff: a) Using vertices instead of sprites b) Using the immediate mode of d3d (see http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dnardir3d/html/d3dim.asp) Is it correct ? and if so, do you have some documentation about vertices or immediate mode, in order to achieve what I want ? Also, if there are better solutions (that is, faster techniques related to d3d to do what I want), I would be pleased to know them 3) Finally, between opengl and d3d, is there a difference in speed ? (for what I want to do) thank you very much Vincent Torri [Edited by - Vincent Torri on July 11, 2007 3:06:58 PM]

Share this post


Link to post
Share on other sites
Evil Steve    2017
Quote:
Original post by Vincent Torri
So my first question is: is it possible, and if yes, how ?
Yes, it's certainly possible.
You'll want to lock the top level of the texture (and each level in turn if you have mipmaps - which you almost certainly don't want - see #2), that'll give you a pointer to memory you can copy into.

EDIT: Here's some code from my engine:

void PTexture::Update(const u32* pData)
{
Assert(m_desc.Usage & D3DUSAGE_DYNAMIC, "Update() only valid on dynamic textures");
Assert(m_nLevels == 1, "Can only Update() textures with one mip level in them");

// Lock texture
D3DLOCKED_RECT d3dRect;
HRESULT hResult = m_pTexture->LockRect(0, &d3dRect, NULL, 0);
if(FAILED(hResult))
{
ELog::Get().DebugFormat(L"TEXTURE : IDirect3DTexture9::LockRect() failed. Error: %s\n",
DXGetErrorString(hResult));
return;
}

// Fill - do a fast copy if we can
if((u32)d3dRect.Pitch == m_desc.Width * 4)
{
memcpy(d3dRect.pBits, pData, m_desc.Width * m_desc.Height * 4);
}
else
{
// Need to copy scanline by scanline to avoid crapping up the pitch
for(UINT y=0; y<m_desc.Height; ++y)
{
memcpy((BYTE*)d3dRect.pBits + y*d3dRect.Pitch, pData, m_desc.Width * 4);
pData += m_desc.Width;
}
}

// Unlock
m_pTexture->UnlockRect(0);
}



Quote:
Original post by Vincent Torri
2) My second question is about speed. My main cincern is speed. I've already written a code with directdraw 7. The speed is the same than a similar code on linux, using software routines. I don't know if it is normal or not. I wanted to get more speed, so I tried to do that with direct3d, in order to use hardware accelerated features of d3d.

With all the doc and tutorial I've read, I found several things to speed up all that stuff:

a) Using vertices instead of sprites
b) Using the immediate mode of d3d
Notice the date on that link: 1997; 10 years ago [smile] - non-immediate mode hasn't existed since D3D5 or so; All D3D is immediate mode now, and there's no retained mode.
Using vertices instead of sprites won't make much difference at all here.

Things that will make a difference though:
  • Create your texture as D3DUSAGE_DYNAMIC. Otherwise the texture will probably be dumped into video RAM and updating it will be extremely expensive.
  • Don't create any mip-maps (Set the 3rd parameter of CreateTexture() to 1 instead of 0)
  • Don't update the texture every frame if you can help it (depends what you're doing really). It's better to update the texture once at load time, and then never have to touch it. If that's the case, don't bother with D3DUSAGE_DYNAMIC.
  • If you update and render the texture every frame, it might be a good idea to use 4 or so textures in a round-robbin fassion. That way D3D doesn't have to wait for the data to be uploaded to the graphics card before it renders the frame, but you'll get 4 frames of "lag" on the texture.
  • When you lock the texture, you can write directly into that, instead of writing to a memory buffer, then copying that buffer to the locked texture.

    If you're using dynamic textures, then you can lock the texture, if not, you'll have to either put the texture into D3DPOOL_MANAGED, or use IDirect3DDevice9::UpdateTexture to copy the data to the texture instead.

    Quote:
    Original post by Vincent Torri
    3) Finally, between opengl and d3d, is there a difference in speed ? (for what I want to do)
    Almost certainly not. I can't really day for sure, since I'm not an OpenGL person, but I'll be surprised if there's a significant performance difference provided both ways are optimal for their own API.

    Share this post


    Link to post
    Share on other sites
    Vincent Torri    122
    Quote:
    Original post by Evil Steve
    You'll want to lock the top level of the texture (and each level in turn if you have mipmaps - which you almost certainly don't want - see #2), that'll give you a pointer to memory you can copy into.

    haa, ok. thank you ! I'll try that.
    Quote:

    Quote:
    Original post by Vincent Torri
    2) My second question is about speed. With all the doc and tutorial I've read, I found several things to speed up all that stuff:

    a) Using vertices instead of sprites
    b) Using the immediate mode of d3d

    Notice the date on that link: 1997; 10 years ago - non-immediate mode hasn't existed since D3D5 or so; All D3D is immediate mode now, and there's no retained mode.
    Using vertices instead of sprites won't make much difference at all here.

    ok. That saves me some work. That immediate mode is a bit a pain to implement. Same for vertices, btw.
    Quote:

    Things that will make a difference though:
  • Create your texture as D3DUSAGE_DYNAMIC. Otherwise the texture will probably be dumped into video RAM and updating it will be extremely expensive.
  • Don't create any mip-maps (Set the 3rd parameter of CreateTexture() to 1 instead of 0)
  • Don't update the texture every frame if you can help it (depends what you're doing really). It's better to update the texture once at load time, and then never have to touch it. If that's the case, don't bother with D3DUSAGE_DYNAMIC.
  • If you update and render the texture every frame, it might be a good idea to use 4 or so textures in a round-robbin fassion. That way D3D doesn't have to wait for the data to be uploaded to the graphics card before it renders the frame, but you'll get 4 frames of "lag" on the texture.
  • When you lock the texture, you can write directly into that, instead of writing to a memory buffer, then copying that buffer to the locked texture.

    If you're using dynamic textures, then you can lock the texture, if not, you'll have to either put the texture into D3DPOOL_MANAGED, or use IDirect3DDevice9::UpdateTexture to copy the data to the texture instead.

  • What I want to do is the engine of a canvas library. What it does is exactly what I try to do : having a rectangle of some size (i know that size only at runtime, so I think that I have to create the texture each time I need it) with some data, and drawing it at some position. These rectangles are created by the user of the lib.

    But the engine is written such that I have to render a sequence of such rectangles. I know the number of these rectangles and their size. So I think that I can do what you describe in your 4th point ("round-robin fashion"). Could you please elaborate a bit on that technic, please ? Or maybe is there something else to do in that case ?
    Quote:

    Quote:
    Original post by Vincent Torri
    3) Finally, between opengl and d3d, is there a difference in speed ? (for what I want to do)
    Almost certainly not. I can't really day for sure, since I'm not an OpenGL person, but I'll be surprised if there's a significant performance difference provided both ways are optimal for their own API.

    ok.

    thank you very much for your answer !

    Vincent Torri

    PS: if you are interested, that canvas is named 'evas' and is part of the enlightenment project.

    Share this post


    Link to post
    Share on other sites
    Evil Steve    2017
    Quote:
    Original post by Vincent Torri
    What I want to do is the engine of a canvas library. What it does is exactly what I try to do : having a rectangle of some size (i know that size only at runtime, so I think that I have to create the texture each time I need it) with some data, and drawing it at some position. These rectangles are created by the user of the lib.
    You definitely want to avoid creating the texture every frame. Only create the texture when the canvas size changes, otherwise you'll get horrible performance (Creating D3D resources is very expensive). Locking the texture each frame (Or using the 4-texture method) is ok though, so long as you create the texture as dynamic.
    I'm not sure exactly how often you have to lock the texture to make a dynamic texture better, but if you're doing it more than once a second, I'd go for dynamic, and even if you lock it less frequently, you're likely to see a stutter with a non-dynamic texture (See the 4-texture method stuff below) while D3D uploads the texture.

    Quote:
    Original post by Vincent Torri
    But the engine is written such that I have to render a sequence of such rectangles. I know the number of these rectangles and their size. So I think that I can do what you describe in your 4th point ("round-robin fashion"). Could you please elaborate a bit on that technic, please ? Or maybe is there something else to do in that case ?
    If you have one texture, it goes like this:
    Lock texture and fill it with data
    Render textured quad / sprite
    However, in the background, this is happening:
    Lock texture and fill it with data
    Unlock texture. D3D now starts to send the texture to the video card
    Request rendering of textured quad / sprite
    D3D has to wait for the texture to finish transferring to video memory before it can render the textured quad
    Transfer completes, quad gets rendered

    Now, you can use several textures (I'll only use 2 in this example) to get around the stall while D3D uploads the texture. Your code does this:
    Startup: Lock and fill all textures
    Start of frame 1:
    Lock texture B and fill it with data
    Render textured quad / sprite with texture A
    Present. End of frame 1
    Start of frame 2:
    Lock texture A and fill it with data
    Render textured quad / sprite with texture B
    Present. End of frame 2
    Start of frame 3:
    Lock texture B and fill it with data
    Render textured quad / sprite with texture A
    Present. End of frame 3
    So, you're constantly going through the textures, one after another (If you had 4 textures, then frame 1 you'd update D and use A, frame 2 you'd update A and use B, frame 3 you'd update B and use C, frame 4 you'd update C and use D, repeat).
    The point is that there's now a 1 frame gap between locking a texture and it being used. That means you have 1 frame of "lag", since you're displaying the texture from the previous frame, but it gives D3D a whole extra frame to upload the texture to the card.

    If the bottleneck in your application does turn out to be texture uploading, this is a nice and easy fix for it. But I'd profile your app (PIX, in the DirectX SDK is good for this, and NVPerfHUD for NVidia cards) and see if this is actually a bottleneck, since it's possible that D3D has enough time to transfer the texture to the graphics card anyway, and adding this round-robbin system will only introduce lag in your texture, and require more video memory.


    Incidently, using a dynamic texture usually causes D3D (The video card driver, more correctly) to put the texture into AGP memory, or somewhere else where it's faster for D3D to access but slower for the card, so it averages out better. Not using a dynamic texture usually places the texture into video memory, and getting a texture there from CPU-accessible memory can be pretty expensive.

    Share this post


    Link to post
    Share on other sites
    Vincent Torri    122
    ok, I understand a bit more how it works, now. Creating the texture before is a bit how I managed to do the same thing with directdraw and its surfaces.

    about the dynamic texture, I can't know if there will be animations or not. So I'll use dynamic textures. The best is checking if an animation is done or not, and use a dynamic texture in that case. I'll do some tests.

    I'll check if I can use the "round-robin" technic in my engine. It can be very interesting for animations.

    thank you for your explanations.

    Share this post


    Link to post
    Share on other sites
    Vincent Torri    122
    Evil Steve:

    About your code:

    [source lang=cpp]
    for(UINT y=0; y<m_desc.Height; ++y)
    {
    memcpy((BYTE*)d3dRect.pBits + y*d3dRect.Pitch, pData, m_desc.Width * 4);
    pData += m_desc.Width;
    }



    maybe you should avoid y*d3dRect.Pitch and use pointer arithmetic, maybe you can also compute m_desc.Width * 4 as a pitch and use it.

    Share this post


    Link to post
    Share on other sites
    Nik02    4348
    Quote:
    Original post by Vincent Torri
    Evil Steve:

    About your code:

    *** Source Snippet Removed ***

    maybe you should avoid y*d3dRect.Pitch and use pointer arithmetic, maybe you can also compute m_desc.Width * 4 as a pitch and use it.


    Surface width * bytes per pixel may not be equal to the pitch. If you assume that it is, you'll run into problems later.

    Share this post


    Link to post
    Share on other sites
    Vincent Torri    122
    as I'm away from my home computer and as i didn't take with me my small test code, I wanted to re-write it.

    Unfortunately, it does not work. Here is the complete code:


    // g++ -g -Wall -o d3d d3d.cpp -ld3d9 -ld3dx9d

    #include <cstdlib>
    #include <cstdio>

    #include <windows.h>
    #include <d3d9.h>
    #include <d3dx9.h>

    typedef struct Data Data;

    struct Data
    {
    LPDIRECT3D9 object;
    LPDIRECT3DDEVICE9 device;
    LPD3DXSPRITE sprite;
    LPDIRECT3DTEXTURE9 texture;
    int mask_r;
    int mask_g;
    int mask_b;
    };


    static LRESULT CALLBACK
    MainWndProc(HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam)
    {
    switch (uMsg)
    {
    case WM_CREATE:
    return 0;
    case WM_DESTROY:
    PostQuitMessage(0);
    return 0;
    case WM_CLOSE:
    PostQuitMessage(0);
    return 0;
    default:
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    }

    Data *
    data_init (HWND window,
    int width,
    int height)
    {
    D3DPRESENT_PARAMETERS pp;
    D3DDISPLAYMODE dm;
    D3DSURFACE_DESC sd;
    Data *d;

    d = (Data *)malloc (sizeof (Data));
    if (!d)
    goto no_data;

    d->object = Direct3DCreate9 (D3D_SDK_VERSION);
    if (!d->object)
    goto no_object;

    if (FAILED (d->object->GetAdapterDisplayMode (D3DADAPTER_DEFAULT, &dm)))
    goto no_device;

    ZeroMemory(&pp, sizeof(pp));
    pp.BackBufferFormat = dm.Format;
    pp.BackBufferCount = 1;
    pp.SwapEffect = D3DSWAPEFFECT_FLIP;
    pp.hDeviceWindow = window;
    pp.Windowed = TRUE;

    if (FAILED(d->object->CreateDevice (D3DADAPTER_DEFAULT,
    D3DDEVTYPE_HAL,
    window,
    D3DCREATE_HARDWARE_VERTEXPROCESSING,
    &pp,
    &d->device)))
    goto no_device;

    if (FAILED (D3DXCreateSprite (d->device, &d->sprite)))
    goto no_sprite;

    if (FAILED (d->device->CreateTexture (width, height, 1,
    D3DUSAGE_DYNAMIC,
    dm.Format,
    D3DPOOL_DEFAULT,
    &d->texture, NULL)))
    goto no_texture;

    if (FAILED (d->texture->GetLevelDesc (0, &sd)))
    goto no_level_desc;

    switch (sd.Format) {
    case D3DFMT_A8R8G8B8:
    case D3DFMT_X8R8G8B8:
    d->mask_r = 0x00ff0000;
    d->mask_g = 0x0000ff00;
    d->mask_b = 0x000000ff;
    break;
    case D3DFMT_R5G6B5:
    d->mask_r = 0xf800;
    d->mask_g = 0x07e0;
    d->mask_b = 0x001f;
    break;
    default:
    goto no_level_desc;
    }

    return d;

    no_level_desc:
    d->texture->Release ();
    no_texture:
    d->sprite->Release ();
    no_sprite:
    d->device->Release ();
    no_device:
    d->object->Release ();
    no_object:
    free (d);
    no_data:
    return NULL;
    }

    void
    data_shutdown (Data *d)
    {
    if (!d)
    return;

    d->texture->Release ();
    d->sprite->Release ();
    d->device->Release ();
    d->object->Release ();
    free (d);
    }

    void
    data_paint (Data *d)
    {
    D3DLOCKED_RECT d3d_rect;
    RECT rect;
    int w;
    int h;
    int depth;
    int pitch;
    unsigned char *tmp;
    unsigned char *d3d_tmp;
    static int foo = 0;

    void *surf;

    w = 64;
    h = 64;
    depth = 4;
    pitch = depth * w;

    surf = calloc (w * h * depth, 1);
    if (!surf) {
    printf ("pas bon \n");
    return;
    }
    tmp = (unsigned char *)surf;
    for (int r = 0; r < w; r++) {
    for (int g = 0; g < h; g++, tmp += depth) {
    tmp[0] = (r * 2 + foo) % 256;
    tmp[1] = (g + foo) % 256;
    tmp[2] = (w - 1 - g) * 4;
    }
    }
    foo++;

    rect.left = 0;
    rect.top = 0;
    rect.right = w;
    rect.bottom = h;

    if (FAILED (d->device->BeginScene ()))
    return;

    if (FAILED (d->sprite->Begin (0)))
    return;
    if (FAILED (d->texture->LockRect (0, &d3d_rect, NULL, D3DLOCK_DISCARD))) {
    d->sprite->End ();
    d->device->EndScene ();
    return;
    }

    tmp = (unsigned char *)surf;
    d3d_tmp = (unsigned char *)d3d_rect.pBits;
    for (int j = 0; j < h; j++, tmp += pitch, d3d_tmp += d3d_rect.Pitch)
    memcpy (d3d_tmp, tmp, pitch);

    d->texture->UnlockRect(0);

    d->sprite->Draw (d->texture, &rect, NULL, NULL,
    D3DCOLOR_ARGB (0, 0, 0, 0));
    d->sprite->End ();

    d->device->EndScene ();
    d->device->Present (NULL, NULL, NULL, NULL);

    free (surf);
    }

    int WINAPI
    WinMain(HINSTANCE hinstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
    #if 0
    main ()
    #endif
    {
    WNDCLASS wc;
    RECT rect;
    MSG msg;
    HINSTANCE instance;
    HWND window;
    Data *d;
    int width;
    int height;

    instance = GetModuleHandle(0);
    if (!instance)
    goto no_instance;

    ZeroMemory(&wc, sizeof(wc));
    wc.lpfnWndProc = MainWndProc;
    wc.hInstance = instance;
    wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor (NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
    wc.lpszClassName = "Direct3D_test";

    if(!RegisterClass(&wc))
    goto no_window_class;

    width = 320;
    height = 200;

    rect.left = 0;
    rect.top = 0;
    rect.right = width;
    rect.bottom = height;
    AdjustWindowRect (&rect, WS_OVERLAPPEDWINDOW | WS_SIZEBOX, FALSE);

    window = CreateWindow("Direct3D_test",
    "Direct3D_test",
    WS_OVERLAPPEDWINDOW | WS_SIZEBOX,
    CW_USEDEFAULT, CW_USEDEFAULT,
    rect.right - rect.left, rect.bottom - rect.top,
    NULL, NULL, instance, NULL);
    if (!window)
    goto no_window;

    d = data_init (window, width, height);
    if (!d)
    goto no_data;

    ShowWindow(window, SW_SHOWDEFAULT);
    UpdateWindow(window);

    while (GetMessage (&msg, NULL, 0, 0))
    {
    TranslateMessage (&msg);
    DispatchMessage (&msg);
    data_paint (d);
    }

    data_shutdown (d);
    DestroyWindow (window);
    UnregisterClass ("Direct3D_test", instance);
    FreeLibrary (instance);

    return EXIT_SUCCESS;

    no_data:
    DestroyWindow (window);
    no_window:
    UnregisterClass ("Direct3D_test", instance);
    no_window_class:
    FreeLibrary (instance);
    no_instance:
    return EXIT_FAILURE;
    }





    this program creates a window and displays a small animation in a 64x64 pixels large square at the top-left of the window. The window is created, but no animation is displayed.

    I don't really know where the problem is (maybe in the initialisation of direct3d, in data_init).
    does someone see the problem ?

    thank you very much

    [Edited by - Vincent Torri on July 29, 2007 12:19:52 PM]

    Share this post


    Link to post
    Share on other sites

    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

    Sign in to follow this  

    • Similar Content

      • By Zaphyk
        I am developing my engine using the OpenGL 3.3 compatibility profile. It runs as expected on my NVIDIA card and on my Intel Card however when I tried it on an AMD setup it ran 3 times worse than on the other setups. Could this be a AMD driver thing or is this probably a problem with my OGL code? Could a different code standard create such bad performance?
      • By Kjell Andersson
        I'm trying to get some legacy OpenGL code to run with a shader pipeline,
        The legacy code uses glVertexPointer(), glColorPointer(), glNormalPointer() and glTexCoordPointer() to supply the vertex information.
        I know that it should be using setVertexAttribPointer() etc to clearly define the layout but that is not an option right now since the legacy code can't be modified to that extent.
        I've got a version 330 vertex shader to somewhat work:
        #version 330 uniform mat4 osg_ModelViewProjectionMatrix; uniform mat4 osg_ModelViewMatrix; layout(location = 0) in vec4 Vertex; layout(location = 2) in vec4 Normal; // Velocity layout(location = 3) in vec3 TexCoord; // TODO: is this the right layout location? out VertexData { vec4 color; vec3 velocity; float size; } VertexOut; void main(void) { vec4 p0 = Vertex; vec4 p1 = Vertex + vec4(Normal.x, Normal.y, Normal.z, 0.0f); vec3 velocity = (osg_ModelViewProjectionMatrix * p1 - osg_ModelViewProjectionMatrix * p0).xyz; VertexOut.velocity = velocity; VertexOut.size = TexCoord.y; gl_Position = osg_ModelViewMatrix * Vertex; } What works is the Vertex and Normal information that the legacy C++ OpenGL code seem to provide in layout location 0 and 2. This is fine.
        What I'm not getting to work is the TexCoord information that is supplied by a glTexCoordPointer() call in C++.
        Question:
        What layout location is the old standard pipeline using for glTexCoordPointer()? Or is this undefined?
         
        Side note: I'm trying to get an OpenSceneGraph 3.4.0 particle system to use custom vertex, geometry and fragment shaders for rendering the particles.
      • By markshaw001
        Hi i am new to this forum  i wanted to ask for help from all of you i want to generate real time terrain using a 32 bit heightmap i am good at c++ and have started learning Opengl as i am very interested in making landscapes in opengl i have looked around the internet for help about this topic but i am not getting the hang of the concepts and what they are doing can some here suggests me some good resources for making terrain engine please for example like tutorials,books etc so that i can understand the whole concept of terrain generation.
         
      • By KarimIO
        Hey guys. I'm trying to get my application to work on my Nvidia GTX 970 desktop. It currently works on my Intel HD 3000 laptop, but on the desktop, every bind textures specifically from framebuffers, I get half a second of lag. This is done 4 times as I have three RGBA textures and one depth 32F buffer. I tried to use debugging software for the first time - RenderDoc only shows SwapBuffers() and no OGL calls, while Nvidia Nsight crashes upon execution, so neither are helpful. Without binding it runs regularly. This does not happen with non-framebuffer binds.
        GLFramebuffer::GLFramebuffer(FramebufferCreateInfo createInfo) { glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); textures = new GLuint[createInfo.numColorTargets]; glGenTextures(createInfo.numColorTargets, textures); GLenum *DrawBuffers = new GLenum[createInfo.numColorTargets]; for (uint32_t i = 0; i < createInfo.numColorTargets; i++) { glBindTexture(GL_TEXTURE_2D, textures[i]); GLint internalFormat; GLenum format; TranslateFormats(createInfo.colorFormats[i], format, internalFormat); // returns GL_RGBA and GL_RGBA glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, createInfo.width, createInfo.height, 0, format, GL_FLOAT, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); DrawBuffers[i] = GL_COLOR_ATTACHMENT0 + i; glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, textures[i], 0); } if (createInfo.depthFormat != FORMAT_DEPTH_NONE) { GLenum depthFormat; switch (createInfo.depthFormat) { case FORMAT_DEPTH_16: depthFormat = GL_DEPTH_COMPONENT16; break; case FORMAT_DEPTH_24: depthFormat = GL_DEPTH_COMPONENT24; break; case FORMAT_DEPTH_32: depthFormat = GL_DEPTH_COMPONENT32; break; case FORMAT_DEPTH_24_STENCIL_8: depthFormat = GL_DEPTH24_STENCIL8; break; case FORMAT_DEPTH_32_STENCIL_8: depthFormat = GL_DEPTH32F_STENCIL8; break; } glGenTextures(1, &depthrenderbuffer); glBindTexture(GL_TEXTURE_2D, depthrenderbuffer); glTexImage2D(GL_TEXTURE_2D, 0, depthFormat, createInfo.width, createInfo.height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthrenderbuffer, 0); } if (createInfo.numColorTargets > 0) glDrawBuffers(createInfo.numColorTargets, DrawBuffers); else glDrawBuffer(GL_NONE); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "Framebuffer Incomplete\n"; glBindFramebuffer(GL_FRAMEBUFFER, 0); width = createInfo.width; height = createInfo.height; } // ... // FBO Creation FramebufferCreateInfo gbufferCI; gbufferCI.colorFormats = gbufferCFs.data(); gbufferCI.depthFormat = FORMAT_DEPTH_32; gbufferCI.numColorTargets = gbufferCFs.size(); gbufferCI.width = engine.settings.resolutionX; gbufferCI.height = engine.settings.resolutionY; gbufferCI.renderPass = nullptr; gbuffer = graphicsWrapper->CreateFramebuffer(gbufferCI); // Bind glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); // Draw here... // Bind to textures glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textures[0]); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textures[1]); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[2]); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, depthrenderbuffer); Here is an extract of my code. I can't think of anything else to include. I've really been butting my head into a wall trying to think of a reason but I can think of none and all my research yields nothing. Thanks in advance!
      • By Adrianensis
        Hi everyone, I've shared my 2D Game Engine source code. It's the result of 4 years working on it (and I still continue improving features ) and I want to share with the community. You can see some videos on youtube and some demo gifs on my twitter account.
        This Engine has been developed as End-of-Degree Project and it is coded in Javascript, WebGL and GLSL. The engine is written from scratch.
        This is not a professional engine but it's for learning purposes, so anyone can review the code an learn basis about graphics, physics or game engine architecture. Source code on this GitHub repository.
        I'm available for a good conversation about Game Engine / Graphics Programming
    • Popular Now