[LWJGL] How to fix texture bleeding?

Hello again, I’ve got another question! It seems that, while designing my gaming library, I keep running into one issue after another that I’ve never encountered before. I’ve been on this problem for a while, but I only just today learned that it’s called Texture Bleeding. Since I’m trying to write a library I’m hoping to learn a way to fix the bleeding programmatically rather than in a shader, as I want this library to be as simple for users to use as possible. Here’s an example of the texture bleeding going on:

As you can see based on the texture for the blend map being used here, there shouldn’t be any of the sand texture being blended on the left side of the map, as it is completely red on the blend map texture. Same with the bottom of the map, stone shouldn’t be blended there as the blend map is completely black there. From what I can tell it’s like the entire texture has been offset by a certain amount and is just throwing the texture coordinates that are offset off the map onto the opposite side of the map, if that makes sense (not quite sure if I am describing it correctly, hopefully you can see what I mean though).

I’m not sure if LWJGL has always been doing this and in previous projects I’ve just never noticed or if it’s an error in my code somewhere. I can’t think of anything at all that’d cause this to happen based on my coding, but who knows. I’ve tried researching other people who have had the same issue as me, but I can’t seem to fix this. I tried using:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);

While this does stop the texture bleeding, it also prevents all the blending between textures that actually should be happening on the terrain.

Can anyone help me out with this? Is there a way to fix this programmatically in my library for the convenience of the library users, or can it only be fixed in a shader? Also, if you know, does LWJGL always act like this, or is it probably just an error in my code somewhere? I’m sorry if this was a long post, I am terrible at describing issues with programming , but if you need any more information please just ask. I will provide as much of the needed info as I can for you.

Thank you in advance guys (and gals)!

I also read somewhere this should fix the bleeding issue:


GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);

However, when I use this it just completely distorts the textures beyond recognition like so:

Now again I’m not sure if this could be due to errors in my code, or if I could possibly be using those methods wrong. I’m sorry but I’m not entirely sure, I don’t know how the glTexParameteri(int, int, int) method actually works unfortunately.

Edit / Update: After a little debugging I’ve come to realize that these methods do actually work, but only for the blendmap itself. For some reason it completely screws with my tiled textures that are supposed to be rendered to each tile of the heightmap though. Previous to using those methods, to tile my textures for the triangles, I’d just multiple the texture coordinate of the blendmap by 127.0f (texture size is 128), and that worked perfectly for me. After using the two aforementioned methods, however, using the same equation causes LWJGL to draw the tiled texture wayyy larger than what will even fit on the entire heightmap. However if I divide by 127.0f instead, rather than fixing it like I’d have expected/hoped, it still leads to a way-too-large texture being drawn. Any ideas?


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

Looks like you posted just after I’d already posted about those methods not working for me, sorry about that mate.

Use a 2D texture array instead (GL_TEXTURE_2D_ARRAY). In many cases it’s just a 3D texture, but the advantage here is how mipmaps and filtering works.

3D texture mipmaps: 0: 4x4x4, 1: 2x2x2, 2: 1x1x1
2D texture array mipmaps: 0: 4x4x4, 1: 2x2x4: 2: 1x1x4.

As you can see, the layers in the 2D texture array don’t get blended together. In addition, there is no possible way that you can get texture bleeding between layers as they are separated into individual layers, meaning that GL_CLAMP_TO_EDGE will solve all cases of bleeding that you can possibly get.

Okay, so I’m now using the following code to correct the texture bleeding:


GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);

Don’t get me wrong, this code does “work” for what I need it to do, but it causes some errors as well. The code results in the following:

