+ added an extra render pass to render the scene upside down (so it looks fine)

Signed-off-by: Alexis Maiquez <almamu@almamu.com>
This commit is contained in:
Alexis Maiquez 2021-09-03 03:24:55 +02:00
parent 16ed2f30de
commit 2ffb5f1b24
7 changed files with 259 additions and 68 deletions

View File

@ -231,10 +231,6 @@ int main (int argc, char* argv[])
// TODO: FIGURE OUT THE REQUIRED INPUT MODE, AS SOME WALLPAPERS USE THINGS LIKE MOUSE POSITION
// glfwSetInputMode (window, GLFW_STICKY_KEYS, GL_TRUE);
// set the scene clear color
auto sceneInformation = project->getWallpaper ()->as <WallpaperEngine::Core::CScene> ();
FloatColor clearColor = sceneInformation->getClearColor ();
// enable depth text
glEnable (GL_DEPTH_TEST);
glDepthFunc (GL_LESS);
@ -252,10 +248,8 @@ int main (int argc, char* argv[])
g_Time = (float) glfwGetTime ();
// get the start time of the frame
startTime = clock ();
// render the scene
wallpaper->render ();
// do buffer swapping
glfwSwapBuffers (window);
// poll for events (like closing the window)

View File

@ -22,6 +22,7 @@ CTexture::CTexture (void* fileData)
this->m_header->height = this->m_header->mipmaps [0]->height;
this->m_header->textureWidth = this->m_header->mipmaps [0]->width;
this->m_header->textureHeight = this->m_header->mipmaps [0]->height;
// TODO: MAYBE IT'S BETTER TO CREATE A TEXTURE OF THE GIVEN SIZE AND COPY OVER WHAT WE READ FROM THE FILE?
}
else
{
@ -86,7 +87,7 @@ CTexture::CTexture (void* fileData)
}
// TODO: USE THIS ONE
uint32_t blockSize = (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
// uint32_t blockSize = (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
auto cur = this->m_header->mipmaps.begin ();
auto end = this->m_header->mipmaps.end ();
@ -146,8 +147,6 @@ CTexture::CTexture (void* fileData)
FreeImage_CloseMemory (memory);
}
}
// TODO: IMPLEMENT SUPPORT FOR NORMAL IMAGES
}
CTexture::~CTexture ()

View File

@ -51,19 +51,23 @@ void CScene::render ()
auto cur = this->m_objects.begin ();
auto end = this->m_objects.end ();
// do not use any framebuffer for now
glBindFramebuffer (GL_FRAMEBUFFER, 0);
// ensure we render over the whole screen
glViewport (0, 0, projection->getWidth (), projection->getHeight ());
// clear screen
FloatColor clearColor = this->getScene ()->getClearColor ();
glClearColor (clearColor.r, clearColor.g, clearColor.b, clearColor.a);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// use the scene's framebuffer by default
glBindFramebuffer (GL_FRAMEBUFFER, this->getWallpaperFramebuffer());
// ensure we render over the whole screen
glViewport (0, 0, projection->getWidth (), projection->getHeight ());
for (; cur != end; cur ++)
(*cur)->render ();
// ensure we render over the whole screen
glViewport (0, 0, projection->getWidth (), projection->getHeight ());
CWallpaper::render ();
}
Core::CScene* CScene::getScene ()

View File

