Nove repo opengl-learning
This commit is contained in:
@@ -0,0 +1,409 @@
|
||||
#include "Framebuffer.h"
|
||||
#include <glad/glad.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "DebugColors.h"
|
||||
#include <stb_image_write.h>
|
||||
#include <ctime>
|
||||
|
||||
int checkFramebufferStatus()
|
||||
{
|
||||
int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case GL_FRAMEBUFFER_COMPLETE:
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Framebuffer.h: " DC_ERROR " code: %#04x\n", (int)status);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Framebuffer::Framebuffer(const int& width, const int& height)
|
||||
{
|
||||
glGenFramebuffers(1, &ID);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ID);
|
||||
|
||||
glGenTextures(1, &ColorBuffer);
|
||||
glBindTexture(GL_TEXTURE_2D, ColorBuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ColorBuffer, 0);
|
||||
|
||||
glGenRenderbuffers(1, &DepthStencilBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, DepthStencilBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, DepthStencilBuffer);
|
||||
|
||||
if (checkFramebufferStatus() != 0)
|
||||
{
|
||||
glDeleteRenderbuffers(1, &DepthStencilBuffer);
|
||||
glDeleteTextures(1, &ColorBuffer);
|
||||
glDeleteFramebuffers(1, &ID);
|
||||
std::cerr << "Framebuffer.h: " DC_ERROR " Could not create framebuffer object." << std::endl;
|
||||
ID = 0;
|
||||
return;
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
}
|
||||
Framebuffer::~Framebuffer()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
void Framebuffer::destroy()
|
||||
{
|
||||
glDeleteRenderbuffers(1, &DepthStencilBuffer);
|
||||
glDeleteTextures(1, &ColorBuffer);
|
||||
glDeleteFramebuffers(1, &ID);
|
||||
}
|
||||
void Framebuffer::UpdateSize(const unsigned int& newWidth, const unsigned int& newHeight)
|
||||
{
|
||||
if (!checkBind())
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ID);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, ColorBuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, newWidth, newHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glDeleteRenderbuffers(1, &DepthStencilBuffer);
|
||||
glGenRenderbuffers(1, &DepthStencilBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, DepthStencilBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, newWidth, newHeight);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, DepthStencilBuffer);
|
||||
}
|
||||
void Framebuffer::Use()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ID);
|
||||
}
|
||||
void Framebuffer::UseDefault()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
void Framebuffer::clearBuffers(float r, float g, float b, float a)
|
||||
{
|
||||
if (!checkBind())
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ID);
|
||||
glClearColor(r, g, b, a);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
void Framebuffer::clearColorBuffer(float r, float g, float b, float a)
|
||||
{
|
||||
if (!checkBind())
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ID);
|
||||
glClearColor(r, g, b, a);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
void Framebuffer::clearDepthBuffer()
|
||||
{
|
||||
if (!checkBind())
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ID);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
void Framebuffer::clearStencilBuffer()
|
||||
{
|
||||
if (!checkBind())
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ID);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
void Framebuffer::clearDepthStencilBuffer()
|
||||
{
|
||||
if (!checkBind())
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ID);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
unsigned int Framebuffer::getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
unsigned int Framebuffer::getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
bool Framebuffer::checkBind()
|
||||
{
|
||||
int id = 0;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &id);
|
||||
if ((unsigned int)id == ID)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
unsigned int Framebuffer::getColorBuffer()
|
||||
{
|
||||
return ColorBuffer;
|
||||
}
|
||||
unsigned int Framebuffer::getDepthSnectilBuffer()
|
||||
{
|
||||
return DepthStencilBuffer;
|
||||
}
|
||||
std::string Framebuffer::screenshot(std::string path)
|
||||
{
|
||||
int id = 0;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &id);
|
||||
|
||||
unsigned char *data = new unsigned char[(int)width * (int)height * 4];
|
||||
this->Use();
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
stbi_flip_vertically_on_write(1);
|
||||
std::string scr_name = path + "/" + getScreenshotName();
|
||||
stbi_write_png(scr_name.c_str(), width, height, 4, data, 4 * width);
|
||||
delete data;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, (unsigned int)id);
|
||||
|
||||
return scr_name;
|
||||
}
|
||||
|
||||
MSFramebuffer::MSFramebuffer(const int& width, const int& height, const unsigned int samples)
|
||||
: Nsamples(samples), intermediateFBO(NULL)
|
||||
{
|
||||
glGenFramebuffers(1, &ID);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ID);
|
||||
|
||||
glGenTextures(1, &ColorBuffer);
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, ColorBuffer);
|
||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGB, width, height, GL_TRUE);
|
||||
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, ColorBuffer, 0);
|
||||
|
||||
glGenRenderbuffers(1, &DepthStencilBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, DepthStencilBuffer);
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH24_STENCIL8, width, height);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, DepthStencilBuffer);
|
||||
|
||||
if (checkFramebufferStatus() != 0)
|
||||
{
|
||||
glDeleteRenderbuffers(1, &DepthStencilBuffer);
|
||||
glDeleteTextures(1, &ColorBuffer);
|
||||
glDeleteFramebuffers(1, &ID);
|
||||
std::cerr << "Framebuffer.h: " DC_ERROR " Could not create multisampled framebuffer object." << std::endl;
|
||||
ID = 0;
|
||||
return;
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
|
||||
intermediateFBO = new Framebuffer(width, height);
|
||||
}
|
||||
MSFramebuffer::~MSFramebuffer()
|
||||
{
|
||||
destroy();
|
||||
delete intermediateFBO;
|
||||
}
|
||||
std::string MSFramebuffer::screenshot(std::string path)
|
||||
{
|
||||
int id = 0;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &id);
|
||||
|
||||
unsigned char *data = new unsigned char[width * height * 4];
|
||||
getColorBuffer();
|
||||
intermediateFBO->Use();
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
stbi_flip_vertically_on_write(1);
|
||||
std::string scr_name = path + "/" + getScreenshotName();
|
||||
stbi_write_png(scr_name.c_str(), width, height, 4, data, 4 * width);
|
||||
delete data;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, (unsigned int)id);
|
||||
|
||||
return scr_name;
|
||||
}
|
||||
void MSFramebuffer::UpdateSize(const unsigned int& newWidth, const unsigned int& newHeight)
|
||||
{
|
||||
if (!checkBind())
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ID);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, ColorBuffer);
|
||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, Nsamples, GL_RGBA, newWidth, newHeight, GL_TRUE);
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
|
||||
|
||||
glDeleteRenderbuffers(1, &DepthStencilBuffer);
|
||||
glGenRenderbuffers(1, &DepthStencilBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, DepthStencilBuffer);
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, Nsamples, GL_DEPTH24_STENCIL8, newWidth, newHeight);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, DepthStencilBuffer);
|
||||
}
|
||||
unsigned int MSFramebuffer::getColorBuffer()
|
||||
{
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, ID);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediateFBO->ID);
|
||||
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
|
||||
return intermediateFBO->getColorBuffer();
|
||||
}
|
||||
unsigned int MSFramebuffer::getDepthSnectilBuffer()
|
||||
{
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, ID);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediateFBO->ID);
|
||||
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
|
||||
return intermediateFBO->getDepthSnectilBuffer();
|
||||
}
|
||||
unsigned int MSFramebuffer::getColorBufferMS()
|
||||
{
|
||||
return ColorBuffer;
|
||||
}
|
||||
|
||||
/* Static functions */
|
||||
void Framebuffer::clearAllBuffers(float r, float g, float b, float a)
|
||||
{
|
||||
glClearColor(r, g, b, a);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
std::string Framebuffer::getScreenshotName()
|
||||
{
|
||||
time_t tim = time(NULL);
|
||||
struct tm *ltm = localtime(&tim);
|
||||
|
||||
char buf[50];
|
||||
snprintf(buf, sizeof(buf), "screenshot_%i%02i%02i_%02i%02i%02i.png",
|
||||
ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec);
|
||||
return std::string(buf);
|
||||
}
|
||||
std::string Framebuffer::screenshot_defaultFBO(unsigned int width, unsigned int height, std::string path)
|
||||
{
|
||||
int id = 0;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &id);
|
||||
|
||||
uint8_t *data = new uint8_t[width * height * 4];
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
stbi_flip_vertically_on_write(1);
|
||||
std::string scr_name = path + "/" + getScreenshotName();
|
||||
stbi_write_png(scr_name.c_str(), width, height, 4, data, 4 * width);
|
||||
delete[] data;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, (unsigned int)id);
|
||||
return scr_name;
|
||||
}
|
||||
|
||||
/* Depthmap Framebuffer */
|
||||
DepthmapFramebuffer::DepthmapFramebuffer(const Resolution& resolution) : resolution(resolution), depth_texture(0), ID(0)
|
||||
{
|
||||
glGenFramebuffers(1, &ID);
|
||||
glGenTextures(1, &depth_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, depth_texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, resolution.Width, resolution.Height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||
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_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
float borderColor[]{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ID);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0);
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
|
||||
if (checkFramebufferStatus() != 0)
|
||||
{
|
||||
glDeleteFramebuffers(1, &ID);
|
||||
glDeleteTextures(1, &depth_texture);
|
||||
std::cerr << "Framebuffer.h " << DC_ERROR << " Could not create Depthmap Framebuffer object.\n";
|
||||
ID = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
DepthmapFramebuffer::DepthmapFramebuffer(const unsigned int& width, const unsigned int& height) :
|
||||
DepthmapFramebuffer(Resolution{width, height})
|
||||
{}
|
||||
DepthmapFramebuffer::~DepthmapFramebuffer()
|
||||
{
|
||||
glDeleteFramebuffers(1, &ID);
|
||||
glDeleteTextures(1, &depth_texture);
|
||||
}
|
||||
void DepthmapFramebuffer::Use() const
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ID);
|
||||
}
|
||||
void DepthmapFramebuffer::Use(GLenum target) const
|
||||
{
|
||||
glBindFramebuffer(target, ID);
|
||||
}
|
||||
unsigned int DepthmapFramebuffer::GetDepthTexture() const
|
||||
{
|
||||
return depth_texture;
|
||||
}
|
||||
void DepthmapFramebuffer::ClearDepthBuffer() const
|
||||
{
|
||||
Use();
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
/* DepthCubemap Framebuffer */
|
||||
DepthCubeFramebuffer::DepthCubeFramebuffer(int width, int height) : Width(width), Height(height)
|
||||
{
|
||||
init();
|
||||
}
|
||||
DepthCubeFramebuffer::~DepthCubeFramebuffer()
|
||||
{
|
||||
glDeleteFramebuffers(1, &ID);
|
||||
glDeleteTextures(1, &depthCubemap);
|
||||
}
|
||||
void DepthCubeFramebuffer::init()
|
||||
{
|
||||
glGenTextures(1, &depthCubemap);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubemap);
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, Width, Height, 0,
|
||||
GL_DEPTH_COMPONENT, GL_FLOAT, 0);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
|
||||
glGenFramebuffers(1, &ID);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, ID);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthCubemap, 0);
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
if (checkFramebufferStatus() != 0)
|
||||
{
|
||||
ID = 0;
|
||||
}
|
||||
}
|
||||
unsigned int DepthCubeFramebuffer::getDepthCubemap() const
|
||||
{
|
||||
return depthCubemap;
|
||||
}
|
||||
void DepthCubeFramebuffer::clearDepth() const
|
||||
{
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
void DepthCubeFramebuffer::Use() const
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
Reference in New Issue
Block a user