0

我有用于创建 N 个窗口的多用途代码(在我最新的数据采集应用程序 3 个窗口中显示原始数据)。我创建了一个大小为 800x256 的窗口,并在其中传输了一个 800x256 像素的图像。然后我注意到我忘记了边界,并且得到了奇怪的工件。现在的重点是,我的窗口中有双线。实际显示窗口的宽度为 784 像素(8 到左边框,8 到右边框),所以我希望我的代码会错过几行来绘制,但相反我会得到一些线并排两次。

我得到的现象是,在 784 像素的宽度中,我得到 2 列,每列两次(好像纹理的大小为 782 像素)。

这里发生了什么?

调用代码:

        GenerateProfile(lastX, lastY);
        OpenGLDisplay_Wrapper((char*)&profile.at(0), 800, 256, false, 8, 1);

轮廓为矢量(800*256);字符值。

我使用的 OpenGL 代码:

/** Based on code by NeHe tutorials
    Adapted to display live camera display with OpenGL
*/

#include "OpenGL-Display.h"

using namespace OGD;

OpenGL_Display::OpenGL_Display(int newId)
{
    xPos = -1;
    yPos = -1;
    ID = newId;
}

OpenGL_Display::~OpenGL_Display()
{
    KillGLWindow();
}

void OpenGL_Display::Init_Display(int width, int height, int posX, int posY, LPCSTR className)
{
    if (!CreateGLWindow((char*)className, width, height, 24, posX, posY, className))
    {
        throw;
    }   
}

LRESULT CALLBACK OpenGL_Display::WndProc(   HWND    hWnd,           // Handle For This Window
                            UINT    uMsg,           // Message For This Window
                            WPARAM  wParam,         // Additional Message Information
                            LPARAM  lParam)         // Additional Message Information
{
    switch (uMsg)                                   // Check For Windows Messages
    {
        case WM_SYSCOMMAND:                         // Intercept System Commands
        {
            switch (wParam)                         // Check System Calls
            {
                case SC_SCREENSAVE:                 // Screensaver Trying To Start?
                case SC_MONITORPOWER:               // Monitor Trying To Enter Powersave?
                return 0;                           // Prevent From Happening
            }
            break;                                  // Exit
        }

        case WM_LBUTTONDOWN:
        {
            for(unsigned int ind = 0; ind < oglDisp.size(); ++ind) {
                if(hWnd == oglDisp.at(ind)->hWnd) {
                    oglDisp.at(ind)->xPos = LOWORD(lParam);
                    oglDisp.at(ind)->yPos = HIWORD(lParam);
                }
            }
        }
        case WM_MOUSEMOVE:
        {
            for(unsigned int ind = 0; ind < oglDisp.size(); ++ind) {
                if((wParam & MK_LBUTTON) && hWnd == oglDisp.at(ind)->hWnd) {
                    oglDisp.at(ind)->xPos = LOWORD(lParam);
                    oglDisp.at(ind)->yPos = HIWORD(lParam);
                }
            }
        }
        break;

        case WM_CLOSE:                              // Did We Receive A Close Message?
        {
            PostQuitMessage(0);                     // Send A Quit Message
            return 0;                               // Jump Back
        }

        case WM_SIZE:                               // Resize The OpenGL Window
        {
            oglDisp.at(0)->ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));  // LoWord=Width, HiWord=Height
            return 0;                               // Jump Back
        }
    }

    // Pass All Unhandled Messages To DefWindowProc
    return DefWindowProc(hWnd,uMsg,wParam,lParam);
}


