227 lines
6.8 KiB
C++
227 lines
6.8 KiB
C++
#include "pixelpipeline.h"
|
|
#include <framebuffer.h>
|
|
#include <texture.h>
|
|
#include <shader.h>
|
|
#include <cstring>
|
|
#include <glm/vec2.hpp>
|
|
#include <qtutils.h>
|
|
#include "mapscene.h"
|
|
#include <parametricmesh.h>
|
|
#include <glm/ext.hpp>
|
|
|
|
#define SCROLL_SPEED 0.998f
|
|
|
|
#define HEX_TO_VEC3(hex) glm::vec3(float((hex & 0xFF0000) >> 16)/255, float((hex & 0x00FF00) >> 8)/255, float(hex & 0x0000FF)/255)
|
|
|
|
inline glm::vec3 getColor(const Pixel &p)
|
|
{
|
|
switch(p.type){
|
|
case Pixel::BEDROCK : return HEX_TO_VEC3(0x101020);
|
|
case Pixel::GRASS : return HEX_TO_VEC3(0x719678);
|
|
case Pixel::MARK : return HEX_TO_VEC3(0x5D7B62);
|
|
case Pixel::ROCK : return HEX_TO_VEC3(0x8C8C8C);
|
|
case Pixel::IRON_ORE : return HEX_TO_VEC3(0x917B61);
|
|
case Pixel::TREE : return HEX_TO_VEC3(0x003800);
|
|
case Pixel::BERRIES : return HEX_TO_VEC3(0x4D6394);
|
|
case Pixel::FOOD : return HEX_TO_VEC3(0xFF7A7A);
|
|
case Pixel::WOOD : return HEX_TO_VEC3(0x634A22);
|
|
case Pixel::STONE : return HEX_TO_VEC3(0x454545);
|
|
case Pixel::IRON : return HEX_TO_VEC3(0x4A4036);
|
|
case Pixel::DUDE :
|
|
// TODO
|
|
return HEX_TO_VEC3(0x0000FF);
|
|
case Pixel::SPAWN :
|
|
// TODO
|
|
return HEX_TO_VEC3(0x0000FF);
|
|
case Pixel::WALL : return HEX_TO_VEC3(0xE6B2A1);
|
|
case Pixel::ROAD : return HEX_TO_VEC3(0xEDB287);
|
|
case Pixel::SWORD : return HEX_TO_VEC3(0xEBEBEB);
|
|
case Pixel::LIBRARY : return HEX_TO_VEC3(0xA37A50);
|
|
case Pixel::DEAD_DUDE : return HEX_TO_VEC3(0xFF0000);
|
|
default : return HEX_TO_VEC3(0x0000FF); // bleu absolu = bug
|
|
}
|
|
}
|
|
|
|
class ToreillerGenerator : public MeshGenerator
|
|
{
|
|
public:
|
|
virtual glm::vec3 evalUV(float u, float v)
|
|
{
|
|
const float MAGIC_RATIO = 1;
|
|
|
|
glm::vec2 relUV = glm::vec2(u-0.5f, v-0.5f);
|
|
float clockAngle = atan2(relUV.y, relUV.x);
|
|
float depthAngle = glm::length(relUV)*3.1416f*MAGIC_RATIO;
|
|
float r = sin(depthAngle);
|
|
return glm::vec3(r*cos(clockAngle), r*sin(clockAngle), cos(depthAngle)-1);
|
|
}
|
|
};
|
|
|
|
// MESH (2D points)
|
|
|
|
class PixelMesh
|
|
{
|
|
private:
|
|
GLuint m_vao;
|
|
GLuint m_vbo;
|
|
|
|
public:
|
|
struct Pix
|
|
{
|
|
glm::vec2 pos;
|
|
glm::vec3 color;
|
|
};
|
|
|
|
std::vector<Pix> m_pixels;
|
|
|
|
PixelMesh(int size)
|
|
{
|
|
glGenVertexArrays(1, &m_vao);
|
|
glBindVertexArray(m_vao);
|
|
|
|
glGenBuffers(1, &m_vbo);
|
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
|
glEnableVertexAttribArray(0);
|
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Pix), (void*)(0));
|
|
glEnableVertexAttribArray(1);
|
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Pix), (void*)(sizeof(glm::vec2)));
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
glBindVertexArray(0);
|
|
}
|
|
|
|
~PixelMesh()
|
|
{
|
|
if(m_vao != 0)
|
|
{
|
|
glDeleteBuffers(1, &m_vbo);
|
|
glDeleteVertexArrays(1, &m_vao);
|
|
m_vao = 0;
|
|
}
|
|
}
|
|
|
|
void draw()
|
|
{
|
|
glDisable(GL_BLEND);
|
|
glDisable(GL_DEPTH_TEST);
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
glBindVertexArray(m_vao);
|
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
|
glBufferData(GL_ARRAY_BUFFER, m_pixels.size() * sizeof(Pix), m_pixels.data(), GL_DYNAMIC_DRAW);
|
|
glDrawArrays(GL_POINTS, 0, m_pixels.size());
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glBindVertexArray(0);
|
|
m_pixels.clear();
|
|
}
|
|
};
|
|
|
|
// PIPELINE
|
|
|
|
PixelPipeline::PixelPipeline(MapScene *map) :
|
|
m_mapWidth(map->getWidth()),
|
|
m_mapHeight(map->getHeight()),
|
|
m_camera(0, 0, 1)
|
|
{
|
|
m_width = 256;
|
|
m_height = 256;
|
|
map->setPipeline(this);
|
|
m_targetFBO = FrameBuffer::screen;
|
|
m_mapFBO = new FrameBuffer();
|
|
m_mapTex = new Texture(GL_RGBA, GL_RGBA, m_mapWidth, m_mapHeight, GL_UNSIGNED_BYTE, GL_TEXTURE_RECTANGLE);
|
|
m_mapTex->setFiltering(GL_NEAREST);
|
|
m_mapTex->setWrap(GL_CLAMP_TO_EDGE);
|
|
m_mapFBO->addTexture(m_mapTex, GL_COLOR_ATTACHMENT0);
|
|
m_mapFBO->initColorAttachments();
|
|
|
|
// set up vao
|
|
|
|
ToreillerGenerator gen;
|
|
m_toreiller = gen.generateParametricMesh(NULL, 40, 40, 1.0f);
|
|
m_toreiller->computeNormals();
|
|
m_toreiller->mergeVertices();
|
|
m_toreiller->initGL();
|
|
|
|
std::string vertSource = QtUtils::fileToString(":shaders/shaders/pixel.vert.glsl").toStdString();
|
|
std::string fragSource = QtUtils::fileToString(":shaders/shaders/pixel.frag.glsl").toStdString();
|
|
m_texMapShader = new Shader(vertSource, fragSource);
|
|
vertSource = QtUtils::fileToString(":shaders/shaders/world.vert.glsl").toStdString();
|
|
fragSource = QtUtils::fileToString(":shaders/shaders/world.frag.glsl").toStdString();
|
|
m_renderShader = new Shader(vertSource, fragSource);
|
|
m_changes = new PixelMesh(map->getWidth() * map->getHeight());
|
|
for(int i=0; i<map->getWidth(); ++i)
|
|
for(int j=0; j<map->getHeight(); ++j)
|
|
pushChange(glm::vec2(i, j), getColor((*map)[i][j]));
|
|
updateChanges();
|
|
}
|
|
|
|
PixelPipeline::~PixelPipeline()
|
|
{
|
|
delete m_mapFBO;
|
|
delete m_mapTex;
|
|
delete m_texMapShader;
|
|
delete m_renderShader;
|
|
delete m_changes;
|
|
}
|
|
|
|
void PixelPipeline::pushChange(const glm::vec2 &pos, const glm::vec3 &color)
|
|
{
|
|
m_changes->m_pixels.push_back({pos, color});
|
|
}
|
|
|
|
void PixelPipeline::updateChanges()
|
|
{
|
|
if(!m_changes->m_pixels.empty())
|
|
{
|
|
m_mapFBO->bindFBO();
|
|
glViewport(0, 0, m_mapWidth, m_mapHeight);
|
|
m_texMapShader->bind();
|
|
m_texMapShader->bindVec2(m_texMapShader->getLocation("texRatio"), glm::vec2(2.0f/m_mapWidth, 2.0f/m_mapHeight));
|
|
m_changes->draw();
|
|
}
|
|
}
|
|
|
|
void PixelPipeline::renderGL(Scene *scene)
|
|
{
|
|
m_targetFBO->bindFBO();
|
|
glViewport(0, 0, m_width, m_height);
|
|
glClearColor(0, 0, 0, 1);
|
|
glDisable(GL_BLEND);
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
m_renderShader->bind();
|
|
m_renderShader->bindVec3(m_renderShader->getLocation("camera"), m_camera);
|
|
m_renderShader->bindVec2(m_renderShader->getLocation("worldSize"), glm::vec2(m_mapWidth, m_mapHeight));
|
|
m_renderShader->bindVec2(m_renderShader->getLocation("screenSize"), glm::vec2(m_width, m_height));
|
|
m_mapTex->bind(0);
|
|
m_renderShader->bindInteger(m_renderShader->getLocation("colorMap"), 0);
|
|
|
|
glClearDepth(1);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
glEnable(GL_DEPTH_TEST);
|
|
m_renderShader->bindMat4(m_renderShader->getLocation("mvp"), m_mvp);
|
|
m_toreiller->draw(m_renderShader);
|
|
}
|
|
|
|
void PixelPipeline::resizeGL(int w, int h)
|
|
{
|
|
m_width = w;
|
|
m_height = h;
|
|
m_mvp = glm::translate(glm::perspectiveFov(70.f, float(w), float(h), 0.1f, 10.f), glm::vec3(0, 0, -3));
|
|
}
|
|
|
|
void PixelPipeline::cameraZoom(int nbScrolls)
|
|
{
|
|
while(nbScrolls != 0)
|
|
{
|
|
if(nbScrolls > 0)
|
|
{
|
|
m_camera.z *= SCROLL_SPEED;
|
|
--nbScrolls;
|
|
}
|
|
else
|
|
{
|
|
m_camera.z /= SCROLL_SPEED;
|
|
++nbScrolls;
|
|
}
|
|
}
|
|
}
|