2015-02-19 7 views
3

* Я старался изо всех сил реализовать реалистичные текстурные функции, используя фреймворчество OpenGL вместе с библиотекой LWJGL с Java. Тем не менее, результатом, который я всегда получаю, является 100% ** черная ** текстура. *OpenGL - Почему моя fbo/текстура остается черной?

Я просто прошу совета относительно проблемы. Я не создаю никаких конкретных фигур. Я связываю свой сгенерированный фреймбуфер и вызываю glClearColor(1, 0, 0, 1);, а затем glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);, а затем отвязываю фреймбуфер. Но когда я пытаюсь отобразить текстуру, связанную с фреймбуфером, текстура показывает только черную, где она на самом деле должна быть красной, верно?

Кроме того, glCheckFramebufferStatus() возвращает GL_FRAMEBUFFER_COMPLETE, поэтому я полагаю, что ошибка лежит внутри части рендеринга, а не фазы инициализации. Но я покажу код инициализации.

Код инициализации:

public RenderableTexture initialize(int width, int height, int internalFormat, int[] attachments, boolean useDepthBuffer) { 
    if(!GLContext.getCapabilities().GL_EXT_framebuffer_object) { 
     System.err.println("FrameBuffers not supported on your graphics card!"); 
    } 

    this.width = width; 
    this.height = height; 
    hasDepthBuffer = useDepthBuffer; 

    fbo = glGenFramebuffers(); 
    glBindFramebuffer(GL_FRAMEBUFFER, fbo); 

    id = glGenTextures(); 
    glBindTexture(GL_TEXTURE_2D, id); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 

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

    glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer) null); 


    if(useDepthBuffer) { 
     rbo = glGenRenderbuffers(); 
     glBindRenderbuffer(GL_RENDERBUFFER, rbo); 
     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); 
     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); 
    } 

    glFramebufferTexture2D(GL_FRAMEBUFFER, attachments[0], GL_TEXTURE_2D, id, 0); 

    int[] drawBuffers = new int[attachments.length]; 

    for(int i = 0; i < attachments.length; i++) 
     if(attachments[i] == GL_DEPTH_ATTACHMENT) 
      drawBuffers[i] = GL_NONE; 
     else 
      drawBuffers[i] = attachments[i]; 

    glDrawBuffers(Util.toIntBuffer(drawBuffers)); 

    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 
     System.err.println("Warning! Incomplete Framebuffer"); 
    glBindFramebuffer(GL_FRAMEBUFFER, 0); 

    return this; 
} 

internalFormat имеет значение GL_RGBA8 и width и height имеют значение 512 и 512. attachments[] содержит только 1 значение и это GL_COLOR_ATTACHMENT0. useDepthBuffer: true.

Вышеупомянутый код вызывается только один раз.

Это код рендеринга:

public RenderManager draw() { 
    glClearColor(bg.x, bg.y, bg.z, bg.w); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    texture.bindAsRenderTarget(true); 
    texture.releaseRenderTarget(); 
    quad.draw(); 

    return this; 
} 

Я установил четкий цвет на черный (0, 0, 0, 1), а затем очистить экран. Затем я звоню texture.bindAsRenderTarget(true);. Объект texture - это тот, который содержит метод initialize сверху, поэтому некоторые переменные распределяются между этим методом и bindAsRenderTarget().

Этот метод выглядит следующим образом:

public RenderableTexture bindAsRenderTarget(boolean clear) { 
    glViewport(0, 0, width, height); 
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); 
    glClearColor(1, 0, 0, 1f); 
    if(clear) 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    return this; 
} 

Как вы можете видеть, что я настроить окно просмотра с размером текстуры/фреймбуфером. Затем я связываю фреймбуфер и устанавливаю прозрачный цвет на красный. Затем, поскольку я прошел true в коде рендеринга, он (как я считаю) очищает связанный с ним фреймбуфер до красного.

texture.releaseRenderTarget(); регулирует видовой экран, чтобы соответствовать дисплей, а затем вызывает glBindFramebuffer(GL_FRAMEBUFFER, 0);

Последняя строка кода quad.draw(); просто связывает textureID текстуры, связанной с фреймбуфером, а затем рисует простой четырехугольник с ним.

Это почти все есть.

Я могу заверить, что я правильно представляю квадрат, так как я могу привязать текстуры, загруженные из файлов PNG, к нему, и текстура успешно показана.

Итак, чтобы сделать вещи ясно, главный вопрос, довольно много:

Почему на земле текстура черный после того, как ясно, как это должно быть красным? Где и что я делаю неправильно?

EDIT: У меня такое чувство, что это может иметь отношение к ограничению разных объектов. Должен ли renderbuffer привязываться в точке рендеринга к его фреймбуу? Не так ли? Это имеет значение? Как насчет текстуры? в какие моменты они должны быть?

+0

Когда вы закончите рисовать текстуру фреймбуфера и освободили фреймбуфер, перед тем, как вы хотите снова отобразить обратно буфер, попробуйте glDrawBuffer (GL_BACK) ; – Robinson

+0

Спасибо за ответ Робинсон :) К сожалению, это не решило ответ. Проблема, вероятно, заключается в рендеринге fbo, а не в обратном буфере. – SporreKing

+0

Ну, это неясно из вашего кода, если проблема на самом деле является рендерингом _into_ текстуры/FBO, или если она передает текстуру в стандартный фреймбуфер. – derhass

ответ

1

Я сделал что-то очень глупое. Класс, который я инициализировал текстуру fbo внутри (RenderableTextue.class), был подклассом Texture.class. Предполагалось, что метод привязки, включающий textID, должен быть унаследован от класса Texture, поскольку я объявил переменную id как protected. Тем не менее, я случайно создал локальную переменную private в подклассе и, таким образом, при создании текстуры, сохраняя textIDID в локальной переменной id и при привязке, используя неинициализированный идентификатор из суперкласса. Извините за тех, кто пытается решить эту проблему, не имея возможности сделать это: s

Смежные вопросы