I'm using OpenGL in Java and I've been trying to draw something on the back buffer, copy it onto a texture, and then draw the texture on to the screen.
This is the code I use to do the copying.
int textureNumber = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureNumber);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_REPLACE);
GL11.glCopyTexImage2D
(
GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA,
0, 0,
NewMath.roundUpTwo(width), NewMath.roundUpTwo(height),
0
);
(The roundUpTwo method just rounds the width and height up to the nearest power of 2.)
Now the problem here is that when I re-draw the texture to the screen, it comes out differently than the way it rendered to the backbuffer.
I don't have enough rep to post images directly <_< so here's a screenshot of the behavior.
Note that the top-left is what happens when I render directly to the screen, the lower-right is what happens when I copy it to a texture and then render the texture.
What I think is happening is that the object I am drawing is made up of a lot of triangles drawn with alpha transparency and with a blending function, and that the CopyTexImage2D function isn't preserving that. I'm not totally sure though because really I have no idea what is happening here.
Is that's what the problem is, how do I fix it? And if it's not, what is and how do I fix it?
am drawing is made up of a lot of triangles drawn with alpha transparency… and … CopyTexImage2D function isn't preserving that
That's not how it works. Once a picture is drawn, no matter to which framebuffer, all that remains are pixels' values. The geometry used doesn't matter from there on.
The most likely problem is, that you're rendering that texture with the state of the previous drawing steps still enabled and those are "bleeding" through. Hard to tell without seeing the source code you use for drawing of all the different stages, though. I suggest you edit your question, adding that code.
Related
I apologize for some of my ignorance as I am fairly new to Slick2D and LWJGL. Essentially what I'm trying to do is make a scene look like night time by covering it with a GL_QUADS rectangle that is tinted blue and is translucent.
That part is easy enough. What I want to do from there is draw triangles into this layer that vary the alpha channel so. The reason I want to do this is so I can simulate a light source by decreasing the opacity of the blue tinted rectangle as it gets closer to the light source.
I drew an example of what the expected result should be with the green being the background, the blue being the nighttime effect created by a blue tinted rectangle, and the increasingly dim light source in the center.
I need to find a way to do this with triangles because I created a raycasting algorithm that generates the result as a series of gradient triangles.
I apologize if this is explained poorly. I will answer any questions you might have.
Here is the chunk of code used to create the blue tinted rectangle:
glColor4f (0.0f,0.0f,1.0f,0.4f);
glBegin(GL_QUADS);
glVertex2f(0,0);
glVertex2f(screenWidth,0);
glVertex2f(screenWidth,screenHeight);
glVertex2f(0,screenHeight);
glEnd();
I would like to write a modified version of the following code to adjusted the alpha channel of that rectangle.
glBegin(GL_TRIANGLES);
setAlphaOfPriorLayer(0.0f);
glVertex2f(x1,y1);
setAlphaOfPriorLayer(0.4f);
glVertex2f(x2,y2);
setAlphaOfPriorLayer(0.4f);
glVertex2f(x3,y3);
glEnd();
Again, I'm using triangles to approximate a circle and allow for proper raycasting.
To achieve this, the use of a Frame Buffer Object is super useful. A FBO allows you to essentially render to a texture which can then be displayed on the screen. In my particular case, I rendered the elements to a FBO then used a shader while drawing it to the screen to get the desired opacities.
I'm working on a scroll-box in minecraft.
The scroll-box has one problem, some controls will render outside of the box, so i decided to look up if it's possible to prevent that.
I found stencils, but it doesn't work out, maybe i did something wrong?
GL11.glEnable(GL11.GL_BLEND);
GL11.glEnable(GL11.GL_STENCIL_TEST);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glClearStencil(0);
GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 1);
GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
and this is the line of rendering the scroll-box background:
Vector4d color = new Vector4d(140, 140, 140, 255);
RenderHelper2D.drawGradientRect(1, 1, this.width-1, this.height-1, color, color);
http://i.imgur.com/Ycg7AKo.png (It's the black outlined gray pattern)
GL11.glBlendFunc(GL11.GL_ONE_MINUS_DST_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glStencilFunc(GL11.GL_EQUAL, 1, 1);
GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP );
render all objectives inside the scroll-box (the buttons). Which shouldn't be shown outside of the box.
gui.drawForeground(renderer);
and reset everything
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glColorMask(true, true, true, true);
GL11.glDisable(GL11.GL_STENCIL_TEST);
I think you are looking for glScissor
It lets you basically assign a rectangular cropping window on your screen, and whatever you draw, nothing will ever be drawn outside of this rectangle.
Don't forget to call glEnable(GL_SCISSOR_TEST) before and glDisable(GL_SCISSOR_TEST) after you draw your scroll box. It won't work without the enable, and it won't stop without the disable ;)
Keep in mind that the values supplied to glScissor are integers for the origin and the width and height of the desired cropping window, the origin being defined as the lower left. Thus,
glEnable(GL_SCISSOR_TEST)
glScissor(0,0,100,100)
:: DRAW YOUR CONTROLS HERE ::
glDisable(GL_SCISSOR_TEST)
will create a 100x100 cropping window in the lower left corner of your screen.
You can use stencilbuffers if you want, but those are for more complicated tasks. Since UI usually works with rectangles, glScissor is perfect for it.
I was trying to follow example codes to simply display a rectangle on a black background, but it didn't seem to be displaying. What I did was
private static void initGL(){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,Display.getWidth(),0,Display.getHeight(),-1,1);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST); //2D mode
glColor3f(0.5f, 0.0f, 1.0f);
glBegin(GL_QUADS);
glVertex2f(-0.75, 0.75);
glVertex2f(-0.75, -0.75);
glVertex2f(0.75, -0.75);
glVertex2f(0.75, 0.75);
glEnd();
}
It doesn't display anything on the screen except for a black background. Does anyone know what I might have done wrong? I'm using lwjgl in eclipse.
First things first: You only have to run the whole
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,Display.getWidth(),0,Display.getHeight(),-1,1);
glMatrixMode(GL_MODELVIEW);
thing once during your program, probably shortly after you run Display.create().
Also, you're tessellating using the wrong vertices. You wrote
glVertex2f(-0.75, 0.75);
glVertex2f(-0.75, -0.75);
glVertex2f(0.75, -0.75);
glVertex2f(0.75, 0.75);
which means draw a rectangle from (-0.75, -0.75) pixels to (0.75, 0.75) pixels. This is too small to be noticed. My guess is you assumed glVertex2f deals with fractions of the display width. It does not. glVertex2f deals with actual coordinates, it just allows fractional pixels, unlike glVertex2i (this is useful believe it or not, it helps with smoother animations). Something like
glVertex2f(100F, 100F);
places a vertex at (100, 100), and is effectively equivalent to
glVertex2i(100, 100);
Also, remember that negative pixels will be rendered off the screen, because OpenGL's origin of the coordinate system, (0, 0), is in the lower left and behaves like the first quadrant from the coordinate system in math class, not like the traditional computer coordinate system with (0, 0) in the upper left.
As for the the black background, LWJGL's Display has a black background by default, so it's recommended to draw a quad with your background color that covers the entire display width and height. One quad won't really affect your performance.
glVertex2f uses same size units as your glOrtho so unless your display width and height are in units of ones, like 10 or less, you may not see anything!
I'm making a game in lwjgl (java opengl) which contains a mesh of textured cubes within it.
I have already fixed the common error of texture coordinates being inaccurate on the edges, my coordinates are 100% accurate.
While moving through the scene, the pixels on the edges of my bright red quads flash teal(which happens to be my clear color) at overlaps with green quads only for a very short moment. There are definately other quads behind the overlaps colored green.
The problem is only with the near and far sides of the top of the cube.
Before you ask, there are NO blue pixels in my texture.
My min/mag filters fixed a brown line at the overlaps of green. but I think this could be part of the problem.
How can I get these pixels to either stay red, or go green?
Or to be more specific, how can I make the blend only use the nearest color and not do any combining?
Here are my params:
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_ALPHA_TEST);
GL11.glAlphaFunc(GL11.GL_GREATER, (float) 0.9);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glColor4f(255, 255, 255, 1.0f);
GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
GL11.glTexParameterf( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
Wow, solved. From looking at screenshots, it's actually my eyes tricking me with teal phantoms, as the borders flash from red to white as the screen moves and the pixel estimation changes. Stare at red long enough, close your eyes, and you'll see teal. I'll be looking up some anti-aliasing guides or changing my filter to blend the colors.
I'm trying to render a colored cube after rendering other cubes that have textures. I have multiple "Drawer" objects that conform to the Drawer interface, and I pass each a reference to the GL object to the draw( final GL gl ) method of each individual implementing class. However, no matter what I do, I seem unable to render a colored cube.
Code sample:
gl.glDisable(GL.GL_TEXTURE_2D);
gl.glColor3f( 1f, 0f, 0f );
gl.glBegin(GL.GL_QUADS);
// Front Face
Point3f point = player.getPosition();
gl.glNormal3f(0.0f, 0.0f, 1.0f);
//gl.glTexCoord2f(0.0f, 0.0f);
gl.glVertex3f(-point.x - 1.0f, -1.0f, -point.z + 1.0f);
//gl.glTexCoord2f(1.0f, 0.0f);
gl.glVertex3f(-point.x + 1.0f, -1.0f, -point.z + 1.0f);
//continue rendering rest of cube. ...
gl.glEnd();
gl.glEnable(GL.GL_TEXTURE_2D);
I've also tried throwing the glColor3f calls before each vertex call, but that still gives me a white cube. What's up?
There are a few things you need to make sure you do.
First off:
gl.glEnable(gl.GL_COLOR_MATERIAL);
This will let you apply colors to your vertices. (Do this before your calls to glColor3f.)
If this still does not resolve the problem, ensure that you are using blending properly (if you're using blending at all.)
For most applications, you'll probably want to use
gl.glEnable(gl.GL_BLEND);
gl.glBlendFunc(gl.GL_SRC_ALPHA,gl.GL_ONE_MINUS_SRC_ALPHA);
If neither of these things solve your problem, you might have to give us some more information about what you're doing/setting up prior to this section of your code.
If lighting is enabled, color comes from the material, not the glColor vertex colors. If your draw function that you mentioned is setting a material for the textured objects (and a white material under the texture would be common) then the rest of the cubes would be white. Using GL_COLOR_MATERIAL sets up OpenGL to take the glColor commands and update the material instead of just the vertex color, so that should work.
So, simply put, if you have lighting enabled, try GL_COLOR_MATERIAL.
One thing you might want to try is: glBindTexture(GL_TEXTURE_2D, 0); to bind the texture to nil.
Some things to check:
Is there a shader active?
Any gl-errors?
What other states did you change? For example GL_COLOR_MATERIAL, blending or lighting will change the appearance of your geometry.
Does it work if you draw the non-textured cube first? And if it does try to figure out at which point it turns white. It's also possible that the cube will only show up in the correct color in the first frame, then there's definitely a GL state involved.
Placing glPushAttrib/glPopAttrib at the beginning/end of your drawing methods might help, but it's better to figure out what caused the problem in the first place.