I'm creating an app that only runs in landscape mode. I'm trying to create a background using a textured quad although I'm not going to worry about texturing yet. I've been trying to simply draw a quad that fills the screen from drawOverlay(GL10 gl) with GL_DEPTH_TEST disabled but whenever I do that the quad does not completely fill the screen and I can see bars of the glClearColor on the bottom and top of the screen.
Unable to draw it using the modelview matrix I was using for all the other objects, I tried to draw it using gluOrtho2D and glOrthof but neither of them worked. I don't really understand how the near and far clipping plane work with orthographic drawing. Whenever I tried to draw it using glOrtho2D or glOrthof, the quad wasn't drawn at all(although the rest of the scene was still rendered).
Here is my attempt at drawing using an orthographic matrix
private void drawOverlay(GL10 gl) {
gl.glDisable(GL10.GL_DEPTH_TEST);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
GLU.gluOrtho2D(gl, 0f, 1f, 1f, 0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
background.draw(gl, 1.0f, 1.0f, 1.0f, 1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glPopMatrix();
gl.glMatrixMode(GL10.GL_MODELVIEW);
}
I call that function from the beginning of onDrawFrame - before anything else is drawn:
public void onDrawFrame(GL10 gl) {
drawOverlay(gl);
gl.glLoadIdentity
//...
}
Here is how "background" is created:
background = new ShapePostcard(1f, 1f);
I'm fairly certain I'm not going to be able to get the quad to cover the screen using the normal modelview matrix, but basically all I was doing was drawing "background" in onDrawFrame before everything else with depth testing disabled.
Thanks for any support!
The easiest way to draw a quad that fills the screen is to set both the projection and model to an identity matrix, and then draw a mesh with coordinates [-1,-1] to [1,1]. Was it this what you were drawing when you saw the borders?
I mean,
(x, y, widht, height) = (-1,-1, 2, 2)
OpenGL ES does not support quads.
http://www.songho.ca/opengl/gl_vertexarray.html
Related
I'm trying to recreate a shadow effect on some 2D sprites in a project using Slick. To do this, I'm recolouring a copy of the sprite and stretching it using Slick OpenGL using this method:
public static void getStretched(Shape shape, Image image) {
TextureImpl.bindNone();
image.getTexture().bind();
SGL GL = Renderer.get();
GL.glEnable(SGL.GL_TEXTURE_2D);
GL.glBegin(SGL.GL_QUADS);
//topleft
GL.glTexCoord2f(0f, 0f);
GL.glVertex2f(shape.getPoints()[0], shape.getPoints()[1]);
//topright
GL.glTexCoord2f(0.5f, 0f);
GL.glVertex2f(shape.getPoints()[2], shape.getPoints()[3]);
//bottom right
GL.glTexCoord2f(1f, 1f);
GL.glVertex2f(shape.getPoints()[4], shape.getPoints()[5]);
//btoom left
GL.glTexCoord2f(0.5f, 1f);
GL.glVertex2f(shape.getPoints()[6], shape.getPoints()[7]);
GL.glEnd();
GL.glDisable(SGL.GL_TEXTURE_2D);
TextureImpl.bindNone();
}
This gives the almost the desired effect, aside from the fact that the image is cropped a bit.
This becomes more extreme for higher distortions
I'm new to using OpenGL, so some help regarding how to fix this would be great.
Furthermore, if I feed an image into the method that was obtained using getSubImage, OpenGL renders the original image, rather than the sub image.
I'm unsure as to why this happens, as the sprite itself is taken from a spritesheet using getSubImage and has no problem rendering.
Help would be greatly appreciated!
I'm recolouring a copy of the sprite and stretching it
The issue is that you stretch the texture coordinates, but the region which is covered by the sprite stays the same. If the shadow exceeds the the region which is covered by the quad primitive, then it is cropped.
You have to "stretch" the vertex coordinates rather than the texture coordinates. Define a rhombic geometry for the shadow and wrap the texture on it:
float distortionX = ...;
GL.glEnable(SGL.GL_TEXTURE_2D);
GL.glBegin(SGL.GL_QUADS);
//topleft
GL.glTexCoord2f(0f, 0f);
GL.glVertex2f(shape.getPoints()[0] + distortionX, shape.getPoints()[1]);
//topright
GL.glTexCoord2f(1f, 0f);
GL.glVertex2f(shape.getPoints()[2] + distortionX, shape.getPoints()[3]);
//bottom right
GL.glTexCoord2f(1f, 1f);
GL.glVertex2f(shape.getPoints()[4], shape.getPoints()[5]);
//btoom left
GL.glTexCoord2f(0f, 1f);
GL.glVertex2f(shape.getPoints()[6], shape.getPoints()[7]);
GL.glEnd();
[...] if I feed an image into the method that was obtained using getSubImage, [...] the sprite itself is taken from a spritesheet [...]
The sprite is covers just a small rectangular region of the entire texture. This region is defined by the texture coordinates. You have to use the same texture coordinates as when you draw the sprite itself.
I want to apply a shader to the whole screen using GLSL in my libGDX game.
To clear the background with a color, I'm using
Gdx.gl.glClearColor(color.r, color.g, color.b, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
However, when I apply my shader to the stage's spritebatch:
stage.getBatch().setShader(shader);
... the shader only applies to drawn sprites of the stage, not the whole screen.
I'm using a shader which turns affected pixels red, just for clarity:
How do I apply my shader to the whole screen?
I figured it out: shaders only apply to rendered textures rendering.
My background drawing code is now the following:
Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(background, 0, 0, width, height);
batch.end();
The variable background is a 2x2 texture which will fill the whole background.
I need someone to help me with this. I can't really figure out how the alpha channel or blending works. The Image is in .bmp format, it loads perfectly.
But I want a specific color to be transparent, in paint that color is R255xG0xB255.
I've been searching for similar topics, but everything I found or tried just seems to mess stuff up, like give me a full black screen or make everything have a magenta touch...
Everything else works just fine with my code... Should I maybe switch to .png? could that solve the issue? does it have any pros or cons if I use png or bmp?
// Initialization Code OpenGL
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, HEIGHT, WIDTH, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glClearColor(1.0f, 0.0f, 1.0f, 0.0f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
while (!Display.isCloseRequested()) {
// Render
glClear(GL_COLOR_BUFFER_BIT);
this.drawMapToScreen();
this.drawCreatureToScreen();
Display.update();
Display.sync(60);
}
Display.destroy();
}
private void drawCreatureToScreen() {
Texture tex3 = SpriteLoader.loadTexture("player");
Color.magenta.bind();
tex3.bind();
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2i((HEIGHT-32)/2,(WIDTH-32)/2);
glTexCoord2f(1, 0);
glVertex2i((HEIGHT-32)/2 +32,(WIDTH-32)/2);
glTexCoord2f(1, 1);
glVertex2i((HEIGHT-32)/2 +32,(WIDTH-32)/2 +32);
glTexCoord2f(0, 1);
glVertex2i((HEIGHT-32)/2,(WIDTH-32)/2 +32);
glEnd();
}
What are looking to do is that when your color is 1.0f, 0.0f, 1.0f (in the eyes of OpenGL: full red, no green, full blue) have the alpha (transparency) channel be zero, so that the pixel is drawn completely transparent. Unfortunately, there is no way to do this in OpenGL, unless you use shaders, and believe me using shaders is far messier than the solution I propose: doing "pre-multiplied alpha" in your image editor. What this means: it doesn't depend on which format you use - .png or .bmp are both fine, and they both support an alpha channel. Alpha is transparency; in OpenGL, you'll be dealing with floats a lot, so I'll use floats here. Alpha is the fourth color channel; we have Red, Green, Blue, and then Alpha. Alpha controls transparency (as a float) by being multiplied by the other channels: if alpha is 0.0f, then that color is fully transparent, but if alpha is 1.0f, it is fully opaque. To sum up: In your editor, you must make sure that the area you want transparent is transparent in the editor. For alpha blending, which still must be enabled for any transparency whatsoever: the generally preferred blend mode is as follows:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Now, blending is a technique for making objects appear transparent, among other things. In your case, you'll want to use the blend function above: use glDisable(GL_BLEND) to disable blending from occurring after enabling it. The blend function above essentially mixes the preexisting colors and colors to be rendered in such a way that an object rendered overlapping another, after said other, makes it appear that the "top" and most recently rendered object is transparent relative to the "bottom" object.
TL;DR:
Make sure the area you want transparent is transparent in your image editor. OpenGL cannot make specific colors have alpha values of 0.0f unless you use a needlessly complex shader.
Use the blending setup glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); to enable blending. Make sure the top object is rendered after the bottom object.
I initialize OpenGL like so to make transparent textures transparent:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
I draw my texture like this:
glPushMatrix();
//translate
//neutralize colors
//bind texture
//vertex points
glPopMatrix();
But when I try to draw a quad immediately afterwards, it won't show up:
glPushMatrix();
{
glTranslatef(x, y, 0);
glColor3f(1f, 0f, 0f);
glBegin(GL_QUADS);
{
glVertex2f(0, 0);
glVertex2f(10, 0);
glVertex2f(10, 10);
glVertex2f(0, 10);
}
glEnd();
}
glPopMatrix();
If I remove the initialization above, the quad appears, but then my texture is no longer transparent.
What am I doing wrong here?
Edit: Should I call glDisable(GL_BLEND); whenever I want to draw something that is not a texture?
You need to disable blending before drawing your quad.
EDIT: Can you post more code? The problem may be somewhere else, for example if you have not disabled the texture before drawing the quads.
There's no need to disable blending when drawing.
I call glBlendFunc(GL_SRC_ALPHA, GL_ONE) when I need to draw transparent cubes (with texture).
I usually disable DEPTH test upon drawing with blend mode enabled:
glEnable(GL_BLEND); // Turn Blending On
glDisable(GL_DEPTH_TEST); // Turn Depth Testing Off
NeHe has a nice tutorial on blending.
Basically, I am trying to let openGL draw a bunch of quads. Each of these quads has different colours. Now my problem is that when I call glColor4f(), the colour is not applied on the material. I found out that that was because I had been using textures somewhere else in the rendering process, so I disabled that. Still, not result. After some googling I came across glColorMaterial(), which did display the quads correctly, but because I used glColour4f() to colour each of the quads, each of the 3D textures objects on the stage were tinted. So now I am a bit stuck; I want to have lighting enabled on my 3D objects, yet those few quads should just be drawn in a flat colour, without any lighting whatsoever. What is the openGL method of doing this?
My openGL context setup:
glViewport(0, 0, dim.width, dim.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, (float)(dim.width/dim.height), 0.1f, 10000.0f);
glMatrixMode(GL_MODELVIEW);
glClearColor(94.0f/255.0f, 161.0f/255.0f, 255.0f/255.0f, 0.5f);
glClearDepth(1.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_CULL_FACE);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT1);
glEnable(GL_TEXTURE_2D);
As Platinum Azure said, you need to disable lighting and texturing right before drawing your quads, and then turn it back on afterwards. Like this:
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
// Draw quads
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
You should be fine to just use glColorf as usual (you don't need glColorMaterial).