2017-12-14 28 views
1

レンダリング画像のコードをOpenGLと書いています。私はGLUTを使用してウィンドウとコールバックを作成しましたが、win32ウィンドウに画像をレンダリングしたいのですが、基本的にCreateWindowEx()というAPIを持っていて、win32のウィンドウを作成するAPIとHWNDHDCしかし、私はGLUTでこのようなものを見つけられませんでした。GLUTにハンドルを送信することは可能ですか?または他のアプローチ?win32ウィンドウでOpenGLを使用して画像をレンダリングする

私のコードは、画面上のレンダリングイメージが正常に表示されます。

int main() 
{  
    __try{  
     int argc = 1; 
     char *argv[1] = { (char*)"GLUTwindow" }; 
     glutInit(&argc, argv); 
     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); 
     glutInitWindowSize(1024, 768); 
     glutInitWindowPosition(0, 0); 
     glutCreateWindow("GLUTwindow"); 
     GLenum err = glewInit(); if (GLEW_OK != err)              __debugbreak(); 
     init(); 
     glutDisplayFunc(display); 
     glutReshapeFunc(reshape); 
     glutMotionFunc(motion); 
     glutMainLoop();   
    } 
    __except (EXCEPTION_EXECUTE_HANDLER) 
    { 

    } 
    return 0; 
} 

void init() 
{ 
    // compile and link the shaders into a program, make it active 
    vShader = compileShader(vertexShader, GL_VERTEX_SHADER); 
    fShader = compileShader(fragmentShader, GL_FRAGMENT_SHADER); 
    std::list<GLuint> tempList; 
    tempList.clear(); 
    tempList.insert(tempList.end(), (GLuint)vShader); 
    tempList.insert(tempList.end(), (GLuint)fShader); 
    program = createProgram(tempList); 
    offset = glGetUniformLocation(program, "offset");           GLCHK; 
    texUnit = glGetUniformLocation(program, "texUnit");           GLCHK; 
    glUseProgram(program);                  GLCHK; 

    // configure texture unit 
    glActiveTexture(GL_TEXTURE0);                GLCHK; 
    glUniform1i(texUnit, 0);                 GLCHK; 

    // create and configure the textures 
    glGenTextures(1, &texture);                 GLCHK; 
    // "Bind" the newly created texture : all future texture functions will modify this texture 
    glBindTexture(GL_TEXTURE_2D, texture);              GLCHK; 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);        GLCHK; 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);        GLCHK; 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);       GLCHK; 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);       GLCHK; 

} 


    void display() 
{ 
    GLuint w, h; std::vector<GLubyte> img; if (lodepng::decode(img, w, h, "test2.png")) __debugbreak(); 
    glBindTexture(GL_TEXTURE_2D, texture);              GLCHK; 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,w,h, 0, GL_RGBA, GL_UNSIGNED_BYTE, &img[0]); GLCHK;  
    glClear(GL_COLOR_BUFFER_BIT);                GLCHK; 
    glBindTexture(GL_TEXTURE_2D, texture);              GLCHK; 
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);              GLCHK; 
    glutSwapBuffers();  
    glutPostRedisplay(); 
} 
+2

