2017-08-04 6 views
0

透明な背景を持つOpenGLウィンドウに3Dオブジェクトを読み込みたいとします。私はNvidia Quadro K3000Mを搭載したUbuntu 16.04マシンでC++を使用しています(インストールされているドライバは最近のNVIDIAバイナリドライバ375.66です)。私は独立して両方の目的を持っています。this threadからX11で透明な背景を持つOpenGLウィンドウを作成し、this tutorialからAssimpとGLFWでオブジェクトをロードすることができます。透明な背景を持つOpenGLウィンドウでassimpを使ってオブジェクトを読み込む

は今、私は両方を組み合わせたいと、それは、少なくともビットで動作します - 私は、オブジェクトをインポートし、透明X11ウィンドウにロードすることができますが、テクスチャのいくつかは奇妙である、今透明です:

GLFW結果:

GLFW result

X11結果:

X11 result

私の問題を明確にするために、インポートされたオブジェクトにGLFWウィンドウではなく透明なX11ウィンドウが表示される理由を理解できません。私は、モデルがX11ウィンドウ内に正しく表示されるような修正を探しています(基本的にはウィンドウマネージャーになる可能性がありますが、X11は透明な背景を表示できる唯一のモデルでした)。

私はLearnOpenGLチュートリアルのメッシュクラスとモデルクラス、およびそれらのシェーダを使用します。私は@ datenwolfが助けてくれることを願っています。ここに私のコードは次のとおりです。

#include "GL/glew.h" 

#include <GL/gl.h> 
#include <GL/glx.h> 
#include <GL/glxext.h> 
#include <X11/Xatom.h> 
#include <X11/extensions/Xrender.h> 
#include <X11/Xutil.h> 

#include <GLFW/glfw3.h> 

#include <glm/glm.hpp> 
#include <glm/gtc/matrix_transform.hpp> 
#include <glm/gtc/type_ptr.hpp> 

#include <includes/learnopengl/filesystem.h> 
#include <includes/learnopengl/shader_m.h> 
#include <includes/learnopengl/camera.h> 
#include <includes/learnopengl/model.h> 

#include <iostream> 
//---------------------------- 
//----- RGBA X11 ------------- 
//---------------------------- 
#define USE_CHOOSE_FBCONFIG 

static void fatalError(const char *why) 
{ 
    fprintf(stderr, "%s", why); 
    exit(0x666); 
} 

static int Xscreen; 
static Atom del_atom; 
static Colormap cmap; 
static Display *Xdisplay; 
static XVisualInfo *visual; 
static XRenderPictFormat *pict_format; 
static GLXFBConfig *fbconfigs, fbconfig; 
static int numfbconfigs; 
static GLXContext render_context; 
static Window Xroot, window_handle; 
static GLXWindow glX_window_handle; 
static int width, height; 

std::string window_choice = "GLFW"; //X11 or GLFW 

static int VisData[] = { 
GLX_RENDER_TYPE, GLX_RGBA_BIT, 
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, 
GLX_DOUBLEBUFFER, True, 
GLX_RED_SIZE, 8, 
GLX_GREEN_SIZE, 8, 
GLX_BLUE_SIZE, 8, 
GLX_ALPHA_SIZE, 8, 
GLX_DEPTH_SIZE, 16, 
None 
}; 

static int isExtensionSupported(const char *extList, const char *extension) 
{ 
    const char *start; 
    const char *where, *terminator; 

    /* Extension names should not have spaces. */ 
    where = strchr(extension, ' '); 
    if (where || *extension == '\0') 
    return 0; 

    /* It takes a bit of care to be fool-proof about parsing the 
    OpenGL extensions string. Don't be fooled by sub-strings, 
    etc. */ 
    for (start = extList; ;) { 
    where = strstr(start, extension); 

    if (!where) 
     break; 

    terminator = where + strlen(extension); 

    if (where == start || *(where - 1) == ' ') 
     if (*terminator == ' ' || *terminator == '\0') 
     return 1; 

    start = terminator; 
    } 
    return 0; 
} 

static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg) 
{ 
    return d && e && arg && (e->type == MapNotify) && (e->xmap.window == *(Window*)arg); 
} 

