Hintergrund Info:OpenGL Rendering Quads an der falschen Position
Ich bin mit OpenGL und LWJGL 3 einige Quads auf dem Bildschirm zu zeichnen. Ich muss wissen, wenn die Maus über einem Quad ist. Wenn ich die Quads auf den Bildschirm rende, verwende ich die OpenGL-Koordinaten von -1 bis 1 für X und Y und mit (0,0) in der Mitte des Bildschirms. Wenn ich die Mausposition bekommen verwende ich
glfwSetCursorPosCallback();
, die mir die Koordinaten im Bereich von 0 bis der Breite oder Höhe des Fensters und mit (0,0) in der oberen linken Ecke (unter der Titelleiste) gibt. Ich nehme dann die Mauskoordinate und berechne die OpenGL-Koordinaten.
Zum Beispiel, wenn meine Fenstergröße (800, 600) und meine Maus bei (200, 200) wäre würde ich (-0.5, 0.33) [da (400, 300) würde zu (0, 0) zuordnen in den OpenGL-Koordinaten].
hier ist also mein Problem:
OpenGL auf die Titelleiste in seinen Koordinaten enthalten, wobei als glfwSetCursorPosCallback();
nicht. Das bedeutet, wenn ich einen Scheitelpunkt bei (-0,5, 0,33) [wie in meinem Beispiel] rendere, rendert er bei ungefähr (200, ~ 210).
Wie Sie sehen können, ist es schwieriger, zwischen den Koordinatensystemen zu wechseln, da die beiden Koordinatensysteme unterschiedliche Bereiche abdecken.
Ich habe nach Möglichkeiten gesucht, die Titelleiste von den OpenGL-Koordinaten auszuschließen, die Titelleiste vollständig zu entfernen und die Höhe der Titelleiste zu erhalten (damit ich sie in meine Berechnungen einbeziehen und die richtigen Anpassungen vornehmen kann) . Ich war nicht in der Lage, herauszufinden, wie ich das tun könnte, also suche ich nach einer Möglichkeit, dies zu tun, oder nach einer anderen Methode, die mein Problem lösen wird.
EDIT 1: Hinzufügen von Code
@Nicol Bolas mir mitgeteilt, dass dies nicht der Fall, wie OpenGL normal funktioniert so muss es etwas in meinem Code verursacht dies sein. Ich glaube, ich habe die Teile meines Codes zur Verfügung gestellt, die für mein Problem verantwortlich sind:
Hier ist meine Renderer-Klasse [ich den drawQuad() -Methode bin mit]
Hinweis: I verwende derzeit nicht die Ansichts-, Modell- oder Projektionsmatrizen in meinen Shadern.
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);
}
}
Und hier ist meine Methode init(), dass mein Fenster erstellt und einrichtet:
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: Temporäre Lösung
konnte ich Verwenden Sie glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
, um den gesamten Rahmen aus dem Fenster zu entfernen, einschließlich Titelleiste, wodurch das Problem behoben wurde. Nun, ich habe natürlich nicht die Möglichkeiten zu schließen, minimieren, etc., auf meinem Fenster, obwohl ich denke, dass ich diese in mir programmieren kann, wenn nötig.Wird aktualisiert, wenn ich andere Lösungen finde.
"* OpenGL enthält die Titelleiste in ihren Koordinaten *" OpenGL hat keine Kenntnis der Titelleiste. Das klingt, als würdest du GLFW irgendwie missbrauchen. Aber wir wissen nicht, was das ist, weil Sie kein [mcve] zur Verfügung gestellt haben. –
Ah, mein Schlechter. Ich dachte, es wäre etwas mit OpenGL, nicht mit meinem Code. Wird bearbeiten. – drewpel