glutはwin32ウィンドウを使用します。独自のウィンドウを作成したいという場合は、glutを使用することはできません。 [こちら](https://www.khronos.org/opengl/wiki/Creating_an_OpenGL_Context_(WGL))と[this](http://www.mbsoftworks.sk/index.php?page=tutorials&series=1&tutorial=2)良い出発点です。 – BDL

+1

'wglCreateContext'は必要な関数の名前です。また、あなたとOpenGLの間にGLUTがあることを理解する必要があります。その仲介者がいなくなると、しばしば当然のことと思われる多くの機能の助けを借りなければ、同じことを達成するためにより多くの努力が必要になります。おそらく、あなたはここで解決策#2でいくつかの使用を見つけるでしょう:https://www.codeproject。com/questions/672673/how-to-save-opengl-images-to-the-bmp-file – enhzflep

+0

@BDL私は既にwin32ウィンドウを持っていますが、メニュー項目もありますが、ウィンドウを作成し、正常に今私は私のレンダリングウィンドウをwin32ウィンドウに置き換えたいだけです。私たちはHWNDハンドルをglutに渡すことはできますか? – Krish

答えて

2

あなたは、Win32のOpenGLのウィンドウを作成したい場合は、任意のウィンドウライブラリなしで、次の操作を実行する必要があります。

#include <GL/gl.h> 
#include <windows.h> 

const std::wstring wnd_class(L"my_wnd_class"); 
HWND hOGLWnd = NULL; 
HGLRC hOGLRenderContext = NULL; 

HWND createWindow(int width, int height) 
{ 
    // Get module handle 
    HMODULE hModule = ::GetModuleHandle(0); 
    if (!hModule) 
     return NULL; 

    // Create window calss 
    WNDCLASSEX wndClassData; 
    memset(&wndClassData, 0, sizeof(WNDCLASSEX)); 
    wndClassData.cbSize   = sizeof(WNDCLASSEX); 
    wndClassData.style   = CS_DBLCLKS; 
    wndClassData.lpfnWndProc = WindowProcedure; 
    wndClassData.cbClsExtra  = 0; 
    wndClassData.cbWndExtra  = 0; 
    wndClassData.hInstance  = hModule; 
    wndClassData.hIcon   = ::LoadIcon(0,IDI_APPLICATION); 
    wndClassData.hCursor  = ::LoadCursor(0,IDC_ARROW); 
    wndClassData.hbrBackground = ::CreateSolidBrush(COLOR_WINDOW+1); 
    wndClassData.lpszMenuName = 0; 
    wndClassData.lpszClassName = wnd_class.c_str(); 
    wndClassData.hIconSm  = 0; 
    if (!::RegisterClassEx(&wndClassData)) 
     return false; 

    // Creaate Window 
    hOGLWnd = ::CreateWindow(wnd_class.c_str(), NULL, WS_OVERLAPPEDWINDOW, 0, 0, width, height, NULL, NULL, hModule, NULL); 
    if (hOGLWnd == NULL) 
     return NULL; 

    // Get device context 
    HDC hDC = ::GetDC(hOGLWnd); 

    // Create OpenGL context 
    DWORD pixelFormatFlags = PFD_SUPPORT_OPENGL | PFD_SUPPORT_COMPOSITION | PFD_GENERIC_ACCELERATED | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; 
    PIXELFORMATDESCRIPTOR pfd = 
    { 
     sizeof(PIXELFORMATDESCRIPTOR), 
     1, 
     pixelFormatFlags,   //Flags 
     PFD_TYPE_RGBA,   //The kind of framebuffer. RGBA or palette. 
     32,      //Colordepth of the framebuffer. 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     24,      //Number of bits for the depthbuffer 
     8,      //Number of bits for the stencilbuffer 
     0,      //Number of Aux buffers in the framebuffer. 
     PFD_MAIN_PLANE, 
     0, 0, 0, 0 
    }; 
    int pixelFormat = ::ChoosePixelFormat(hDC, &pfd); 
    ::SetPixelFormat(hDC, pixelFormat, &pfd); 
    hOGLRenderContext = ::wglCreateContext(hDC); 

    // make OpenGL context the current context 
    ::wglMakeCurrent(hDC, hOGLRenderContext); 

    // release device context 
    ::ReleaseDC(hOGLWnd, hDC); 

    // show the window 
    ::ShowWindow(hOGLWnd, SW_SHOWDEFAULT); 
    return hOGLWnd; 
} 

手順は、ウィンドウメッセージを処理neede、ある表示:

LRESULT CALLBACK WindowProcedure(HWND hWnd, unsigned int msg, WPARAM wparam, LPARAM lparam) 
{ 
    switch(msg) 
    { 
    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 

    case WM_ERASEBKGND: 
     display(); 
     break; 
    } 
    return DefWindowProc(hWnd, msg, wparam, lparam); 
} 

メインループを派遣取得する必要がありウィンドウメッセージ(メッセージループ):

void mainloop(void) 
{ 
    MSG msg; 
    while(::GetMessage(&msg, 0, 0, 0)) 
     ::DispatchMessage(&msg); 
} 
そうでない場合は、

#include <GL/glew.h> 
#include <vector> 
#include <stdexcept> 

int main() 
{ 
    int w = 800; 
    int h = 600; 

    HWND hWnd = createWindow(w, h); 
    if (hWnd == 0) 
     throw std::runtime_error("error initializing window"); 

    if (glewInit() != GLEW_OK) 
     throw std::runtime_error("error initializing glew"); 

    static const std::vector<float> varray 
    { 
     -0.707f, -0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 
     0.707f, -0.75f, 1.0f, 1.0f, 0.0f, 1.0f, 
     0.0f, 0.75f, 0.0f, 0.0f, 1.0f, 1.0f 
    }; 

    GLuint vbo; 
    glGenBuffers(1, &vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    glBufferData(GL_ARRAY_BUFFER, varray.size()*sizeof(*varray.data()), varray.data(), GL_STATIC_DRAW); 

    GLuint vao; 
    glGenVertexArrays(1, &vao); 
    glBindVertexArray(vao); 
    glVertexPointer(2, GL_FLOAT, 6*sizeof(*varray.data()), 0); 
    glEnableClientState(GL_VERTEX_ARRAY); 
    glColorPointer(4, GL_FLOAT, 6*sizeof(*varray.data()), (void*)(2*sizeof(*varray.data()))); 
    glEnableClientState(GL_COLOR_ARRAY); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 

    mainloop();  
    destroyWindow(); 
    return 0; 
} 

void display(void) 
{ 
    RECT clientRect; 
     ::GetClientRect(hOGLWnd, &clientRect); 
    glViewport(0, 0, clientRect.right-clientRect.left, clientRect.bottom-clientRect.top); 
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);  

    glDrawArrays(GL_TRIANGLES, 0, 3); 

    // swap buffers 
    HDC hDC = ::GetDC(hOGLWnd); 
    ::SwapBuffers(hDC); 
    ::ReleaseDC(hOGLWnd, hDC); 

    // create message WM_ERASEBKGND 
    ::InvalidateRect(hOGLWnd, NULL, TRUE); 
} 


注:完全性のseeness簡単なデモプログラムの場合

void destroyWindow(void) 
{ 
    if (HDC currentDC = ::wglGetCurrentDC()) 
     ::wglMakeCurrent(currentDC , NULL); 
    ::DestroyWindow(hOGLWnd); 
    ::wglDeleteContext(hOGLRenderContext); 

    HMODULE hModule = ::GetModuleHandle(0); 
    if (!hModule) 
     return; 
    ::UnregisterClass(wnd_class.c_str(), hModule); 
} 

:ウィンドウは次のようにdestroiedすることができ

ウィンドウを表示する(スキップShowWindow)、あなたはimaを行うことができる隠されたウィンドウを持っているgeレンダリング。 GPUからレンダリングイメージをglReadPixelsで読むことができます。または、テクスチャを添付したフレームバッファを作成し、glGetTexImageでテクスチャを読み取ることができます。

関連する問題