// BlockyFroggy
// Copyright © 2017 John Ryland.
// All rights reserved.
#pragma once
#ifndef GAME_GRAPHICS_H
#define GAME_GRAPHICS_H
#include "OpenGL.h"
#include "GLProgram.h"
#include "Dialog.h"
#include "GameSim.h"
#include "VoxelModel.h"
#include "Math.h"
#include "Camera.h"
#include "VertexArray.h"
#include "Cube.h"
#include "Scene.h"
#include "PolyVertex.h"
#include "Log.h"
#define MODEL_COUNT 27
#define PLAYER_MODEL_COUNT 16
DECLARE_PROGRAM_UNIFORMS(PolyProgram)
DECLARE_UNIFORM(mat4, modelViewProjectionMatrix)
DECLARE_UNIFORM(mat4, shadowMapMVP)
DECLARE_UNIFORM(GLint, shadowMap)
DECLARE_UNIFORM(GLint, texture)
DECLARE_UNIFORM(float, time)
DECLARE_UNIFORM(float, shadowStrength)
DECLARE_UNIFORM(bool, mixNoise)
DECLARE_UNIFORM(vec4attrib, translation) // may not need
DECLARE_PROGRAM_UNIFORMS_END
DECLARE_PROGRAM_UNIFORMS(ShadowProgram)
DECLARE_UNIFORM(mat4, modelViewProjectionMatrix)
DECLARE_UNIFORM(float, time)
DECLARE_UNIFORM(vec4attrib, translation) // may not need
DECLARE_PROGRAM_UNIFORMS_END
template <class UniformsType, class VertexType>
class ProgramContext
{
public:
void setup(const char *a_vertexShader, const char *a_fragmentShader,
Precision a_defaultPrecision, const OptionsType& a_options)
{
// Setup main program
auto bindUniformsFunc = [this](GLuint a_program) { m_uniforms.getLocations(a_program); };
m_program.deleteProgram();
VertexArray<VertexType> v;
m_program.loadShaders(a_vertexShader, a_fragmentShader, a_defaultPrecision, a_options, v.bindAttributesFunction(), bindUniformsFunc);
}
void shutdown()
{
m_program.deleteProgram();
}
//private:
GLProgram m_program;
UniformsType m_uniforms;
GLuint m_framebufferId;
};
class DrawableModels
{
public:
void loadVoxelModel(int index, const char* name, int x, int y, int w, int h, int d, bool direction, int scaling, bool asCubes = false, int yClamp0 = 0, int yClamp1 = 256);
VoxelModels m_models;
std::vector<VertexArray<PolyVertex> > m_modelsVertexArrays;
GLuint m_axisTextureIds[3];
};
// 64 256x256 tiles in a 2048x2048 texture
/*
class TextureManager
{
public:
TextureManager();
~TextureManager();
private:
void LoadPendingTexture(GameUi::TextureLoadJob& job);
};
*/
class GameGraphics
{
public:
DECLARE_LOG_CONTEXT(GGX)
GameGraphics();
~GameGraphics();
void resetVertexBuffers(const std::vector<GameSim::GameObjectList*>& a_objectLists);
void loadVoxelModel(VertexArray<PolyVertex>& vertexArray, const char* name, int x, int y, int w, int h, int d, bool direction, int scaling, bool asCubes = false, int yClamp0 = 0, int yClamp1 = 256);
void reloadShaders();
void initialize();
void shutdown();
void update(float a_elapsed, float a_aspect, const GameUi::UpdateState& a_state, float a_playerPos[3], float a_cameraStyle[8], float a_light[8], float a_debugCamera[8]);
void drawDebug(GameUi::DrawItems& a_state);
void preDraw(float a_time);
void prepareState(GameUi::UpdateState& a_state);
void prepareShadowContext();
void renderShadows();
void prepareScreenContext();
void renderScreen();
void prepareHUDContext();
void setEditModel(int modelIndex) { m_editModel = modelIndex; m_editModelDirty = true; }
void setEditLayer(float editLayer) { m_editLayer = editLayer; m_editModelDirty = true; }
void draw();
// Common code for drawing object lists
void drawObjectListHelper(const GameSim::GameObjectList& a_objs, GLsizei siz, bool direction);
void drawObjectTypeList(const GameSim::GameObjectList& a_objs, int a_voxelModelIndex);
void drawObjectTypeListTiled(const GameSim::GameObjectList& a_objs, int a_voxelModelIndex, int zOff, int wid);
void drawScene();
void drawModelEditLayer();
void drawModelRotatingPreview();
void drawRotatingFrog();
void drawCaroselTest();
void drawHUD();
void drawAuxItems(const GameUi::DrawItems& a_uiItems);
void drawViews(const std::vector<GameUi::View*>& a_views);
void getEditObjectPixels(float editLayer, std::vector<uint32_t>& pixels, int& w, int& h, int& d);
void setEditObjectPixels(float editLayer, const std::vector<uint32_t>& pixels, int w, int h);
void getPalettePixels(std::vector<uint32_t>& pixels);
void LoadPendingTexture(GameUi::TextureLoadJob& job);
// Retrieved from GL viewport
uint32_t m_w = 0, m_h = 0;
private:
std::map<std::string, std::function<void()> > m_viewMap;
OptionsType m_options;
//std::map<std::string,bool> m_options;
int m_editModel = MODEL_COUNT - 1;
float m_editLayer = 0.0;
float m_cameraX, m_cameraY;
float m_playerX, m_playerY, m_playerZ;
float m_time = 0.0;
// HUD
bool m_hudEnabled = true;
GLProgram m_hudProgram;
GLuint m_hudVertexArray;
GLuint m_hudVertexBuffer;
GLuint m_hudTexId = 0;
size_t m_hudItemCount = 0;
// Aux
GLuint m_auxVertexArray;
GLuint m_auxVertexBuffer;
// Shadows
bool m_shadowsEnabled = true;
ProgramContext<PolyProgram, PolyVertex> m_shadowContext;
//GLProgram m_shadowProgram;
GLuint m_shadowTexId = 0;
GLuint m_shadowFramebufferId = 0;
//PolyProgram m_shadowUniforms;
// Polygons
ProgramContext<PolyProgram, PolyVertex> m_normalContext;
//GLProgram m_program;
GLuint m_defaultFramebufferId = 0;
//PolyProgram m_polyUniforms;
// Current Context
ProgramContext<PolyProgram, PolyVertex>* m_currentContext = &m_normalContext;
Camera m_light;
Camera m_camera;
Camera m_debugCamera;
VertexArray<PolyVertex> m_staticPolyVertexArray;
VertexArray<PolyVertex> m_dynamicPolyVertexArray;
VertexArray<PolyVertex> m_editModelVertexArray1;
VertexArray<PolyVertex> m_editModelVertexArray2;
bool m_editModelDirty = true;
int modelIdx = 0;
VoxelModels m_models;
VertexArray<PolyVertex> m_modelsVertexArrays[MODEL_COUNT];
VertexArray<PolyVertex> m_combinedModelsVertexArrays;//[MODEL_COUNT];
VertexArray<PolyVertex> m_modelsVertexArraysCopy[MODEL_COUNT];
// a 2048x2048 image can contain 1024 voxel models which are 16x16x16
// or about 341 models when take in to account needing 3 textures for each axis
// if target 100 different models, need about 19 256x256 texture slots
// if plan to dynamically convert to PVR at runtime, then probably better to
// actually use smaller textures, but means needing to switch texture state
// when rendering
VoxelModels m_playerModels;
VertexArray<PolyVertex> m_playerModelsVertexArrays[PLAYER_MODEL_COUNT];
// Scene
Scene m_scene;
// move to DrawableModels class
uint32_t *m_model_x_axis = nullptr;
uint32_t *m_model_z_axis = nullptr;
void drawCuboid(float frustum[8][4]);
void drawSolidCuboid(float x, float y, float z, float w, float h, float d, uint32_t col, float scale);
VertexArray<PolyVertex> m_cuboidVertexList;
// For debugging
void drawCube(float x, float y, float z, float w, float h, float d, uint32_t color); // For debugging
};
#endif // GAME_GRAPHICS_H