bool OpenGL_Display::CreateGLWindow(char* title, int width, int height, int bits, int posX, int posY, LPCSTR className)
{
    GLuint      PixelFormat;            // Holds The Results After Searching For A Match
    WNDCLASS    wc;                     // Windows Class Structure
    DWORD       dwExStyle;              // Window Extended Style
    DWORD       dwStyle;                // Window Style
    RECT        WindowRect;             // Grabs Rectangle Upper Left / Lower Right Values
    WindowRect.left=(long)0;            // Set Left Value To 0
    WindowRect.right=(long)width;       // Set Right Value To Requested Width
    WindowRect.top=(long)0;             // Set Top Value To 0
    WindowRect.bottom=(long)height;     // Set Bottom Value To Requested Height

    hInstance           = GetModuleHandle(NULL);                // Grab An Instance For Our Window
    wc.style            = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;   // Redraw On Size, And Own DC For Window.
    wc.lpfnWndProc      = WndProc;                              // WndProc Handles Messages
    wc.cbClsExtra       = 0;                                    // No Extra Window Data
    wc.cbWndExtra       = 0;                                    // No Extra Window Data
    wc.hInstance        = hInstance;                            // Set The Instance
    wc.hIcon            = LoadIcon(NULL, IDI_WINLOGO);          // Load The Default Icon
    wc.hCursor          = LoadCursor(NULL, IDC_ARROW);          // Load The Arrow Pointer
    wc.hbrBackground    = NULL;                                 // No Background Required For GL
    wc.lpszMenuName     = NULL;                                 // We Don't Want A Menu
    wc.lpszClassName    = className;                                // Set The Class Name

    int error = 0;
    if ((error=RegisterClass(&wc))==0)                                  // Attempt To Register The Window Class
    {
        char* message = new char[256];
        sprintf_s(message, 256, "Failed To Register The Window Class. Error: %d", error);
        MessageBox(NULL, message,"ERROR",MB_OK|MB_ICONEXCLAMATION);
        delete message;
        return FALSE;                                           // Return FALSE
    }



    dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;           // Window Extended Style
    dwStyle=WS_VISIBLE | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;;                         // Windows Style

    AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);     // Adjust Window To True Requested Size
    //HWND hwndC = GetConsoleWindow();
    // Create The Window
    if (!(hWnd=CreateWindowEx(  dwExStyle,                          // Extended Style For The Window
                                className,                          // Class Name
                                title,                              // Window Title
                                WS_OVERLAPPEDWINDOW,
                                //dwStyle |                         // Defined Window Style
                                //WS_CLIPSIBLINGS |                 // Required Window Style
                                //WS_CLIPCHILDREN,                  // Required Window Style
                                posX, posY,                         // Window Position
                                WindowRect.right-WindowRect.left,   // Calculate Window Width
                                WindowRect.bottom-WindowRect.top,   // Calculate Window Height
                                NULL,                               // No Parent Window
                                NULL,                               // No Menu
                                hInstance,                          // Instance
                                NULL)))                             // Dont Pass Anything To WM_CREATE
    {
        KillGLWindow();                             // Reset The Display
        MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
        return FALSE;                               // Return FALSE
    }

    static  PIXELFORMATDESCRIPTOR pfd=              // pfd Tells Windows How We Want Things To Be
    {
        sizeof(PIXELFORMATDESCRIPTOR),              // Size Of This Pixel Format Descriptor
        1,                                          // Version Number
        PFD_DRAW_TO_WINDOW |                        // Format Must Support Window
        PFD_SUPPORT_OPENGL |                        // Format Must Support OpenGL
        PFD_DOUBLEBUFFER,                           // Must Support Double Buffering
        PFD_TYPE_RGBA,                              // Request An RGBA Format
        bits,                                       // Select Our Color Depth
        0, 0, 0, 0, 0, 0,                           // Color Bits Ignored
        0,                                          // No Alpha Buffer
        0,                                          // Shift Bit Ignored
        0,                                          // No Accumulation Buffer
        0, 0, 0, 0,                                 // Accumulation Bits Ignored
        16,                                         // 16Bit Z-Buffer (Depth Buffer)  
        0,                                          // No Stencil Buffer
        0,                                          // No Auxiliary Buffer
        PFD_MAIN_PLANE,                             // Main Drawing Layer
        0,                                          // Reserved
        0, 0, 0                                     // Layer Masks Ignored
    };

    if (!(hDC=GetDC(hWnd)))                         // Did We Get A Device Context?
    {
        KillGLWindow();                             // Reset The Display
        MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
        return FALSE;                               // Return FALSE
    }

    if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
    {
        KillGLWindow();                             // Reset The Display
        MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
        return FALSE;                               // Return FALSE
    }

    if(!SetPixelFormat(hDC,PixelFormat,&pfd))       // Are We Able To Set The Pixel Format?
    {
        KillGLWindow();                             // Reset The Display
        MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
        return FALSE;                               // Return FALSE
    }

    if (!(hRC=wglCreateContext(hDC)))               // Are We Able To Get A Rendering Context?
    {
        KillGLWindow();                             // Reset The Display
        MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
        return FALSE;                               // Return FALSE
    }

    if(!wglMakeCurrent(hDC,hRC))                    // Try To Activate The Rendering Context
    {
        KillGLWindow();                             // Reset The Display
        MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
        return FALSE;                               // Return FALSE
    }

    ShowWindow(hWnd,SW_SHOW);                       // Show The Window
    SetForegroundWindow(hWnd);                      // Slightly Higher Priority
    SetFocus(hWnd);                                 // Sets Keyboard Focus To The Window
    ReSizeGLScene(width, height);                   // Set Up Our Perspective GL Screen

    if (!InitGL())                                  // Initialize Our Newly Created GL Window
    {
        KillGLWindow();                             // Reset The Display
        MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
        return FALSE;                               // Return FALSE
    }

    return TRUE;                                    // Success
}


