Skybox полностью черный

Я новичок в openGL

Я создал этот скайбокс на LWJGL, но он весь черный

Класс SkyboxRenderer:

private static String[] TEXTURE_FILES = {"right","left","bottom","back","front"};
private RawModel cube;
private int texture;
private SkyboxShader shader;

public SkyboxRenderer(Loader loader, Matrix4f projectionMatirx) {
    cube = loader.loadToVAO(VERTICES, 3);
    texture = loader.loadCubeMap(TEXTURE_FILES);
    shader = new SkyboxShader();
    shader.start();
    shader.loadProjectionMatrix(projectionMatirx);
    shader.stop();
}

public void render(Camera camera){
    shader.start();
    shader.loadViewMatrix(camera);
    GL30.glBindVertexArray(cube.getVaoID());
    GL20.glEnableVertexAttribArray(0);
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texture);
    GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, cube.getVertexCount());
    GL20.glDisableVertexAttribArray(0);
    GL30.glBindVertexArray(0);
    shader.stop();
}

Функция loadCubeMap загрузчика:

public int loadCubeMap(String[] textureFiles){
    int texID = GL11.glGenTextures();
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texID);

    for(int i = 0; i < textureFiles.length;i++){
        TextureData data = decodeTextureFile("res/" + textureFiles[i] + ".png");
        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.getBuffer());

    }
    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);
    GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
    GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
    textures.add(texID);
    return texID;
}

private TextureData decodeTextureFile(String fileName) {
    int width = 0;
    int 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 (Exception e) {
        e.printStackTrace();
        System.err.println("Tried to load texture " + fileName + ", didn't work");
        System.exit(-1);
    }
    return new TextureData(buffer, width, height);
}

Текстуры есть, но скайбокс полностью черный, может кто поможет! Как я могу это исправить

Мне нужно добавить больше деталей для публикации, потому что слишком много кода...

Скайбоксшейдер:

открытый класс SkyboxShader расширяет ShaderProgram{

private static final String VERTEX_FILE = "src/com/redcatengine/skybox/skyboxVertexShader.txt";
private static final String FRAGMENT_FILE = "src/com/redcatengine/skybox/skyboxFragmentShader.txt";

private int location_projectionMatrix;
private int location_viewMatrix;

public SkyboxShader() {
    super(VERTEX_FILE, FRAGMENT_FILE);
}

public void loadProjectionMatrix(Matrix4f matrix){
    super.loadMatrix(location_projectionMatrix, matrix);
}

public void loadViewMatrix(Camera camera){
    Matrix4f matrix = Maths.createViewMatrix(camera);
    matrix.m30 = 0;
    matrix.m31 = 0;
    matrix.m32 = 0;
    super.loadMatrix(location_viewMatrix, matrix);
}

@Override
protected void getAllUniformLocations() {
    location_projectionMatrix = super.getUniformLocation("projectionMatrix");
    location_viewMatrix = super.getUniformLocation("viewMatrix");
}

@Override
protected void bindAttributes() {
    super.bindAttribute(0, "position");
}

}

общедоступный абстрактный класс ShaderProgram {

private int programID;
private int vertexShaderID;
private int fragmentShaderID;

private static FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16);
public ShaderProgram(String vertexFile, String fragmentFile) {
    vertexShaderID = loadShader(vertexFile, GL20.GL_VERTEX_SHADER);
    fragmentShaderID = loadShader(fragmentFile, GL20.GL_FRAGMENT_SHADER);
    programID = GL20.glCreateProgram();
    GL20.glAttachShader(programID, vertexShaderID);
    GL20.glAttachShader(programID, fragmentShaderID);
    bindAttributes();
    GL20.glLinkProgram(programID);
    GL20.glValidateProgram(programID);
    getAllUniformLocations();
}

protected abstract void getAllUniformLocations();

protected int getUniformLocation(String uniformName){
    return GL20.glGetUniformLocation(programID, uniformName); 
}

public void start(){
    GL20.glUseProgram(programID);
}

public void stop(){
    GL20.glUseProgram(0);
}

public void cleanUp(){
    stop();
    GL20.glDetachShader(programID, vertexShaderID);
    GL20.glDetachShader(programID, fragmentShaderID);
    GL20.glDeleteShader(vertexShaderID);
    GL20.glDeleteShader(fragmentShaderID);
    GL20.glDeleteProgram(programID);
}

protected abstract void bindAttributes();

protected void bindAttribute(int attribute, String variableName){
    GL20.glBindAttribLocation(programID, attribute, variableName);
}

protected void loadInt(int location, int value){
    GL20.glUniform1i(location, value);
}


protected void loadFloat(int location, float value){
    GL20.glUniform1f(location, value);
}