static void describe_fbconfig(GLXFBConfig fbconfig) 
{ 
    int doublebuffer; 
    int red_bits, green_bits, blue_bits, alpha_bits, depth_bits; 

    glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_DOUBLEBUFFER, &doublebuffer); 
    glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_RED_SIZE, &red_bits); 
    glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_GREEN_SIZE, &green_bits); 
    glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_BLUE_SIZE, &blue_bits); 
    glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_ALPHA_SIZE, &alpha_bits); 
    glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_DEPTH_SIZE, &depth_bits); 

    fprintf(stderr, "FBConfig selected:\n" 
     "Doublebuffer: %s\n" 
     "Red Bits: %d, Green Bits: %d, Blue Bits: %d, Alpha Bits: %d, Depth Bits: %d\n", 
     doublebuffer == True ? "Yes" : "No", 
     red_bits, green_bits, blue_bits, alpha_bits, depth_bits); 
} 

static void createTheWindow() 
{ 
    XEvent event; 
    int x,y, attr_mask; 
    XSizeHints hints; 
    XWMHints *startup_state; 
    XTextProperty textprop; 
    XSetWindowAttributes attr = {0,}; 
    static char *title = "ARGB OpenGL Window"; 

    Xdisplay = XOpenDisplay(NULL); 
    if (!Xdisplay) { 
     fatalError("Couldn't connect to X server\n"); 
    } 
    Xscreen = DefaultScreen(Xdisplay); 
    Xroot = RootWindow(Xdisplay, Xscreen); 

    fbconfigs = glXChooseFBConfig(Xdisplay, Xscreen, VisData, &numfbconfigs); 
    fbconfig = 0; 
    for(int i = 0; i<numfbconfigs; i++) { 
     visual = (XVisualInfo*) glXGetVisualFromFBConfig(Xdisplay, fbconfigs[i]); 
     if(!visual) 
      continue; 

     pict_format = XRenderFindVisualFormat(Xdisplay, visual->visual); 
     if(!pict_format) 
      continue; 

     fbconfig = fbconfigs[i]; 
     if(pict_format->direct.alphaMask > 0) { 
      break; 
     } 
    } 

    if(!fbconfig) { 
     fatalError("No matching FB config found"); 
    } 

    describe_fbconfig(fbconfig); 

    /* Create a colormap - only needed on some X clients, eg. IRIX */ 
    cmap = XCreateColormap(Xdisplay, Xroot, visual->visual, AllocNone); 

    attr.colormap = cmap; 
    attr.background_pixmap = None; 
    attr.border_pixmap = None; 
    attr.border_pixel = 0; 
    attr.event_mask = 
     StructureNotifyMask | 
     EnterWindowMask | 
     LeaveWindowMask | 
     ExposureMask | 
     ButtonPressMask | 
     ButtonReleaseMask | 
     OwnerGrabButtonMask | 
     KeyPressMask | 
     KeyReleaseMask; 

    attr_mask = 
     CWBackPixmap| 
     CWColormap| 
     CWBorderPixel| 
     CWEventMask; 

    width = 1920; //DisplayWidth(Xdisplay, DefaultScreen(Xdisplay))/2; 
    height = 1080; //DisplayHeight(Xdisplay, DefaultScreen(Xdisplay))/2; 
    x=width/2, y=height/2; 

    window_handle = XCreateWindow( Xdisplay, 
        Xroot, 
        x, y, width, height, 
        0, 
        visual->depth, 
        InputOutput, 
        visual->visual, 
        attr_mask, &attr); 

    if(!window_handle) { 
     fatalError("Couldn't create the window\n"); 
    } 

#if USE_GLX_CREATE_WINDOW 
    int glXattr[] = { None }; 
    glX_window_handle = glXCreateWindow(Xdisplay, fbconfig, window_handle, glXattr); 
    if(!glX_window_handle) { 
     fatalError("Couldn't create the GLX window\n"); 
    } 
#else 
    glX_window_handle = window_handle; 
#endif 

    textprop.value = (unsigned char*)title; 
    textprop.encoding = XA_STRING; 
    textprop.format = 8; 
    textprop.nitems = strlen(title); 

    hints.x = x; 
    hints.y = y; 
    hints.width = width; 
    hints.height = height; 
    hints.flags = USPosition|USSize; 

    startup_state = XAllocWMHints(); 
    startup_state->initial_state = NormalState; 
    startup_state->flags = StateHint; 

    XSetWMProperties(Xdisplay, window_handle,&textprop, &textprop, 
      NULL, 0, 
      &hints, 
      startup_state, 
      NULL); 

    XFree(startup_state); 

    XMapWindow(Xdisplay, window_handle); 
    XIfEvent(Xdisplay, &event, WaitForMapNotify, (char*)&window_handle); 

    if ((del_atom = XInternAtom(Xdisplay, "WM_DELETE_WINDOW", 0)) != None) { 
     XSetWMProtocols(Xdisplay, window_handle, &del_atom, 1); 
    } 
} 