@ -1,7 +1,9 @@
#include "CWallpaper.h"
#include "CScene.h"
#include <utility>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace WallpaperEngine::Render;
@ -11,6 +13,34 @@ CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CCont
m_type (std::move(type))
{
this->setupFramebuffers ();
this->setupShaders ();
GLfloat texCoords [] = {
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f
};
// inverted positions so the final texture is rendered properly
GLfloat position [] = {
-1.0f, 1.0f, 0.0f,
1.0, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f
};
glGenBuffers (1, &this->m_texCoordBuffer);
glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
glBufferData (GL_ARRAY_BUFFER, sizeof (texCoords), texCoords, GL_STATIC_DRAW);
glGenBuffers (1, &this->m_positionBuffer);
glBindBuffer (GL_ARRAY_BUFFER, this->m_positionBuffer);
glBufferData (GL_ARRAY_BUFFER, sizeof (position), position, GL_STATIC_DRAW);
}
CWallpaper::~CWallpaper ()
@ -27,6 +57,161 @@ WallpaperEngine::Core::CWallpaper* CWallpaper::getWallpaperData ()
return this->m_wallpaperData;
}
GLuint CWallpaper::getWallpaperFramebuffer () const
{
return this->m_sceneFramebuffer;
}
GLuint CWallpaper::getWallpaperTexture () const
{
return this->m_sceneTexture;
}
void CWallpaper::setupShaders ()
{
// reserve shaders in OpenGL
GLuint vertexShaderID = glCreateShader (GL_VERTEX_SHADER);
// give shader's source code to OpenGL to be compiled
const char* sourcePointer = "#version 120\n"
"attribute vec3 a_Position;\n"
"attribute vec2 a_TexCoord;\n"
"varying vec2 v_TexCoord;\n"
"void main () {\n"
"gl_Position = vec4 (a_Position, 1.0);\n"
"v_TexCoord = a_TexCoord;\n"
"}";
glShaderSource (vertexShaderID, 1, &sourcePointer, nullptr);
glCompileShader (vertexShaderID);
GLint result = GL_FALSE;
int infoLogLength = 0;
// ensure the vertex shader was correctly compiled
glGetShaderiv (vertexShaderID, GL_COMPILE_STATUS, &result);
glGetShaderiv (vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0)
{
char* logBuffer = new char [infoLogLength + 1];
// ensure logBuffer ends with a \0
memset (logBuffer, 0, infoLogLength + 1);
// get information about the error
glGetShaderInfoLog (vertexShaderID, infoLogLength, nullptr, logBuffer);
// throw an exception about the issue
std::string message = logBuffer;
// free the buffer
delete[] logBuffer;
// throw an exception
throw std::runtime_error (message);
}
// reserve shaders in OpenGL
GLuint fragmentShaderID = glCreateShader (GL_FRAGMENT_SHADER);
// give shader's source code to OpenGL to be compiled
sourcePointer = "#version 120\n"
"uniform sampler2D g_Texture0;\n"
"varying vec2 v_TexCoord;\n"
"void main () {\n"
"gl_FragColor = texture2D (g_Texture0, v_TexCoord);\n"
"}";
glShaderSource (fragmentShaderID, 1, &sourcePointer, nullptr);
glCompileShader (fragmentShaderID);
result = GL_FALSE;
infoLogLength = 0;
// ensure the vertex shader was correctly compiled
glGetShaderiv (fragmentShaderID, GL_COMPILE_STATUS, &result);
glGetShaderiv (fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0)
{
char* logBuffer = new char [infoLogLength + 1];
// ensure logBuffer ends with a \0
memset (logBuffer, 0, infoLogLength + 1);
// get information about the error
glGetShaderInfoLog (fragmentShaderID, infoLogLength, nullptr, logBuffer);
// throw an exception about the issue
std::string message = logBuffer;
// free the buffer
delete[] logBuffer;
// throw an exception
throw std::runtime_error (message);
}
// create the final program
this->m_shader = glCreateProgram ();
// link the shaders together
glAttachShader (this->m_shader, vertexShaderID);
glAttachShader (this->m_shader, fragmentShaderID);
glLinkProgram (this->m_shader);
// check that the shader was properly linked
result = GL_FALSE;
infoLogLength = 0;
glGetProgramiv (this->m_shader, GL_LINK_STATUS, &result);
glGetProgramiv (this->m_shader, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0)
{
char* logBuffer = new char [infoLogLength + 1];
// ensure logBuffer ends with a \0
memset (logBuffer, 0, infoLogLength + 1);
// get information about the error
glGetProgramInfoLog (this->m_shader, infoLogLength, nullptr, logBuffer);
// throw an exception about the issue
std::string message = logBuffer;
// free the buffer
delete[] logBuffer;
// throw an exception
throw std::runtime_error (message);
}
// after being liked shaders can be dettached and deleted
glDetachShader (this->m_shader, vertexShaderID);
glDetachShader (this->m_shader, fragmentShaderID);
glDeleteShader (vertexShaderID);
glDeleteShader (fragmentShaderID);
// get textures
this->g_Texture0 = glGetUniformLocation (this->m_shader, "g_Texture0");
this->a_Position = glGetAttribLocation (this->m_shader, "a_Position");
this->a_TexCoord = glGetAttribLocation (this->m_shader, "a_TexCoord");
}
void CWallpaper::render ()
{
// write to default's framebuffer
glBindFramebuffer (GL_FRAMEBUFFER, GL_NONE);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable (GL_BLEND);
glDisable (GL_DEPTH_TEST);
// do not use any shader
glUseProgram (this->m_shader);
// activate scene texture
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, this->getWallpaperTexture ());
// set uniforms and attribs
glEnableVertexAttribArray (this->a_TexCoord);
glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
glVertexAttribPointer (this->a_TexCoord, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray (this->a_Position);
glBindBuffer (GL_ARRAY_BUFFER, this->m_positionBuffer);
glVertexAttribPointer (this->a_Position, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glUniform1i (this->g_Texture0, 0);
// write the framebuffer as is to the screen
glBindBuffer (GL_ARRAY_BUFFER, this->m_texCoordBuffer);
glDrawArrays (GL_TRIANGLES, 0, 6);
}
void CWallpaper::pinpongFramebuffer (GLuint* drawTo, GLuint* inputTexture)
{
// get current main framebuffer and texture so we can swap them
@ -47,7 +232,7 @@ void CWallpaper::pinpongFramebuffer (GLuint* drawTo, GLuint* inputTexture)
this->m_subTexture = currentMainTexture;
}
void CWallpaper::setupFramebuffers ()
void CWallpaper::createFramebuffer (GLuint* framebuffer, GLuint* depthbuffer, GLuint* texture)
{
int windowWidth = 1920;
int windowHeight = 1080;
@ -62,12 +247,12 @@ void CWallpaper::setupFramebuffers ()
GLenum drawBuffers [1] = {GL_COLOR_ATTACHMENT0};
// create the main framebuffer
glGenFramebuffers (1, &this->m_mainFramebuffer);
glBindFramebuffer (GL_FRAMEBUFFER, this->m_mainFramebuffer);
glGenFramebuffers (1, framebuffer);
glBindFramebuffer (GL_FRAMEBUFFER, *framebuffer);
// create the main texture
glGenTextures (1, &this->m_mainTexture);
glGenTextures (1, texture);
// bind the new texture to set settings on it
glBindTexture (GL_TEXTURE_2D, this->m_mainTexture);
glBindTexture (GL_TEXTURE_2D, *texture);
// give OpenGL an empty image
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, windowWidth, windowHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
@ -78,46 +263,24 @@ void CWallpaper::setupFramebuffers ()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// create the depth render buffer for the main framebuffer
glGenRenderbuffers (1, &this->m_mainDepthBuffer);
glBindRenderbuffer (GL_RENDERBUFFER, this->m_mainDepthBuffer);
glGenRenderbuffers (1, depthbuffer);
glBindRenderbuffer (GL_RENDERBUFFER, *depthbuffer);
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT, windowWidth, windowHeight);
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, this->m_mainDepthBuffer);
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *depthbuffer);
// set the texture as the colour attachmend #0
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->m_mainTexture, 0);
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texture, 0);
// finally set the list of draw buffers
glDrawBuffers (1, drawBuffers);
// ensure first framebuffer is okay
if (glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
throw std::runtime_error ("Framebuffers are not properly set");
// create the sub framebuffer
glGenFramebuffers (1, &this->m_subFramebuffer);
glBindFramebuffer (GL_FRAMEBUFFER, this->m_subFramebuffer);
// create the sub texture
glGenTextures (1, &this->m_subTexture);
// bind the new texture to set settings on it
glBindTexture (GL_TEXTURE_2D, this->m_subTexture);
// give OpenGL an empty image
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, windowWidth, windowHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
// set filtering parameters, otherwise the texture is not rendered
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);
// create the depth render buffer for the main framebuffer
glGenRenderbuffers (1, &this->m_subDepthBuffer);
glBindRenderbuffer (GL_RENDERBUFFER, this->m_subDepthBuffer);
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT, windowWidth, windowHeight);
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, this->m_subDepthBuffer);
// set the texture as the colour attachmend #0
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->m_subTexture, 0);
// finally set the list of draw buffers
glDrawBuffers (1, drawBuffers);
// ensure second framebuffer is okay
if (glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
throw std::runtime_error ("Framebuffers are not properly set");
}
void CWallpaper::setupFramebuffers ()
{
this->createFramebuffer (&this->m_mainFramebuffer, &this->m_mainDepthBuffer, &this->m_mainTexture);
this->createFramebuffer (&this->m_subFramebuffer, &this->m_subDepthBuffer, &this->m_subTexture);
// create framebuffer for the scene
this->createFramebuffer (&this->m_sceneFramebuffer, &this->m_sceneDepthBuffer, &this->m_sceneTexture);
}

