LWJGL仅渲染单一纹理问题:Minecraft克隆开发OpenGL渲染异常求助
问题根因
你遇到的问题本质是两个核心逻辑错误导致的:
- 每次获取纹理时都创建新的
Texture实例,既浪费显存资源,也没有复用同一路径的纹理对象 - 你仅调用了纹理加载方法,没有在绘制对应方块前绑定对应纹理的ID,OpenGL是状态机,默认会使用最后一次绑定的纹理完成所有绘制操作,所以才会出现所有方块都显示同一种纹理的问题
修复方案
1. 新增纹理缓存避免重复创建
修改Texture类,增加静态缓存复用同路径的纹理实例:
import java.util.HashMap; import java.util.Map; public class Texture { // 新增纹理缓存,key为纹理路径,value为对应的Texture实例 private static final Map<String, Texture> TEXTURE_CACHE = new HashMap<>(); private String location; private int id; private boolean loaded = false; // 构造方法改为私有,禁止外部直接new private Texture(String location) { this.location = location; } // 新增获取纹理实例的静态方法 public static Texture getInstance(String path) { if (TEXTURE_CACHE.containsKey(path)) { return TEXTURE_CACHE.get(path); } Texture texture = new Texture(path); TEXTURE_CACHE.put(path, texture); return texture; } // 原有loadTexture、getId方法保持不变 public void loadTexture() { if (!this.loaded) { this.loaded = true; try { InputStream stream = new FileInputStream("Textures/" + this.location); PNGDecoder decoder = new PNGDecoder(stream); ByteBuffer buffer = ByteBuffer.allocateDirect(4 * decoder.getWidth() * decoder.getHeight()); decoder.decode(buffer, decoder.getWidth() * 4); buffer.flip(); this.id = GL11.glGenTextures(); GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.id); GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer); GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D); } catch (Exception e) { e.printStackTrace(); } } } public int getId() { return this.id; } }
修改方块类的getTexture方法,不要直接new Texture,改用缓存获取:
// 泥土方块的getTexture @Override public Texture getTexture() { return Texture.getInstance("Dirt.png"); } // 石头方块的getTexture @Override public Texture getTexture() { return Texture.getInstance("Stone.png"); }
2. 绘制方块前绑定对应纹理
你原来的ChunkData.render方法只做了纹理加载,没有绑定纹理的逻辑,需要在绘制每个方块之前,先绑定对应方块的纹理ID:
public void render() { // 示例仅针对你提到的两个方块,批量渲染可遍历整个blocks数组 Block stoneBlock = blocks[1][1][2]; if (stoneBlock != null) { stoneBlock.getTexture().loadTexture(); // 绑定石头纹理 GL11.glBindTexture(GL11.GL_TEXTURE_2D, stoneBlock.getTexture().getId()); // 执行石头方块的绘制逻辑 // ... 此处保留你原有绘制方块的代码 } Block dirtBlock = blocks[2][2][2]; if (dirtBlock != null) { dirtBlock.getTexture().loadTexture(); // 绑定泥土纹理 GL11.glBindTexture(GL11.GL_TEXTURE_2D, dirtBlock.getTexture().getId()); // 执行泥土方块的绘制逻辑 // ... 此处保留你原有绘制方块的代码 } }
额外优化建议
可以在游戏启动阶段就预加载所有需要用到的方块纹理,不需要在渲染时判断是否加载,避免渲染过程中出现卡顿。
内容的提问来源于stack exchange,提问作者dadogamer 580
相关产品推荐
相关产品推荐

