Rendering

So, I’m using OpenGL (lwjgl), and waited to look into the best ways for rendering. At the moment, I just have a draw method that runs for every object, which draws it on the screen. Now, the thing is I’m using the default way to render.

Example code:

	texture.bind();
	
	GL11.glColor3f(0f, 1.0f, 0f);
	
	GL11.glPushMatrix();
    	GL11.glBegin(GL11.GL_QUADS);
    		GL11.glTexCoord2f(0,1);
        	GL11.glVertex2f(x, y);
        	GL11.glTexCoord2f(1,1);
        	GL11.glVertex2f(x + width, y);
        	GL11.glTexCoord2f(1,0);
        	GL11.glVertex2f(x + width, y + height);
        	GL11.glTexCoord2f(0,0);
        	GL11.glVertex2f(x, y + height);
        GL11.glEnd();
    GL11.glPopMatrix();

but… I feel like it’s better to use VBO’s. Now, VBO’s seem more complicated, but every time I look up a tutorial, I just can’t understand it. Since this is for my 2D side scroller game, are VBO’s the best to use? (I’m also using slick to render the pictures).

I’ll keep looking at tutorials, but if anyone has experience with VBO’s or what not, that would be sweet.

You aren’t using the default way to render, you’re using a deprecated way to render.

If it’s your first 2-D side-scroller I imagine that it won’t be super graphics heavy, so your deprecated way of rendering (called immediate rendering) would suffice. At most you’ll just have to make sure you do some optimizing. However, I strongly recommend you learn how to use VBOs, and use them for this project, because if/when you ever move to 3-D games or graphics-heavy games VBO usage is almost necessary.

So I know little about optimizing rendering. Is it bad the way I’m doing it?

All Objects have a draw method and runs the code I gave earlier.

In the main game loop for like the level, it would run that method for every object.

I have things like bullets, and objects moving a lot, and when I tried it before it lagged the game so much that it was unplayable. I think I was setting the texture in it also… so now i just set the texture in the constructor.

you can improve the performance by reducing the number of


GL11.glBegin(GL11.GL_QUADS);

GL11.glEnd();

calls you produce.

e.g.


	public void render() { 
		GL11.glBegin(GL11.GL_QUADS);
		level.render();
		player.render();
		GL11.glEnd();
	}

inside your Player class


	public void render() {
	GL11.glTexCoord2f(0,1);
          GL11.glVertex2f(x, y);
          GL11.glTexCoord2f(1,1);
          GL11.glVertex2f(x + width, y);
          GL11.glTexCoord2f(1,0);
          GL11.glVertex2f(x + width, y + height);
          GL11.glTexCoord2f(0,0);
          GL11.glVertex2f(x, y + height);
	}

which would then put it all into one call, but you would not be able to change textures, so you would need to use a SpriteSheet, and produce the correct TexCoords for each sprite.

EDIT:

And yes, using VBO’s would be better performance, but for your first OpenGL game, it should be enough. After you produce a game or two, and are a bit more familiar with OpenGL, learn how to use VBO’s, unless if you wish to start now.

A good old display list sometimes beats a vbo. But I recommend to lern whats state of the art.
(Except you wanna finish the game :persecutioncomplex:)

-ClaasJG

Maybe you’re already aware of this, but in addition to being deprecated (as noted above), immediate mode isn’t even available in newer OpenGL versions/configurations. Whether that matters for you depends, I suppose, but it’s something to be aware of. It’s also not available in OpenGL ES, in case you ever plan to work with that API.

Unfortunately, doing it the modern way isn’t that straightforward, as you’ve discovered - there’s a lot of boilerplate and a lot of stuff that has to be ‘just so’ in order to get anything on screen.

A suggestion that’s often made is to use a library that takes care of this work for you, such as LibGDX. Although there is something to be said for doing it yourself so as to learn what’s going on under the hood, immediate mode is so disconnected from modern practices that you may not be gaining much by using OpenGL directly in this case.

In any case, if your priority is productivity and/or performance, using a library like LibGDX may be worth considering. If however your primary goal is to learn about the technology, it might be worth tackling modern OpenGL despite the difficulties involved.

Ok, I understand I guess that what I’m using “works” for this version, and I know it’s not supported in the newer versions. I also see how limiting the amount of calls would be helpful, but I have one big issue that’s keeping me from actually trying anything with rendering.

I changed a lot of my code to be organized over these last few days, and I couldn’t even get it to run. I believe this has something to do with OpenGL, but I don’t know what I did to make it happen.

