OpenGL - draw pixels to screen?

前端 未结 4 1530
南笙
南笙 2021-01-01 00:06

I want to draw a 2D array of pixel data (RGB / grayscale values) on the screen as fast as possible, using OpenGL. The pixel data changes frequently.

I had hoped that

4条回答
  •  迷失自我
    2021-01-01 00:13

    My solution for getting dynamically changing image data to the screen in OpenGL,

    #define WIN32_LEAN_AND_MEAN
    
    #include "wx/wx.h"
    #include "wx/sizer.h"
    #include "wx/glcanvas.h"
    #include "BasicGLPane.h"
    
    // include OpenGL
    #ifdef __WXMAC__
    #include "OpenGL/glu.h"
    #include "OpenGL/gl.h"
    #else
    #include 
    #include 
    #endif
    #include "ORIScanMainFrame.h"
    
    BEGIN_EVENT_TABLE(BasicGLPane, wxGLCanvas)
    EVT_MOTION(BasicGLPane::mouseMoved)
    EVT_LEFT_DOWN(BasicGLPane::mouseDown)
    EVT_LEFT_UP(BasicGLPane::mouseReleased)
    EVT_RIGHT_DOWN(BasicGLPane::rightClick)
    EVT_LEAVE_WINDOW(BasicGLPane::mouseLeftWindow)
    EVT_SIZE(BasicGLPane::resized)
    EVT_KEY_DOWN(BasicGLPane::keyPressed)
    EVT_KEY_UP(BasicGLPane::keyReleased)
    EVT_MOUSEWHEEL(BasicGLPane::mouseWheelMoved)
    EVT_PAINT(BasicGLPane::render)
    END_EVENT_TABLE()
    
    // Test data for image generation.  floats range 0.0 to 1.0, in RGBRGBRGB... order.
    // Array is 1024 * 3 long. Note that 32 * 32 is 1024 and is the largest image we can randomly generate.
    float* randomFloatRGB;
    float* randomFloatRGBGrey;
    
    BasicGLPane::BasicGLPane(wxFrame* parent, int* args) :
        wxGLCanvas(parent, wxID_ANY, args, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE)
    {
        m_context = new wxGLContext(this);
    
        randomFloatRGB = new float[1024 * 3];
        randomFloatRGBGrey = new float[1024 * 3];
        // In GL images 0,0 is in the lower left corner so the draw routine does a vertical flip to get 'regular' images right side up.
        for (int i = 0; i < 1024; i++) {
            // Red
            randomFloatRGB[i * 3] = static_cast  (rand()) / static_cast  (RAND_MAX);
            // Green
            randomFloatRGB[i * 3 + 1] = static_cast  (rand()) / static_cast  (RAND_MAX);
            // Blue
            randomFloatRGB[i * 3 + 2] = static_cast  (rand()) / static_cast  (RAND_MAX);
            // Telltale 2 white pixels in 0,0 corner.
            if (i < 2) {
                randomFloatRGB[i * 3] = randomFloatRGB[i * 3 + 1] = randomFloatRGB[i * 3 + 2] = 1.0f;
            }
    
            randomFloatRGBGrey[i * 3] = randomFloatRGB[i * 3];
            randomFloatRGBGrey[i * 3 + 1] = randomFloatRGB[i * 3];
            randomFloatRGBGrey[i * 3 + 2] = randomFloatRGB[i * 3];
        }
    
        // To avoid flashing on MSW
        SetBackgroundStyle(wxBG_STYLE_CUSTOM);
    }
    
    BasicGLPane::~BasicGLPane()
    {
        delete m_context;
    }
    
    void BasicGLPane::resized(wxSizeEvent& evt)
    {
        //  wxGLCanvas::OnSize(evt);
        Refresh();
    }
    
    int BasicGLPane::getWidth()
    {
        return GetSize().x;
    }
    
    int BasicGLPane::getHeight()
    {
        return GetSize().y;
    }
    
    void BasicGLPane::render(wxPaintEvent& evt)
    {
        assert(GetParent());
        assert(GetParent()->GetParent());
        ORIScanMainFrame* mf = dynamic_cast(GetParent()->GetParent());
        assert(mf);
    
        switch (mf->currentMainView) {
        case ORIViewSelection::ViewCamera:
            renderCamera(evt);
            break;
        case ORIViewSelection::ViewDepth:
            renderDepth(evt);
            break;
        case ORIViewSelection::ViewPointCloud:
            renderPointCloud(evt);
            break;
        case ORIViewSelection::View3DModel:
            render3DModel(evt);
            break;
        default:
            renderNone(evt);
        }
    }
    
    void BasicGLPane::renderNone(wxPaintEvent& evt) {
        if (!IsShown())
            return;
        SetCurrent(*(m_context));
        glPushAttrib(GL_ALL_ATTRIB_BITS);
        glClearColor(0.08f, 0.11f, 0.15f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glFlush();
        SwapBuffers();
        glPopAttrib();
    }
    
    GLuint makeOpenGlTextureFromDataLuninanceFloats(int width, int height, float* f) {
        GLuint textureID;
    
        glEnable(GL_TEXTURE_2D);
        glGenTextures(1, &textureID);
    
        // "Bind" the newly created texture : all future texture functions will modify this texture
        glBindTexture(GL_TEXTURE_2D, textureID);
    
        // Give the image to OpenGL
        glTexImage2D(GL_TEXTURE_2D, 0, GL_FLOAT, width, height, 0, GL_FLOAT, GL_LUMINANCE, f);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    
        return textureID;
    }
    
    GLuint makeOpenGlTextureFromRGBInts(int width, int height, unsigned int* f) {
        GLuint textureID;
    
    
        glEnable(GL_TEXTURE_2D);
        glGenTextures(1, &textureID);
    
        // "Bind" the newly created texture : all future texture functions will modify this texture
        glBindTexture(GL_TEXTURE_2D, textureID);
    
        // Give the image to OpenGL
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_INT, f);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    
        return textureID;
    }
    
    /// 
    /// Range of each float is 0.0f to 1.0f
    /// 
    /// 
    /// 
    /// 
    /// 
    GLuint makeOpenGlTextureFromRGBFloats(int width, int height, float* floatRGB) {
        GLuint textureID;
    
        // 4.6.0 NVIDIA 457.30  (R Keene machine, 11/25/2020)
        // auto sss = glGetString(GL_VERSION);
    
        glGenTextures(1, &textureID);
    
        // "Bind" the newly created texture : all future texture functions will modify this texture
        glBindTexture(GL_TEXTURE_2D, textureID);
    
        // Give the image to OpenGL
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, floatRGB);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    
        return textureID;
    }
    
    void BasicGLPane::DrawTextureToScreenFloat(int w, int h, float* floatDataPtr, GLuint (*textureFactory)(int width, int height, float* floatRGB)) {
        if (w <= 0 || h <= 0 || floatDataPtr == NULL || w > 5000 || h > 5000) {
            assert(false);
            return;
        }
    
        SetCurrent(*(m_context));
    
        glPushAttrib(GL_ALL_ATTRIB_BITS);
        glPushMatrix();
        glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
    
        glClearColor(0.15f, 0.11f, 0.02f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        glEnable(GL_TEXTURE_2D);
    
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
    
        // 4.6.0 NVIDIA 457.30  (R Keene machine, 11/25/2020)
        // auto sss = glGetString(GL_VERSION);
    
        float onePixelW = (float)getWidth() / (float)w;
        float onePixelH = (float)getHeight() / (float)h;
        float orthoW = w;
        float orthoH = h;
        if (onePixelH > onePixelW) {
            orthoH = h * onePixelH / onePixelW;
        }
        else {
            orthoW = w * onePixelW / onePixelH;
        }
        // We want the image at the top of the window, not the bottom if the window is too tall.
        int topOfScreen = (float)getHeight() / onePixelH;
    
        // If the winjdow resizes after creation you need to change the viewport.
        glViewport(0, 0, getWidth(), getHeight());
        gluOrtho2D(0.0, orthoW, (double)topOfScreen - (double)orthoH, topOfScreen);
    
        GLuint myTextureName = textureFactory(w, h, floatDataPtr);
    
        glBegin(GL_QUADS);
        {
            // This order of UV coords and verticies will do the vertical flip of the image to get the 'regular' image 0,0
            // in the top left corner.
            glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, 0.0f, 0.0f);
            glTexCoord2f(1.0f, 1.0f); glVertex3f(0.0f + w, 0.0f, 0.0f);
            glTexCoord2f(1.0f, 0.0f); glVertex3f(0.0f + w, 0.0f + h, 0.0f);
            glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, 0.0f + h, 0.0f);
        }
        glEnd();
    
        glDeleteTextures(1, &myTextureName);
    
        glFlush();
        SwapBuffers();
    
    
        glPopClientAttrib();
        glPopMatrix();
        glPopAttrib();
    }
    
    void BasicGLPane::DrawTextureToScreenMat(wxPaintEvent& evt, cv::Mat m, float brightness) {
        m.type();
        if (m.empty()) {
            renderNone(evt);
            return;
        }
    
        if (m.type() == CV_32FC1) { // Grey scale.
            DrawTextureToScreenFloat(m.cols, m.rows, (float*)m.data, makeOpenGlTextureFromDataLuninanceFloats);
        }
        if (m.type() == CV_32FC3) { // Color.
            DrawTextureToScreenFloat(m.cols, m.rows, (float*)m.data, makeOpenGlTextureFromRGBFloats);
        }
        else {
            renderNone(evt);
        }
    }
    
    void BasicGLPane::renderCamera(wxPaintEvent& evt) {
        if (!IsShown())
            return;
        DrawTextureToScreenMat(evt, ORITopControl::Instance->im_white);
    }
    
    void BasicGLPane::renderDepth(wxPaintEvent& evt) {
        if (!IsShown())
            return;
        DrawTextureToScreenMat(evt, ORITopControl::Instance->depth_map);
    }
    
    void BasicGLPane::render3DModel(wxPaintEvent& evt) {
        if (!IsShown())
            return;
        SetCurrent(*(m_context));
        glPushAttrib(GL_ALL_ATTRIB_BITS);
        glPushMatrix();
    
        glClearColor(0.08f, 0.11f, 0.15f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    
    
        glFlush();
        SwapBuffers();
    
        glPopMatrix();
        glPopAttrib();
    }
    
    void BasicGLPane::renderPointCloud(wxPaintEvent& evt) {
        if (!IsShown())
            return;
        boost::unique_lock lk(ORITopControl::Instance->pointCloudCacheMutex);
    
        SetCurrent(*(m_context));
        glPushAttrib(GL_ALL_ATTRIB_BITS);
        glPushMatrix();
    
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
    
        glViewport(0, 0, getWidth(), getHeight());
    
        glClearColor(0.08f, 0.11f, 0.15f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        if (ORITopControl::Instance->pointCloudCache.size() > 0) {
            glMatrixMode(GL_PROJECTION);
            gluPerspective( /* field of view in degree */ 40.0,
                /* aspect ratio */ 1.0,
                /* Z near */ 1.0, /* Z far */ 500.0);
            glMatrixMode(GL_MODELVIEW);
            gluLookAt(100, 70, 200, // Eye
                25, 25, 25, // Look at pt
                0, 0, 1); // Up Vector
    
            glPointSize(2.0);
            glBegin(GL_POINTS);
            // Use explicit for loop because pointCloudFragments can grow asynchronously.
            for (int i = 0; i < ORITopControl::Instance->pointCloudCache.size(); i++) {
                auto frag = ORITopControl::Instance->pointCloudCache[i];
                auto current_point_cloud_ptr = frag->cloud;
                glPushMatrix();
                // glMultMatrixf(frag->xform.data());
                for (size_t n = 0; n < current_point_cloud_ptr->size(); n++) {
                    glColor3ub(255, 255, 255);
                    glVertex3d(current_point_cloud_ptr->points[n].x, current_point_cloud_ptr->points[n].y, current_point_cloud_ptr->points[n].z);
                }
                glPopMatrix();
            }
            glEnd();
        }
    
        glFlush();
        SwapBuffers();
    
        glPopMatrix();
        glPopAttrib();
    }
    

提交回复
热议问题