The only issue with this is, as I explained in the picture, the stone dirt, grass, and sand texture should all be tiled but instead they’re stretched across the entire heightmap. Here’s the fragment shader code rendering the heightmap:


	vec2 tiledTexCoords = passTexCoords * 1.0f;
	//vec2 tiledTexCoords = passTexCoords * 127.0f; //Correctly tiled textures previous to using glTexParameteri(), not sure why it no longer works
	
	vec4 blendColor = texture(blendMapTexture, passTexCoords);
	
	float backgroundTextureAmount = 1 - (blendColor.r + blendColor.g + blendColor.b);
	
	vec4 backgroundColor = texture(backgroundTexture, tiledTexCoords) * backgroundTextureAmount;
	vec4 rColor = texture(rTexture, tiledTexCoords) * blendColor.r;
	vec4 gColor = texture(gTexture, tiledTexCoords) * blendColor.g;
	vec4 bColor = texture(bTexture, tiledTexCoords) * blendColor.b;
	
	vec4 totalColor = backgroundColor + rColor + gColor + bColor;
	
	gl_FragColor = totalColor * baseColor;

You need to do two things:

  1. use different texture coordinates to lookup your blendmap and your diffuse textures. The texture coordinates you sample the diffuse textures will need to be scaled to whatever tiling factor you need.
  2. use different wrap texture parameters for both textures. For the blendmap use clamp to edge, and for the diffuse textures (which you sample with out-of-0…1-interval coordinates) use any repeat mode you like.

I fixed it myself! :slight_smile:

The trouble code (simplified):


glActiveTexture(GL_ACTIVE_TEXTURES[i]);
glBindTexture(GL_TEXTURE_2D, texturePack.getTexture(i).getTextureID());

GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);

Basically all this trouble was caused by the fact that I was binding the texture before calling glTexParameteri(int, int, int), meaning the first loop through I was binding a texture without using glTexParameteri(int, int, int), hence all the wackiness.

It wasn’t an issue with my shader, or my texture coordinates, or anything else. Literally just that. :slight_smile:

So now just one last question for now:
Do you guys think I have enough complete for a WIP post in the WIP section of java-gaming, or should I wait a bit?

Does the game itself have any playable content? If not, maybe it would be best for hype to do it later?

It isn’t a game, it’s a 3D Game Library. Everything you see on the screen, which includes the collision detection and such, using my game library doesn’t take very many lines of code to create at all.

It’s just an easy-to-use 3D Game Library. Currently includes support for 3D Models, heightmaps, multi-texturing, text rendering, collision detection, console + custom command creation, and a convenient component based architecture, but indeed it is still a work in progress.

Here’s the main code that creates what you see in the images above:


	public Game()
	{	
		camera = new FPSCamera(new Vector3f(0.0f, 0.0f, 0.0f), new Vector3f(0.0f, 0.0f, 0.0f));
		//Component Based Architecture seemed like the best way to go here. A real pain to accomplish though.
		heightmap = new GameObject(new MultiTexturedModelComponent(Preloads.HEIGHTMAP0, Preloads.HEIGHTMAP_SHADER), new TerrainColliderComponent(Preloads.HEIGHTMAP0););
		entity = new GameObject(new TexturedModelComponent(Preloads.PLAYER_TEXTURED_MODEL, Preloads.STATIC_SHADER), new TransformComponent(new Vector3f(50.0f, heightmapColliderComponent.getHeightAtWorldPosition(new Vector3f(50.0f, 0.0f, -50.0f)), -50.0f), new Vector3f(0.0f, 0.0f, 0.0f)));
	}
	
	public void update()
	{
		camera.update();
		heightmap.update();
		entity.update();
	}
	
	public void render()
	{
		camera.lookThrough();
		heightmap.render();
		entity.render();
	}

Oh.

People will talk down on the game engine. If you aren’t solving a problem, people here don’t care. Most popular response would be, ‘just use libgdx’ or a more seasoned library with everything you need.

Well, making game engines isn’t going to make any new games or most likely result in a better engine than existing ones. Nothing wrong with making an engine for learning purposes though, as long as you’ve understood that.

I don’t want to use a more “seasoned” library, I want to write my own. Also there is no single library with absolutely “everything I need”. I am creating my own Gaming Library, which will (of course) be higher-level than LWJGL. In my opinion the library will never be finished, as there will always be more things that can be added to it, more functionality, easier ways to do things.

