202 lines
5.6 KiB
C++
202 lines
5.6 KiB
C++
#include "GBuffer.hpp"
|
|
|
|
#include <GL/glew.h>
|
|
|
|
#include "debug/Logger.hpp"
|
|
|
|
static debug::Logger logger("gl-gbuffer");
|
|
|
|
void GBuffer::createColorBuffer() {
|
|
glGenTextures(1, &colorBuffer);
|
|
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
|
glTexImage2D(
|
|
GL_TEXTURE_2D,
|
|
0,
|
|
GL_RGB,
|
|
width,
|
|
height,
|
|
0,
|
|
GL_RGB,
|
|
GL_UNSIGNED_BYTE,
|
|
nullptr
|
|
);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glFramebufferTexture2D(
|
|
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0
|
|
);
|
|
}
|
|
|
|
void GBuffer::createPositionsBuffer() {
|
|
glGenTextures(1, &positionsBuffer);
|
|
glBindTexture(GL_TEXTURE_2D, positionsBuffer);
|
|
glTexImage2D(
|
|
GL_TEXTURE_2D,
|
|
0,
|
|
GL_RGBA16F,
|
|
width,
|
|
height,
|
|
0,
|
|
GL_RGBA,
|
|
GL_FLOAT,
|
|
nullptr
|
|
);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glFramebufferTexture2D(
|
|
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, positionsBuffer, 0
|
|
);
|
|
}
|
|
|
|
void GBuffer::createNormalsBuffer() {
|
|
glGenTextures(1, &normalsBuffer);
|
|
glBindTexture(GL_TEXTURE_2D, normalsBuffer);
|
|
glTexImage2D(
|
|
GL_TEXTURE_2D,
|
|
0,
|
|
GL_RGBA16F,
|
|
width,
|
|
height,
|
|
0,
|
|
GL_RGBA,
|
|
GL_FLOAT,
|
|
nullptr
|
|
);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glFramebufferTexture2D(
|
|
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normalsBuffer, 0
|
|
);
|
|
}
|
|
|
|
void GBuffer::createDepthBuffer() {
|
|
glGenRenderbuffers(1, &depthBuffer);
|
|
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
|
glFramebufferRenderbuffer(
|
|
GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer
|
|
);
|
|
}
|
|
|
|
GBuffer::GBuffer(uint width, uint height) : width(width), height(height) {
|
|
glGenFramebuffers(1, &fbo);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
|
|
|
createColorBuffer();
|
|
createPositionsBuffer();
|
|
createNormalsBuffer();
|
|
|
|
GLenum attachments[3] = {
|
|
GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2
|
|
};
|
|
glDrawBuffers(3, attachments);
|
|
|
|
createDepthBuffer();
|
|
|
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
|
logger.error() << "framebuffer is not complete!";
|
|
}
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
GBuffer::~GBuffer() {
|
|
glDeleteTextures(1, &colorBuffer);
|
|
glDeleteTextures(1, &positionsBuffer);
|
|
glDeleteTextures(1, &normalsBuffer);
|
|
glDeleteRenderbuffers(1, &depthBuffer);
|
|
glDeleteFramebuffers(1, &fbo);
|
|
}
|
|
|
|
void GBuffer::bind() {
|
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
}
|
|
|
|
void GBuffer::unbind() {
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
void GBuffer::bindBuffers() const {
|
|
glActiveTexture(GL_TEXTURE2);
|
|
glBindTexture(GL_TEXTURE_2D, normalsBuffer);
|
|
|
|
glActiveTexture(GL_TEXTURE1);
|
|
glBindTexture(GL_TEXTURE_2D, positionsBuffer);
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
|
}
|
|
|
|
void GBuffer::resize(uint width, uint height) {
|
|
if (this->width == width && this->height == height) {
|
|
return;
|
|
}
|
|
this->width = width;
|
|
this->height = height;
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
|
glTexImage2D(
|
|
GL_TEXTURE_2D,
|
|
0,
|
|
GL_RGB,
|
|
width,
|
|
height,
|
|
0,
|
|
GL_RGB,
|
|
GL_UNSIGNED_BYTE,
|
|
nullptr
|
|
);
|
|
glFramebufferTexture2D(
|
|
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0
|
|
);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, positionsBuffer);
|
|
glTexImage2D(
|
|
GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, nullptr
|
|
);
|
|
glFramebufferTexture2D(
|
|
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, positionsBuffer, 0
|
|
);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, normalsBuffer);
|
|
glTexImage2D(
|
|
GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, nullptr
|
|
);
|
|
glFramebufferTexture2D(
|
|
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normalsBuffer, 0
|
|
);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
std::unique_ptr<ImageData> GBuffer::toImage() const {
|
|
auto data = std::make_unique<ubyte[]>(width * height * 3);
|
|
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, data.get());
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
return std::make_unique<ImageData>(
|
|
ImageFormat::rgb888, width, height, std::move(data)
|
|
);
|
|
}
|
|
|
|
uint GBuffer::getWidth() const {
|
|
return width;
|
|
}
|
|
|
|
uint GBuffer::getHeight() const {
|
|
return height;
|
|
}
|