int OpenGL_Display::LoadGLTextures()                                    // Load Bitmaps And Convert To Textures
{
    // Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit

    glGenTextures(1, &texture);                 // Create The Texture
    // Typical Texture Generation Using Data From The Bitmap
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); // Minimizing filter, in case display is smaller image size
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // Magnifying filter, in case display is smaller image size

    return 1;                                       // Return The Status
}

GLvoid OpenGL_Display::ReSizeGLScene(GLsizei width, GLsizei height)     // Resize And Initialize The GL Window
{
    if (height==0)                                      // Prevent A Divide By Zero
    {
        height=1;                                       // Making Height Equal One
    }

    glViewport(0,0,width,height);                       // Reset The Current Viewport

    glMatrixMode(GL_PROJECTION);                        // Select The Projection Matrix
    glLoadIdentity();                                   // Reset The Projection Matrix

    // Calculate The Aspect Ratio Of The Window
    gluPerspective(25.0f,1.0f,0.1f,100.0f);

    glMatrixMode(GL_MODELVIEW);                         // Select The Modelview Matrix
    glLoadIdentity();                                   // Reset The Modelview Matrix
}

int OpenGL_Display::InitGL(GLvoid)                                      // All Setup For OpenGL Goes Here
{
    if (!LoadGLTextures())                              // Jump To Texture Loading Routine
    {
        return FALSE;                                   // If Texture Didn't Load Return FALSE
    }

    glEnable(GL_TEXTURE_2D);                            // Enable Texture Mapping
    glShadeModel(GL_SMOOTH);                            // Enable Smooth Shading
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);               // Black Background
    glClearDepth(1.0f);                                 // Depth Buffer Setup
    glDisable(GL_DEPTH_TEST);                           // Enables Depth Testing
    glDepthFunc(GL_LEQUAL);                             // The Type Of Depth Testing To Do
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Really Nice Perspective Calculations
    return TRUE;                                        // Initialization Went OK
}

void OpenGL_Display::GetMouseCords(int& x, int& y)      // All Setup For OpenGL Goes Here
{
    x = xPos;
    y = yPos;
}

void OpenGL_Display::UpdateGLBuffers(int width, int height, char* imageData, int bpp) 
{
    glBindTexture(GL_TEXTURE_2D, texture);
    if(bpp == 8)
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, imageData);
    } 
    else
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, width, height, 0, GL_RED, GL_UNSIGNED_SHORT, imageData);
    }
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
}

