I have been trying to render a VBO that is 1/3 of the size of the screen resolution of the screen to a Quad that is the size of the screen. What am I doing wrong?
public void initGL() {
frameBufferID = glGenFramebuffersEXT();
colorBufferID = glGenTextures();
depthBufferID = glGenRenderbuffersEXT();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferID);
glBindTexture(GL_TEXTURE_2D, colorBufferID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, WIDTH / SCALE, HEIGHT / SCALE, 0, GL_RGBA, GL_INT, (java.nio.ByteBuffer)null);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, colorBufferID, 0);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBufferID);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL14.GL_DEPTH_COMPONENT24, WIDTH / SCALE, HEIGHT / SCALE);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBufferID);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
public void render() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLU.gluPerspective(90.0f, WIDTH/(float)HEIGHT, 0.001f, 1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, WIDTH / SCALE, HEIGHT / SCALE);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferID);
glClearColor(1.0f, 0.0f, 0.0f, 0.5f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1, 1, 1);
// Render game code here
glBegin(GL_LINES);
{
glVertex2f(0, 0);
glVertex2f(1, 1);
}
glEnd();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, WIDTH, 0, HEIGHT, 0.001f, 1000.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D, colorBufferID);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, WIDTH, HEIGHT);
glTranslatef(0, 0, -1);
//Draw Quad
glBegin(GL_QUADS);
{
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(1, 0);
glVertex2f(WIDTH, 0);
glTexCoord2f(1, 1);
glVertex2f(WIDTH, HEIGHT);
glTexCoord2f(0, 1);
glVertex2f(0, HEIGHT);
}
glEnd();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
I'm trying to render the things in the VBO in Perspective, and then draw the fullscreen Quad in Orthographic. But everything I've tried doesn't work... Like at all. Is there anything I've screwed up?
You are rendering a quad with a completely red texture in front of a red background, so there is not much to see.
The lines you are trying to render into the texture are actually outside of the frustum, as you draw in the z=0 plane, while your frustum is in the range z=[-0.001,-1000].
For debugging purposes, I recommend to change the clear color between your two draw passes, so that you can better see which of the two passes fails.
Related
My skybox is displayed, but does not display the textures that I load from the image. Instead, it shows the transparent color if i set glTexImage2D how GL_RGBA, or black color if i set glTexImage2D how GL_RGB.
I am using a render with MultisampledFbo support.
My texture loading code looks like this:
private int loadSkyboxTextures(){
glGenBuffers(vbo);
glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, POINTS, GL_STATIC_DRAW);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glGenVertexArrays(vao);
glBindVertexArray(vao[0]);
glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);
glVertexPointer(3, GL_FLOAT, 3 * Float.BYTES, NULL);
glTexCoordPointer (3, GL_FLOAT, 3 * Float.BYTES, NULL);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
int texID = glGenTextures();
glBindTexture(GL_TEXTURE_CUBE_MAP, texID);
for(int i = 0; i < TEXTURE_FILES.length; i++){
InputStream file = getClass().getResourceAsStream(TEXTURE_FILES[i]);
byte[] pixelData = new byte[0];
try {
pixelData = new byte[file.available()];
file.read(pixelData);
} catch (IOException e) {
e.printStackTrace();
}
ByteBuffer byteBuffer = ByteBuffer.wrap(pixelData);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, 512, 512, 0,
GL_RGB, GL_UNSIGNED_BYTE, byteBuffer);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
return texID;
}
Cube Render Code:
private void drawSkybox(){
glColor4f(1,1,1,1);
glDepthMask(false);
glEnable(GL_TEXTURE_CUBE_MAP);
glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);
glBindVertexArray(vao[0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, texId);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glDepthMask(true);
glDisable(GL_TEXTURE_CUBE_MAP);
}
The cube rendering call in the main render function:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
view = viewX || viewY || viewZ;
if(view)
glPushMatrix();
int rot = 180;
glDisable(GL_LIGHTING);
glViewport(0, 0, WIDTH, HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-max, max, -1, 1, 10, -10);
glRotated(cameraX, 1f, 0f, 0);
glRotated(cameraY, 0f, 1f, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
drawSkybox(texId);
glViewport(0, 0, WIDTH, HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
...
//render camera and other objects
For cube map textures, the texture coordinates are 3-dimensional and treated as a vector form the center of the cube map.
Since you draw a cube, which is centered around (0, 0, 0), you can use the the vertex coordinates for the texture coordinates, too. You do not use a shader program, so you have to use fixed function attributes. Specify the vertex coordinates by glVertexPointer and the texture coordinates by glTexCoordPointer. Enable the client-side capability (glEnableClientState) GL_VERTEX_ARRAY and GL_TEXTURE_COORD_ARRAY.
Specify the Vertex Array Object. It is sufficient to execute that code once at intialization:
glGenBuffers(vbo);
glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, POINTS, GL_STATIC_DRAW);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glGenVertexArrays(vao);
glBindVertexArray(vao[0]);
glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);
glVertexPointer(3, GL_FLOAT, false, 3 * Float.BYTES, NULL);
glTexCoordPointer (3, GL_FLOAT, false, 3 * Float.BYTES, NULL);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindVertexArray(0);
When you draw the skybox it is sufficient to bind the cubemap texture to enable cube-mapped texturing and to bind the VAO:
private void drawSkybox(){
GL11.glColor4f(1,1,1,1);
glDepthMask(false);
glEnable(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, texID);
glBindVertexArray(vao[0]);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glDepthMask(true);
glDisable(GL_TEXTURE_CUBE_MAP);
}
There are some further issues:
The image is not read correctly. See I have a black texture.
Clear the depth buffer after drawing the skybox. See Skybox textures do not display correctly
In LWJGL 3.2.1 I'm drawing a triangle using vertices and viewing it with a perspective (frustum) projection. I'm trying to use the triangle to orientate myself in 3D space to figure out where I am and how to direct myself. When I rotate the triangle, it gets smaller instead of rotating around the set point.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(0, windowWidth, windowHeight, 0, 0, 100);
glMatrixMode(GL_MODELVIEW);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glRotatef(5f, 0f, 0f, 0f);
glMatrixMode(GL_MODELVIEW);
glBegin(GL_POLYGON);
glVertex3f(-0f, -0f, 0f);
glVertex3f(0f, 1f, 0f);
glVertex3f(1f, 1f, 0f);
glEnd();
glPopMatrix();
glfwSwapBuffers(window);
glfwPollEvents();
}
Am I rotating it incorrectly or something?
I have a wall in an OpenGL program drawn like this:
public void draw() {
if(!door){
glBegin(GL_QUADS);
glVertex3f(posx, 0f, posz);
glVertex3f(posx, y, posz);
glVertex3f(posx+x, y, posz);
glVertex3f(posx+x, 0f, posz);
}
else{
glBegin(GL_QUADS);
glVertex3f(posx, 0f, posz);
glVertex3f(posx, y, posz);
glVertex3f(posx+x/3, y, posz);
glVertex3f(posx+x/3, 0, posz);
glEnd();
glBegin(GL_QUADS);
glVertex3f(posx+x/3, y, posz);
glVertex3f(posx+2*x/3, y, posz);
glVertex3f(posx+2*x/3, 3*y/4, posz);
glVertex3f(posx+x/3, 3*y/4, posz);
glEnd();
glBegin(GL_QUADS);
glVertex3f(posx+2*x/3, y, posz);
glVertex3f(posx+x, y, posz);
glVertex3f(posx+x, 0, posz);
glVertex3f(posx+2*x/3, 0, posz);
}
glEnd();
}
What is the easiest way to draw an image on the wall?
After a lot of searching, I finally found the answer. This works in 3d space. I hope this helps someone out there!
public void drawLetterOnZYWall(Texture letter,zyWall wall) {
glBindTexture(GL_TEXTURE_2D, letter.getTextureID());
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(1, 0);
glVertex3f(wall.getPosX()+0.01f, WALL_HEIGHT, wall.getPosZ());
glTexCoord2f(0, 0);
glVertex3f(wall.getPosX()+0.01f, WALL_HEIGHT, wall.getPosZ() + wall.getWidth()/10);
glTexCoord2f(0, 1);
glVertex3f(wall.getPosX()+0.01f, (float)WALL_HEIGHT*((float)8/(float)10), wall.getPosZ() + wall.getWidth()/10);
glTexCoord2f(1, 1);
glVertex3f(wall.getPosX()+0.01f, (float)WALL_HEIGHT*((float)8/(float)10), wall.getPosZ());
glTexCoord2f(1, 0);
glVertex3f(wall.getPosX()-0.01f, WALL_HEIGHT, wall.getPosZ());
glTexCoord2f(0, 0);
glVertex3f(wall.getPosX()-0.01f, WALL_HEIGHT, wall.getPosZ() + wall.getWidth()/10);
glTexCoord2f(0, 1);
glVertex3f(wall.getPosX() - 0.01f, (float)WALL_HEIGHT*((float)8/(float)10), wall.getPosZ() + wall.getWidth()/10);
glTexCoord2f(1, 1);
glVertex3f(wall.getPosX()-0.01f, (float)WALL_HEIGHT*((float)8/(float)10), wall.getPosZ());
glEnd();
glDisable(GL_TEXTURE_2D);
}
For some reason I cannot fo the life of me figuire out what i'm doing wrong here. I am tring to render a 2d orthographic hud ontop of my 3d stuff which is rendered via shaders not draw calls. I've spent almost 8 hours and well I suck, please help. There are no errors in the console!
EngineWindow.bindAsRenderTarget(); //Set render target to display.
glDepthMask(false);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_CLAMP);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
System.out.println(this.x + " " + this.y + " " + this.width + " " + this.height); //Its at the right position too.
GL13.glActiveTexture(GL13.GL_TEXTURE0);
texture.bind(); //Binds blue texture with writing.
glBegin(GL_QUADS);
glVertex2i(x, y);
glTexCoord2f(0f, 0f);
glVertex2i(x, y+height);
glTexCoord2f(0f, 1f);
glVertex2i(x+width, y+height);
glTexCoord2f(1f, 1f);
glVertex2i(x+width, y);
glTexCoord2f(1f, 0f);
glEnd();
glPopMatrix();
glDepthFunc(GL_LESS);
glDepthMask(true);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glDisable(GL_BLEND);
glEnable(GL_DEPTH_CLAMP);
First, I'll start with my code because I've identified which block is causing the issue.
// init
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 800, 0, 600, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glEnable(GL11.GL_TEXTURE_2D);
// BEGINNING OF OFFENDING CODE
BufferedImage image = ImageIO.read(new File("res/button.png"));
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
IntBuffer buffer = BufferUtils.createIntBuffer(pixels.length);
for (int pixel : pixels)
buffer.put(pixel);
buffer.flip();
int button = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, button);
//Setup wrap mode
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
// END OF OFFENDING CODE
This is what things are supposed to look like without the textured quad.
This is what happens when I render with the offending code (with the textured quad).
This is what happens when I render with the offending code (without the textured quad).
For reference, this is the texture
I can't seem to figure out which GL11 call is affecting the rest of the Display and why it would be affecting the rest of the display. From what I understand, all of the calls that follow GL11.glBindTexture are limited to the bound texture, aren't they?
Edit: Additional Rendering Code
private static void renderQuad(int x, int y, int width, int height) {
GL11.glPushMatrix();
GL11.glBegin(GL11.GL_QUADS);
GL11.glVertex2f(x, y);
GL11.glVertex2f(x + width, y);
GL11.glVertex2f(x + width, y + height);
GL11.glVertex2f(x, y + height);
GL11.glEnd();
GL11.glPopMatrix();
}
The method used for the red quads.
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glColor3f(0.5f,0.5f,1.0f);
renderQuad(0, 0, 800, 600);
// render action bar
GL11.glColor3f(0.2f,0.2f,1.0f);
renderQuad(0, 0, 800, 200);
GL11.glColor3f(1.0f,0.0f,0.0f);
renderQuad(50, 50, 100, 60);
renderQuad(200, 50, 100, 60);
// render textured quad
GL11.glPushMatrix();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, button);
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2d(0.0,1.0);
GL11.glVertex2f(x, y);
GL11.glTexCoord2d(1.0,1.0);
GL11.glVertex2f(x + width, y);
GL11.glTexCoord2d(1.0,0.0);
GL11.glVertex2f(x + width, y + height);
GL11.glTexCoord2d(0.0,0.0);
GL11.glVertex2f(x, y + height);
GL11.glEnd();
GL11.glPopMatrix();
First of all, I think there's a problem with your texture loading. I believe the order of the bytes is reversed or something similar, which is why you get the red on black. Here's a working load-texture-from-BufferedImage example taken from my own code:
BufferedImage image = ImageIO.read(new File("<file path>.png"));
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 4);
for(int y = 0; y < image.getHeight(); y++){
for(int x = 0; x < image.getWidth(); x++){
int pixel = pixels[y * image.getWidth() + x];
buffer.put((byte) ((pixel >> 16) & 0xFF)); // Red component
buffer.put((byte) ((pixel >> 8) & 0xFF)); // Green component
buffer.put((byte) (pixel & 0xFF)); // Blue component
buffer.put((byte) ((pixel >> 24) & 0xFF)); // Alpha component. Only for RGBA
}
}
buffer.flip(); //FOR THE LOVE OF GOD DO NOT FORGET THIS
// You now have a ByteBuffer filled with the color data of each pixel.
// Now just create a texture ID and bind it. Then you can load it using
// whatever OpenGL method you want, for example:
int textureID = GL11.glGenTextures(); //Generate texture ID
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID); //Bind texture ID
//Setup wrap mode
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
//Setup texture scaling filtering
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
//Send texel data to OpenGL
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
Now, to the actual rendering problem:
For OpenGL, GL_TEXTURE_2D must be enabled or disabled depending on whether or not the polygon you are drawing is textured. If you do not supply texture coordinates for each vertex, then the last texture coords call still holds and is used for each vertex. So, you'll get a quad using one pixel's worth of texture. This is what's causing the black quads - it's taking from one pixel from a corner of your improperly loaded texture. So, your fixed rendering code:
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glColor3f(0.5f,0.5f,1.0f);
renderQuad(0, 0, 800, 600);
// render action bar
GL11.glColor3f(0.2f,0.2f,1.0f);
renderQuad(0, 0, 800, 200);
GL11.glColor3f(1.0f,0.0f,0.0f);
renderQuad(50, 50, 100, 60);
renderQuad(200, 50, 100, 60);
GL11.glEnable(GL11.GL_TEXTURE_2D);
// render textured quad
GL11.glColor3f(1.0f, 1.0f, 1.0f);
GL11.glPushMatrix();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, button);
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2d(0.0,1.0);
GL11.glVertex2f(x, y);
GL11.glTexCoord2d(1.0,1.0);
GL11.glVertex2f(x + width, y);
GL11.glTexCoord2d(1.0,0.0);
GL11.glVertex2f(x + width, y + height);
GL11.glTexCoord2d(0.0,0.0);
GL11.glVertex2f(x, y + height);
GL11.glEnd();
GL11.glPopMatrix();
On a side note, you can use simply glEnable() instead of GL11.glEnable() if you do:
import static org.lwjgl.opengl.GL11.*;
instead of simply
import org.lwjgl.opengl.GL11;