Exception in thread "main" java.lang.RuntimeException: No OpenGL context found in the current thread.
	at org.lwjgl.opengl.GLContext.getCapabilities(GLContext.java:124)
	at org.lwjgl.opengl.GL11.glGetError(GL11.java:1299)
	at org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer.glGetError(ImmediateModeOGLRenderer.java:384)
	at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:249)
	at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:200)
	at org.newdawn.slick.opengl.TextureLoader.getTexture(TextureLoader.java:64)
	at org.newdawn.slick.opengl.TextureLoader.getTexture(TextureLoader.java:24)
	at Files.AbstractTile.setTexture(AbstractTile.java:104)
	at Creatures.Player.<init>(Player.java:33)
	at Levels.FirstLevel.<init>(FirstLevel.java:25)
	at Files.Start.<init>(Start.java:18)
	at Files.GameMain.<init>(GameMain.java:184)
	at Files.GameMain.main(GameMain.java:205)

I looked up the error, but it didn’t really help me find the issue. It’s saying a meoth I made, setTexture, isn’t working. The thing is, I used this previously and it worked fine. If you wanna see this, here you go:

	public void setTexture(String type, String dir)
	{
		try
		{
            // load texture from PNG file
            texture = TextureLoader.getTexture(type, ResourceLoader.getResourceAsStream(dir));
        }
		catch (IOException e)
		{
            e.printStackTrace();
        }
    }

So ya, I don’t know exactly what is causing the issue, but if anyone see’s what’s wrong I could then test these different forms of rendering in my game. I’m not trying to just find an answer here btw, I would love to learn more so feel free to explain it if you would like me to understand it better :).

Ok, I guess the issue is that I can’t set a texture in the constructor? Well, talking about optimizing, what’s the best way to set a texture then? Before I just set it every time it would draw, but I could see how that is bad. I have a feeling there’s a better way of rendering textures and using them, plus spritesheets are a whole other issue. Welp, if anyone has advice that would be great for textures/rendering.

you got to start the OpenGL first before you can declare a texture, so creating a texture can not be your first thing, you must initialize OpenGL, then create your texture.

You are also correct, you want to reuse the same texture.

The thing that I didn’t understand was… when I create my objects, it’s within a level class file. That file in itself is already being rendered through the game loop. OpenGL is started up by then, it’s just I’m trying to loop up a texture within the constructor of an object. I saw some people say it’s what you said, but others said I’m just trying to do too much in the constructor :/. I don’t know which is correct, but my only thought for this is just to put it in my draw method, and just have a counter to make sure it only runs once (setTexture).

you cant do “to much in the constructor”, you can run your entire game through the constructor if you really want to.

your stack trace failed because of “No OpenGL context found in the current thread.”, which gives the impression that OpenGL has not yet been initialized.

Try and move where you load your textures, as this would be your issue, put it directly before you start your game loop, and it should work.

Ok, so I ran into an issue with VBO’s now. I know there’s a tutorial/example someone made on here for it, but it didn’t really make sense for me. Also, I watched some video tutorials, and I thought I understood how it worked. The issue is though, I tried doing it for creatures/player… but when i run it, I get a fatal error.

Fatal Error

# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000000572cbb80, pid=4228, tid=2236
#
# JRE version: Java(TM) SE Runtime Environment (8.0_45-b14) (build 1.8.0_45-b14)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.45-b02 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C  [atio6axx.dll+0x16bb80]

So :confused: I guess I’m not using VBO’s correctly. Also, I was confused on how I would efficiently update data/the location in them.

I really want to learn/use VBO’s, but I guess the way I want to use them makes it a little more complicated for me. I can show how I’m using them, but any suggestions/advice would be great.