static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) 
{ 
    fputs("Error at context creation", stderr); 
    return 0; 
} 

static void createTheRenderContext() 
{ 
    int dummy; 
    if (!glXQueryExtension(Xdisplay, &dummy, &dummy)) { 
     fatalError("OpenGL not supported by X server\n"); 
    } 

#if USE_GLX_CREATE_CONTEXT_ATTRIB 
    #define GLX_CONTEXT_MAJOR_VERSION_ARB  0x2091 
    #define GLX_CONTEXT_MINOR_VERSION_ARB  0x2092 
    render_context = NULL; 
    if(isExtensionSupported(glXQueryExtensionsString(Xdisplay, DefaultScreen(Xdisplay)), "GLX_ARB_create_context")) { 
     typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); 
     glXCreateContextAttribsARBProc glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddressARB((const GLubyte *) "glXCreateContextAttribsARB"); 
     if(glXCreateContextAttribsARB) { 
      int context_attribs[] = 
      { 
       GLX_CONTEXT_MAJOR_VERSION_ARB, 3, 
       GLX_CONTEXT_MINOR_VERSION_ARB, 0, 
       //GLX_CONTEXT_FLAGS_ARB  , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, 
       None 
      }; 

      int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler); 

      render_context = glXCreateContextAttribsARB(Xdisplay, fbconfig, 0, True, context_attribs); 

      XSync(Xdisplay, False); 
      XSetErrorHandler(oldHandler); 

      fputs("glXCreateContextAttribsARB failed", stderr); 
     } else { 
      fputs("glXCreateContextAttribsARB could not be retrieved", stderr); 
     } 
    } else { 
      fputs("glXCreateContextAttribsARB not supported", stderr); 
    } 

    if(!render_context) 
    { 
#else 
    { 
#endif 
     render_context = glXCreateNewContext(Xdisplay, fbconfig, GLX_RGBA_TYPE, 0, True); //GLX_RGBA_TYPE 
     if (!render_context) { 
      fatalError("Failed to create a GL context\n"); 
     } 
    } 

    if (!glXMakeContextCurrent(Xdisplay, glX_window_handle, glX_window_handle, render_context)) { 
     fatalError("glXMakeCurrent failed for window\n"); 
    } 
} 

static int updateTheMessageQueue() 
{ 
    XEvent event; 
    XConfigureEvent *xc; 

    while (XPending(Xdisplay)) 
    { 
     XNextEvent(Xdisplay, &event); 
     switch (event.type) 
     { 
     case ClientMessage: 
      if (event.xclient.data.l[0] == del_atom) 
      { 
       return 0; 
      } 
     break; 

     case ConfigureNotify: 
      xc = &(event.xconfigure); 
      width = xc->width; 
      height = xc->height; 
      break; 
     } 
    } 
    return 1; 
} 
//---------------------------- 
//----- GLFW ----------------- 
//---------------------------- 

// settings 
const unsigned int SCR_WIDTH = 1920; 
const unsigned int SCR_HEIGHT = 1080; 

// camera 
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); 
float lastX = SCR_WIDTH/2.0f; 
float lastY = SCR_HEIGHT/2.0f; 
bool firstMouse = true; 

// timing 
float deltaTime = 0.0f; 
float lastFrame = 0.0f; 

