protot/src/modules/RenderModule.h

508 lines
10 KiB
C++

#pragma once
#include <cstdint>
#include <map>
#include <vector>
#include "math_types.h"
#include <bgfx/bgfx.h>
#include "Globals.h"
#include "RenderUtils.h"
struct Entity;
struct Camera {
Vector3f eye;
Vector3f poi;
Vector3f up;
float near;
float far;
float fov;
bool orthographic;
float width;
float height;
float mtxProj[16];
float mtxView[16];
float mtxEnv[16];
Camera() :
eye {5.f, 4.f, 5.f},
poi {0.f, 2.f, 0.f},
up {0.f, 1.f, 0.f},
near (0.1f),
far (150.f),
fov (60.f),
orthographic (false),
width (-1.f),
height (-1.f),
mtxProj {
1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f},
mtxView {
1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f},
mtxEnv {
1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f}
{}
void updateMatrices();
};
struct Light {
bgfx::UniformHandle u_shadowMap;
bgfx::UniformHandle u_shadowMapParams;
bgfx::UniformHandle u_lightPos;
bgfx::UniformHandle u_lightMtx;
bgfx::TextureHandle shadowMapTexture;
bgfx::FrameBufferHandle shadowMapFB;
float pos[4];
float dir[3];
float mtxView[16];
float mtxProj[16];
float mtxLight[16];
float mtxShadow[16];
float shadowMapBias;
uint16_t shadowMapSize;
bool enabled;
float near;
float far;
float area;
Light() :
u_shadowMap (BGFX_INVALID_HANDLE),
u_lightPos (BGFX_INVALID_HANDLE),
u_lightMtx (BGFX_INVALID_HANDLE),
shadowMapTexture (BGFX_INVALID_HANDLE),
shadowMapFB (BGFX_INVALID_HANDLE),
pos {0.f, 10.f, 10.f, 1.0f},
dir {-1.f, -1.f, -1.f},
mtxView {
1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f
},
mtxProj {
1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f
},
mtxShadow {
1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f
},
shadowMapBias (0.004f),
shadowMapSize (2048),
near (0.1f),
far (100.f),
area (10.f),
enabled (false)
{
}
};
struct Transform {
Quaternion rotation = Quaternion (0.0f, 0.0f, 0.0f, 1.0f);
Vector3f translation = Vector3f (0.0f, 0.0f, 0.0f);
Vector3f scale = Vector3f (1.0f, 1.0f, 1.0f);
Transform () {};
Transform (
const Vector3f &translation,
const Quaternion &rotation,
const Vector3f &scale)
:
translation(translation),
rotation(rotation),
scale(scale)
{}
Transform (const Matrix44f& mat) {
fromMatrix(mat);
}
Matrix44f toMatrix() const {
Matrix44f result;
Matrix33f scale_mat (
scale[0], 0.0f, 0.0f,
0.0f, scale[1], 0.0f,
0.0f, 0.0f, scale[2]
);
result.block<3,3>(0,0) = scale_mat * rotation.toMatrix();
result.block<1,3>(3,0) = translation.transpose();
result.block<3,1>(0,3) = Vector3f::Zero();
result(3,3) = 1.0f;
return result;
}
void fromMatrix(const Matrix44f &matrix) {
// Extract rotation matrix and the quaternion
Matrix33f rot_matrix (matrix.block<3,3>(0,0));
Vector3f row0 = rot_matrix.block<1,3>(0,0).transpose();
Vector3f row1 = rot_matrix.block<1,3>(1,0).transpose();
Vector3f row2 = rot_matrix.block<1,3>(2,0).transpose();
scale.set(
row0.norm(),
row1.norm(),
row2.norm()
);
rot_matrix.block<1,3>(0,0) = (row0 / scale[0]).transpose();
rot_matrix.block<1,3>(1,0) = (row1 / scale[1]).transpose();
rot_matrix.block<1,3>(2,0) = (row2 / scale[2]).transpose();
rotation = Quaternion::fromMatrix(rot_matrix).normalize();
row0 = rot_matrix.block<1,3>(0,0).transpose();
row1 = rot_matrix.block<1,3>(1,0).transpose();
row2 = rot_matrix.block<1,3>(2,0).transpose();
Vector3f trans (
matrix(3,0),
matrix(3,1),
matrix(3,2)
);
translation = trans;
}
Transform operator*(const Transform &other) const {
Matrix44f this_mat (toMatrix());
Matrix44f other_mat (other.toMatrix());
return Transform(this_mat * other_mat);
}
Vector3f operator*(const Vector3f &vec) const {
assert(false);
return Vector3f::Zero();
}
static Transform fromTrans(
const Vector3f &translation
) {
return Transform (
translation,
Quaternion(0.0f, 0.0f, 0.0f, 1.0f),
Vector3f(1.0f, 1.0f, 1.0f)
);
}
static Transform fromTransRot(
const Vector3f &translation,
const Quaternion &rotation
) {
return Transform (
translation,
rotation,
Vector3f(1.0f, 1.0f, 1.0f)
);
}
static Transform fromTransRot(
const Vector3f &translation,
const Matrix33f &rotation
) {
return Transform (
translation,
Quaternion::fromMatrix(rotation),
Vector3f(1.0f, 1.0f, 1.0f)
);
}
static Transform fromTransRotScale(
const Vector3f &translation,
const Quaternion &rotation,
const Vector3f &scale
) {
return Transform (translation, rotation, scale);
}
};
struct Skeleton {
/// index of the mParent. Children must have higher indices than heir
// mParents
std::vector<int> mParent;
/// Transforms relative to their mParents.
std::vector<Transform> mLocalTransforms;
/// Absolute transforms.
std::vector<Matrix44f> mBoneMatrices;
int AddBone(
const int parent_index,
const Transform& transform
) {
assert (parent_index == -1 || parent_index < mParent.size());
mParent.push_back(parent_index);
mLocalTransforms.push_back(transform);
if (parent_index != -1) {
mBoneMatrices.push_back(transform.toMatrix() * mBoneMatrices[parent_index]);
} else {
mBoneMatrices.push_back(transform.toMatrix());
}
return mBoneMatrices.size() - 1;
}
void UpdateMatrices(const Matrix44f &world_transform);
int Length() const {
return mBoneMatrices.size();
}
};
struct SkeletonMeshes {
Skeleton& mSkeleton;
typedef std::pair<Mesh*, int> MeshBoneIndex;
std::vector<MeshBoneIndex> mMeshBoneIndices;
SkeletonMeshes(Skeleton &skeleton) :
mSkeleton(skeleton)
{}
~SkeletonMeshes() {
for(MeshBoneIndex& mesh_bone : mMeshBoneIndices) {
delete mesh_bone.first;
}
}
void AddMesh (Mesh* mesh, int bone_index) {
mMeshBoneIndices.push_back (MeshBoneIndex (mesh, bone_index));
}
const Matrix44f GetBoneMatrix(int index) const {
assert (index >= 0 && index < Length());
assert (mMeshBoneIndices[index].second < mSkeleton.mBoneMatrices.size());
return mSkeleton.mBoneMatrices[mMeshBoneIndices[index].second];
}
const Mesh* GetMesh(int index) const {
assert (index >= 0 && index < Length());
return mMeshBoneIndices[index].first;
}
int Length() const {
return mMeshBoneIndices.size();
}
};
struct Entity {
Transform mTransform;
Vector4f mColor;
Skeleton mSkeleton;
SkeletonMeshes mSkeletonMeshes;
Entity() :
mColor (1.f, 1.f, 1.f, 1.f ),
mSkeletonMeshes(mSkeleton)
{}
};
struct LightProbe
{
enum Enum
{
Bolonga,
Kyoto,
Count
};
void load(const char* _name);
void destroy()
{
bgfx::destroyTexture(m_tex);
bgfx::destroyTexture(m_texIrr);
}
bgfx::TextureHandle m_tex;
bgfx::TextureHandle m_texIrr;
};
struct Path {
std::vector<Vector3f> points;
std::vector<Vector4f> colors;
float thickness = 0.1f;
float miter = 0.0f;
bgfx::DynamicVertexBufferHandle mVertexBufferHandle = BGFX_INVALID_HANDLE;
bgfx::DynamicIndexBufferHandle mIndexBufferHandle = BGFX_INVALID_HANDLE;
~Path();
void UpdateBuffers();
};
struct DebugCommand {
enum CommandType {
Line,
Axes,
Circle,
Invalid
};
CommandType type;
Vector3f from;
float radius;
Vector3f to;
Vector4f color = Vector4f(1.f, 1.f, 1.f, 1.f);
};
struct Renderer {
bool initialized;
bool drawDebug;
bool drawFloor = true;
bool drawSkybox = true;
uint32_t width;
uint32_t height;
bgfx::UniformHandle sceneDefaultTextureSampler;
bgfx::TextureHandle sceneDefaultTexture;
LightProbe mLightProbes[LightProbe::Count];
LightProbe::Enum mCurrentLightProbe;
std::vector<Entity*> entities;
std::vector<Camera> cameras;
std::vector<Light> lights;
std::vector<Path> debugPaths;
std::vector<DebugCommand> debugCommands;
uint16_t activeCameraIndex;
Renderer() :
initialized(false),
drawDebug(false),
width (0),
height (0)
{}
// initialize simple geometries (cube, sphere, ...)
void createGeometries();
// create uniforms, load shaders, and create render targets
void setupShaders();
// setup renderpasses and wire up render targets
void setupRenderPasses();
void initialize(int width, int height);
void shutdown();
void paintGL();
void paintGLSimple();
void resize (int width, int height);
// check whether shader files were modified and reload them. Returns
// true on success, otherwise false
bool updateShaders();
Entity* createEntity();
bool destroyEntity (Entity* entity);
// debug commands
void drawDebugLine (
const Vector3f &from,
const Vector3f &to,
const Vector3f &color);
void drawDebugAxes (
const Vector3f &pos,
const Matrix33f &orientation,
const float &scale);
void drawDebugCircle (
const Vector3f &pos,
const Vector3f &normal,
const float radius,
const Vector4f &color = Vector4f (1.f, 1.f, 1.f, 1.f));
void drawDebugSphere (
const Vector3f &pos,
const float radius,
const Vector4f &color = Vector4f(1.f, 1.f, 1.f, 1.f));
};
struct RenderProgram {
bgfx::ProgramHandle program;
std::string vertexShaderFileName;
int vertexShaderFileModTime;
std::string fragmentShaderFileName;
int fragmentShaderFileModTime;
RenderProgram () :
vertexShaderFileName(""),
vertexShaderFileModTime(-1),
fragmentShaderFileName(""),
fragmentShaderFileModTime(-1)
{
program = BGFX_INVALID_HANDLE;
}
RenderProgram (
const char* vertex_shader_file_name,
const char* fragment_shader_file_name
)
:
vertexShaderFileName(vertex_shader_file_name),
vertexShaderFileModTime(-1),
fragmentShaderFileName(fragment_shader_file_name),
fragmentShaderFileModTime(-1)
{
program = BGFX_INVALID_HANDLE;
}
bool reload();
bool checkModified() const;
bool valid() const {
return bgfx::isValid(program);
}
};
struct RenderState {
enum {
Skybox,
ShadowMap,
Scene,
SceneTextured,
Lines,
LinesOccluded,
Debug,
Count
};
struct Texture {
uint32_t m_flags;
bgfx::UniformHandle m_sampler;
bgfx::TextureHandle m_texture;
uint8_t m_stage;
};
uint64_t m_state;
uint8_t m_numTextures;
RenderProgram m_program;
uint8_t m_viewId;
Texture m_textures[4];
};