—draw method—

	public void drawCreature()
	{
		if (hasinit == false)
		{
			setTexture("PNG", "Player.png");
			initVBO();
			hasinit = true;
		}
		updateVBO();
	}
	public void initVBO()
	{
		glBindTexture(GL_TEXTURE_2D, texture.getTextureID());
		
		vertexData = BufferUtils.createFloatBuffer(amountOfVertices * vertexSize);
        vertexData.put(new float[]{x, y, x + width, y, x + width, y + height, x, y + height});
        vertexData.flip();

        colorData = BufferUtils.createFloatBuffer(amountOfVertices * colorSize);
        colorData.put(new float[]{1, 1, 1});
        colorData.flip();
        
        textureData = BufferUtils.createFloatBuffer(amountOfVertices * vertexSize);
        textureData.put(new float[]{0, 1, 1, 1, 1, 0, 0, 0});
        textureData.flip();

        vboVertexHandle = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
        glBufferData(GL_ARRAY_BUFFER, vertexData, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        vboColorHandle = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboColorHandle);
        glBufferData(GL_ARRAY_BUFFER, colorData, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        
        vboTexCoordHandle = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboTexCoordHandle);
        glBufferData(GL_ARRAY_BUFFER, textureData, GL_STATIC_DRAW);
        glTexCoordPointer(3, GL_FLOAT, 0, 0);
	}
	public void updateVBO()
	{
         glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
         glVertexPointer(vertexSize, GL_FLOAT, 0, 0L);

         glBindBuffer(GL_ARRAY_BUFFER, vboColorHandle);
         glColorPointer(colorSize, GL_FLOAT, 0, 0L);
         
         glBindBuffer(GL_ARRAY_BUFFER, vboTexCoordHandle);
         glTexCoordPointer(vertexSize, GL_FLOAT, 0, 0L);

         glEnableClientState(GL_VERTEX_ARRAY);
         glEnableClientState(GL_COLOR_ARRAY);
         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
         
         glDrawArrays(GL_QUADS, 0, amountOfVertices);
         
         glDisableClientState(GL_COLOR_ARRAY);
         glDisableClientState(GL_VERTEX_ARRAY);
         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	}

You can assume I use int’s and FloatBuffers when appropriate. I hate asking for help over and over, but VBO’s have been something I waited to learn cause of something like this…

Yes, it can be tricky, unfortunately. There are certainly a lot of ways to get things wrong.

Currently it looks like you’re using VBOs with the fixed-function pipeline. The fixed-function pipeline, like immediate mode, is deprecated in more recent versions of OpenGL, but there’s no reason to tackle all aspects of modern OpenGL at once, I don’t think. In any case, getting VBOs working with fixed-function seems like a good first step.

As for your code, the first thing that jumped out at me is this:

colorData.put(new float[]{1, 1, 1});

Here you’re only storing one color in the VBO, but you should be storing four color entries, one for each vertex (just as you’ve done with positions and texture coordinates). This seems like the kind of thing that could cause an error of the sort you’re seeing.

oh, well what’s the way to do vbo’s that’s up to date? Also, i realize now how the color works from what you’re saying.

I wouldn’t worry about that for now - I’d just focus on getting your current implementation working and then add stuff incrementally. (The answer to your question though is that modern OpenGL uses a programmable pipeline where the rendering is done via shaders/programs. Also, maybe I’m wrong about how you’re doing things - I just skimmed the code, so maybe I missed something.)

[quote]Also, i realize now how the color works from what you’re saying.
[/quote]
Did that fix the crash?

I’m not at my computer atm, but when I get home I’ll try. Also, using the way I’m doing it, how would I update the data (like location of verticies)? The only thing I would think of is to retun my initVBO method with the coords. but then it would remake the vbo’s, so idk.

I guess first of all it kind of depends on how many entities (quads or whatever) you’re planning on rendering per frame. Do you have an estimate for that?

The two most obvious options are probably the following:

  1. Don’t update the VBOs and just use a separate transform for each entity (this is assuming the vertices remain static in the local space of the object, which is typical). This basically means a separate draw call for each entity. This isn’t the optimal way to render or to use VBOs, but if you’re not rendering 100s or 1000s of entities, it might be an acceptable solution.

  2. Do the transformations yourself and store the pre-transformed geometry in your VBOs. Along with grouping by texture or render state (and possibly the use of texture atlases), this approach can allow you to reduce draw calls to a minimum, more or less. If you go with option 2, you then have to decide how to go about updating the VBO data. There are a few ways to do this, but you generally don’t have to recreate your VBOs every frame (for example, you can use glBufferSubData() to update the contents of an existing VBO).

Can you provide a little more info about your rendering requirements? Are you just rendering ‘sprites’ (e.g. textured quads), more or less? If so, at most, how many quads do you expect to render in a single frame?

Well, each block or creature renders 1 quad, and creatures have weapons that can shoot projectiles. each projectile renders 1 quad. i guess each object will have 3 - 4 VBO’s, but ya. I have the game limited to 60 frames.

What’s the most quads you expect to render per frame, approximately?

per frame? I mean i guess i expect at max 100 or so in the future. But let’s just assume a lot.