2017-08-16 4 views
-1

背景情報:OpenGLのレンダリングクワッド

私は、画面上にいくつかのクワッドを描画するOpenGLとLWJGL 3を使用しています。私はマウスがクワッド上にあることを知る必要があります。クワッドをスクリーンにレンダリングするとき、私はXとYの両方に-1から1の範囲の、そしてスクリーンの中央で(0,0)の範囲のOpenGL座標を使用します。私は、マウスの位置を取得すると、私は(タイトルバーの下)左上隅に私に0からウィンドウの幅または高さにし、(0,0)に至るまでの座標を与える

glfwSetCursorPosCallback(); 

を使用しています。次に、マウス座標をとり、OpenGLの座標を計算します。

たとえば、ウィンドウサイズが(800、600)でマウスが(200,200)の場合、(400、300)は(0、0) OpenGLの座標で]。が

OpenGLはないglfwSetCursorPosCallback();としてその座標でのタイトルバーを、含まれています

は、だからここに私の問題です。つまり、(私の例のように)頂点を(-0.5、0.33)にレンダリングすると、周囲(200、〜210)でレンダリングされます。

ご覧のとおり、2つの座標系が異なる領域をカバーしているため、座標系を切り替えるのが難しくなります。

タイトルバーを完全に取り除き、タイトルバーの高さを得るために、OpenGLの座標からタイトルバーを除外する方法を探しました(私は計算に含めて正しい調整をすることができます) 。私はどのようにこれらのいずれかを行う方法を見つけることができませんでしたので、私はそうする方法、または私の問題を解決する別の方法を探しています。


EDIT 1:追加コード

@Nicolボーラは、OpenGLが正常に動作しますので、私のコードでこれを原因となる何かが存在する必要がありますどのようにこれはないことを教えてくれました。

ここ


注[私はdrawQuad()メソッドを使用しています]私のレンダラクラスである:私は私の問題のために責任を負うことになる私のコードの一部を提供してきたと考えている私は現在、シェーダのビュー、モデル、または投影行列を使用していません。

private void init() { 


    // Setup an error callback. The default implementation 
    // will print the error message in System.err. 
    GLFWErrorCallback.createPrint(System.err).set(); 

    // Initialize GLFW. Most GLFW functions will not work before doing this. 
    if (!glfwInit()) 
     throw new IllegalStateException("Unable to initialize GLFW"); 

    // Configure GLFW 
    glfwDefaultWindowHints(); // optional, the current window hints are already the default 
    glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation 
    glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); // the window will be resizable 

    // ONLY ON MAC OSX (?) 
    //glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Tell GLFW to use OpenGL verison 3.x 
    //glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); // Tell GLFW to use OpenGL version x.2 (combined -> 3.2) 
    //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 
    //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); // Should be forward compatible 

    // Create the window 
    window = glfwCreateWindow(WIDTH, HEIGHT, "Game_19_v0.0.1", NULL, NULL); 
    if (window == NULL) 
     throw new RuntimeException("Failed to create the GLFW window"); 

    // Setup a key callback. It will be called every time a key is pressed, repeated or released. 
    glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> { 
     if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) 
      glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop 
    }); 

    // Get the thread stack and push a new frame 
    try (MemoryStack stack = stackPush()) { 
     IntBuffer pWidth = stack.mallocInt(1); // int* 
     IntBuffer pHeight = stack.mallocInt(1); // int* 

     // Get the window size passed to glfwCreateWindow 
     glfwGetWindowSize(window, pWidth, pHeight); 

     // Get the resolution of the primary monitor 
     GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); 

     // Center the window 
     glfwSetWindowPos(
       window, 
       (vidmode.width() - pWidth.get(0))/2, 
       (vidmode.height() - pHeight.get(0))/2 
     ); 
    } // the stack frame is popped automatically 

    // Make the OpenGL context current 
    glfwMakeContextCurrent(window); 
    // Enable v-sync 
    glfwSwapInterval(1); 

    // Make the window visible 
    glfwShowWindow(window); 

    // This line is critical for LWJGL's interoperation with GLFW's 
    // OpenGL context, or any context that is managed externally. 
    // LWJGL detects the context that is current in the current thread, 
    // creates the GLCapabilities instance and makes the OpenGL 
    // bindings available for use. 
    GL.createCapabilities(); 

    // Input 
    glfwSetCursorPosCallback(window, cursorPosCallback = new MouseInput()); 

    // Create renderer 
    renderer = new Renderer(); 
    renderer.init(); 

    // To Render: 
    buttonManager = new ButtonManager(); 

} 


