Skybox отображает черный цвет при загрузке текстур с помощью LWJGL и PNGDecoder - PullRequest
0 голосов
/ 06 января 2019

Я загружаю текстуру скайбокса карты куба (3D-координаты, а не 2D), и скайбокс оказывается черным. Я не получаю никаких ошибок, и скайбокс отображается в нужных местах и ​​все такое, но что-то все еще не так.

У меня есть собственный класс CubeMap, который просто берет String[] для имен файлов текстур и загружает их со следующим кодом:

public class CubeMap {

    private int cubeMapID;

    public CubeMap (String[] textureFiles) {
        this.cubeMapID = GL11.glGenTextures();
        GL13.glActiveTexture(GL13.GL_TEXTURE0);
        GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, cubeMapID);

        for (int i = 0; i < textureFiles.length; i++) {
            Image data = Loader.decodeTextureFile("res/textures/" + textureFiles[i]);
            GL11.glTexImage2D(GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL11.GL_RGBA, data.getWidth(), data.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, data.getByteBuffer());
        }

        GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
        GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
    }

    public int getCubeMapID() {
        return cubeMapID;
    }

    public void destroy () {
        GL11.glDeleteTextures(cubeMapID);
    }
}

Метод decodeTextureFile() в Loader:

public static Image decodeTextureFile (String fileName) {

    int width = 0, height = 0;
    ByteBuffer buffer = null;

    try {

        FileInputStream in = new FileInputStream(fileName);
        PNGDecoder decoder = new PNGDecoder(in);

        width = decoder.getWidth();
        height = decoder.getHeight();
        buffer = ByteBuffer.allocateDirect(4 * width * height);

        decoder.decode(buffer, width * 4, Format.RGBA);

        buffer.flip();
        in.close();

    } catch (IOException e) {
        System.out.println("Error : Decoding in loader failed; IO - Error");
        System.exit(-1);
    }

    return new Image (width, height, buffer);
}

Кроме того, у меня есть класс SkyBox, который создает CubeMap и сохраняет вершины предустановленного массива в vertexArray и vertexBuffer (эта часть кода работает нормально, поэтому я не вижу необходимо добавить код модели)

public class SkyBox extends Model {

    private static final float SIZE = 500f;

    private static final float[] VERTICES = {
            -SIZE,  SIZE, -SIZE,
            -SIZE, -SIZE, -SIZE,
            SIZE, -SIZE, -SIZE,
             SIZE, -SIZE, -SIZE,
             SIZE,  SIZE, -SIZE,
            -SIZE,  SIZE, -SIZE,

            -SIZE, -SIZE,  SIZE,
            -SIZE, -SIZE, -SIZE,
            -SIZE,  SIZE, -SIZE,
            -SIZE,  SIZE, -SIZE,
            -SIZE,  SIZE,  SIZE,
            -SIZE, -SIZE,  SIZE,

             SIZE, -SIZE, -SIZE,
             SIZE, -SIZE,  SIZE,
             SIZE,  SIZE,  SIZE,
             SIZE,  SIZE,  SIZE,
             SIZE,  SIZE, -SIZE,
             SIZE, -SIZE, -SIZE,

            -SIZE, -SIZE,  SIZE,
            -SIZE,  SIZE,  SIZE,
             SIZE,  SIZE,  SIZE,
             SIZE,  SIZE,  SIZE,
             SIZE, -SIZE,  SIZE,
            -SIZE, -SIZE,  SIZE,

            -SIZE,  SIZE, -SIZE,
             SIZE,  SIZE, -SIZE,
             SIZE,  SIZE,  SIZE,
             SIZE,  SIZE,  SIZE,
            -SIZE,  SIZE,  SIZE,
            -SIZE,  SIZE, -SIZE,

            -SIZE, -SIZE, -SIZE,
            -SIZE, -SIZE,  SIZE,
             SIZE, -SIZE, -SIZE,
             SIZE, -SIZE, -SIZE,
            -SIZE, -SIZE,  SIZE,
             SIZE, -SIZE,  SIZE
    };

    private CubeMap cubeMap;
    private int vertexArrayID;
    private int vertexCount;

    public SkyBox (String[] textures) {
        cubeMap = new CubeMap(textures);
        vertexArrayID = super.createVertexArray();
        super.storeData(0, 3, VERTICES);

        vertexCount = VERTICES.length / 3;

        GL30.glBindVertexArray(0);
    }

    public CubeMap getCubeMap() {
        return cubeMap;
    }

    public int getVertexArrayID() {
        return vertexArrayID;
    }

    public int getVertexCount() {
        return vertexCount;
    }

    public void destroy () {
        cubeMap.destroy();
    }
}

У меня есть класс SkyboxShader, и я вполне уверен, что он функционирует должным образом. Фактический рендеринг SkyBox происходит в классе SkyboxRenderer:

public class SkyboxRenderer {

    private SkyboxShader shader;

    public SkyboxRenderer (SkyboxShader shader) {
        this.shader = shader;
    }

    public void render (SkyBox skyBox) {
        shader.bind();
        shader.useMatrices();
        GL30.glBindVertexArray(skyBox.getVertexArrayID());
        GL20.glEnableVertexAttribArray(0);

        GL13.glActiveTexture(GL13.GL_TEXTURE0);
        GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, skyBox.getCubeMap().getCubeMapID());

        GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, skyBox.getVertexCount());

        GL20.glDisableVertexAttribArray(0);
        GL30.glBindVertexArray(0);
        shader.unbind();
    }
}

Если кто-нибудь знает, как решить эту проблему, это будет с благодарностью. Любой дополнительный код будет опубликован по запросу. Заранее спасибо!


Редактирование

Редактировать: Image класс является пользовательским и просто хранит ByteBuffer и ширину и высоту. Getters предоставляется, но без дополнительной функциональности.

Редактировать: я даже пытался рефакторинг всего моего кода, чтобы не преобладать.

Редактировать: Я думаю, что ошибка заключается в карте куба, а не в текстурах или другом коде, так как я могу заставить его работать, когда я просто использую 6 различных квадов для рендеринга блока.

Редактировать: я решил проблему. Я забыл вызвать метод .create() на шейдере типа в рендере.

1 Ответ

0 голосов
/ 28 января 2019

ЗАКРЫТО: Я забыл добавить вызов метода shader.create (); в функции SkyboxRenderer.init (), чтобы никакие шейдерные программы не были связаны.

...