Advertisement Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

179 Neutral

About mattdesl

  • Rank

Personal Information


  • Twitter
  1. Linear interpolation (sometimes called 'lerp' or 'mix') is a really handy function for creative coding, game development and generative art. The function interpolates within the range [start..end] based on a 't' parameter, where 't' is typically within a [0..1] range. For example, divide 'loop time' by 'loop duration' and you get a 't' value between 0.0 and 1.0. Now you can map this 't' value to a new range, such as `lerp(20, 50, t)` to gradually increase a circle's radius, or `lerp(20, 10, t)` to gradually decrease its line thickness. Another example: you can use linear interpolation to smoothly animate from one coordinate to another. Define a start point (x1, y1) and end point (x2, y2), then interpolate the 'x' and 'y' dimensions separately to find the computed point in between. Or use linear interpolation to spring toward a moving target. Each frame, interpolate from the current value to the target value with a small 't' parameter, such as 0.05. It's like saying: walk 5% toward the target each frame. A more advanced example, but built on the same concept, is interpolating from one color (red) to another (blue). To do this, we interpolate the (R, G, B) or (H, S, L) channels of the color individually, just like we would with a 2D or 3D coordinate. Another quick example is to choose a random point along a line segment. There are lots of ways to use linear interpolation, and lots more types of interpolation (cubic, bilinear, etc). These concepts also lead nicely into areas like: curves, splines and parametric equations. Source code for each of these examples is available here: About the author: Matt DesLauriers is a creative coder and generative artist based in London. He combines code and emergent systems to make art for the web, print media, and physical installations. Note: This brief introduction to lerp was originally published as a Twitter thread and is republished here with the kind permission of the original author. [Wayback Machine Archive]
  2. There is some useful information and code here:
  3. If you were using GL 3+, you can utilize geometry shaders and instancing.    But really there is no need to restrict your audience to GL 3+ (it's not yet very widely supported, especially not in the casual market). GL 2+ functionality will be more than enough for a 2D sprite batcher.   The simplest way to optimize your sprite batcher is to send as little as possible to GL. Update your uniforms (e.g. ortho 2D projection matrix) only as necessary, and only pass the attributes you really need. If you know some of your data is static, you can use multiple VBOs, otherwise you should just stick to interleaved data.   My sprite batcher uses the following attributes per vertex:   { x, y, color, u, v }     The color is a packed float. That means 5 attributes per vertex, and 4 vertices per sprite using element indices. One-off transformations (like sprite rotation) are done in CPU before passing vetex position.   Most of the time, optimizing in 2D is more about using texture atlases, improving batch rendering, and minimizing overdraw rather than worrying about small things like whether or not to interleave your VBO data. Besides, 99% of the time a 2D game will become fill-rate bound before it becomes vertex bound.   On the subject of fill rate, you can use hexagons or some other non-rectangular primitive as an optimization (although it comes at the cost of more vertices and may be undesirable depending on you sprites).    For more reading on my sprite batcher:   Using plain old VBOs or even vertex arrays will be plenty fast, but if you want to squeeze a bit more performance out of GL 2.0 you should look into mapped VBOs:
  4. mattdesl

    Porting to OpenGL

      GL 3.0+ is still not very widely supported. If you are targeting a casual market, you may want to stick with 2.0 as your target. In this thread it was listed that as few as 51% of Minecraft users supports GL 3.0+. It really comes down to what you need; GL 2 is a fine target for most purposes and can be used in almost the same way as the 3+ programmable pipeline (shaders, custom built-ins, etc). Many drivers will support geometry shaders, FBOs, float textures, etc. through extensions. For example, 93% of drivers support FBO EXT, and it's pretty much a staple in any driver in the last several years.    GL 2.0 and GLSL < 150 is also more compatible with OpenGL ES, so it will prepare you for iOS/Android/WebGL graphics programming.
  5. A VBO should be performant enough for the vast majority of cases. If you need better performance you can pass points and expand them to triangles in a geometry shader.   Read up here on some techniques for VBO optimization with sprite batching:   Since ultimately the performance may vary depending on the driver, the absolute "fastest" solution is to use whatever works best for the driver. For example, in the intro cutscene of your game you might benchmark a few different rendering techniques, and pick whichever runs the fastest.
  6. mattdesl

    Good books for OpenGL

    I'm writing a tutorial series aimed at beginners wanting to learn the programmable pipeline and GLSL shaders, check it out here:
  7. If you do not need perfectly scalable fonts, then plain old bitmap fonts are very simple and hassle-free.    You can see my minimal implementation here.
  8. Doing the the matrix calculations in software shouldn't be too bad. But if you are CPU limited (maybe the case on Android) then here is an alternative that does the matrix calculation on the GPU:   Pass a vec4 Rotation (rotX, rotY, rotZ, angle) to your vertex shader. Then calculate the rotation matrix in your shader:   mat4 transform = mat4(1.0); //identity   ... make rotation matrix from axis and angle ...   gl_Position = projection * view * transform * a_position;   Theoretically you could put the Position and Normal attributes into a separate static VBO since they are unchanged (and update the view matrix instead). If you fill all your instance data in one go, you could end up with a single draw call per frame.
  9. mattdesl

    Default color attribute

    If you are using version 330 you should be doing some things a bit differently in GLSL:   - Use "in" and "out" instead of "varying" and "attribute" - Use layout(location=X) to specify the index to bind the attribute to - Use a custom output instead of gl_FragColor   Also just so you know, GL 3.0+ is still not very widely supported. If you are targeting a casual market, you may want to stick with 2.0 as your target. In one thread it was listed that as few as 51% of Minecraft users supports GL 3.0+. It really comes down to what you need; GL 2 is a fine target for most purposes and can be used in almost the same way as the 3+ programmable pipeline. Many drivers will support geometry shaders, FBOs, float textures, etc. through extensions.
  10. Your code looks extremely complicated for something so simple. Are you making a 2D game? Why are you using world coordinates instead of orthographic projection? In addition to ortho, texture states, etc. you should also read up a little on classes and object oriented programming. For example, you might: Define a "Texture" class which wraps OpenGL textures (bind, wrap modes, filtering, etc) and pads for NPOT Define a "TextureRegion" class utility which determines normalized texture coordinates from un-normalized pixel coordinates Define a "TextureAtlas" (or "SpriteSheet") class which splits a TextureRegion into an array of many TextureRegion objects Also, the whole point of a sprite sheet is to reduce texture binds and state changes. Bind the texture atlas, glBegin quads, specify the vertices for all of your sprites within that sheet, then glEnd to push the data to the GPU. Here's a very simple example, similar to what I use: public class TextureRegion { protected float normalizedWidth, normalizedHeight; protected float width, height; protected float centerX, centerY; protected float textureOffsetX, textureOffsetY; protected Texture texture; public TextureRegion(Texture texture) { this.texture = texture; //e.g. a 240x240 PNG image would be loaded as a 256x256 texture this.normalizedWidth = texture.getImageWidth() / (float) texture.getTextureWidth(); this.normalizedHeight = texture.getImageHeight() / (float) texture.getTextureHeight(); this.width = texture.getImageWidth(); this.height = texture.getImageHeight(); this.centerX = width / 2f; this.centerY = height / 2f; } public TextureRegion copy() { TextureRegion img = new TextureRegion(texture); return img; } public TextureRegion getSubImage(float x, float y, float width, float height) { float tx = ( x / this.width * normalizedWidth ) + textureOffsetX; float ty = ( y / this.height * normalizedHeight ) + textureOffsetY; float tw = width / this.width * normalizedWidth; float th = height / this.height * normalizedHeight; TextureRegion img = copy(); img.textureOffsetX = tx; img.textureOffsetY = ty; img.width = width; img.height = height; img.normalizedWidth = tw; img.normalizedHeight = th; img.centerX = width / 2f; img.centerY = height / 2f; return img; } // ideally you should use a modern solution like VBOs and place rendering elsewhere... public void begin() { GL11.glEnable(GL11.GL_TEXTURE_2D); texture.bind(); GL11.glBegin(GL11.GL_QUADS); } public void end() { GL11.glEnd(); GL11.glDisable(GL11.GL_TEXTURE_2D); } public void draw(float x, float y) { GL11.glTexCoord2f(textureOffsetX, textureOffsetY; //TOP LEFT GL11.glVertex2f(x, y); GL11.glTexCoord2f(textureOffsetX, textureOffsetY+normalizedHeight); //BOTTOM LEFT GL11.glVertex2f(x, y+height); GL11.glTexCoord2f(textureOffsetX+normalizedWidth, textureOffsetY+normalizedHeight); //BOTTOM RIGHT GL11.glVertex2f(x+width, y+height); GL11.glTexCoord2f(textureOffsetX+normalizedWidth, textureOffsetY); //TOP RIGHT GL11.glVertex2f(x+width, y); } }
  11. NeHe's tutorials are old and outdated, and it's a terrible place to start learning today's OpenGL. Instead, you should be learning the "modern" programmable pipeline (GLSL). I'd also suggest using a framework (other than GLUT) to help you through common tasks like window creation, PNG decoding, etc. Java and LWJGL/JOGL are popular choices for this as you jump right into OpenGL programming without the need for memory management, OS hacks, display code, context creation, etc. If you want to stick with C++, there are a number of libraries like SDL and GLFW that will help set up the basics for you. This series covers context creation and other things from a more "modern" perspective: And here's another popular "modern OpenGL" tutorial:
  12. mattdesl

    Problem with textures in 2D game

    Generally you will want to use GL_TEXTURE_2D and two triangles (or a quad). GL_TEXTURE_RECTANGLE was originally used for a means of achieving non-power-of-two textures; now most modern hardware supports NPOT textures with GL_TEXTURE_2D.
  • Advertisement

Important Information

By using, you agree to our community Guidelines, Terms of Use, and Privacy Policy. is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!