I can't figure out why this:
glPushMatrix();
GL11.glBindTexture(this.target, this.textureID);
glColor3f(1, 1, 1);
glTranslated(posX, posY, 0);
glBegin(GL_QUADS);
{
glTexCoord2d(posXLeft, posYTop);
glVertex2d(0, 0);
glTexCoord2d(posXLeft, posYBottom);
glVertex2d(0, verH);
glTexCoord2d(posXRight, posYBottom);
glVertex2d(verW, verH);
glTexCoord2d(posXRight, posYTop);
glVertex2d(verW, 0);
}
glEnd();
glPopMatrix();
is working perfectly, where posX and posY are obviously the position in pixels, posXLeft etc is the ratio of the texture to show.
But this:
glPushMatrix();
GL11.glBindTexture(this.target, this.textureID);
glColor3f(1, 1, 1);
glTranslated(posX, posY, 0);
glBegin(GL_LINES);
{
glVertex2d(10, 10);
glVertex2d(800, 600);
}
glEnd();
glPopMatrix();
isn't. And it should be even easier to draw lines instead of a piece of a texture.
What I want to reach is to add some zig-zag lines on a texture to simulate cracks as it is damaged or broken, but I can't even draw a single line, so I am stuck here.
Any advice?
You still got texturing enabled in your line drawing code. But you don't specify texture coordinates, so you'll draw your line with a solid color as defined by texture at the currently set texture coordinate.
My suggestion: Disable texturing for drawing that line.
As said by datenwolf you have to disable the texturing, thes thing is that than you have to re-enable it, although you will have problems the next cycle of drawing if that property is not set correctly.
the solution is:
glPushMatrix();
GL11.glBindTexture(this.target, this.textureID);
glColor3f(1, 1, 1);
glDisable(GL_TEXTURE_2D);
glTranslated(posX, posY, 0);
glBegin(GL_LINES);
{
glVertex2d(10, 10);
glVertex2d(800, 600);
}
glEnd();
glEnable(GL_TEXTURE_2D);
glPopMatrix();
and that should solve your problem.
Related
I am programming a GUI framework in lwjgl (opengl for java). I've recently implemented rounded rectangles by rendering a couple of normal rectangles surrounded by circles. To render the circles I used GL11.GL_POINTS. I now reached the point, where I am trying to implement animations and for a window open animation, I decided to GL11.glScaled() it from small to normal. That works fine, but unfortunately my circles don't get resized.
I tried changing my GL_POINTS circle render method against a method that uses TRIANGLE_FANs and that worked fine. My problem there was, that the circles didn't look smooth and round at all and if I increase the rendered triangles it starts to lag very quick. Even though my computer isn't bad at all.
This is the code I've used to render circles with GL_POINTS.
GL11.glEnable(GL11.GL_POINT_SMOOTH);
GL11.glHint(GL11.GL_POINT_SMOOTH_HINT, GL11.GL_NICEST);
GL11.glPointSize(radius);
GL11.glBegin(GL11.GL_POINTS);
GL11.glVertex2d(x, y);
GL11.glEnd();
GL11.glDisable(GL11.GL_POINT_SMOOTH);
This is the code I've used to scale the circles
GL11.glPushMatrix();
GL11.glTranslated(x, y, 0);
GL11.glScaled(2.0f, 2.0f, 1);
GL11.glTranslated(-x, -y, 0);
render circles
GL11.glPopMatrix();
I expect the circles to scale accordingly to the number I've put into glScaled()
Currently they aren't rescaling at all, just rendered at their normal size.
Here's a demonstration of how to properly render a circle using triangle fans:
public void render() {
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
// Coordinate system starts out as screen space coordinates
glOrtho(0, 400, 300, 0, 1, -1);
glColor3d(1, 0.5, 0.5);
renderCircle(120, 120, 100);
glColor3d(0.5, 1, 0.5);
renderCircle(300, 200, 50);
glColor3d(0.5, 0.5, 1);
renderCircle(200, 250, 30);
}
private void renderCircle(double centerX, double centerY, double radius) {
glPushMatrix();
glTranslated(centerX, centerY, 0);
glScaled(radius, radius, 1);
// Another translation here would be wrong
renderUnitCircle();
glPopMatrix();
}
private void renderUnitCircle() {
glBegin(GL_TRIANGLE_FAN);
int numVertices = 100;
double angle = 2 * Math.PI / numVertices;
for (int i = 0; i < numVertices; ++i) {
glVertex2d(Math.cos(i*angle), Math.sin(i*angle));
}
glEnd();
}
Output image:
The GL_POINT_SIZE value is actually the size of the point in pixels onscreen, not current coordinate units. For that reason your circles were unaffected by GL_SCALE. That's one reason not to use GL_POINTS to render circles. The other (arguably more important) reason being that GL_POINT_SIZE is severely deprecated and unsupported in newer OpenGL profiles.
So, I wanted to program a simple game using lwjgl, however I encountered a problem even before the pre-pre-pre-alpha phase, right at the beginning.
As long as I don't have a texture for it, I wanted to draw the player just using a simple rectangle. However, my Code does nothing.
here's my openGL initialization Code:
glMatrixMode(GL_PROJECTION);
glOrtho(0, 640, 480, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
and here's the main loop:
while(!Display.isCloseRequested()) {
//Main loop
glClear(GL_COLOR_BUFFER_BIT);
player.update();
Display.update();
Display.sync(60);
}
Display.destroy();
System.exit(0);
The player.update() function checks for Input and calls the draw function, which looks like this:
public void draw() {
glBegin(GL_QUADS);
glVertex2f(x * World.TILE_SIZE, y * World.TILE_SIZE);
glVertex2f(x * World.TILE_SIZE + World.TILE_SIZE, y * World.TILE_SIZE);
glVertex2f(x * World.TILE_SIZE + World.TILE_SIZE, y * World.TILE_SIZE
+ World.TILE_SIZE);
glVertex2f(x * World.TILE_SIZE, y * World.TILE_SIZE + World.TILE_SIZE);
glEnd();
}
To me, this looks like very simple lwjgl-code that should work without any problems, except it doesn't. When executed, it just gives me a black window, without any rectangles drawn on it. Any suggestions?
thanks in advance
-v0xelDev
Fixed.
Found the answer here.
Appearently, I can't draw simple coloured shapes with GL_TEXTURE_2D enabled, my openGL initialization code now looks like this:
glMatrixMode(GL_PROJECTION);
glOrtho(0, 640, 480, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_TEXTURE_2D);
//glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
I am making a platformer which I started developing with default java functions, but now am switching to OpenGL for everything. I have done everything like I always do with OpenGL, and what I did works fine in my other OpenGL projects. Now my problem is that LWJGL/OpenGL is scaling my textures in a very strange way.
It seems to be related to my screen's aspect ratio. (8:5)
I already had to flip the screen to make it the right way round, but as you can see the text is working fine, it's just the textured rect, and it isn't even straight on the bottom.
Here are the most important snippets from the two classes which actually use OpenGL:
Metamorph.java (main class)
public static void initGL()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, Display.getWidth(), 0, Display.getHeight(), 1, -1);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_MODELVIEW);
glClearColor(0, 0, 0, 1);
glDisable(GL_DEPTH_TEST);
}
public void render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glScalef(1.0f, -1.0f, 1.0f);
glTranslatef(0f, -720f, 0f);
//glScalef(1280f/800, 720f/500, 1f);
renderer.render();
Display.update();
Display.sync(60);
}
Renderer.java (rendering stuff)
private void renderMainMenuWithGL()
{
//System.out.println("Main Menu!");
glColor4f(1, 1, 1, 1);
try
{
Texture bg = loadTexture("mockery");
bg.bind();
} catch (Exception e)
{
e.printStackTrace();
}
//drawQuad(0, 0, 1280, 720, 0, 0, 1280, 720);
glPushMatrix();
{
glBegin(GL_QUADS);
glTexCoord2f(0, 0);glVertex2f(0, 0);
glTexCoord2f(0, 1);glVertex2f(0, 720);
glTexCoord2f(1, 1);glVertex2f(1280, 720);
glTexCoord2f(1, 0);glVertex2f(1280, 0);
glEnd();
}
glPopMatrix();
TrueTypeFont f = loadFont(MAINFONT, Font.PLAIN, 50);
TrueTypeFont fb = loadFont(MAINFONT, Font.PLAIN, 48);
int sel = -1;
if(Mouse.getX() > 1000 && Mouse.getX() < 1240 && Mouse.getY() > 282.5F && Mouse.getY()< 737.5F)
sel = Math.round((Mouse.getY() - 337.5F)/75F);
if(sel == 0)
drawStringRight(fb, 1240, 350, "Story", new Color(0xff516b6b));
else
drawStringRight(f, 1240, 350, "Story", new Color(0xff516b6b));
}
private void drawStringRight(TrueTypeFont f, int x, int y, String s, Color c)
{
glPushMatrix();
f.drawString(x-f.getWidth(s), y, s, c);
glPopMatrix();
}
I am also open to advice on file structure/what I did wrong elsewhere, but keep in mind this is heavily WIP
The only possible problem I can see from what you have posted is the scaling and translating you are doing prior to rendering. You should not need to do this with your projection matrix setup the way it is. Other possibilities are that either the dimensions are not really 1280x720 as you think or you have modified one of the matrices further in the code you have not posted. I would try setting both the modelview and projection matrices to the identity matrix and then use glOrtho as you have above immediatly before drawing your quad, and use Display.getWidth and Display.getHeight instead of 1280/720 for the vertex coords.
This works fine for me:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, Display.getWidth(), 0, Display.getHeight(), 1, -1);
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex2i(0, 0);
glTexCoord2f(1,0);
glVertex2i(Display.getWidth(), 0);
glTexCoord2f(1,1);
glVertex2i(Display.getWidth(), Display.getHeight());
glTexCoord2f(0,1);
glVertex2i(0, Display.getHeight());
glEnd();
If this still doesnt work, make sure that the viewport is also set to the entire display: glViewport(0,0,Display.getWidth(),Display.getHeight()).
Aswell, I notice that you are using glPushMatrix() and glPopMatrix before and after drawing, which does nothing and is not needed. Push and pop are used to save the current projection or modelview matrix and then reload it later, so that you can apply transformations inbetween and undo them when needed.
You're setting the projection matrix such that the coordinates of the corners of the window are (0,0) through (1680, 1050), and those are mapped into an area that covers 1280x800 pixels. Then you're drawing a 1280x720 image into it, so the screen coordinates of the image come out to span only 800x500 pixels. If you use 1280x720 in your glOrtho() call, I believe it will fix the issue. That is, you want the size of the window, not the size of the display in that call.
I wrote a small particle system in Java with the LWJGL.
So therefore I am using openGL.
Now I read, that changing a texture is very slow. So I make sure, that I only change a texture which is used for a bunch of particles and then draw all these particles.
Still my FPS drop from about 8000 to 4000 although there are only 60 particles at the same time drawn.
I know that the problem is the rendering, because when I just update particles but do not draw them, then I have no drop in FPS.
It would be great if someone could tell me what is wrong with my OpenGL code.
This is the particle emitter which manages the particles:
public void render() {
//Initialize....
GL11.glMatrixMode(GL11.GL_MODELVIEW);
BloodParticle.PARTICLE_TEXTURE.bind();
for(Integer index : this.getBlockedParticles()){
this.getParticles()[index].render();
}
GL11.glDisable(GL11.GL_TEXTURE_2D);
}
This is the render method of a single particle:
public void render() {
if(!this.isAlive()){
return;
}
// Store matrix
GL11.glPushMatrix();
// Set to particle's position and scale
GL11.glTranslatef(this.getPosition().getX(), this.getPosition().getY(), 0);
GL11.glScalef(3.5f, 3.5f, 1.0f);
// Set the current alpha.
GL11.glColor4f(1.0f, 1.0f, 1.0f, this.getAlphaFade());
//Draw the texture on a quad.
GL11.glBegin(GL11.GL_QUADS);
{
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(-PARTICLE_TEXTURE.getImageWidth()/2.0f,
-PARTICLE_TEXTURE.getImageHeight()/2.0f);
GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(-PARTICLE_TEXTURE.getImageWidth()/2.0f,
PARTICLE_TEXTURE.getImageHeight()/2.0f);
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(PARTICLE_TEXTURE.getImageWidth()/2.0f,
PARTICLE_TEXTURE.getImageHeight()/2.0f);
GL11.glTexCoord2f(1, 0);
GL11.glVertex2f(PARTICLE_TEXTURE.getImageWidth()/2.0f,
-PARTICLE_TEXTURE.getImageHeight()/2.0f);
}
GL11.glEnd();
//Get the matrix again.
GL11.glPopMatrix();
}
I know that 4000 FPS are much more than enough. But I am just scared about this drop to half the FPS and with only one emitter in the game currently.
I know that this will become a problem with a fixed FPS of 60 and more than 3 emitter.
State changes have nothing to do with your performance problem.
This has:
//Draw the texture on a quad.
GL11.glBegin(GL11.GL_QUADS);
{
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(-PARTICLE_TEXTURE.getImageWidth()/2.0f,
-PARTICLE_TEXTURE.getImageHeight()/2.0f);
GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(-PARTICLE_TEXTURE.getImageWidth()/2.0f,
PARTICLE_TEXTURE.getImageHeight()/2.0f);
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(PARTICLE_TEXTURE.getImageWidth()/2.0f,
PARTICLE_TEXTURE.getImageHeight()/2.0f);
GL11.glTexCoord2f(1, 0);
GL11.glVertex2f(PARTICLE_TEXTURE.getImageWidth()/2.0f,
-PARTICLE_TEXTURE.getImageHeight()/2.0f);
}
GL11.glEnd();
Think about it: Each and every particle causes 8 calls into OpenGL. At several thousand particles this is a huge overhead. Even worse, you're not even batching several quads into a single glBegin/*glEnd* block.
Here's how to improve performance: Don't use glBegin/glVertex/glEnd aka the immediate mode
Use Vertex Arrays!
For some reason enabling alpha blending results in me not being able to draw run-of-the-mill coloured shapes. The order in which everything is drawn makes no difference. Even if the only thing being drawn is the coloured shape, it still won't show.
Disabling alpha blending fixes this, but disables alpha blending (obviously). This leads me to believe the problem is in how I'm initializing openGL.
The textured objects are contained in the world, which is commented out. Commenting "world.run();" out makes no difference, only disabling alpha blending does.
public class Core {
int width=800, height=600;
//World world;
public void Start(){
try {
Display.setDisplayMode(new DisplayMode(width,height));
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
System.exit(0);
}
initGL();
System.out.println("OpenGL version: " + GL11.glGetString(GL11.GL_VERSION));
boolean Close = Display.isCloseRequested();
//world = new World(width, height);
while(!Close){
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE) || Display.isCloseRequested())
Close = true;
//world.run();
GL11.glColor4d(1, 0, 0, 1);
GL11.glBegin(GL11.GL_QUADS);
GL11.glVertex2d(0, 0);
GL11.glVertex2d(0, 50);
GL11.glVertex2d(50, 50);
GL11.glVertex2d(50, 0);
GL11.glEnd();
Display.update();
//Display.sync(60);
}
}
public void initGL(){
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
// enable alpha blending
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);
}
public static void main(String args[]){
Core m = new Core();
m.Start();
}
}
This is for a 2D app where I'm trying to draw metaballs behind the texture of a black-and-white world map.
Run-of-the-mill coloured shapes refers to the following,
GL11.glColor4d(1, 0, 0, 1);
GL11.glBegin(GL11.GL_QUADS);
GL11.glVertex2d(0, 0);
GL11.glVertex2d(0, 50);
GL11.glVertex2d(50, 50);
GL11.glVertex2d(50, 0);
GL11.glEnd();
Even if drawn on its own, as long as alpha blending is enabled, it won't show up.
UPDATE:
The constructor for world was loading (but not drawing) a texture. Removing that part of the code lets the coloured square show up. I have deduced that the problem will occur as long as a texture is loaded, regardless of whether it is displayed or not.
You've got glEnable(GL_TEXTURE_2D) in initGL, but I don't see it disabled anywhere.
You know you have to disable texturing if you want to draw an untextured object, right?