Also, you say that the library won’t be well received because I’m not “solving a problem”, but I am. I’m solving all of the problems I have when it comes to game programming, I’m making it faster and easier for me to do all the things that normally take me quite a bit of time.

I’m solving the exact same problem that each and every other gaming library out there solves. I’m making games easier and much faster to create, and I’m making the code 10x easier to understand and read.

I just want to clarify that I am making a Gaming Library, not a Game Engine. This Game Library, just like LWJGL, allows you to make literally just about any game that you want/can think of. All it does is make it easier, unlike a Game Engine that is designed to create specific kinds of games.

The library has both 2D and 3D utilities/capabilities, as well as numerous utilities for common game math, easy networking/multi-player capabilities, file loading, file parsing (example font files, heightmaps, bumpmaps, splatmaps, a variety of 3D Model/Mesh files from multiple Modelling Engines like Blender, animation files [frame animation, skeletal animation, etc], and so much more).

Kust like LibGDX if my library can’t do something it’s intended to be coupled with LWJGL as well. Maybe I’m just biased, but I already love the library a ton. And yes, I initially started programming this library for the learning experience and that’s still a major reason that I am doing this. However, now it has turned into so much more! :slight_smile:

If you’re going to want anyone to use it, it’s going to have to be very advanced.

You’re going to at-least need:

  • a modern g-buffer based rendering pipeline
  • material support
  • Animation support
  • Sound support
  • Collision support ( more than basic ray testing. Smooth collision response )
  • Networking
  • Some sort of world editor

Something like this doesn’t really exist with Java yet. There’s JMonkey and it’s close, but it’s quite old and could be made more efficient.

But if it’s just for you, have fun! :slight_smile:

Thanks for the advice man, I’m probably going to quickly write out on paper all of the things I intend on adding to the engine in the near future soon. Call me old fashioned, but I actually use a lot of pen/paper when I program. For example I work out a lot of the trigonometry involved in game programming on paper. Also I almost always have a TODO list that I’m constantly adding/scratching out items on, with a priority system and such as well. While I don’t always strictly abide by it (shit happens, ya’ know?), it’s still extremely helpful in staying on task and actually having a plan.

That’s the beauty of my game library though (in my mind at least), I literally get to work at my own pace to add all the things I want to add. I don’t have an intended release date, I’m just learning tons of new things and being productive as I do it. All the things that I’ve always hated doing, or neglected to learn to do because it’s so time consuming, I finally get to force myself to do with the reassurance that it’s the only time I need to learn to do it. Because after I learn it once, not only will I finally know how to do it or have the general idea down, but this library will also act as a personal knowledge base of all the gaming knowledge that I know.

I’m not sure if I’m making sense, but I’m trying my best. Basically this library isn’t just a useful programming tool, but for me specifically it also acts as a database of knowledge and a way to force me to learn things I’ve always avoided because they’re on the more complicated end of the spectrum, and since the library uses a Component Based Architecture I can just keep adding more and more stuff.

On the list of things I avoided learning until this library idea came along (been working on it for quite a while now):

  • Component Based Architecture ;D
  • VAO Rendering (previously stuck to immediate rendering)
  • Shaders
  • 3D Lighting
  • Heightmap Collision
  • Integrating Accurate Float Math into my Programs
  • Multi-Texturing / Texture Blending
  • Simple Animation
  • Rendering Text (Non-Deprecated using texture atlas and parsing .FNT Files)

And so much more. I’ve come so far from using immediate-mode rendering, creating the most simplistic games imaginable without any useful rendering functions like shaders.

Keep at it! :slight_smile:
Not many people decide to pursue modern graphics programming using LWJGL!

Thank you! I wasn’t aware it was that rare of a thing to be doing. Regardless though I’m learning a lot, I’m having a lot of fun, and I’m seeing real progress! Once I add a few more features I’ll definitely be releasing a WIP Project post with my progress so far.