View File

@ -32,7 +32,7 @@ namespace WallpaperEngine::Render
/**
* Performs a render pass of the wallpaper
*/
virtual void render () = 0;
virtual void render ();
/**
* @return The container to resolve files for this wallpaper
@ -47,7 +47,18 @@ namespace WallpaperEngine::Render
*/
void pinpongFramebuffer (GLuint* drawTo, GLuint* inputTexture);
/**
* @return The scene's framebuffer
*/
GLuint getWallpaperFramebuffer () const;
/**
* @return The scene's texture
*/
GLuint getWallpaperTexture () const;
protected:
void createFramebuffer (GLuint* framebuffer, GLuint* depthbuffer, GLuint* texture);
CContainer* m_container;
Core::CWallpaper* m_wallpaperData;
@ -81,9 +92,34 @@ namespace WallpaperEngine::Render
GLuint m_subTexture;
/**
* Setups OpenGL's framebuffers for ping-pong
* The framebuffer used for the scene output
*/
GLuint m_sceneFramebuffer;
/**
* The depthbuffer used for the scene output
*/
GLuint m_sceneDepthBuffer;
/**
* The texture used for the scene output
*/
GLuint m_sceneTexture;
GLuint m_texCoordBuffer;
GLuint m_positionBuffer;
GLuint m_shader;
// shader variables
GLint g_Texture0;
GLint g_ModelViewProjectionMatrix;
GLint a_Position;
GLint a_TexCoord;
/**
* Setups OpenGL's framebuffers for ping-pong and scene rendering
*/
void setupFramebuffers ();
/**
* Setups OpenGL's shaders for this wallpaper backbuffer
*/
void setupShaders ();
private:
/**

View File

@ -140,10 +140,8 @@ void CImage::render ()
if (this->getImage ()->isVisible () == false)
return;
GLuint drawTo = 0;
GLuint drawTo = this->getScene()->getWallpaperFramebuffer();
GLuint inputTexture = this->m_texture->getTextureID ();
// get the orthogonal projection
auto projection = this->getScene ()->getScene ()->getOrthogonalProjection ();
// pinpong current buffer
this->getScene ()->pinpongFramebuffer (&drawTo, nullptr);
@ -166,7 +164,7 @@ void CImage::render ()
this->getScene ()->pinpongFramebuffer (nullptr, &inputTexture);
// render the main material
this->m_material->render (0, inputTexture);
this->m_material->render (this->getScene()->getWallpaperFramebuffer(), inputTexture);
/*
glBindFramebuffer (GL_FRAMEBUFFER, 0);
// set the viewport, for now use the scene width/height but we might want to use image's size TODO: INVESTIGATE THAT

View File

@ -51,7 +51,7 @@ CPass::CPass (CMaterial* material, Core::Objects::Images::Materials::CPass* pass
void CPass::render (GLuint drawTo, GLuint input)
{
// clear whatever buffer we're drawing to if we're not drawing to screen
if (drawTo > 0)
if (drawTo != this->m_material->getImage()->getScene()->getWallpaperFramebuffer())
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// set texture blending
@ -95,7 +95,7 @@ void CPass::render (GLuint drawTo, GLuint input)
// this should not be required once we do some prediction on rendering things
// but for now should be enough
this->a_TexCoord = (input == this->m_material->getImage ()->getTexture ()->getTextureID ()) ? *this->m_material->getImage ()->getTexCoordBuffer () : *this->m_material->getImage ()->getPassTexCoordBuffer ();
this->a_Position = (drawTo > 0) ? *this->m_material->getImage ()->getPassVertexBuffer () : *this->m_material->getImage ()->getVertexBuffer ();
this->a_Position = (drawTo != this->m_material->getImage()->getScene()->getWallpaperFramebuffer()) ? *this->m_material->getImage ()->getPassVertexBuffer () : *this->m_material->getImage ()->getVertexBuffer ();
// use the shader we have registered
glUseProgram (this->m_programID);
@ -173,7 +173,7 @@ void CPass::render (GLuint drawTo, GLuint input)
}
// start actual rendering now
glBindBuffer (GL_ARRAY_BUFFER, (drawTo > 0) ? *this->m_material->getImage ()->getPassVertexBuffer () : *this->m_material->getImage ()->getVertexBuffer ());
glBindBuffer (GL_ARRAY_BUFFER, (drawTo != this->m_material->getImage()->getScene()->getWallpaperFramebuffer()) ? *this->m_material->getImage ()->getPassVertexBuffer () : *this->m_material->getImage ()->getVertexBuffer ());
glDrawArrays (GL_TRIANGLES, 0, 6);
// disable vertex attribs array
@ -270,10 +270,6 @@ void CPass::setupShaders ()
// support three textures for now
this->g_Texture0Rotation = glGetUniformLocation (this->m_programID, "g_Texture0Rotation");
this->g_Texture0Translation = glGetUniformLocation (this->m_programID, "g_Texture0Translation");
// bind a_TexCoord and a_Position
this->a_TexCoord = glGetAttribLocation (this->m_programID, "a_TexCoord");
this->a_Position = glGetAttribLocation (this->m_programID, "a_Position");
}
void CPass::setupAttributes ()
@ -413,8 +409,9 @@ void CPass::setupShaderVariables ()
CShaderVariable* var = vertexVar == nullptr ? pixelVar : vertexVar;
// ensure the shader's and the constant are of the same type
if ((*cur).second->getType () != var->getType ())
throw std::runtime_error ("Constant and pixel/vertex variable are not of the same type");
// TODO: CHECK THIS, THERE'S SOME BACKGROUNDS WHERE THIS HAPPENS :/
/*if ((*cur).second->getType () != var->getType ())
throw std::runtime_error ("Constant and pixel/vertex variable are not of the same type");*/
// now determine the constant's type and register the correct uniform for it
if ((*cur).second->is <CShaderConstantFloat> ())