protected void loadVector(int location, Vector3f value){
    GL20.glUniform3f(location, value.x, value.y, value.z);
}

protected void load2DVector(int location, Vector2f value){
    GL20.glUniform2f(location, value.x, value.y);
}

protected void loadBoolean(int location, boolean value){
    float toLoad = 0;
    if(value)toLoad = 1;else toLoad = 0;
    GL20.glUniform1f(location, toLoad);
}

protected void loadMatrix(int location, Matrix4f matrix){
    matrix.store(matrixBuffer);
    matrixBuffer.flip();
    GL20.glUniformMatrix4(location, false, matrixBuffer);
}

private static int loadShader(String file, int type){
    StringBuilder shaderSource = new StringBuilder();
    try{
        BufferedReader reader = new BufferedReader(new FileReader(file));
        String line;
        while((line = reader.readLine()) != null){
            shaderSource.append(line).append("\n");
        }
        reader.close();
    }catch(IOException e){
        System.err.println("Could not read shader file!");
        e.printStackTrace();
        System.exit(-1);
    }
    int shaderID = GL20.glCreateShader(type);
    GL20.glShaderSource(shaderID, shaderSource);
    GL20.glCompileShader(shaderID);
    if(GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS)==GL11.GL_FALSE){
        System.out.println(GL20.glGetShaderInfoLog(shaderID, 500));
        System.out.println("Could not compile shader.");
        System.exit(-1);    
    }
    return shaderID;
}

}

скайбоксфрагментшейдер:

#version 400

in vec3 textureCoords;
out vec4 out_Color;

uniform samplerCube cubeMap;

void main(void){
    out_Color = texture(cubeMap, textureCoords);
}

SkyboxVertexShader

#version 400

in vec3 position;
out vec3 textureCoords;

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;

void main(void){

    gl_Position = projectionMatrix * viewMatrix * vec4(position, 1.0); 
    textureCoords = position;

}`

person Alice the Spider    schedule 13.12.2015    source источник
comment
как выглядит ваш код шейдера скайбокса?   -  person derhass    schedule 13.12.2015
comment
@derhass Я добавляю это в пост с вопросами, другие шейдеры работают отлично   -  person Alice the Spider    schedule 13.12.2015
comment
Являются ли текстуры, которые вы загружаете для кубической карты, квадратными?   -  person Reto Koradi    schedule 13.12.2015
comment
@RetoKoradi да текстуры 1024x1024   -  person Alice the Spider    schedule 13.12.2015
comment
@KodeKishin: вы до сих пор не включили фактический исходный код файлов шейдеров. Тот факт, что другие шейдеры работают, не очень помогает в этом вопросе. Ваш шейдер скайбокса должен правильно сэмплировать текстуру кубической карты, и совершенно неясно, делает он это или нет.   -  person derhass    schedule 13.12.2015
comment
@derhass, спасибо за помощь, я добавил и других, ты знаешь, почему скайбокс черный?   -  person Alice the Spider    schedule 13.12.2015


Ответы (1)


Текстура карты куба не является полным кубом:

Ваш код загрузчика перебирает все файлы в массиве, с которым он вызывается:

for(int i = 0; i < textureFiles.length;i++){
    // [...]
    GL11.glTexImage2D(GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, [...])
}

Однако ваш входной массив содержит всего 5 всего:

String[] TEXTURE_FILES = {"right","left","bottom","back","front"};

Вы предоставляете только 5 граней для куба и забыли «верхнюю» грань.

Согласно спецификации GL (цитаты из раздела 8.17 спецификации основного профиля OpenGL 4.5< /а>),

Текстура карты куба является завершенной MIP-картой, если каждое из шести изображений текстуры, рассматриваемых по отдельности, является завершенной MIP-картой. Кроме того, текстура карты куба является завершенной кубом, если выполняются все следующие условия:

  • Текстурные изображения level_base каждой из шести граней кубической карты имеют одинаковые положительные и квадратные размеры.

  • Каждое из изображений levelbase было указано с одним и тем же внутренним форматом.

Далее идет определение полноты текстуры:

Используя предыдущие определения, текстура считается завершенной, если не выполняется какое-либо из следующих условий:

  • [...]
  • Текстура представляет собой текстуру карты куба и не является полным кубом.
  • [...]

Итак, ваша текстура кубической карты не завершена.

Раздел 11.1.3.5 гласит:

Если в шейдере используется сэмплер, а связанная с ним текстура не завершена, как определено в разделе 8.17, (0; 0; 0; 1) будет возвращено для нетеневого сэмплера и 0 для теневого семплера.

Так что действительно, ваша кубическая карта должна выглядеть полностью черной.

person derhass    schedule 13.12.2015
comment
Большое спасибо :D @derhass - person Alice the Spider; 13.12.2015