int main(int argc, char *argv[]) 
{ 
    GLFWwindow* window; 

    if (window_choice == "X11") 
    { 
     createTheWindow(); 
     createTheRenderContext(); 
    } 
    else if (window_choice == "GLFW") 
    { 
     // glfw: initialize and configure 
     glfwInit(); 
     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 
     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 
     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 

     #ifdef __APPLE__ 
      glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X 
     #endif 

     // glfw window creation 
     window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); 
     if (window == NULL) 
     { 
      std::cout << "Failed to create GLFW window" << std::endl; 
      glfwTerminate(); 
      return -1; 
     } 
     glfwMakeContextCurrent(window); 
    } 

    //Load GLEW 
    GLenum err = glewInit(); 
    if (GLEW_OK != err) 
    { 
     // Problem: glewInit failed, something is seriously wrong 
     fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); 
    } 
    fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION)); 

    // configure global opengl state 
    // ----------------------------- 
    glEnable(GL_DEPTH_TEST); 

    //Build and compile shaders 
    Shader ourShader("/home/daniel/aureate/tools/Testing/assimp/1.model_loading.vs", "/home/daniel/aureate/tools/Testing/assimp/1.model_loading.fs"); 

    //Load models 
    Model ourModel(FileSystem::getPath("resources/objects/nanosuit/nanosuit.obj")); 

    if (window_choice == "X11") 
    { 
     while (updateTheMessageQueue()) 
     { 
      //RGBA 
      glClearColor(0.0, 0.0, 0.0, 0.0); 
      glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 

      ourShader.use(); 

      glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), 1.777f, 0.1f, 100.0f); //1920/1080 = 1.777 
      glm::mat4 view = camera.GetViewMatrix(); 
      ourShader.setMat4("projection", projection); 
      ourShader.setMat4("view", view); 

      // render the loaded model 
      glm::mat4 model; 
      model = glm::translate(model, glm::vec3(0.0f, -1.75f, 0.0f)); // translate it down so it's at the center of the scene 
      model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f)); // it's a bit too big for our scene, so scale it down 
      ourShader.setMat4("model", model); 
      ourModel.Draw(ourShader); 

      glXSwapBuffers(Xdisplay, glX_window_handle); 
     } 
    } 
    else if (window_choice == "GLFW") 
    { 
     while (!glfwWindowShouldClose(window)) 
     { 
      // per-frame time logic 
      // -------------------- 
      float currentFrame = glfwGetTime(); 
      deltaTime = currentFrame - lastFrame; 
      lastFrame = currentFrame; 

      // render 
      // ------ 
      glClearColor(0.2f, 0.3f, 0.3f, 0.0f); 
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

      // don't forget to enable shader before setting uniforms 
      ourShader.use(); 

      // view/projection transformations 
      glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH/(float)SCR_HEIGHT, 0.1f, 100.0f); 
      glm::mat4 view = camera.GetViewMatrix(); 
      ourShader.setMat4("projection", projection); 
      ourShader.setMat4("view", view); 

      // render the loaded model 
      glm::mat4 model; 
      model = glm::translate(model, glm::vec3(0.0f, -1.75f, 0.0f)); // translate it down so it's at the center of the scene 
      model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f)); // it's a bit too big for our scene, so scale it down 
      ourShader.setMat4("model", model); 
      ourModel.Draw(ourShader); 

      glfwSwapBuffers(window); 
     } 

     glfwTerminate(); 
     return 0; 
    } 
} 

答えて

0

だから私の問題を明確にする:インポートしたオブジェクトがGLFWウィンドウ内でX11ウィンドウ内の透明度を持っていない理由を私は理解していません。

透明X11ウィンドウを作成すると、そのウィンドウのアルファチャンネルが透明チャンネルとして使用されます。 GLFWで作成された透明でないウィンドウにレンダリングすると、フレームバッファのアルファチャンネルは何の効果もありません。

ここで見ているのは、テクスチャの一部に透明部分があることです。しかし、GLの独自のブレンディングを有効にしない限り、これらのアルファ値は決して観察可能な効果を持ちません。しかし、シェーダーはまだテクスチャのアルファ値を出力フレームバッファにコピーします。 GLFWの場合、デフォルトのフレームバッファにアルファチャンネルがあるかどうかは明白ではありません(明示的にリクエストすることはできますが、そうでないと確信することはできません)が、まったく無関係ですそのアルファチャンネルは使用されていないからです。

透明なX11ウィンドウコードパスでは、デフォルトのフレームバッファにアルファチャンネルが絶対必要です。そこに終わるアルファ値は実際に効果があります。あなたはそれらのOHPフィルムを使用しない場合、あなたは物事のカップルを行うことができ

:彼らは代わりに (r,g,b,a)

  • の出力(r,g,b,1)はテクスチャにGL_RGBベースのフォーマットを使用するように

    • はシェーダを変更ファイルからアルファ値を無視する
    • テクスチャ/素材の説明に透明度が含まれないように修正しました

    X11ウィンドウ(基本的にはどのウィンドウマネージャでも構いませんが、透明な背景を表示できるのはX11だけです)。

    いいえ、X11はウィンドウマネージャではありません。あなたが使用しているウィンドウマネージャー/コンポジターはわかりませんが、透明性をサポートするいくつかの選択肢があります。一方、あなたは確かに私のシステムに影響を与えることができないだろう、これは私がそれが欲しい方法です。

  • +0

    こんにちは、お返事ありがとうございます:)このモデルでは、このモデルで何か変わったようです - 私はBlenderで正確に同じオブジェクトをレンダリングして二重チェックし、そこには透明シートも表示されません。しかし、あなたのヒントのおかげで、私は今いくつかの他の3Dモデルを試してみましたが、X11ウィンドウ内でうまく表示されています。 – slisystem

    関連する問題