EDIT 2:一時的な解決策

私がすることができた

public class Renderer { 

    private VertexArrayObject vao; 
    private VertexBufferObject vbo; 
    private ShaderProgram shaderProgram; 

    private FloatBuffer vertices; 
    private int numVertices; 
    private boolean drawing; 

    //private Font font; 
    //private Font debugFont; 


    public void drawQuad(float x, float y, float width, float height, Color c) { 
    /* Calculate Vertex positions */ 
     float x1 = x; 
     float y1 = y; 
     float x2 = x + width; 
     float y2 = y - height; 

    /* Calculate color */ 
     float r = c.getRed(); 
     float g = c.getGreen(); 
     float b = c.getBlue(); 

    /* Put data into buffer */ 
     vertices.put(x1).put(y1).put(0.0f).put(r).put(g).put(b); 
     vertices.put(x1).put(y2).put(0.0f).put(r).put(g).put(b); 
     vertices.put(x2).put(y2).put(0.0f).put(r).put(g).put(b); 
     vertices.put(x2).put(y1).put(0.0f).put(r).put(g).put(b); 

    /* We drawed X vertices */ 
     numVertices += 4; 
    } 


    // Initialize renderer 
    public void init(){ 

     // Set up shader programs 
     setupShaderProgram(); 

     // Enable blending (?????) 
     glEnable(GL_BLEND); 
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

    } 

    // Clears drawing area 
    public void clear() { 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    } 

    // Begin rendering 
    public void begin() { 
     if (drawing) throw new IllegalStateException("Renderer is already drawing."); 
     drawing = true; 
     numVertices = 0; 
    } 

    // End rendering 
    public void end() { 
     if (!drawing) throw new IllegalStateException("Renderer is not drawing."); 
     drawing = false; 
     flush(); 
    } 

    // Flushes data to GPU to get rendered 
    public void flush() { 
     if (numVertices > 0) { 
      vertices.flip(); 

      if (vao != null) vao.bind(); 
      else vbo.bind(GL_ARRAY_BUFFER); 
      specifyVertexAttributes(); 
     } 
     shaderProgram.use(); 

     // Upload the new vertex data 
     vbo.bind(GL_ARRAY_BUFFER); 
     vbo.uploadSubData(GL_ARRAY_BUFFER, 0, vertices); 

     // Draw batch 
     glDrawArrays(GL_QUADS, 0, numVertices); 

     // Clear vertex data for next batch 
     vertices.clear(); 
     numVertices = 0; 
    } 

    private void setupShaderProgram() { 

     // Generate VertexArrayObject 
     if (Game.is32Supported()) { 
      vao = new VertexArrayObject(); 
      vao.bind(); 
     } else { 
      throw new RuntimeException("OpenGL 3.2 not supported."); 
     } 

     // Generate VertexBufferObject 
     vbo = new VertexBufferObject(); 
     vbo.bind(GL_ARRAY_BUFFER); 

     // Create FloatBuffer 
     vertices = MemoryUtil.memAllocFloat(4096); 

     // Upload null data to allocate storage for the VBO 
     long size = vertices.capacity() * Float.BYTES; 
     vbo.uploadData(GL_ARRAY_BUFFER, size, GL_DYNAMIC_DRAW); 

     // Initialize variables 
     numVertices = 0; 
     drawing = false; 

     // Load Shaders: 
     Shader vertexShader, fragmentShader; 
     if (Game.is32Supported()) { 
      vertexShader = Shader.loadShader(GL_VERTEX_SHADER, "res/shaders/vshader.vert"); 
      fragmentShader = Shader.loadShader(GL_FRAGMENT_SHADER, "res/shaders/fshader.frag"); 
     } else { 
      throw new RuntimeException("OpenGL 3.2 not supported."); 
     } 

     // Create ShaderProgram 
     shaderProgram = new ShaderProgram(); 
     shaderProgram.attachShader(vertexShader); 
     shaderProgram.attachShader(fragmentShader); 
     if (Game.is32Supported()) { 
      shaderProgram.bindFragmentDataLocation(0, "fragColor"); 
     } 
     shaderProgram.link(); 
     shaderProgram.use(); 

     // Delete linked shaders 
     vertexShader.delete(); 
     fragmentShader.delete(); 

     // Get width & height of framebuffer 
     long window = GLFW.glfwGetCurrentContext(); 
     int width, height; 
     try (MemoryStack stack = MemoryStack.stackPush()) { 
      IntBuffer widthBuffer = stack.mallocInt(1); 
      IntBuffer heightBuffer = stack.mallocInt(1); 
      GLFW.glfwGetFramebufferSize(window, widthBuffer, heightBuffer); 
      width = widthBuffer.get(); 
      height = heightBuffer.get(); 
     } 

     // Specify vertex pointers 
     specifyVertexAttributes(); 

     // Set Model Matrix to identity matrix 
     Matrix4f model = new Matrix4f(); 
     int uniModel = shaderProgram.getUniformLocation("model"); 
     shaderProgram.setUniform(uniModel, model); 

     // Set View Matrix to identity matrix 
     Matrix4f view = new Matrix4f(); 
     int uniView = shaderProgram.getUniformLocation("view"); 
     shaderProgram.setUniform(uniView, view); 

     // Set Projection Matrix to an orthographic projection 
     Matrix4f projection = Matrix4f.orthographic(0f, width, 0f, height, -1f, 1f); 
     int uniProjection = shaderProgram.getUniformLocation("projection"); 
     shaderProgram.setUniform(uniProjection, projection); 

    } 

