PostProcessing
This commit is contained in:
45
postprocessing.fs
Normal file
45
postprocessing.fs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#version 330 core
|
||||||
|
in vec2 TexCoords;
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
uniform sampler2D scene;
|
||||||
|
uniform vec2 offsets[9];
|
||||||
|
uniform int edge_kernel[9];
|
||||||
|
uniform float blur_kernel[9];
|
||||||
|
|
||||||
|
uniform bool chaos;
|
||||||
|
uniform bool confuse;
|
||||||
|
uniform bool shake;
|
||||||
|
|
||||||
|
|
||||||
|
void main ()
|
||||||
|
{
|
||||||
|
color = vec4(0.0, 0.0,0.0,1.0);
|
||||||
|
vec3 sample[9];
|
||||||
|
|
||||||
|
if(chaos || shake)
|
||||||
|
for (int i = 0; i < 9; i++)
|
||||||
|
sample[i] = vec3(texture(scene,TexCoords.st + offsets[i]));
|
||||||
|
|
||||||
|
// process effects
|
||||||
|
if (chaos)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 9; i ++)
|
||||||
|
color += vec4(sample[i] * edge_kernel[i], 0.0);
|
||||||
|
color.a = 1.0;
|
||||||
|
}
|
||||||
|
else if (confuse)
|
||||||
|
{
|
||||||
|
color = vec4(1.0 - texture(scene, TexCoords).rgb, 1.0);
|
||||||
|
}
|
||||||
|
else if (shake)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 9; i++)
|
||||||
|
color += vec4(sample[i] * blur_kernel[i], 0.0);
|
||||||
|
color.a = 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color = texture(scene, TexCoords);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
postprocessing.vs
Normal file
36
postprocessing.vs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#version 330 core
|
||||||
|
layout (location = 0) in vec4 vertex;
|
||||||
|
|
||||||
|
out vec2 TexCoords;
|
||||||
|
|
||||||
|
uniform bool chaos;
|
||||||
|
uniform bool confuse;
|
||||||
|
uniform bool shake;
|
||||||
|
uniform float time;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(vertex.xy, 0.0, 1.0);
|
||||||
|
vec2 texture = vertex.zw;
|
||||||
|
if( chaos)
|
||||||
|
{
|
||||||
|
float strength = 0.3;
|
||||||
|
vec2 pos = vec2(texture.x + sin(time) * strength, texture.y + cos(time) * strength);
|
||||||
|
TexCoords = pos;
|
||||||
|
}
|
||||||
|
else if (confuse)
|
||||||
|
{
|
||||||
|
TexCoords = vec2(1.0 - texture.x, 1.0 - texture.y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TexCoords = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(shake)
|
||||||
|
{
|
||||||
|
float strength = 0.01;
|
||||||
|
gl_Position.x += cos(time * 10) * strength;
|
||||||
|
gl_Position.y += cos(time * 15) * strength;
|
||||||
|
}
|
||||||
|
}
|
||||||
47
src/game.cpp
47
src/game.cpp
@@ -1,5 +1,6 @@
|
|||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "particleGenerator.h"
|
#include "particleGenerator.h"
|
||||||
|
#include "postprocessor.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
@@ -7,6 +8,7 @@ typedef std::tuple<bool, Direction,glm::vec2> Collision;
|
|||||||
|
|
||||||
ParticleGenerator* Particles;
|
ParticleGenerator* Particles;
|
||||||
SpriteRenderer* Renderer;
|
SpriteRenderer* Renderer;
|
||||||
|
PostProcessor* effects;
|
||||||
|
|
||||||
// Initial size of the player paddle
|
// Initial size of the player paddle
|
||||||
const glm::vec2 PLAYER_SIZE (100.0f, 20.0f);
|
const glm::vec2 PLAYER_SIZE (100.0f, 20.0f);
|
||||||
@@ -89,6 +91,7 @@ Game::~Game()
|
|||||||
delete player;
|
delete player;
|
||||||
delete ball;
|
delete ball;
|
||||||
delete Particles;
|
delete Particles;
|
||||||
|
delete effects;
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::Game(unsigned int width, unsigned int height)
|
Game::Game(unsigned int width, unsigned int height)
|
||||||
@@ -102,13 +105,17 @@ void Game::Init()
|
|||||||
// Load shaders
|
// Load shaders
|
||||||
ResourceManager::LoadShader("shader.vs", "shader.fs", nullptr, "sprite");
|
ResourceManager::LoadShader("shader.vs", "shader.fs", nullptr, "sprite");
|
||||||
ResourceManager::LoadShader("particle.vs", "particle.fs", nullptr, "particle");
|
ResourceManager::LoadShader("particle.vs", "particle.fs", nullptr, "particle");
|
||||||
|
ResourceManager::LoadShader("postprocessing.vs", "postprocessing.fs", nullptr, "postprocessing");
|
||||||
// configure shaders
|
// configure shaders
|
||||||
glm::mat4 projection = glm::ortho(0.0f, static_cast<float>(this->Width), static_cast<float>(this->Height), 0.0f, -1.0f, 1.0f);
|
glm::mat4 projection = glm::ortho(0.0f, static_cast<float>(this->Width), static_cast<float>(this->Height), 0.0f, -1.0f, 1.0f);
|
||||||
ResourceManager::GetShader("sprite").Use().SetInteger("image", 0);
|
ResourceManager::GetShader("sprite").Use().SetInteger("image", 0);
|
||||||
ResourceManager::GetShader("sprite").SetMatrix4("projection", projection);
|
ResourceManager::GetShader("sprite").SetMatrix4("projection", projection);
|
||||||
ResourceManager::GetShader("particle").Use().SetMatrix4("projection", projection);
|
ResourceManager::GetShader("particle").Use().SetInteger("sprite", 0);
|
||||||
|
ResourceManager::GetShader("particle").SetMatrix4("projection", projection);
|
||||||
// set render-specific controls
|
// set render-specific controls
|
||||||
Renderer = new SpriteRenderer(ResourceManager::GetShader("sprite"));
|
Renderer = new SpriteRenderer(ResourceManager::GetShader("sprite"));
|
||||||
|
Particles = new ParticleGenerator(ResourceManager::GetShader("particle"), ResourceManager::GetTexture("particle"), 500);
|
||||||
|
effects = new PostProcessor(ResourceManager::GetShader("postprocessing"), this->Width, this->Height);
|
||||||
// load textures
|
// load textures
|
||||||
ResourceManager::LoadTexture("textures/awesomeface.png", true, "face");
|
ResourceManager::LoadTexture("textures/awesomeface.png", true, "face");
|
||||||
ResourceManager::LoadTexture("textures/background.jpg", false, "background");
|
ResourceManager::LoadTexture("textures/background.jpg", false, "background");
|
||||||
@@ -135,10 +142,10 @@ void Game::Init()
|
|||||||
|
|
||||||
ball = new BallObject(ballPos, BALL_RADIUS, INITIAL_BALL_VELOCITY, ResourceManager::GetTexture("face"));
|
ball = new BallObject(ballPos, BALL_RADIUS, INITIAL_BALL_VELOCITY, ResourceManager::GetTexture("face"));
|
||||||
|
|
||||||
Particles = new ParticleGenerator(ResourceManager::GetShader("particle"), ResourceManager::GetTexture("particle"), 500);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float ShakeTime = 0.0f;
|
||||||
|
|
||||||
void Game::DoCollisions()
|
void Game::DoCollisions()
|
||||||
{
|
{
|
||||||
@@ -153,6 +160,11 @@ void Game::DoCollisions()
|
|||||||
{
|
{
|
||||||
box.Destroyed = true;
|
box.Destroyed = true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ShakeTime = 0.05f;
|
||||||
|
effects->Shake = true;
|
||||||
|
}
|
||||||
// Collision resolution
|
// Collision resolution
|
||||||
Direction dir = std::get<1>(collision);
|
Direction dir = std::get<1>(collision);
|
||||||
glm::vec2 diff_vector = std::get<2>(collision);
|
glm::vec2 diff_vector = std::get<2>(collision);
|
||||||
@@ -236,28 +248,43 @@ void Game::Update(float dt)
|
|||||||
this->DoCollisions();
|
this->DoCollisions();
|
||||||
|
|
||||||
Particles->Update(dt, *ball, 2, glm::vec2(ball->Radius /2.0f));
|
Particles->Update(dt, *ball, 2, glm::vec2(ball->Radius /2.0f));
|
||||||
|
|
||||||
|
if(ShakeTime > 0.0f)
|
||||||
|
{
|
||||||
|
ShakeTime -= dt;
|
||||||
|
if (ShakeTime <= 0.0f)
|
||||||
|
effects->Shake = false;
|
||||||
|
}
|
||||||
|
|
||||||
if(ball->Position.y >= this->Height)
|
if(ball->Position.y >= this->Height)
|
||||||
{
|
{
|
||||||
this->ResetLevel();
|
this->ResetLevel();
|
||||||
this->ResetPlayer();
|
this->ResetPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::Render()
|
void Game::Render()
|
||||||
{
|
{
|
||||||
if(this->State == GAME_ACTIVE)
|
if(this->State == GAME_ACTIVE)
|
||||||
{
|
{
|
||||||
// draw background
|
effects->BeginRender();
|
||||||
Renderer->DrawSprite(ResourceManager::GetTexture("background"),
|
// draw background
|
||||||
glm::vec2(0.0f, 0.0f), glm::vec2(this->Width, this->Height), 0.0f);
|
Renderer->DrawSprite(ResourceManager::GetTexture("background"),
|
||||||
|
glm::vec2(0.0f, 0.0f), glm::vec2(this->Width, this->Height), 0.0f);
|
||||||
|
|
||||||
// draw level
|
// draw level
|
||||||
this->Levels[this->Level].Draw(*Renderer);
|
this->Levels[this->Level].Draw(*Renderer);
|
||||||
|
// draw player
|
||||||
|
player->Draw(*Renderer);
|
||||||
|
// draw particles
|
||||||
|
Particles->Draw();
|
||||||
|
// draw ball
|
||||||
|
ball->Draw(*Renderer);
|
||||||
|
|
||||||
player->Draw(*Renderer);
|
effects->EndRender();
|
||||||
Particles->Draw();
|
effects->Render(glfwGetTime());
|
||||||
ball->Draw(*Renderer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
123
src/postprocessor.cpp
Normal file
123
src/postprocessor.cpp
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
#include "postprocessor.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
PostProcessor::PostProcessor(Shader shader, unsigned int width, unsigned int height)
|
||||||
|
: postProcessingShader(shader), Texture(), Width(width), Height(height), Confuse(false), Chaos(false), Shake(false)
|
||||||
|
{
|
||||||
|
// initialize renderbuffer & framebuffer objects
|
||||||
|
glGenFramebuffers(1, &this->MSFBO);
|
||||||
|
glGenFramebuffers(1, &this->FBO);
|
||||||
|
glGenRenderbuffers(1, &this->RBO);
|
||||||
|
|
||||||
|
// initialize renderbuffer storage
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, this->MSFBO);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, this->RBO);
|
||||||
|
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGB, width, height);
|
||||||
|
// attach the renderbuffer to our framebuffer as a colour attachment
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, this->RBO);
|
||||||
|
|
||||||
|
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
{
|
||||||
|
std::cout << "ERROR::POSTPROCESSOR: Failed to initialize MSFBO" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init fbo & texture to lit multisampled color-buffer to
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, this->FBO);
|
||||||
|
this->Texture.Generate(width, height, NULL);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->Texture.ID, 0);
|
||||||
|
|
||||||
|
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
{
|
||||||
|
std::cout << "ERROR::POSTPROCESOR: Failed to initialize FBO" << std::endl;
|
||||||
|
}
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
this->initRenderData();
|
||||||
|
this->postProcessingShader.SetInteger("scene", 0 , true);
|
||||||
|
float offset = 1.0f/ 300.0f;
|
||||||
|
float offsets[9][2] = {
|
||||||
|
{ -offset, offset }, // top-left
|
||||||
|
{ 0.0f, offset }, // top-center
|
||||||
|
{ offset, offset }, // top-right
|
||||||
|
{ -offset, 0.0f }, // center-left
|
||||||
|
{ 0.0f, 0.0f }, // center-center
|
||||||
|
{ offset, 0.0f }, // center - right
|
||||||
|
{ -offset, -offset }, // bottom-left
|
||||||
|
{ 0.0f, -offset }, // bottom-center
|
||||||
|
{ offset, -offset } // bottom-right
|
||||||
|
};
|
||||||
|
glUniform2fv(glGetUniformLocation(this->postProcessingShader.ID, "offsets"), 9, (float*)offsets);
|
||||||
|
|
||||||
|
int edge_kernel[9] = {
|
||||||
|
-1, -1, -1,
|
||||||
|
-1, 8, -1,
|
||||||
|
-1, -1, -1
|
||||||
|
};
|
||||||
|
glUniform1iv(glGetUniformLocation(this->postProcessingShader.ID, "edge_kernel"), 9, edge_kernel);
|
||||||
|
|
||||||
|
float blur_kernel[9] = {
|
||||||
|
1.0f / 16.0f, 2.0f / 16.0f, 1.0f / 16.0f,
|
||||||
|
2.0f / 16.0f, 4.0f / 16.0f, 2.0f / 16.0f,
|
||||||
|
1.0f / 16.0f, 2.0f / 16.0f, 1.0f / 16.0f
|
||||||
|
};
|
||||||
|
glUniform1fv(glGetUniformLocation(this->postProcessingShader.ID, "blur_kernel"), 9, blur_kernel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PostProcessor::BeginRender()
|
||||||
|
{
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, this->MSFBO);
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PostProcessor::EndRender()
|
||||||
|
{
|
||||||
|
// Resolves multisampled texture into intermediat FBO for the texture
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, this->MSFBO);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, this->FBO);
|
||||||
|
glBlitFramebuffer(0,0, this->Width, this->Height, 0, 0, this->Width, this->Height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PostProcessor::Render(float time)
|
||||||
|
{
|
||||||
|
this->postProcessingShader.Use();
|
||||||
|
this->postProcessingShader.SetFloat("time", time);
|
||||||
|
this->postProcessingShader.SetInteger("confuse", this->Confuse);
|
||||||
|
this->postProcessingShader.SetInteger("chaos", this->Chaos);
|
||||||
|
this->postProcessingShader.SetInteger("shake", this->Shake);
|
||||||
|
|
||||||
|
// render textured quad
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
this->Texture.Bind();
|
||||||
|
glBindVertexArray(this->VAO);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PostProcessor::initRenderData()
|
||||||
|
{
|
||||||
|
unsigned int VBO;
|
||||||
|
float vertices[] = {
|
||||||
|
-1.0f, -1.0f, 0.0f, 0.0f,
|
||||||
|
1.0f, 1.0f, 1.0f, 1.0f,
|
||||||
|
-1.0f, 1.0f, 0.0f, 1.0f,
|
||||||
|
|
||||||
|
-1.0f, -1.0f, 0.0f, 0.0f,
|
||||||
|
1.0f, -1.0f, 1.0f, 0.0f,
|
||||||
|
1.0f, 1.0f, 1.0f, 1.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &this->VAO);
|
||||||
|
glGenBuffers(1, &VBO);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindVertexArray(this->VAO);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*) 0);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER,0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
|
||||||
|
}
|
||||||
32
src/postprocessor.h
Normal file
32
src/postprocessor.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "texture2d.h"
|
||||||
|
#include "spriterenderer.h"
|
||||||
|
#include "shader.h"
|
||||||
|
|
||||||
|
class PostProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Shader postProcessingShader;
|
||||||
|
Texture2D Texture;
|
||||||
|
unsigned int Width, Height;
|
||||||
|
|
||||||
|
bool Confuse, Chaos, Shake;
|
||||||
|
|
||||||
|
PostProcessor(Shader shader, unsigned int width, unsigned int height);
|
||||||
|
|
||||||
|
void BeginRender();
|
||||||
|
|
||||||
|
void EndRender();
|
||||||
|
|
||||||
|
void Render(float time);
|
||||||
|
private:
|
||||||
|
unsigned int MSFBO, FBO; // MSFBO = Multisample frame buffer object
|
||||||
|
unsigned int RBO;
|
||||||
|
unsigned int VAO;
|
||||||
|
|
||||||
|
void initRenderData();
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user