I have the code for a room provided to me, I need to add a sphere in the room. It goes like this:
PushMatrix();
//draw floor,walls,ceilings
PushMatrix();
//draw some boxes on front wall
PopMatrix();
PushMatrix();
//drawing sphere;
glLoadIdentity();
glColor3f(1, 0, 0);
glTranslatef(0, ypos, 0);
glutSolidSphere(2, 20, 20);
PopMatrix();
PopMatrix();
But all the walls etc turn red (and no sphere) when I do this. Why does that happen even after pushing another matrix?
Calling glColor*() sets the current color. This color doesn't change before you call glColor*() again. In other words glPushMatrix() and glPopMatrix() has no effect on the current color.
Thus if you in //draw some boxes on front wall don't call glColor*(). Then due to you setting the color to red by calling glColor3f(1, 0, 0) then everything is going to be red from that point on.
Considering:
glMatrixMode(GL_PROJECTION);
gluPerspective(40, 1, 1, 40);
glMatrixMode(GL_MODELVIEW);
Then:
glPushMatrix();
glTranslatef(0, 0, -10);
glColor3f(1, 0, 0);
glutSolidSphere(2, 20, 20);
glPopMatrix();
By doing the above you should see a sphere.
Thus if you before didn't see the sphere at all. Then it's probably due to ypos being outside your view. If you were referring to the whole screen being red, then I'm assuming ypos to be around 0, which means that it would be filling the whole screen (Again assuming you don't translate the view in any other way).
I'm trying to render self-transparent textures to the framebuffer, but I'm getting not what I guessed: everything previously rendered on the framebuffer gets ignored, and this texture blends with the colour I cleaned my main canvas.
That's what I would like to get, but without using framebuffers:
package test;
import com.badlogic.gdx.*;
import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.*;
public class GdxTest extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
#Override
public void create () {
batch = new SpriteBatch();
Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
pixmap.setColor(1, 1, 1, 1);
pixmap.fillRectangle(0, 0, 1, 1);
// Generating a simple 1x1 white texture
img = new Texture(pixmap);
pixmap.dispose();
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.setColor(1, 1, 1, 1);
batch.draw(img, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.setColor(0, 0, 0, 0.5f);
batch.draw(img, 0, 0, 300, 300);
batch.end();
}
}
And it works as perfectly as it should do:
http://i.stack.imgur.com/wpFNg.png
And that's what I get with using of framebuffer (I can't understand why the second rendered texture doesn't blend with the previous one, as it do without framebuffer):
package test;
import com.badlogic.gdx.*;
import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.*;
import com.badlogic.gdx.graphics.glutils.*;
public class GdxTest extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
FrameBuffer buffer;
TextureRegion region;
#Override
public void create () {
batch = new SpriteBatch();
Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
pixmap.setColor(1, 1, 1, 1);
pixmap.fillRectangle(0, 0, 1, 1);
// Generating a simple 1x1 white texture
img = new Texture(pixmap);
pixmap.dispose();
// Generating a framebuffer
buffer = new FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
region = new TextureRegion(buffer.getColorBufferTexture());
region.flip(false, true);
}
#Override
public void render () {
// Filling with red shows the problem
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
buffer.begin();
batch.begin();
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setColor(1, 1, 1, 1);
batch.draw(img, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.setColor(0, 0, 0, 0.5f);
batch.draw(img, 0, 0, 300, 300);
batch.end();
buffer.end();
batch.begin();
batch.setColor(1, 1, 1, 1);
batch.draw(region, 0, 0);
batch.end();
}
}
And an unpredictable result:
http://i.stack.imgur.com/UdDKD.png
So how could I make the framebuffer version work the way the first version does? ;)
The easy answer is to disable blending when rendering to the screen.
But I think it is good to understand why this is happening if you want to use FBO. So let's walk through what's actually going on.
First make sure to understand what the color of the texture and the color of the batch (the vertex color) does: they are multiplied. So when setting the batch color to 0,0,0,0.5 and the texture pixel (texel) is 1,1,1,1 this will result in a value of 1*0,1*0,1*0,1*0.5 = 0,0,0,0.5.
Next make sure to understand how blending works. Blending is enabled by default and will use the SRC_ALPHA and ONE_MINUS_SRC_ALPHA functions. This means that the source value (the texel) is multiplied by the source alpha and that the destination value (the screen pixel) is multiplied by one minus the source alpha. So if your screen pixel has the value 1,1,1,1 and your texel has the value 0,0,0,0.5 then the screen pixel will be set to:(0.5*0, 0.5*0, 0.5*0, 0.5*0.5) + ((1-0.5)*1, (1-0.5)*1, (1-0.5)*1, (1-0.5)*1) which is (0,0,0,0.25) + (0.5, 0.5, 0.5, 0.5) = (0.5, 0.5, 0.5, 0.75).
So let's see how that works for you in your first code:
You clear the screen with 1, 0, 0, 1, in other words: every pixel of the screen contains the value 1, 0, 0, 1.
Then you render a full rectangle with each texel value 1,1,1,1, every pixel of the screen now contains the value 1, 1, 1, 1.
Then you render a smaller rectangle with each texel value 0,0,0,0.5, every pixel on that part of the screen now contains the value 0.5, 0.5, 0.5, 0.75.
Got a feeling about the issue already? Let's see what happens in your second code:
You clear the screen with 1, 0, 0, 1: every pixel of the screen contains the value 1, 0, 0, 1.
You bind the FBO and clear it with 1, 1, 1, 1: every pixel of the FBO contains the value 1, 1, 1, 1.
You render a full rectangle with each texel value 1,1,1,1 to the FBO: every pixel of the FBO now contains the value 1,1,1,1.
You render a smaller rectangle with each texel value 0,0,0,0.5, every pixel on that part of the FBO now contains the value 0.5, 0.5, 0.5, 0.75.
Then you bind the screen again as the render target of which each pixel still contains the value 1, 0, 0, 1.
Finally you render the FBO texture as full rectangle to the screen, causing these texels to be blended with the screen pixels. For the smaller rectangle this means blending 0.5, 0.5, 0.5, 0.75 multiplied by 0.75 and 1, 0, 0, 1 multiplied by 1-0.75=0.25, which will result in 0.375, 0.375, 0.375, 0.5625 and 0.25, 0, 0, 0.25. So the final color is 0.625, 0.375, 0.375, 0,8125
Make sure to understand this process, otherwise it can cause quite some frustrating weird issues. If you find it hard to follow then you could take pen and paper and manually calculate the value for each step.
I am going to make a adventure game in 2D with Grass,Trees and other things if i can make these. My problem is that when i use glTexCoord2f to clamp the texture to a quad then they get seperated from each others about 25 pixels. These quads is supposed to be connected together like any 2D games.
Im loading them with SlickUtil and the size of the Texture is 100x100
Here's my source code for rendering quads and InitGL
public static void Render(){
example--;
GL11.glLoadIdentity();
Color.white.bind();
system.Game.ground.bind();
GL11.glTranslatef(example, 0, 0);
//I used for loop for cloning quad at each side.
for(int x = 0; x <= width; x++){
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(x * 100, 0);
GL11.glTexCoord2f(1, 0);
GL11.glVertex2f(x * 100 + 100, 0);
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(x * 100 + 100, 100);
GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(x * 100, 100);
GL11.glEnd();
}
GL11.glLoadIdentity();
}
Heres my InitGL Code.
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glViewport(0,0,width,height);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, width, height, 0, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
SlickUtil only reads Textures with dimensions that are powers of two. The reason is, that only since OpenGL 2.0, OpenGL could read textures with non-power-of-two dimensions. Try loading a texture with the dimensions of 128 by 128 pixels. Then display it with 100 by 100 pixels (like you did in your example).
I mapped texture coordinates like:
static float texCoord[] = {
0, 1,
1, 1,
1, 0,
0, 0
};
And by drawing it:
void Rectangle::Draw()
{
const float vertices[] = {
x, y,
x + width, y,
x, y - height,
x + width, y - height
};
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glColor3ub(255, 255, 255);
glVertexPointer(2, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 2, texCoord);
if (IsTypeHorizontal()) glBindTexture(GL_TEXTURE_2D, texture_H);
else /* (IsTypeVertical())*/ glBindTexture(GL_TEXTURE_2D, texture_V);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
Texture drawn in vertical (height > width) is good but in horizontal (height < width), texture appears to be inverted. Even if I separate the texture coordinates by texCoord_H and texCoord_V, image drawn is still inverted?
What do I still need to know ? What is the problem here in my code?
PS. I upload texture in OpenGL using SOIL
Try:
static float texCoord[] = {
0, 1,
1, 1,
0, 0,
1, 0
};
Most OpenGL newbies get confused by the fact, that with the usual set of projection, transforms and viewport mapping parameters OpenGL considers image origin to be in the lower left and coordinates increating toward the right and up. This is in contrast to most computer graphics systems that assume the origin to be in the upper left and vertical dimension increasing downwards.
Probably that is your issue.
After many times of changing and swapping texture coordinates, I realize that I've wasted my time. The real problem is here
glTexCoordPointer(2, GL_FLOAT, 2, texCoord);
3rd parameter (w/c is the stride) 'causes the bug, it should be 0.
I have a texture drawn in a GLcontrol and I want to draw points on top of it. Instead, I get the full texture set to the colour of the point I want to draw. I guess that I have to disable the texture format and enable the points drawings, but cant reach the solution...
Here is the draw function:
Basically the point to draw is ROI[0], but instead drawing just the point I got the image shown below (the image is grayscale before drawing "the point").
private: void drawImg(int img){
int w=this->glControl_create_grid->Width;
int h=this->glControl_create_grid->Height;
GL::MatrixMode(MatrixMode::Projection);
GL::LoadIdentity();
GL::Ortho(0, w, 0, h, -1, 1); // Bottom-left corner pixel has coordinate (0, 0)
GL::Viewport(0, 0, w, h); // Use all of the glControl painting area
GL::Clear(ClearBufferMask::ColorBufferBit | ClearBufferMask::DepthBufferBit);
GL::ClearColor(Color::LightGray);
GL::MatrixMode(MatrixMode::Modelview);
GL::LoadIdentity();
GL::Enable(EnableCap::Texture2D);
GL::BindTexture(TextureTarget::Texture2D, img);
OpenTK::Graphics::OpenGL::ErrorCode error=GL::GetError();
GL::Begin(BeginMode::Quads);
GL::TexCoord2(0, 0);
GL::Vertex2(0 ,h);
GL::TexCoord2(1, 0);
GL::Vertex2(w, h);
GL::TexCoord2(1, 1);
GL::Vertex2(w, 0);
GL::TexCoord2(0, 1);
GL::Vertex2(0, 0);
GL::End();
GL::Disable(EnableCap::Texture2D);
if (ROI[0].x!=0||ROI[0].y!=0){
GL::Color3(Color::Red);
GL::Begin(BeginMode::Points);
GL::Vertex2(ROI[0].x,ROI[0].y);
GL::End();
}
}
What should I change in my code? I can't seem to achieve it....
I found the answer. It seems that the color also applies to textures when binding them so I just needed to add GL::Color3(Color::White) before drawing the texture.