    // Specifies the vertex shader pointers (attributes) 
    private void specifyVertexAttributes() { 

     int posAttrib = shaderProgram.getAttributeLocation("position"); 
     shaderProgram.enableVertexAttribute(posAttrib); 
     shaderProgram.pointVertexAttribute(posAttrib, 3, 6 * Float.BYTES, 0); 

     int colAttrib = shaderProgram.getAttributeLocation("color"); 
     shaderProgram.enableVertexAttribute(colAttrib); 
     shaderProgram.pointVertexAttribute(colAttrib, 3, 6 * Float.BYTES, 3 * Float.BYTES); 

    } 

} 

そしてここでは、作成し、私の窓を設定し、私のinit()メソッドでありますglfwWindowHint(GLFW_DECORATED, GLFW_FALSE);を使用して、問題を修正したタイトルバーを含むウィンドウから枠線全体を削除してください。しかし、今では私のウィンドウに閉じる、最小化するなどのオプションはありませんが、必要に応じて自分でプログラムすることはできます。他の解決策が見つかると更新されます。

+6

"* OpenGLには、その座標にタイトルバーが含まれています。*" OpenGLには、タイトルバーについての知識はありません。これはGLFWを何らかの方法で悪用しているようです。しかし、私たちはあなたが[mcve]を提供しなかったので、その方法は分かりません。 –

+0

ああ、私の悪い。私はそれがOpenGLで、私のコードではないと思った。編集します。 – drewpel

答えて

0

GLFW関数は通常、ウィンドウのクライアント領域(タイトルバー、スクロールバーなどを含まない内側のウィンドウ領域)で動作しますので、glfwSetCursorPosCallbackは期待値を与えています。あなたのOpenGLのフレームバッファは、(それが不適切なセットアップまたは単にプラットフォーム固有の詳細なのかどうか)タイトルバーの後ろに物事をレンダリングするいくつかの理由である場合、あなたはまだglfwGetWindowFrameSizeを使用して、タイトルバーのサイズを得ることができる必要があります:

IntBuffer pLeft = stack.mallocInt(1); // int* 
IntBuffer pTop = stack.mallocInt(1); // int* 
IntBuffer pRight = stack.mallocInt(1); // int* 
IntBuffer pBottom = stack.mallocInt(1); // int* 

// Get the window border sizes 
glfwGetWindowFrameSize(window, pLeft, pTop, pRight, pBottom); 

(免責事項:私はC++ APIにしか慣れていないので、上のコードの構文に従っています)

タイトルバーのサイズはtop変数に格納され、 glfwSetCursorPosCallbackglfwGetWindowSizeから取得します。

float adjustedYpos = ypos + top; 
float adjustedHeight = height + top; 
float normalizedY = adjustedYpos/adjustedHeight; 
float openglY = normalizedY * -2.0f - 1.0f 

このopenglY値はクリップ空間がタイトルバーのサイズに基づいて調整座標のOpenGL [1 -1]であるべきです。