You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 17:06:02