int OpenGL_Display::DrawGLScene(bool flip)                                  // Here's Where We Do All The Drawing
{
    GLenum mError = glGetError();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
    glLoadIdentity();                                   // Reset The View
    glTranslatef(0.0f,0.0f,-5.0f);
    mError = glGetError();
    glBindTexture(GL_TEXTURE_2D, texture);
    mError = glGetError();
    glColor4f(1.0, 1.0, 1.0, 1.0);
    mError = glGetError();
    if(flip)
    {
        glBegin(GL_QUADS);
            // Front Face
            glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  0.5f);
            glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  0.5f);
            glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  0.5f);
            glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  0.5f);
        glEnd();
        mError = glGetError();
    }
    else
    {
        glBegin(GL_QUADS);
            // Front Face
            glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, -1.0f,  0.5f);
            glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, -1.0f,  0.5f);
            glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  0.5f);
            glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  0.5f);
        glEnd();
        mError = glGetError();
    }
    mError = glGetError();  
    return TRUE;                                        // Keep Going
}

GLvoid OpenGL_Display::KillGLWindow(GLvoid)                             // Properly Kill The Window
{
    if (fullscreen)                                     // Are We In Fullscreen Mode?
    {
        ChangeDisplaySettings(NULL,0);                  // If So Switch Back To The Desktop
        ShowCursor(TRUE);                               // Show Mouse Pointer
    }

    if (hRC)                                            // Do We Have A Rendering Context?
    {
        if (!wglMakeCurrent(NULL,NULL))                 // Are We Able To Release The DC And RC Contexts?
        {
            MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
        }

        if (!wglDeleteContext(hRC))                     // Are We Able To Delete The RC?
        {
            MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
        }
        hRC=NULL;                                       // Set RC To NULL
    }

    if (hDC && !ReleaseDC(hWnd,hDC))                    // Are We Able To Release The DC
    {
        MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
        hDC=NULL;                                       // Set DC To NULL
    }

    if (hWnd && !DestroyWindow(hWnd))                   // Are We Able To Destroy The Window?
    {
        MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
        hWnd=NULL;                                      // Set hWnd To NULL
    }

    if (!UnregisterClass("OpenGL_Display",hInstance))           // Are We Able To Unregister Class
    {
        MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
        hInstance=NULL;                                 // Set hInstance To NULL
    }
}

void OpenGL_Display::DrawNewImage(int width, int height, char* imageData, bool flip, int bpp)
{
    BOOL returnVal = wglMakeCurrent(hDC, hRC);

    UpdateGLBuffers(width, height, imageData, bpp); 
    DrawGLScene(flip);
    SwapBuffers(hDC);
    wglMakeCurrent(NULL, NULL);
}

void OpenGLDisplay_Init(int width, int height, int posX, int posY, int ID, LPCSTR className)
{
    for(unsigned int i = 0; i < oglDisp.size(); ++i) {
        if(oglDisp.at(i)->ID == ID) {
            return;
        }
    }

    oglDisp.push_back(new OGD::OpenGL_Display(ID));
    oglDisp.at(oglDisp.size()-1)->Init_Display(width, height, posX, posY, className); //by default this ID is latest
    wglMakeCurrent(NULL, NULL);
    GLenum mError = glGetError();
}

void OpenGLDisplay_Wrapper(char* image, int width, int height, bool flip, int bpp, int ID)
{
    for(unsigned int i = 0; i < oglDisp.size(); ++i) {
        if(oglDisp.at(i)->ID == ID) {
            oglDisp.at(i)->DrawNewImage(width, height, image, flip, bpp);   
            return;
        }
    }   
}

void OpenGLDisplay_MousePos(int& x, int& y, int ID)
{
    for(unsigned int i = 0; i < oglDisp.size(); ++i) {
        if(oglDisp.at(i)->ID == ID) {
            oglDisp.at(i)->GetMouseCords(x, y); 
            return;
        }
    }   
}
4

1 回答 1

2

我要做的第一件事是将 whats inOpenGL_Display::InitGLOpenGL_Display::ResizeGLSceneinto移动到OpenGL_Display::DrawScene这些调用实际所属的位置。

在渲染帧时多次更改视口和投影是一件非常常见的事情,如果它周围有 ResizeGLScene 事物,那么它就像是明显解决方案的心理障碍。

现在要解决您的伪影,这些伪影来自纹理坐标 0 和 1 不在纹理像素中心,而是在包裹的相邻像素的边界上。对于 N 像素宽的纹理,像素的中心坐标为 (x + 0.5)/N,其中 x in [0; N-1]。

于 2013-09-18T08:35:01.007 回答