commit
76fb2e42d3
@ -45,6 +45,16 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"buildPresets": [
|
"buildPresets": [
|
||||||
|
{
|
||||||
|
"name": "Debug build",
|
||||||
|
"configurePreset": "default-vs-msvc-windows",
|
||||||
|
"configuration": "Debug"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Release build",
|
||||||
|
"configurePreset": "default-vs-msvc-windows",
|
||||||
|
"configuration": "Release"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "default-vs-msvc-windows",
|
"name": "default-vs-msvc-windows",
|
||||||
"configurePreset": "default-vs-msvc-windows",
|
"configurePreset": "default-vs-msvc-windows",
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
layout (location = 0) in vec3 v_position;
|
layout (location = 0) in vec3 v_position;
|
||||||
layout (location = 1) in vec2 v_texCoord;
|
layout (location = 1) in vec2 v_texCoord;
|
||||||
layout (location = 2) in vec3 v_color;
|
layout (location = 2) in vec3 v_color;
|
||||||
layout (location = 3) in float v_light;
|
layout (location = 3) in vec4 v_light;
|
||||||
|
|
||||||
out vec4 a_color;
|
out vec4 a_color;
|
||||||
out vec2 a_texCoord;
|
out vec2 a_texCoord;
|
||||||
@ -31,8 +31,7 @@ void main() {
|
|||||||
vec3 pos3d = modelpos.xyz - u_cameraPos;
|
vec3 pos3d = modelpos.xyz - u_cameraPos;
|
||||||
modelpos.xyz = apply_planet_curvature(modelpos.xyz, pos3d);
|
modelpos.xyz = apply_planet_curvature(modelpos.xyz, pos3d);
|
||||||
|
|
||||||
vec4 decomp_light = decompress_light(v_light);
|
vec3 light = v_light.rgb;
|
||||||
vec3 light = decomp_light.rgb;
|
|
||||||
float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz) /
|
float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz) /
|
||||||
u_torchlightDistance);
|
u_torchlightDistance);
|
||||||
light += torchlight * u_torchlightColor;
|
light += torchlight * u_torchlightColor;
|
||||||
@ -41,7 +40,7 @@ void main() {
|
|||||||
|
|
||||||
a_dir = modelpos.xyz - u_cameraPos;
|
a_dir = modelpos.xyz - u_cameraPos;
|
||||||
vec3 skyLightColor = pick_sky_color(u_cubemap);
|
vec3 skyLightColor = pick_sky_color(u_cubemap);
|
||||||
a_color.rgb = max(a_color.rgb, skyLightColor.rgb*decomp_light.a) * v_color;
|
a_color.rgb = max(a_color.rgb, skyLightColor.rgb*v_light.a) * v_color;
|
||||||
a_color.a = u_opacity;
|
a_color.a = u_opacity;
|
||||||
|
|
||||||
float dist = length(u_view * u_model * vec4(pos3d * FOG_POS_SCALE, 0.0));
|
float dist = length(u_view * u_model * vec4(pos3d * FOG_POS_SCALE, 0.0));
|
||||||
|
|||||||
@ -1,28 +1,17 @@
|
|||||||
#ifndef COMMONS_GLSL_
|
#ifndef COMMONS_GLSL_
|
||||||
#define COMMONS_GLSL_
|
#define COMMONS_GLSL_
|
||||||
|
|
||||||
#include <constants>
|
#include <constants>
|
||||||
|
|
||||||
vec4 decompress_light(float compressed_light) {
|
|
||||||
vec4 result;
|
|
||||||
int compressed = floatBitsToInt(compressed_light);
|
|
||||||
result.r = ((compressed >> 24) & 0xFF) / 255.f;
|
|
||||||
result.g = ((compressed >> 16) & 0xFF) / 255.f;
|
|
||||||
result.b = ((compressed >> 8) & 0xFF) / 255.f;
|
|
||||||
result.a = (compressed & 0xFF) / 255.f;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 pick_sky_color(samplerCube cubemap) {
|
vec3 pick_sky_color(samplerCube cubemap) {
|
||||||
vec3 skyLightColor = texture(cubemap, vec3(0.4f, 0.0f, 0.4f)).rgb;
|
vec3 skyLightColor = texture(cubemap, vec3(0.4f, 0.0f, 0.4f)).rgb;
|
||||||
skyLightColor *= SKY_LIGHT_TINT;
|
skyLightColor *= SKY_LIGHT_TINT;
|
||||||
skyLightColor = min(vec3(1.0), skyLightColor*SKY_LIGHT_MUL);
|
skyLightColor = min(vec3(1.0f), skyLightColor * SKY_LIGHT_MUL);
|
||||||
skyLightColor = max(MIN_SKY_LIGHT, skyLightColor);
|
skyLightColor = max(MIN_SKY_LIGHT, skyLightColor);
|
||||||
return skyLightColor;
|
return skyLightColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 apply_planet_curvature(vec3 modelPos, vec3 pos3d) {
|
vec3 apply_planet_curvature(vec3 modelPos, vec3 pos3d) {
|
||||||
modelPos.y -= pow(length(pos3d.xz)*CURVATURE_FACTOR, 3.0);
|
modelPos.y -= pow(length(pos3d.xz) * CURVATURE_FACTOR, 3.0f);
|
||||||
return modelPos;
|
return modelPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,10 +7,13 @@ out vec4 f_color;
|
|||||||
uniform sampler2D u_texture0;
|
uniform sampler2D u_texture0;
|
||||||
uniform samplerCube u_cubemap;
|
uniform samplerCube u_cubemap;
|
||||||
uniform bool u_alphaClip;
|
uniform bool u_alphaClip;
|
||||||
|
uniform bool u_debugLights;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec3 fogColor = texture(u_cubemap, a_dir).rgb;
|
vec3 fogColor = texture(u_cubemap, a_dir).rgb;
|
||||||
vec4 tex_color = texture(u_texture0, a_texCoord);
|
vec4 tex_color = texture(u_texture0, a_texCoord);
|
||||||
|
if (u_debugLights)
|
||||||
|
tex_color.rgb = vec3(1.0);
|
||||||
float alpha = a_color.a * tex_color.a;
|
float alpha = a_color.a * tex_color.a;
|
||||||
if (u_alphaClip) {
|
if (u_alphaClip) {
|
||||||
if (alpha < 0.2f)
|
if (alpha < 0.2f)
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
layout (location = 0) in vec3 v_position;
|
layout (location = 0) in vec3 v_position;
|
||||||
layout (location = 1) in vec2 v_texCoord;
|
layout (location = 1) in vec2 v_texCoord;
|
||||||
layout (location = 2) in float v_light;
|
layout (location = 2) in vec4 v_light;
|
||||||
|
|
||||||
out vec4 a_color;
|
out vec4 a_color;
|
||||||
out vec2 a_texCoord;
|
out vec2 a_texCoord;
|
||||||
@ -27,13 +27,12 @@ uniform vec3 u_torchlightColor;
|
|||||||
uniform float u_torchlightDistance;
|
uniform float u_torchlightDistance;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 modelpos = u_model * vec4(v_position, 1.0);
|
vec4 modelpos = u_model * vec4(v_position, 1.0f);
|
||||||
vec3 pos3d = modelpos.xyz-u_cameraPos;
|
vec3 pos3d = modelpos.xyz-u_cameraPos;
|
||||||
modelpos.xyz = apply_planet_curvature(modelpos.xyz, pos3d);
|
modelpos.xyz = apply_planet_curvature(modelpos.xyz, pos3d);
|
||||||
|
|
||||||
vec4 decomp_light = decompress_light(v_light);
|
vec3 light = v_light.rgb;
|
||||||
vec3 light = decomp_light.rgb;
|
float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz) /
|
||||||
float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz) /
|
|
||||||
u_torchlightDistance);
|
u_torchlightDistance);
|
||||||
light += torchlight * u_torchlightColor;
|
light += torchlight * u_torchlightColor;
|
||||||
a_color = vec4(pow(light, vec3(u_gamma)),1.0f);
|
a_color = vec4(pow(light, vec3(u_gamma)),1.0f);
|
||||||
@ -41,7 +40,7 @@ void main() {
|
|||||||
|
|
||||||
a_dir = modelpos.xyz - u_cameraPos;
|
a_dir = modelpos.xyz - u_cameraPos;
|
||||||
vec3 skyLightColor = pick_sky_color(u_cubemap);
|
vec3 skyLightColor = pick_sky_color(u_cubemap);
|
||||||
a_color.rgb = max(a_color.rgb, skyLightColor.rgb*decomp_light.a);
|
a_color.rgb = max(a_color.rgb, skyLightColor.rgb*v_light.a);
|
||||||
|
|
||||||
a_distance = length(u_view * u_model * vec4(pos3d * FOG_POS_SCALE, 0.0));
|
a_distance = length(u_view * u_model * vec4(pos3d * FOG_POS_SCALE, 0.0));
|
||||||
float depth = (a_distance / 256.0);
|
float depth = (a_distance / 256.0);
|
||||||
|
|||||||
@ -257,12 +257,12 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto& [_, def] : content->blocks.getDefs()) {
|
for (const auto& [_, def] : content->blocks.getDefs()) {
|
||||||
if (!def->modelName.empty() &&
|
if (!def->model.name.empty() &&
|
||||||
def->modelName.find(':') == std::string::npos) {
|
def->model.name.find(':') == std::string::npos) {
|
||||||
loader.add(
|
loader.add(
|
||||||
AssetType::MODEL,
|
AssetType::MODEL,
|
||||||
MODELS_FOLDER + "/" + def->modelName,
|
MODELS_FOLDER + "/" + def->model.name,
|
||||||
def->modelName
|
def->model.name
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,12 @@
|
|||||||
#include "png.hpp"
|
#include "png.hpp"
|
||||||
|
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
#include <GL/glew.h>
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "debug/Logger.hpp"
|
#include "debug/Logger.hpp"
|
||||||
#include "io/io.hpp"
|
#include "io/io.hpp"
|
||||||
#include "graphics/core/GLTexture.hpp"
|
#include "graphics/core/Texture.hpp"
|
||||||
#include "graphics/core/ImageData.hpp"
|
#include "graphics/core/ImageData.hpp"
|
||||||
|
|
||||||
static debug::Logger logger("png-coder");
|
static debug::Logger logger("png-coder");
|
||||||
@ -206,7 +205,7 @@ std::unique_ptr<ImageData> png::load_image(const ubyte* bytes, size_t size) {
|
|||||||
|
|
||||||
std::unique_ptr<Texture> png::load_texture(const ubyte* bytes, size_t size) {
|
std::unique_ptr<Texture> png::load_texture(const ubyte* bytes, size_t size) {
|
||||||
auto image = load_image(bytes, size);
|
auto image = load_image(bytes, size);
|
||||||
auto texture = GLTexture::from(image.get());
|
auto texture = Texture::from(image.get());
|
||||||
texture->setNearestFilter();
|
texture->setNearestFilter();
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ std::unique_ptr<Content> ContentBuilder::build() {
|
|||||||
// Generating runtime info
|
// Generating runtime info
|
||||||
def.rt.id = blockDefsIndices.size();
|
def.rt.id = blockDefsIndices.size();
|
||||||
def.rt.emissive = *reinterpret_cast<uint32_t*>(def.emission);
|
def.rt.emissive = *reinterpret_cast<uint32_t*>(def.emission);
|
||||||
def.rt.solid = def.model == BlockModel::block;
|
def.rt.solid = def.model.type == BlockModelType::BLOCK;
|
||||||
def.rt.extended = def.size.x > 1 || def.size.y > 1 || def.size.z > 1;
|
def.rt.extended = def.size.x > 1 || def.size.y > 1 || def.size.z > 1;
|
||||||
|
|
||||||
const float EPSILON = 0.01f;
|
const float EPSILON = 0.01f;
|
||||||
|
|||||||
@ -86,20 +86,23 @@ template<> void ContentUnitLoader<Block>::loadUnit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// block model
|
// block model
|
||||||
std::string modelTypeName = BlockModelMeta.getNameString(def.model);
|
auto& model = def.model;
|
||||||
|
std::string modelTypeName = BlockModelTypeMeta.getNameString(model.type);
|
||||||
root.at("model").get(modelTypeName);
|
root.at("model").get(modelTypeName);
|
||||||
root.at("model-name").get(def.modelName);
|
root.at("model-name").get(def.model.name);
|
||||||
if (BlockModelMeta.getItem(modelTypeName, def.model)) {
|
if (BlockModelTypeMeta.getItem(modelTypeName, model.type)) {
|
||||||
if (def.model == BlockModel::custom && def.customModelRaw == nullptr) {
|
if (model.type == BlockModelType::CUSTOM && def.model.customRaw == nullptr) {
|
||||||
if (root.has("model-primitives")) {
|
if (root.has("model-primitives")) {
|
||||||
def.customModelRaw = root["model-primitives"];
|
def.model.customRaw = root["model-primitives"];
|
||||||
} else if (def.modelName.empty()) {
|
} else if (def.model.name.empty()) {
|
||||||
throw std::runtime_error(name + ": no 'model-primitives' or 'model-name' found");
|
throw std::runtime_error(
|
||||||
|
name + ": no 'model-primitives' or 'model-name' found"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!modelTypeName.empty()) {
|
} else if (!modelTypeName.empty()) {
|
||||||
logger.error() << "unknown model: " << modelTypeName;
|
logger.error() << "unknown model: " << modelTypeName;
|
||||||
def.model = BlockModel::none;
|
model.type = BlockModelType::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cullingModeName = CullingModeMeta.getNameString(def.culling);
|
std::string cullingModeName = CullingModeMeta.getNameString(def.culling);
|
||||||
@ -171,9 +174,9 @@ template<> void ContentUnitLoader<Block>::loadUnit(
|
|||||||
"block " + util::quote(def.name) + ": invalid block size"
|
"block " + util::quote(def.name) + ": invalid block size"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (def.model == BlockModel::block &&
|
if (model.type == BlockModelType::BLOCK &&
|
||||||
(def.size.x != 1 || def.size.y != 1 || def.size.z != 1)) {
|
(def.size.x != 1 || def.size.y != 1 || def.size.z != 1)) {
|
||||||
def.model = BlockModel::aabb;
|
model.type = BlockModelType::AABB;
|
||||||
def.hitboxes = {AABB(def.size)};
|
def.hitboxes = {AABB(def.size)};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ void corecontent::setup(Input& input, ContentBuilder& builder) {
|
|||||||
block.skyLightPassing = true;
|
block.skyLightPassing = true;
|
||||||
block.obstacle = false;
|
block.obstacle = false;
|
||||||
block.selectable = false;
|
block.selectable = false;
|
||||||
block.model = BlockModel::none;
|
block.model.type = BlockModelType::NONE;
|
||||||
block.pickingItem = CORE_EMPTY;
|
block.pickingItem = CORE_EMPTY;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|||||||
@ -203,7 +203,8 @@ void Engine::updateHotkeys() {
|
|||||||
if (input->jpressed(Keycode::F2)) {
|
if (input->jpressed(Keycode::F2)) {
|
||||||
saveScreenshot();
|
saveScreenshot();
|
||||||
}
|
}
|
||||||
if (input->jpressed(Keycode::F8)) {
|
if (input->pressed(Keycode::LEFT_CONTROL) && input->pressed(Keycode::F3) &&
|
||||||
|
input->jpressed(Keycode::U)) {
|
||||||
gui->toggleDebug();
|
gui->toggleDebug();
|
||||||
}
|
}
|
||||||
if (input->jpressed(Keycode::F11)) {
|
if (input->jpressed(Keycode::F11)) {
|
||||||
|
|||||||
@ -35,10 +35,10 @@ void ContentGfxCache::refresh(const Block& def, const Atlas& atlas) {
|
|||||||
sideregions[def.rt.id * 6 + side] = atlas.get(TEXTURE_NOTFOUND);
|
sideregions[def.rt.id * 6 + side] = atlas.get(TEXTURE_NOTFOUND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (def.model == BlockModel::custom) {
|
if (def.model.type == BlockModelType::CUSTOM) {
|
||||||
auto model = assets.require<model::Model>(def.modelName);
|
auto model = assets.require<model::Model>(def.model.name);
|
||||||
// temporary dirty fix tbh
|
// temporary dirty fix tbh
|
||||||
if (def.modelName.find(':') == std::string::npos) {
|
if (def.model.name.find(':') == std::string::npos) {
|
||||||
for (auto& mesh : model.meshes) {
|
for (auto& mesh : model.meshes) {
|
||||||
size_t pos = mesh.texture.find(':');
|
size_t pos = mesh.texture.find(':');
|
||||||
if (pos == std::string::npos) {
|
if (pos == std::string::npos) {
|
||||||
|
|||||||
@ -93,11 +93,11 @@ std::shared_ptr<UINode> create_debug_panel(
|
|||||||
panel->add(create_label(gui, []() { return L"fps: "+fpsString;}));
|
panel->add(create_label(gui, []() { return L"fps: "+fpsString;}));
|
||||||
|
|
||||||
panel->add(create_label(gui, []() {
|
panel->add(create_label(gui, []() {
|
||||||
return L"meshes: " + std::to_wstring(Mesh::meshesCount);
|
return L"meshes: " + std::to_wstring(MeshStats::meshesCount);
|
||||||
}));
|
}));
|
||||||
panel->add(create_label(gui, []() {
|
panel->add(create_label(gui, []() {
|
||||||
int drawCalls = Mesh::drawCalls;
|
int drawCalls = MeshStats::drawCalls;
|
||||||
Mesh::drawCalls = 0;
|
MeshStats::drawCalls = 0;
|
||||||
return L"draw-calls: " + std::to_wstring(drawCalls);
|
return L"draw-calls: " + std::to_wstring(drawCalls);
|
||||||
}));
|
}));
|
||||||
panel->add(create_label(gui, []() {
|
panel->add(create_label(gui, []() {
|
||||||
|
|||||||
@ -184,16 +184,21 @@ void LevelScreen::saveWorldPreview() {
|
|||||||
void LevelScreen::updateHotkeys() {
|
void LevelScreen::updateHotkeys() {
|
||||||
auto& settings = engine.getSettings();
|
auto& settings = engine.getSettings();
|
||||||
|
|
||||||
if (input.jpressed(Keycode::O)) {
|
|
||||||
settings.graphics.frustumCulling.toggle();
|
|
||||||
}
|
|
||||||
if (input.jpressed(Keycode::F1)) {
|
if (input.jpressed(Keycode::F1)) {
|
||||||
hudVisible = !hudVisible;
|
hudVisible = !hudVisible;
|
||||||
}
|
}
|
||||||
if (input.jpressed(Keycode::F3)) {
|
if (!input.pressed(Keycode::LEFT_CONTROL)) {
|
||||||
debug = !debug;
|
if (input.jpressed(Keycode::F3)) {
|
||||||
hud->setDebug(debug);
|
debug = !debug;
|
||||||
renderer->setDebug(debug);
|
hud->setDebug(debug);
|
||||||
|
renderer->setDebug(debug);
|
||||||
|
}
|
||||||
|
} else if (input.pressed(Keycode::F3)) {
|
||||||
|
if (input.jpressed(Keycode::L)) {
|
||||||
|
renderer->toggleLightsDebug();
|
||||||
|
} else if (input.jpressed(Keycode::O)) {
|
||||||
|
settings.graphics.frustumCulling.toggle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,19 +4,12 @@
|
|||||||
#include "gl_util.hpp"
|
#include "gl_util.hpp"
|
||||||
#include "maths/UVRegion.hpp"
|
#include "maths/UVRegion.hpp"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
inline constexpr uint B2D_VERTEX_SIZE = 8;
|
|
||||||
|
|
||||||
Batch2D::Batch2D(size_t capacity) : capacity(capacity), color(1.0f){
|
Batch2D::Batch2D(size_t capacity) : capacity(capacity), color(1.0f){
|
||||||
const VertexAttribute attrs[] = {
|
buffer = std::make_unique<Batch2DVertex[]>(capacity );
|
||||||
{2}, {2}, {4}, {0}
|
mesh = std::make_unique<Mesh<Batch2DVertex>>(buffer.get(), 0);
|
||||||
};
|
|
||||||
|
|
||||||
buffer = std::make_unique<float[]>(capacity * B2D_VERTEX_SIZE);
|
|
||||||
mesh = std::make_unique<Mesh>(buffer.get(), 0, attrs);
|
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
||||||
const ubyte pixels[] = {
|
const ubyte pixels[] = {
|
||||||
@ -51,28 +44,20 @@ void Batch2D::vertex(
|
|||||||
float u, float v,
|
float u, float v,
|
||||||
float r, float g, float b, float a
|
float r, float g, float b, float a
|
||||||
) {
|
) {
|
||||||
buffer[index++] = x;
|
buffer[index].position = {x, y};
|
||||||
buffer[index++] = y;
|
buffer[index].uv = {u * region.getWidth() + region.u1, v * region.getHeight() + region.v1};
|
||||||
buffer[index++] = u * region.getWidth() + region.u1;
|
buffer[index].color = {r, g, b, a};
|
||||||
buffer[index++] = v * region.getHeight() + region.v1;
|
index++;
|
||||||
buffer[index++] = r;
|
|
||||||
buffer[index++] = g;
|
|
||||||
buffer[index++] = b;
|
|
||||||
buffer[index++] = a;
|
|
||||||
}
|
}
|
||||||
void Batch2D::vertex(
|
void Batch2D::vertex(
|
||||||
glm::vec2 point,
|
glm::vec2 point,
|
||||||
glm::vec2 uvpoint,
|
glm::vec2 uvpoint,
|
||||||
float r, float g, float b, float a
|
float r, float g, float b, float a
|
||||||
) {
|
) {
|
||||||
buffer[index++] = point.x;
|
buffer[index].position = point;
|
||||||
buffer[index++] = point.y;
|
buffer[index].uv = {uvpoint.x * region.getWidth() + region.u1, uvpoint.y * region.getHeight() + region.v1};
|
||||||
buffer[index++] = uvpoint.x * region.getWidth() + region.u1;
|
buffer[index].color = {r, g, b, a};
|
||||||
buffer[index++] = uvpoint.y * region.getHeight() + region.v1;
|
index++;
|
||||||
buffer[index++] = r;
|
|
||||||
buffer[index++] = g;
|
|
||||||
buffer[index++] = b;
|
|
||||||
buffer[index++] = a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch2D::texture(const Texture* new_texture){
|
void Batch2D::texture(const Texture* new_texture){
|
||||||
@ -99,14 +84,14 @@ void Batch2D::setRegion(UVRegion region) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Batch2D::point(float x, float y, float r, float g, float b, float a){
|
void Batch2D::point(float x, float y, float r, float g, float b, float a){
|
||||||
if (index + 6*B2D_VERTEX_SIZE >= capacity)
|
if (index + 6 >= capacity)
|
||||||
flush();
|
flush();
|
||||||
setPrimitive(DrawPrimitive::point);
|
setPrimitive(DrawPrimitive::point);
|
||||||
vertex(x, y, 0, 0, r,g,b,a);
|
vertex(x, y, 0, 0, r,g,b,a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch2D::line(float x1, float y1, float x2, float y2, float r, float g, float b, float a){
|
void Batch2D::line(float x1, float y1, float x2, float y2, float r, float g, float b, float a){
|
||||||
if (index + 6*B2D_VERTEX_SIZE >= capacity) {
|
if (index + 6 >= capacity) {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
setPrimitive(DrawPrimitive::line);
|
setPrimitive(DrawPrimitive::line);
|
||||||
@ -119,7 +104,7 @@ void Batch2D::rect(float x, float y, float w, float h){
|
|||||||
const float g = color.g;
|
const float g = color.g;
|
||||||
const float b = color.b;
|
const float b = color.b;
|
||||||
const float a = color.a;
|
const float a = color.a;
|
||||||
if (index + 6*B2D_VERTEX_SIZE >= capacity) {
|
if (index + 6 >= capacity) {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
setPrimitive(DrawPrimitive::triangle);
|
setPrimitive(DrawPrimitive::triangle);
|
||||||
@ -142,7 +127,7 @@ void Batch2D::rect(
|
|||||||
bool flippedY,
|
bool flippedY,
|
||||||
glm::vec4 tint
|
glm::vec4 tint
|
||||||
) {
|
) {
|
||||||
if (index + 6 * B2D_VERTEX_SIZE >= capacity) {
|
if (index + 6 >= capacity) {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
setPrimitive(DrawPrimitive::triangle);
|
setPrimitive(DrawPrimitive::triangle);
|
||||||
@ -230,14 +215,14 @@ void Batch2D::rect(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Batch2D::lineRect(float x, float y, float w, float h) {
|
void Batch2D::lineRect(float x, float y, float w, float h) {
|
||||||
if (index + 8 * B2D_VERTEX_SIZE >= capacity) {
|
if (index + 8 >= capacity) {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
setPrimitive(DrawPrimitive::line);
|
setPrimitive(DrawPrimitive::line);
|
||||||
|
|
||||||
vertex(x, y, 0.0f, 0.0f, color.r, color.g, color.b, color.a);
|
vertex(x, y, 0.0f, 0.0f, color.r, color.g, color.b, color.a);
|
||||||
vertex(x, y+h, 0.0f, 1.0f, color.r, color.g, color.b, color.a);
|
vertex(x, y+h, 0.0f, 1.0f, color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
vertex(x, y+h, 0.0f, 1.0f, color.r, color.g, color.b, color.a);
|
vertex(x, y+h, 0.0f, 1.0f, color.r, color.g, color.b, color.a);
|
||||||
vertex(x+w, y+h, 1.0f, 1.0f, color.r, color.g, color.b, color.a);
|
vertex(x+w, y+h, 1.0f, 1.0f, color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
@ -253,7 +238,7 @@ void Batch2D::rect(
|
|||||||
float u, float v, float tx, float ty,
|
float u, float v, float tx, float ty,
|
||||||
float r, float g, float b, float a
|
float r, float g, float b, float a
|
||||||
){
|
){
|
||||||
if (index + 6*B2D_VERTEX_SIZE >= capacity) {
|
if (index + 6 >= capacity) {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
setPrimitive(DrawPrimitive::triangle);
|
setPrimitive(DrawPrimitive::triangle);
|
||||||
@ -271,7 +256,7 @@ void Batch2D::parallelogram(
|
|||||||
float u, float v, float tx, float ty,
|
float u, float v, float tx, float ty,
|
||||||
float r, float g, float b, float a
|
float r, float g, float b, float a
|
||||||
){
|
){
|
||||||
if (index + 6*B2D_VERTEX_SIZE >= capacity) {
|
if (index + 6 >= capacity) {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
setPrimitive(DrawPrimitive::triangle);
|
setPrimitive(DrawPrimitive::triangle);
|
||||||
@ -292,7 +277,7 @@ void Batch2D::rect(
|
|||||||
float r3, float g3, float b3,
|
float r3, float g3, float b3,
|
||||||
float r4, float g4, float b4, int sh
|
float r4, float g4, float b4, int sh
|
||||||
){
|
){
|
||||||
if (index + 30*B2D_VERTEX_SIZE >= capacity) {
|
if (index + 30 >= capacity) {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
setPrimitive(DrawPrimitive::triangle);
|
setPrimitive(DrawPrimitive::triangle);
|
||||||
@ -378,7 +363,7 @@ void Batch2D::sprite(
|
|||||||
void Batch2D::flush() {
|
void Batch2D::flush() {
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
return;
|
return;
|
||||||
mesh->reload(buffer.get(), index / B2D_VERTEX_SIZE);
|
mesh->reload(buffer.get(), index);
|
||||||
mesh->draw(gl::to_glenum(primitive));
|
mesh->draw(gl::to_glenum(primitive));
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,32 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "commons.hpp"
|
#include "commons.hpp"
|
||||||
#include "maths/UVRegion.hpp"
|
#include "maths/UVRegion.hpp"
|
||||||
|
#include "MeshData.hpp"
|
||||||
|
|
||||||
|
template<typename VertexStructure>
|
||||||
class Mesh;
|
class Mesh;
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
|
struct Batch2DVertex {
|
||||||
|
glm::vec2 position;
|
||||||
|
glm::vec2 uv;
|
||||||
|
glm::vec4 color;
|
||||||
|
|
||||||
|
static constexpr VertexAttribute ATTRIBUTES[] {
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 2},
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 2},
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 4},
|
||||||
|
{{}, 0}};
|
||||||
|
};
|
||||||
|
|
||||||
class Batch2D : public Flushable {
|
class Batch2D : public Flushable {
|
||||||
std::unique_ptr<float[]> buffer;
|
std::unique_ptr<Batch2DVertex[]> buffer;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
std::unique_ptr<Mesh> mesh;
|
std::unique_ptr<Mesh<Batch2DVertex>> mesh;
|
||||||
std::unique_ptr<Texture> blank;
|
std::unique_ptr<Texture> blank;
|
||||||
size_t index;
|
size_t index;
|
||||||
glm::vec4 color;
|
glm::vec4 color;
|
||||||
|
|||||||
@ -3,21 +3,15 @@
|
|||||||
#include "Mesh.hpp"
|
#include "Mesh.hpp"
|
||||||
#include "Texture.hpp"
|
#include "Texture.hpp"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "maths/UVRegion.hpp"
|
#include "maths/UVRegion.hpp"
|
||||||
|
|
||||||
/// xyz, uv, rgba
|
Batch3D::Batch3D(size_t capacity)
|
||||||
inline constexpr uint B3D_VERTEX_SIZE = 9;
|
|
||||||
|
|
||||||
Batch3D::Batch3D(size_t capacity)
|
|
||||||
: capacity(capacity) {
|
: capacity(capacity) {
|
||||||
const VertexAttribute attrs[] = {
|
|
||||||
{3}, {2}, {4}, {0}
|
|
||||||
};
|
|
||||||
|
|
||||||
buffer = std::make_unique<float[]>(capacity * B3D_VERTEX_SIZE);
|
|
||||||
mesh = std::make_unique<Mesh>(buffer.get(), 0, attrs);
|
buffer = std::make_unique<Batch3DVertex[]>(capacity);
|
||||||
|
mesh = std::make_unique<Mesh<Batch3DVertex>>(buffer.get(), 0);
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
||||||
const ubyte pixels[] = {
|
const ubyte pixels[] = {
|
||||||
@ -40,69 +34,54 @@ void Batch3D::vertex(
|
|||||||
float x, float y, float z, float u, float v,
|
float x, float y, float z, float u, float v,
|
||||||
float r, float g, float b, float a
|
float r, float g, float b, float a
|
||||||
) {
|
) {
|
||||||
buffer[index++] = x;
|
buffer[index].position = {x, y, z};
|
||||||
buffer[index++] = y;
|
buffer[index].uv = {u, v};
|
||||||
buffer[index++] = z;
|
buffer[index].color = {r, g, b, a};
|
||||||
buffer[index++] = u;
|
index++;
|
||||||
buffer[index++] = v;
|
|
||||||
buffer[index++] = r;
|
|
||||||
buffer[index++] = g;
|
|
||||||
buffer[index++] = b;
|
|
||||||
buffer[index++] = a;
|
|
||||||
}
|
}
|
||||||
void Batch3D::vertex(
|
void Batch3D::vertex(
|
||||||
glm::vec3 coord, float u, float v,
|
glm::vec3 coord, float u, float v,
|
||||||
float r, float g, float b, float a
|
float r, float g, float b, float a
|
||||||
) {
|
) {
|
||||||
buffer[index++] = coord.x;
|
buffer[index].position = coord;
|
||||||
buffer[index++] = coord.y;
|
buffer[index].uv = {u, v};
|
||||||
buffer[index++] = coord.z;
|
buffer[index].color = {r, g, b, a};
|
||||||
buffer[index++] = u;
|
index++;
|
||||||
buffer[index++] = v;
|
|
||||||
buffer[index++] = r;
|
|
||||||
buffer[index++] = g;
|
|
||||||
buffer[index++] = b;
|
|
||||||
buffer[index++] = a;
|
|
||||||
}
|
}
|
||||||
void Batch3D::vertex(
|
void Batch3D::vertex(
|
||||||
glm::vec3 point,
|
glm::vec3 point,
|
||||||
glm::vec2 uvpoint,
|
glm::vec2 uvpoint,
|
||||||
float r, float g, float b, float a
|
float r, float g, float b, float a
|
||||||
) {
|
) {
|
||||||
buffer[index++] = point.x;
|
buffer[index].position = point;
|
||||||
buffer[index++] = point.y;
|
buffer[index].uv = uvpoint;
|
||||||
buffer[index++] = point.z;
|
buffer[index].color = {r, g, b, a};
|
||||||
buffer[index++] = uvpoint.x;
|
index++;
|
||||||
buffer[index++] = uvpoint.y;
|
|
||||||
buffer[index++] = r;
|
|
||||||
buffer[index++] = g;
|
|
||||||
buffer[index++] = b;
|
|
||||||
buffer[index++] = a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch3D::face(
|
void Batch3D::face(
|
||||||
const glm::vec3& coord,
|
const glm::vec3& coord,
|
||||||
float w, float h,
|
float w, float h,
|
||||||
const glm::vec3& axisX,
|
const glm::vec3& axisX,
|
||||||
const glm::vec3& axisY,
|
const glm::vec3& axisY,
|
||||||
const UVRegion& region,
|
const UVRegion& region,
|
||||||
const glm::vec4& tint
|
const glm::vec4& tint
|
||||||
) {
|
) {
|
||||||
if (index + B3D_VERTEX_SIZE * 6 > capacity) {
|
if (index + 6 >= capacity) {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
vertex(coord, region.u1, region.v1,
|
vertex(coord, region.u1, region.v1,
|
||||||
tint.r, tint.g, tint.b, tint.a);
|
tint.r, tint.g, tint.b, tint.a);
|
||||||
vertex(coord + axisX * w, region.u2, region.v1,
|
vertex(coord + axisX * w, region.u2, region.v1,
|
||||||
tint.r, tint.g, tint.b, tint.a);
|
tint.r, tint.g, tint.b, tint.a);
|
||||||
vertex(coord + axisX * w + axisY * h, region.u2, region.v2,
|
vertex(coord + axisX * w + axisY * h, region.u2, region.v2,
|
||||||
tint.r, tint.g, tint.b, tint.a);
|
tint.r, tint.g, tint.b, tint.a);
|
||||||
|
|
||||||
vertex(coord, region.u1, region.v1,
|
vertex(coord, region.u1, region.v1,
|
||||||
tint.r, tint.g, tint.b, tint.a);
|
tint.r, tint.g, tint.b, tint.a);
|
||||||
vertex(coord + axisX * w + axisY * h, region.u2, region.v2,
|
vertex(coord + axisX * w + axisY * h, region.u2, region.v2,
|
||||||
tint.r, tint.g, tint.b, tint.a);
|
tint.r, tint.g, tint.b, tint.a);
|
||||||
vertex(coord + axisY * h, region.u1, region.v2,
|
vertex(coord + axisY * h, region.u1, region.v2,
|
||||||
tint.r, tint.g, tint.b, tint.a);
|
tint.r, tint.g, tint.b, tint.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,18 +113,18 @@ void Batch3D::sprite(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Batch3D::sprite(
|
void Batch3D::sprite(
|
||||||
const glm::vec3& pos,
|
const glm::vec3& pos,
|
||||||
const glm::vec3& up,
|
const glm::vec3& up,
|
||||||
const glm::vec3& right,
|
const glm::vec3& right,
|
||||||
float w, float h,
|
float w, float h,
|
||||||
const UVRegion& uv,
|
const UVRegion& uv,
|
||||||
const glm::vec4& color
|
const glm::vec4& color
|
||||||
){
|
){
|
||||||
const float r = color.r;
|
const float r = color.r;
|
||||||
const float g = color.g;
|
const float g = color.g;
|
||||||
const float b = color.b;
|
const float b = color.b;
|
||||||
const float a = color.a;
|
const float a = color.a;
|
||||||
if (index + 6*B3D_VERTEX_SIZE >= capacity) {
|
if (index + 6 >= capacity) {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,17 +173,17 @@ void Batch3D::xSprite(
|
|||||||
float w, float h, const UVRegion& uv, const glm::vec4& tint, bool shading
|
float w, float h, const UVRegion& uv, const glm::vec4& tint, bool shading
|
||||||
) {
|
) {
|
||||||
face(
|
face(
|
||||||
glm::vec3(-w * 0.25f, 0.0f, -w * 0.25f),
|
glm::vec3(-w * 0.25f, 0.0f, -w * 0.25f),
|
||||||
w, h,
|
w, h,
|
||||||
glm::vec3(1, 0, 0),
|
glm::vec3(1, 0, 0),
|
||||||
glm::vec3(0, 1, 0),
|
glm::vec3(0, 1, 0),
|
||||||
uv, (shading ? do_tint(1.0f)*tint : tint)
|
uv, (shading ? do_tint(1.0f)*tint : tint)
|
||||||
);
|
);
|
||||||
face(
|
face(
|
||||||
glm::vec3(w * 0.25f, 0.0f, w * 0.5f - w * 0.25f),
|
glm::vec3(w * 0.25f, 0.0f, w * 0.5f - w * 0.25f),
|
||||||
w, h,
|
w, h,
|
||||||
glm::vec3(0, 0, -1),
|
glm::vec3(0, 0, -1),
|
||||||
glm::vec3(0, 1, 0),
|
glm::vec3(0, 1, 0),
|
||||||
uv, (shading ? do_tint(0.9f)*tint : tint)
|
uv, (shading ? do_tint(0.9f)*tint : tint)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -221,41 +200,41 @@ void Batch3D::cube(
|
|||||||
const glm::vec3 Z(0.0f, 0.0f, 1.0f);
|
const glm::vec3 Z(0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
face(
|
face(
|
||||||
coord+glm::vec3(0.0f, 0.0f, 0.0f),
|
coord+glm::vec3(0.0f, 0.0f, 0.0f),
|
||||||
size.x, size.y, X, Y, texfaces[5],
|
size.x, size.y, X, Y, texfaces[5],
|
||||||
(shading ? do_tint(0.8)*tint : tint)
|
(shading ? do_tint(0.8)*tint : tint)
|
||||||
);
|
);
|
||||||
face(
|
face(
|
||||||
coord+glm::vec3(size.x, 0.0f, -size.z),
|
coord+glm::vec3(size.x, 0.0f, -size.z),
|
||||||
size.x, size.y, -X, Y, texfaces[4],
|
size.x, size.y, -X, Y, texfaces[4],
|
||||||
(shading ? do_tint(0.8f)*tint : tint)
|
(shading ? do_tint(0.8f)*tint : tint)
|
||||||
);
|
);
|
||||||
face(
|
face(
|
||||||
coord+glm::vec3(0.0f, size.y, 0.0f),
|
coord+glm::vec3(0.0f, size.y, 0.0f),
|
||||||
size.x, size.z, X, -Z, texfaces[3],
|
size.x, size.z, X, -Z, texfaces[3],
|
||||||
(shading ? do_tint(1.0f)*tint : tint)
|
(shading ? do_tint(1.0f)*tint : tint)
|
||||||
);
|
);
|
||||||
face(
|
face(
|
||||||
coord+glm::vec3(0.0f, 0.0f, -size.z),
|
coord+glm::vec3(0.0f, 0.0f, -size.z),
|
||||||
size.x, size.z, X, Z, texfaces[2],
|
size.x, size.z, X, Z, texfaces[2],
|
||||||
(shading ? do_tint(0.7f)*tint : tint)
|
(shading ? do_tint(0.7f)*tint : tint)
|
||||||
);
|
);
|
||||||
face(
|
face(
|
||||||
coord+glm::vec3(0.0f, 0.0f, -size.z),
|
coord+glm::vec3(0.0f, 0.0f, -size.z),
|
||||||
size.z, size.y, Z, Y, texfaces[0],
|
size.z, size.y, Z, Y, texfaces[0],
|
||||||
(shading ? do_tint(0.9f)*tint : tint)
|
(shading ? do_tint(0.9f)*tint : tint)
|
||||||
);
|
);
|
||||||
face(
|
face(
|
||||||
coord+glm::vec3(size.x, 0.0f, 0.0f),
|
coord+glm::vec3(size.x, 0.0f, 0.0f),
|
||||||
size.z, size.y, -Z, Y, texfaces[1],
|
size.z, size.y, -Z, Y, texfaces[1],
|
||||||
(shading ? do_tint(0.9f)*tint : tint)
|
(shading ? do_tint(0.9f)*tint : tint)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch3D::blockCube(
|
void Batch3D::blockCube(
|
||||||
const glm::vec3& size,
|
const glm::vec3& size,
|
||||||
const UVRegion(&texfaces)[6],
|
const UVRegion(&texfaces)[6],
|
||||||
const glm::vec4& tint,
|
const glm::vec4& tint,
|
||||||
bool shading
|
bool shading
|
||||||
) {
|
) {
|
||||||
cube((1.0f - size) * -0.5f, size, texfaces, tint, shading);
|
cube((1.0f - size) * -0.5f, size, texfaces, tint, shading);
|
||||||
@ -264,27 +243,27 @@ void Batch3D::blockCube(
|
|||||||
void Batch3D::vertex(
|
void Batch3D::vertex(
|
||||||
const glm::vec3& coord, const glm::vec2& uv, const glm::vec4& tint
|
const glm::vec3& coord, const glm::vec2& uv, const glm::vec4& tint
|
||||||
) {
|
) {
|
||||||
if (index + B3D_VERTEX_SIZE >= capacity) {
|
if (index + 1 >= capacity) {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
vertex(coord, uv, tint.r, tint.g, tint.b, tint.a);
|
vertex(coord, uv, tint.r, tint.g, tint.b, tint.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch3D::point(const glm::vec3& coord, const glm::vec4& tint) {
|
void Batch3D::point(const glm::vec3& coord, const glm::vec4& tint) {
|
||||||
if (index + B3D_VERTEX_SIZE >= capacity) {
|
if (index + 1 >= capacity) {
|
||||||
flushPoints();
|
flushPoints();
|
||||||
}
|
}
|
||||||
vertex(coord, {}, tint.r, tint.g, tint.b, tint.a);
|
vertex(coord, {}, tint.r, tint.g, tint.b, tint.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch3D::flush() {
|
void Batch3D::flush() {
|
||||||
mesh->reload(buffer.get(), index / B3D_VERTEX_SIZE);
|
mesh->reload(buffer.get(), index);
|
||||||
mesh->draw();
|
mesh->draw();
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch3D::flushPoints() {
|
void Batch3D::flushPoints() {
|
||||||
mesh->reload(buffer.get(), index / B3D_VERTEX_SIZE);
|
mesh->reload(buffer.get(), index);
|
||||||
mesh->draw(GL_POINTS);
|
mesh->draw(GL_POINTS);
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,19 +2,33 @@
|
|||||||
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "commons.hpp"
|
#include "commons.hpp"
|
||||||
|
#include "MeshData.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdlib.h>
|
#include <cstdlib>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
class Mesh;
|
template<typename VertexStructure> class Mesh;
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
struct UVRegion;
|
struct UVRegion;
|
||||||
|
|
||||||
|
struct Batch3DVertex {
|
||||||
|
glm::vec3 position;
|
||||||
|
glm::vec2 uv;
|
||||||
|
glm::vec4 color;
|
||||||
|
|
||||||
|
static constexpr VertexAttribute ATTRIBUTES[] {
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 3},
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 2},
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 4},
|
||||||
|
{{}, 0}};
|
||||||
|
};
|
||||||
|
|
||||||
class Batch3D : public Flushable {
|
class Batch3D : public Flushable {
|
||||||
std::unique_ptr<float[]> buffer;
|
std::unique_ptr<Batch3DVertex[]> buffer;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
std::unique_ptr<Mesh> mesh;
|
std::unique_ptr<Mesh<Batch3DVertex>> mesh;
|
||||||
std::unique_ptr<Texture> blank;
|
std::unique_ptr<Texture> blank;
|
||||||
size_t index;
|
size_t index;
|
||||||
glm::vec4 tint {1.0f};
|
glm::vec4 tint {1.0f};
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
Cubemap::Cubemap(uint width, uint height, ImageFormat imageFormat)
|
Cubemap::Cubemap(uint width, uint height, ImageFormat imageFormat)
|
||||||
: GLTexture(0, width, height)
|
: Texture(0, width, height)
|
||||||
{
|
{
|
||||||
glGenTextures(1, &id);
|
glGenTextures(1, &id);
|
||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, id);
|
glBindTexture(GL_TEXTURE_CUBE_MAP, id);
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "GLTexture.hpp"
|
#include "Texture.hpp"
|
||||||
|
|
||||||
/// @brief Cubemap texture
|
/// @brief Cubemap texture
|
||||||
class Cubemap : public GLTexture {
|
class Cubemap : public Texture {
|
||||||
public:
|
public:
|
||||||
Cubemap(uint width, uint height, ImageFormat format);
|
Cubemap(uint width, uint height, ImageFormat format);
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#include "Framebuffer.hpp"
|
#include "Framebuffer.hpp"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include "GLTexture.hpp"
|
#include "Texture.hpp"
|
||||||
|
|
||||||
Framebuffer::Framebuffer(uint fbo, uint depth, std::unique_ptr<Texture> texture)
|
Framebuffer::Framebuffer(uint fbo, uint depth, std::unique_ptr<Texture> texture)
|
||||||
: fbo(fbo), depth(depth), texture(std::move(texture))
|
: fbo(fbo), depth(depth), texture(std::move(texture))
|
||||||
@ -25,7 +25,7 @@ static std::unique_ptr<Texture> create_texture(int width, int height, int format
|
|||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
|
||||||
return std::make_unique<GLTexture>(tex, width, height);
|
return std::make_unique<Texture>(tex, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
Framebuffer::Framebuffer(uint width, uint height, bool alpha)
|
Framebuffer::Framebuffer(uint width, uint height, bool alpha)
|
||||||
|
|||||||
@ -1,101 +0,0 @@
|
|||||||
#include "GLTexture.hpp"
|
|
||||||
#include "gl_util.hpp"
|
|
||||||
|
|
||||||
#include <GL/glew.h>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
uint Texture::MAX_RESOLUTION = 1024; // Window.initialize overrides it
|
|
||||||
|
|
||||||
GLTexture::GLTexture(uint id, uint width, uint height)
|
|
||||||
: Texture(width, height), id(id) {
|
|
||||||
}
|
|
||||||
|
|
||||||
GLTexture::GLTexture(const ubyte* data, uint width, uint height, ImageFormat imageFormat)
|
|
||||||
: Texture(width, height) {
|
|
||||||
glGenTextures(1, &id);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
||||||
|
|
||||||
GLenum format = gl::to_glenum(imageFormat);
|
|
||||||
glTexImage2D(
|
|
||||||
GL_TEXTURE_2D, 0, format, width, height, 0,
|
|
||||||
format, GL_UNSIGNED_BYTE, static_cast<const GLvoid*>(data)
|
|
||||||
);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glGenerateMipmap(GL_TEXTURE_2D);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLTexture::~GLTexture() {
|
|
||||||
glDeleteTextures(1, &id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLTexture::bind() const {
|
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLTexture::unbind() const {
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLTexture::reload(const ImageData& image) {
|
|
||||||
width = image.getWidth();
|
|
||||||
height = image.getHeight();
|
|
||||||
reload(image.getData());
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLTexture::reload(const ubyte* data) {
|
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
|
|
||||||
GL_RGBA, GL_UNSIGNED_BYTE, static_cast<const GLvoid*>(data));
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<ImageData> GLTexture::readData() {
|
|
||||||
auto data = std::make_unique<ubyte[]>(width * height * 4);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
|
||||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.get());
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
return std::make_unique<ImageData>(
|
|
||||||
ImageFormat::rgba8888, width, height, std::move(data)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLTexture::setNearestFilter() {
|
|
||||||
bind();
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLTexture::setMipMapping(bool flag, bool pixelated) {
|
|
||||||
bind();
|
|
||||||
if (flag) {
|
|
||||||
glTexParameteri(
|
|
||||||
GL_TEXTURE_2D,
|
|
||||||
GL_TEXTURE_MIN_FILTER,
|
|
||||||
pixelated ? GL_NEAREST : GL_LINEAR_MIPMAP_NEAREST
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
glTexParameteri(
|
|
||||||
GL_TEXTURE_2D,
|
|
||||||
GL_TEXTURE_MIN_FILTER,
|
|
||||||
pixelated ? GL_NEAREST : GL_LINEAR
|
|
||||||
);
|
|
||||||
}
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<GLTexture> GLTexture::from(const ImageData* image) {
|
|
||||||
uint width = image->getWidth();
|
|
||||||
uint height = image->getHeight();
|
|
||||||
void* data = image->getData();
|
|
||||||
return std::make_unique<GLTexture>(static_cast<ubyte*>(data), width, height, image->getFormat());
|
|
||||||
}
|
|
||||||
|
|
||||||
uint GLTexture::getId() const {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Texture.hpp"
|
|
||||||
|
|
||||||
class GLTexture : public Texture {
|
|
||||||
protected:
|
|
||||||
uint id;
|
|
||||||
public:
|
|
||||||
GLTexture(uint id, uint width, uint height);
|
|
||||||
GLTexture(const ubyte* data, uint width, uint height, ImageFormat format);
|
|
||||||
virtual ~GLTexture();
|
|
||||||
|
|
||||||
virtual void bind() const override;
|
|
||||||
virtual void unbind() const override;
|
|
||||||
virtual void reload(const ubyte* data);
|
|
||||||
|
|
||||||
void setNearestFilter();
|
|
||||||
|
|
||||||
virtual void reload(const ImageData& image) override;
|
|
||||||
|
|
||||||
virtual void setMipMapping(bool flag, bool pixelated) override;
|
|
||||||
|
|
||||||
virtual std::unique_ptr<ImageData> readData() override;
|
|
||||||
virtual uint getId() const override;
|
|
||||||
|
|
||||||
virtual UVRegion getUVRegion() const override {
|
|
||||||
return UVRegion(0.0f, 0.0f, 1.0f, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::unique_ptr<GLTexture> from(const ImageData* image);
|
|
||||||
};
|
|
||||||
@ -3,12 +3,11 @@
|
|||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
inline constexpr uint LB_VERTEX_SIZE = (3+4);
|
|
||||||
|
|
||||||
LineBatch::LineBatch(size_t capacity) : capacity(capacity) {
|
LineBatch::LineBatch(size_t capacity) : capacity(capacity) {
|
||||||
const VertexAttribute attrs[] = { {3},{4}, {0} };
|
|
||||||
buffer = std::make_unique<float[]>(capacity * LB_VERTEX_SIZE * 2);
|
buffer = std::make_unique<LineVertex[]>(capacity * 2);
|
||||||
mesh = std::make_unique<Mesh>(buffer.get(), 0, attrs);
|
mesh = std::make_unique<Mesh<LineVertex>>(buffer.get(), 0);
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,31 +15,21 @@ LineBatch::~LineBatch(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LineBatch::line(
|
void LineBatch::line(
|
||||||
float x1, float y1,
|
float x1, float y1,
|
||||||
float z1, float x2,
|
float z1, float x2,
|
||||||
float y2, float z2,
|
float y2, float z2,
|
||||||
float r, float g, float b, float a
|
float r, float g, float b, float a
|
||||||
) {
|
) {
|
||||||
if (index + LB_VERTEX_SIZE * 2 >= capacity) {
|
if (index + 2 >= capacity) {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
buffer[index] = x1;
|
buffer[index].position = {x1,y1,z1};
|
||||||
buffer[index+1] = y1;
|
buffer[index].color = {r,g,b,a};
|
||||||
buffer[index+2] = z1;
|
index++;
|
||||||
buffer[index+3] = r;
|
|
||||||
buffer[index+4] = g;
|
|
||||||
buffer[index+5] = b;
|
|
||||||
buffer[index+6] = a;
|
|
||||||
index += LB_VERTEX_SIZE;
|
|
||||||
|
|
||||||
buffer[index] = x2;
|
buffer[index].position = {x2,y2,z2};
|
||||||
buffer[index+1] = y2;
|
buffer[index].color = {r,g,b,a};
|
||||||
buffer[index+2] = z2;
|
index++;
|
||||||
buffer[index+3] = r;
|
|
||||||
buffer[index+4] = g;
|
|
||||||
buffer[index+5] = b;
|
|
||||||
buffer[index+6] = a;
|
|
||||||
index += LB_VERTEX_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LineBatch::box(float x, float y, float z, float w, float h, float d,
|
void LineBatch::box(float x, float y, float z, float w, float h, float d,
|
||||||
@ -68,7 +57,7 @@ void LineBatch::box(float x, float y, float z, float w, float h, float d,
|
|||||||
void LineBatch::flush(){
|
void LineBatch::flush(){
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
return;
|
return;
|
||||||
mesh->reload(buffer.get(), index / LB_VERTEX_SIZE);
|
mesh->reload(buffer.get(), index);
|
||||||
mesh->draw(GL_LINES);
|
mesh->draw(GL_LINES);
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,12 +5,24 @@
|
|||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "commons.hpp"
|
#include "commons.hpp"
|
||||||
|
#include "MeshData.hpp"
|
||||||
|
|
||||||
|
template<typename VertexStructure>
|
||||||
class Mesh;
|
class Mesh;
|
||||||
|
|
||||||
|
struct LineVertex {
|
||||||
|
glm::vec3 position;
|
||||||
|
glm::vec4 color;
|
||||||
|
|
||||||
|
static constexpr VertexAttribute ATTRIBUTES[] {
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 3},
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 4},
|
||||||
|
{{}, 0}};
|
||||||
|
};
|
||||||
|
|
||||||
class LineBatch : public Flushable {
|
class LineBatch : public Flushable {
|
||||||
std::unique_ptr<Mesh> mesh;
|
std::unique_ptr<Mesh<LineVertex>> mesh;
|
||||||
std::unique_ptr<float[]> buffer;
|
std::unique_ptr<LineVertex[]> buffer;
|
||||||
size_t index;
|
size_t index;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -1,93 +1,4 @@
|
|||||||
#include "Mesh.hpp"
|
#include "graphics/core/Mesh.hpp"
|
||||||
#include <assert.h>
|
|
||||||
#include <GL/glew.h>
|
|
||||||
|
|
||||||
int Mesh::meshesCount = 0;
|
int MeshStats::meshesCount = 0;
|
||||||
int Mesh::drawCalls = 0;
|
int MeshStats::drawCalls = 0;
|
||||||
|
|
||||||
inline size_t calc_vertex_size(const VertexAttribute* attrs) {
|
|
||||||
size_t vertexSize = 0;
|
|
||||||
for (int i = 0; attrs[i].size; i++) {
|
|
||||||
vertexSize += attrs[i].size;
|
|
||||||
}
|
|
||||||
assert(vertexSize != 0);
|
|
||||||
return vertexSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mesh::Mesh(const MeshData& data)
|
|
||||||
: Mesh(data.vertices.data(),
|
|
||||||
data.vertices.size() / calc_vertex_size(data.attrs.data()),
|
|
||||||
data.indices.data(),
|
|
||||||
data.indices.size(),
|
|
||||||
data.attrs.data()) {}
|
|
||||||
|
|
||||||
Mesh::Mesh(const float* vertexBuffer, size_t vertices, const int* indexBuffer, size_t indices, const VertexAttribute* attrs) :
|
|
||||||
ibo(0),
|
|
||||||
vertices(0),
|
|
||||||
indices(0)
|
|
||||||
{
|
|
||||||
meshesCount++;
|
|
||||||
vertexSize = 0;
|
|
||||||
for (int i = 0; attrs[i].size; i++) {
|
|
||||||
vertexSize += attrs[i].size;
|
|
||||||
}
|
|
||||||
|
|
||||||
glGenVertexArrays(1, &vao);
|
|
||||||
glGenBuffers(1, &vbo);
|
|
||||||
|
|
||||||
reload(vertexBuffer, vertices, indexBuffer, indices);
|
|
||||||
|
|
||||||
// attributes
|
|
||||||
int offset = 0;
|
|
||||||
for (int i = 0; attrs[i].size; i++) {
|
|
||||||
int size = attrs[i].size;
|
|
||||||
glVertexAttribPointer(i, size, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (GLvoid*)(offset * sizeof(float)));
|
|
||||||
glEnableVertexAttribArray(i);
|
|
||||||
offset += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mesh::~Mesh(){
|
|
||||||
meshesCount--;
|
|
||||||
glDeleteVertexArrays(1, &vao);
|
|
||||||
glDeleteBuffers(1, &vbo);
|
|
||||||
if (ibo != 0) glDeleteBuffers(1, &ibo);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mesh::reload(const float* vertexBuffer, size_t vertices, const int* indexBuffer, size_t indices){
|
|
||||||
glBindVertexArray(vao);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
||||||
if (vertexBuffer != nullptr && vertices != 0) {
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertexSize * vertices, vertexBuffer, GL_STREAM_DRAW);
|
|
||||||
} else {
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, 0, {}, GL_STREAM_DRAW);
|
|
||||||
}
|
|
||||||
if (indexBuffer != nullptr && indices != 0) {
|
|
||||||
if (ibo == 0) glGenBuffers(1, &ibo);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * indices, indexBuffer, GL_STATIC_DRAW);
|
|
||||||
}
|
|
||||||
else if (ibo != 0) {
|
|
||||||
glDeleteBuffers(1, &ibo);
|
|
||||||
}
|
|
||||||
this->vertices = vertices;
|
|
||||||
this->indices = indices;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mesh::draw(unsigned int primitive) const {
|
|
||||||
drawCalls++;
|
|
||||||
glBindVertexArray(vao);
|
|
||||||
if (ibo != 0) {
|
|
||||||
glDrawElements(primitive, indices, GL_UNSIGNED_INT, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
glDrawArrays(primitive, 0, vertices);
|
|
||||||
}
|
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mesh::draw() const {
|
|
||||||
draw(GL_TRIANGLES);
|
|
||||||
}
|
|
||||||
@ -1,39 +1,54 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "typedefs.hpp"
|
|
||||||
#include "MeshData.hpp"
|
#include "MeshData.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
struct MeshStats {
|
||||||
|
static int meshesCount;
|
||||||
|
static int drawCalls;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename VertexStructure>
|
||||||
class Mesh {
|
class Mesh {
|
||||||
unsigned int vao;
|
unsigned int vao;
|
||||||
unsigned int vbo;
|
unsigned int vbo;
|
||||||
unsigned int ibo;
|
unsigned int ibo;
|
||||||
size_t vertices;
|
size_t vertexCount;
|
||||||
size_t indices;
|
size_t indexCount;
|
||||||
size_t vertexSize;
|
|
||||||
public:
|
public:
|
||||||
Mesh(const MeshData& data);
|
explicit Mesh(const MeshData<VertexStructure>& data);
|
||||||
Mesh(const float* vertexBuffer, size_t vertices, const int* indexBuffer, size_t indices, const VertexAttribute* attrs);
|
|
||||||
Mesh(const float* vertexBuffer, size_t vertices, const VertexAttribute* attrs) :
|
Mesh(
|
||||||
Mesh(vertexBuffer, vertices, nullptr, 0, attrs) {};
|
const VertexStructure* vertexBuffer,
|
||||||
|
size_t vertices,
|
||||||
|
const uint32_t* indexBuffer,
|
||||||
|
size_t indices
|
||||||
|
);
|
||||||
|
|
||||||
|
Mesh(const VertexStructure* vertexBuffer, size_t vertices)
|
||||||
|
: Mesh<VertexStructure>(vertexBuffer, vertices, nullptr, 0) {};
|
||||||
|
|
||||||
~Mesh();
|
~Mesh();
|
||||||
|
|
||||||
/// @brief Update GL vertex and index buffers data without changing VAO attributes
|
/// @brief Update GL vertex and index buffers data without changing VAO
|
||||||
|
/// attributes
|
||||||
/// @param vertexBuffer vertex data buffer
|
/// @param vertexBuffer vertex data buffer
|
||||||
/// @param vertices number of vertices in new buffer
|
/// @param vertexCount number of vertices in new buffer
|
||||||
/// @param indexBuffer indices buffer
|
/// @param indexBuffer indices buffer
|
||||||
/// @param indices number of values in indices buffer
|
/// @param indexCount number of values in indices buffer
|
||||||
void reload(const float* vertexBuffer, size_t vertices, const int* indexBuffer = nullptr, size_t indices = 0);
|
void reload(
|
||||||
|
const VertexStructure* vertexBuffer,
|
||||||
|
size_t vertexCount,
|
||||||
|
const uint32_t* indexBuffer = nullptr,
|
||||||
|
size_t indexCount = 0
|
||||||
|
);
|
||||||
|
|
||||||
/// @brief Draw mesh with specified primitives type
|
/// @brief Draw mesh with specified primitives type
|
||||||
/// @param primitive primitives type
|
/// @param primitive primitives type
|
||||||
void draw(unsigned int primitive) const;
|
void draw(unsigned int primitive) const;
|
||||||
|
|
||||||
/// @brief Draw mesh as triangles
|
/// @brief Draw mesh as triangles
|
||||||
void draw() const;
|
void draw() const;
|
||||||
|
|
||||||
/// @brief Total numbers of alive mesh objects
|
|
||||||
static int meshesCount;
|
|
||||||
static int drawCalls;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#include "graphics/core/Mesh.inl"
|
||||||
|
|||||||
124
src/graphics/core/Mesh.inl
Normal file
124
src/graphics/core/Mesh.inl
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MeshData.hpp"
|
||||||
|
#include "gl_util.hpp"
|
||||||
|
|
||||||
|
inline constexpr size_t calc_size(const VertexAttribute attrs[]) {
|
||||||
|
size_t vertexSize = 0;
|
||||||
|
for (int i = 0; attrs[i].count; i++) {
|
||||||
|
vertexSize += attrs[i].size();
|
||||||
|
}
|
||||||
|
return vertexSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexStructure>
|
||||||
|
Mesh<VertexStructure>::Mesh(const MeshData<VertexStructure>& data)
|
||||||
|
: Mesh(
|
||||||
|
data.vertices.data(),
|
||||||
|
data.vertices.size(),
|
||||||
|
data.indices.data(),
|
||||||
|
data.indices.size()
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexStructure>
|
||||||
|
Mesh<VertexStructure>::Mesh(
|
||||||
|
const VertexStructure* vertexBuffer,
|
||||||
|
size_t vertices,
|
||||||
|
const uint32_t* indexBuffer,
|
||||||
|
size_t indices
|
||||||
|
)
|
||||||
|
: vao(0), vbo(0), ibo(0), vertexCount(0), indexCount(0) {
|
||||||
|
static_assert(
|
||||||
|
calc_size(VertexStructure::ATTRIBUTES) == sizeof(VertexStructure)
|
||||||
|
);
|
||||||
|
|
||||||
|
const auto& attrs = VertexStructure::ATTRIBUTES;
|
||||||
|
MeshStats::meshesCount++;
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &vao);
|
||||||
|
glGenBuffers(1, &vbo);
|
||||||
|
|
||||||
|
reload(vertexBuffer, vertices, indexBuffer, indices);
|
||||||
|
|
||||||
|
// attributes
|
||||||
|
int offset = 0;
|
||||||
|
for (int i = 0; attrs[i].count; i++) {
|
||||||
|
const VertexAttribute& attr = attrs[i];
|
||||||
|
glVertexAttribPointer(
|
||||||
|
i,
|
||||||
|
attr.count,
|
||||||
|
gl::to_glenum(attr.type),
|
||||||
|
attr.normalized,
|
||||||
|
sizeof(VertexStructure),
|
||||||
|
(GLvoid*)(size_t)offset
|
||||||
|
);
|
||||||
|
glEnableVertexAttribArray(i);
|
||||||
|
offset += attr.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexStructure>
|
||||||
|
Mesh<VertexStructure>::~Mesh() {
|
||||||
|
MeshStats::meshesCount--;
|
||||||
|
glDeleteVertexArrays(1, &vao);
|
||||||
|
glDeleteBuffers(1, &vbo);
|
||||||
|
if (ibo != 0) {
|
||||||
|
glDeleteBuffers(1, &ibo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexStructure>
|
||||||
|
void Mesh<VertexStructure>::reload(
|
||||||
|
const VertexStructure* vertexBuffer,
|
||||||
|
size_t vertexCount,
|
||||||
|
const uint32_t* indexBuffer,
|
||||||
|
size_t indexCount
|
||||||
|
) {
|
||||||
|
this->vertexCount = vertexCount;
|
||||||
|
this->indexCount = indexCount;
|
||||||
|
glBindVertexArray(vao);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
|
if (vertexBuffer != nullptr && vertexCount != 0) {
|
||||||
|
glBufferData(
|
||||||
|
GL_ARRAY_BUFFER,
|
||||||
|
vertexCount * sizeof(VertexStructure),
|
||||||
|
vertexBuffer,
|
||||||
|
GL_STREAM_DRAW
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, 0, {}, GL_STREAM_DRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indexBuffer != nullptr && indexCount != 0) {
|
||||||
|
if (ibo == 0) glGenBuffers(1, &ibo);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
||||||
|
glBufferData(
|
||||||
|
GL_ELEMENT_ARRAY_BUFFER,
|
||||||
|
sizeof(uint32_t) * indexCount,
|
||||||
|
indexBuffer,
|
||||||
|
GL_STATIC_DRAW
|
||||||
|
);
|
||||||
|
} else if (ibo != 0) {
|
||||||
|
glDeleteBuffers(1, &ibo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexStructure>
|
||||||
|
void Mesh<VertexStructure>::draw(unsigned int primitive) const {
|
||||||
|
MeshStats::drawCalls++;
|
||||||
|
glBindVertexArray(vao);
|
||||||
|
if (ibo != 0) {
|
||||||
|
glDrawElements(primitive, indexCount, GL_UNSIGNED_INT, nullptr);
|
||||||
|
} else {
|
||||||
|
glDrawArrays(primitive, 0, vertexCount);
|
||||||
|
}
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexStructure>
|
||||||
|
void Mesh<VertexStructure>::draw() const {
|
||||||
|
draw(GL_TRIANGLES);
|
||||||
|
}
|
||||||
@ -1,19 +1,46 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "util/Buffer.hpp"
|
#include "util/Buffer.hpp"
|
||||||
|
|
||||||
/// @brief Vertex attribute info
|
/// @brief Vertex attribute info
|
||||||
struct VertexAttribute {
|
struct VertexAttribute {
|
||||||
ubyte size;
|
enum class Type {
|
||||||
|
FLOAT,
|
||||||
|
INT, UNSIGNED_INT,
|
||||||
|
SHORT, UNSIGNED_SHORT,
|
||||||
|
BYTE, UNSIGNED_BYTE
|
||||||
|
};
|
||||||
|
|
||||||
|
Type type = Type::FLOAT;
|
||||||
|
bool normalized = false;
|
||||||
|
ubyte count = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr uint32_t size() const {
|
||||||
|
switch (type) {
|
||||||
|
case Type::FLOAT:
|
||||||
|
return count * sizeof(float);
|
||||||
|
case Type::UNSIGNED_INT:
|
||||||
|
case Type::INT:
|
||||||
|
return count * sizeof(int32_t);
|
||||||
|
case Type::UNSIGNED_SHORT:
|
||||||
|
case Type::SHORT:
|
||||||
|
return count * sizeof(int16_t);
|
||||||
|
case Type::UNSIGNED_BYTE:
|
||||||
|
case Type::BYTE:
|
||||||
|
return count * sizeof(int8_t);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Raw mesh data structure
|
/// @brief Raw mesh data structure
|
||||||
|
template<typename VertexStructure>
|
||||||
struct MeshData {
|
struct MeshData {
|
||||||
util::Buffer<float> vertices;
|
util::Buffer<VertexStructure> vertices;
|
||||||
util::Buffer<int> indices;
|
util::Buffer<uint32_t> indices;
|
||||||
util::Buffer<VertexAttribute> attrs;
|
util::Buffer<VertexAttribute> attrs;
|
||||||
|
|
||||||
MeshData() = default;
|
MeshData() = default;
|
||||||
@ -22,8 +49,8 @@ struct MeshData {
|
|||||||
/// @param indices nullable indices buffer
|
/// @param indices nullable indices buffer
|
||||||
/// @param attrs vertex attribute sizes (must be null-terminated)
|
/// @param attrs vertex attribute sizes (must be null-terminated)
|
||||||
MeshData(
|
MeshData(
|
||||||
util::Buffer<float> vertices,
|
util::Buffer<VertexStructure> vertices,
|
||||||
util::Buffer<int> indices,
|
util::Buffer<uint32_t> indices,
|
||||||
util::Buffer<VertexAttribute> attrs
|
util::Buffer<VertexAttribute> attrs
|
||||||
) : vertices(std::move(vertices)),
|
) : vertices(std::move(vertices)),
|
||||||
indices(std::move(indices)),
|
indices(std::move(indices)),
|
||||||
|
|||||||
@ -12,12 +12,16 @@
|
|||||||
PostProcessing::PostProcessing(size_t effectSlotsCount)
|
PostProcessing::PostProcessing(size_t effectSlotsCount)
|
||||||
: effectSlots(effectSlotsCount) {
|
: effectSlots(effectSlotsCount) {
|
||||||
// Fullscreen quad mesh bulding
|
// Fullscreen quad mesh bulding
|
||||||
float vertices[] {
|
PostProcessingVertex meshData[]{
|
||||||
-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
|
{{-1.0f, -1.0f}},
|
||||||
-1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f
|
{{-1.0f, 1.0f}},
|
||||||
|
{{1.0f, 1.0f}},
|
||||||
|
{{-1.0f, -1.0f}},
|
||||||
|
{{1.0f, 1.0f}},
|
||||||
|
{{1.0f, -1.0f}},
|
||||||
};
|
};
|
||||||
VertexAttribute attrs[] {{2}, {0}};
|
|
||||||
quadMesh = std::make_unique<Mesh>(vertices, 6, attrs);
|
quadMesh = std::make_unique<Mesh<PostProcessingVertex>>(meshData, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
PostProcessing::~PostProcessing() = default;
|
PostProcessing::~PostProcessing() = default;
|
||||||
|
|||||||
@ -2,14 +2,24 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include "MeshData.hpp"
|
||||||
|
|
||||||
class Mesh;
|
template<typename VertexStructure> class Mesh;
|
||||||
class Assets;
|
class Assets;
|
||||||
class Framebuffer;
|
class Framebuffer;
|
||||||
class DrawContext;
|
class DrawContext;
|
||||||
class ImageData;
|
class ImageData;
|
||||||
class PostEffect;
|
class PostEffect;
|
||||||
|
|
||||||
|
struct PostProcessingVertex {
|
||||||
|
glm::vec2 position;
|
||||||
|
|
||||||
|
static constexpr VertexAttribute ATTRIBUTES[] {
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 2},
|
||||||
|
{{}, 0}};
|
||||||
|
};
|
||||||
|
|
||||||
/// @brief Framebuffer with blitting with shaders.
|
/// @brief Framebuffer with blitting with shaders.
|
||||||
/// @attention Current implementation does not support multiple render passes
|
/// @attention Current implementation does not support multiple render passes
|
||||||
/// for multiple effects. Will be implemented in v0.21
|
/// for multiple effects. Will be implemented in v0.21
|
||||||
@ -18,7 +28,7 @@ class PostProcessing {
|
|||||||
std::unique_ptr<Framebuffer> fbo;
|
std::unique_ptr<Framebuffer> fbo;
|
||||||
std::unique_ptr<Framebuffer> fboSecond;
|
std::unique_ptr<Framebuffer> fboSecond;
|
||||||
/// @brief Fullscreen quad mesh as the post-processing canvas
|
/// @brief Fullscreen quad mesh as the post-processing canvas
|
||||||
std::unique_ptr<Mesh> quadMesh;
|
std::unique_ptr<Mesh<PostProcessingVertex>> quadMesh;
|
||||||
std::vector<std::shared_ptr<PostEffect>> effectSlots;
|
std::vector<std::shared_ptr<PostEffect>> effectSlots;
|
||||||
public:
|
public:
|
||||||
PostProcessing(size_t effectSlotsCount);
|
PostProcessing(size_t effectSlotsCount);
|
||||||
|
|||||||
@ -1,6 +1,103 @@
|
|||||||
#include "Texture.hpp"
|
#include "Texture.hpp"
|
||||||
#include "GLTexture.hpp"
|
#include "gl_util.hpp"
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
uint Texture::MAX_RESOLUTION = 1024; // Window.initialize overrides it
|
||||||
|
|
||||||
|
Texture::Texture(uint id, uint width, uint height)
|
||||||
|
: id(id), width(width), height(height) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture::Texture(const ubyte* data, uint width, uint height, ImageFormat imageFormat)
|
||||||
|
: width(width), height(height) {
|
||||||
|
glGenTextures(1, &id);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, id);
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
|
GLenum format = gl::to_glenum(imageFormat);
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_2D, 0, format, width, height, 0,
|
||||||
|
format, GL_UNSIGNED_BYTE, static_cast<const GLvoid*>(data)
|
||||||
|
);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture::~Texture() {
|
||||||
|
glDeleteTextures(1, &id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::bind() const {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::unbind() const {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::reload(const ImageData& image) {
|
||||||
|
width = image.getWidth();
|
||||||
|
height = image.getHeight();
|
||||||
|
reload(image.getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::reload(const ubyte* data) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, id);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
|
||||||
|
GL_RGBA, GL_UNSIGNED_BYTE, static_cast<const GLvoid*>(data));
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ImageData> Texture::readData() {
|
||||||
|
auto data = std::make_unique<ubyte[]>(width * height * 4);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, id);
|
||||||
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.get());
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
return std::make_unique<ImageData>(
|
||||||
|
ImageFormat::rgba8888, width, height, std::move(data)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::setNearestFilter() {
|
||||||
|
bind();
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::setMipMapping(bool flag, bool pixelated) {
|
||||||
|
bind();
|
||||||
|
if (flag) {
|
||||||
|
glTexParameteri(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
GL_TEXTURE_MIN_FILTER,
|
||||||
|
pixelated ? GL_NEAREST : GL_LINEAR_MIPMAP_NEAREST
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
glTexParameteri(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
GL_TEXTURE_MIN_FILTER,
|
||||||
|
pixelated ? GL_NEAREST : GL_LINEAR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<Texture> Texture::from(const ImageData* image) {
|
std::unique_ptr<Texture> Texture::from(const ImageData* image) {
|
||||||
return GLTexture::from(image);
|
uint width = image->getWidth();
|
||||||
|
uint height = image->getHeight();
|
||||||
|
void* data = image->getData();
|
||||||
|
return std::make_unique<Texture>(
|
||||||
|
static_cast<ubyte*>(data), width, height, image->getFormat()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Texture::getId() const {
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,33 +8,39 @@
|
|||||||
|
|
||||||
class Texture {
|
class Texture {
|
||||||
protected:
|
protected:
|
||||||
|
uint id;
|
||||||
uint width;
|
uint width;
|
||||||
uint height;
|
uint height;
|
||||||
|
|
||||||
Texture(uint width, uint height) : width(width), height(height) {}
|
|
||||||
public:
|
public:
|
||||||
static uint MAX_RESOLUTION;
|
Texture(uint id, uint width, uint height);
|
||||||
|
Texture(const ubyte* data, uint width, uint height, ImageFormat format);
|
||||||
|
virtual ~Texture();
|
||||||
|
|
||||||
virtual ~Texture() {}
|
virtual void bind() const;
|
||||||
|
virtual void unbind() const;
|
||||||
|
void reload(const ubyte* data);
|
||||||
|
|
||||||
virtual void bind() const = 0;
|
void setNearestFilter();
|
||||||
virtual void unbind() const = 0;
|
|
||||||
|
|
||||||
virtual void reload(const ImageData& image) = 0;
|
void reload(const ImageData& image);
|
||||||
|
|
||||||
virtual std::unique_ptr<ImageData> readData() = 0;
|
void setMipMapping(bool flag, bool pixelated);
|
||||||
|
|
||||||
virtual uint getWidth() const {
|
std::unique_ptr<ImageData> readData();
|
||||||
|
uint getId() const;
|
||||||
|
|
||||||
|
UVRegion getUVRegion() const {
|
||||||
|
return UVRegion(0.0f, 0.0f, 1.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint getWidth() const {
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
virtual uint getHeight() const {
|
|
||||||
|
uint getHeight() const {
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
virtual UVRegion getUVRegion() const = 0;
|
|
||||||
|
|
||||||
virtual uint getId() const = 0;
|
|
||||||
|
|
||||||
virtual void setMipMapping(bool flag, bool pixelated) = 0;
|
|
||||||
|
|
||||||
static std::unique_ptr<Texture> from(const ImageData* image);
|
static std::unique_ptr<Texture> from(const ImageData* image);
|
||||||
|
static uint MAX_RESOLUTION;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#include "TextureAnimation.hpp"
|
#include "TextureAnimation.hpp"
|
||||||
#include "GLTexture.hpp"
|
#include "Texture.hpp"
|
||||||
#include "Framebuffer.hpp"
|
#include "Framebuffer.hpp"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "commons.hpp"
|
#include "commons.hpp"
|
||||||
#include "ImageData.hpp"
|
#include "ImageData.hpp"
|
||||||
|
#include "MeshData.hpp"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
@ -23,4 +24,25 @@ namespace gl {
|
|||||||
};
|
};
|
||||||
return primitives[static_cast<int>(primitive)];
|
return primitives[static_cast<int>(primitive)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline GLenum to_glenum(VertexAttribute::Type type) {
|
||||||
|
using Type = VertexAttribute::Type;
|
||||||
|
switch (type) {
|
||||||
|
case Type::FLOAT:
|
||||||
|
return GL_FLOAT;
|
||||||
|
case Type::UNSIGNED_INT:
|
||||||
|
return GL_UNSIGNED_INT;
|
||||||
|
case Type::INT:
|
||||||
|
return GL_INT;
|
||||||
|
case Type::UNSIGNED_SHORT:
|
||||||
|
return GL_UNSIGNED_SHORT;
|
||||||
|
case Type::SHORT:
|
||||||
|
return GL_SHORT;
|
||||||
|
case Type::UNSIGNED_BYTE:
|
||||||
|
return GL_UNSIGNED_BYTE;
|
||||||
|
case Type::BYTE:
|
||||||
|
return GL_BYTE;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,8 +44,8 @@ void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) {
|
|||||||
}
|
}
|
||||||
if (vox->id != BLOCK_VOID) {
|
if (vox->id != BLOCK_VOID) {
|
||||||
const auto& def = level.content.getIndices()->blocks.require(vox->id);
|
const auto& def = level.content.getIndices()->blocks.require(vox->id);
|
||||||
switch (def.model) {
|
switch (def.model.type) {
|
||||||
case BlockModel::block:
|
case BlockModelType::BLOCK:
|
||||||
batch->cube(
|
batch->cube(
|
||||||
glm::vec3(wrapper.position) + glm::vec3(0.5f),
|
glm::vec3(wrapper.position) + glm::vec3(0.5f),
|
||||||
glm::vec3(1.01f),
|
glm::vec3(1.01f),
|
||||||
@ -54,7 +54,7 @@ void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case BlockModel::aabb: {
|
case BlockModelType::AABB: {
|
||||||
const auto& aabb =
|
const auto& aabb =
|
||||||
(def.rotatable ? def.rt.hitboxes[vox->state.rotation]
|
(def.rotatable ? def.rt.hitboxes[vox->state.rotation]
|
||||||
: def.hitboxes)
|
: def.hitboxes)
|
||||||
|
|||||||
@ -32,17 +32,17 @@ std::unique_ptr<ImageData> BlocksPreview::draw(
|
|||||||
cache.getRegion(id, 4), cache.getRegion(id, 5)};
|
cache.getRegion(id, 4), cache.getRegion(id, 5)};
|
||||||
|
|
||||||
glm::vec3 offset(0.1f, 0.5f, 0.1f);
|
glm::vec3 offset(0.1f, 0.5f, 0.1f);
|
||||||
switch (def.model) {
|
switch (def.model.type) {
|
||||||
case BlockModel::none:
|
case BlockModelType::NONE:
|
||||||
// something went wrong...
|
// something went wrong...
|
||||||
break;
|
break;
|
||||||
case BlockModel::block:
|
case BlockModelType::BLOCK:
|
||||||
shader.uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset));
|
shader.uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset));
|
||||||
batch.blockCube(glm::vec3(size * 0.63f), texfaces,
|
batch.blockCube(glm::vec3(size * 0.63f), texfaces,
|
||||||
glm::vec4(1.0f), !def.rt.emissive);
|
glm::vec4(1.0f), !def.rt.emissive);
|
||||||
batch.flush();
|
batch.flush();
|
||||||
break;
|
break;
|
||||||
case BlockModel::aabb:
|
case BlockModelType::AABB:
|
||||||
{
|
{
|
||||||
glm::vec3 hitbox {};
|
glm::vec3 hitbox {};
|
||||||
for (const auto& box : def.hitboxes) {
|
for (const auto& box : def.hitboxes) {
|
||||||
@ -60,7 +60,7 @@ std::unique_ptr<ImageData> BlocksPreview::draw(
|
|||||||
}
|
}
|
||||||
batch.flush();
|
batch.flush();
|
||||||
break;
|
break;
|
||||||
case BlockModel::custom:{
|
case BlockModelType::CUSTOM:{
|
||||||
glm::vec3 pmul = glm::vec3(size * 0.63f);
|
glm::vec3 pmul = glm::vec3(size * 0.63f);
|
||||||
glm::vec3 hitbox = glm::vec3(1.0f);
|
glm::vec3 hitbox = glm::vec3(1.0f);
|
||||||
glm::vec3 poff = glm::vec3(0.0f, 0.0f, 1.0f);
|
glm::vec3 poff = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||||
@ -78,7 +78,7 @@ std::unique_ptr<ImageData> BlocksPreview::draw(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BlockModel::xsprite: {
|
case BlockModelType::XSPRITE: {
|
||||||
shader.uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset));
|
shader.uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset));
|
||||||
glm::vec3 right = glm::normalize(glm::vec3(1.f, 0.f, -1.f));
|
glm::vec3 right = glm::normalize(glm::vec3(1.f, 0.f, -1.f));
|
||||||
batch.sprite(
|
batch.sprite(
|
||||||
|
|||||||
@ -9,7 +9,8 @@
|
|||||||
#include "lighting/Lightmap.hpp"
|
#include "lighting/Lightmap.hpp"
|
||||||
#include "frontend/ContentGfxCache.hpp"
|
#include "frontend/ContentGfxCache.hpp"
|
||||||
|
|
||||||
const glm::vec3 BlocksRenderer::SUN_VECTOR (0.2275f,0.9388f,-0.1005f);
|
const glm::vec3 BlocksRenderer::SUN_VECTOR(0.528265f, 0.833149f, -0.163704f);
|
||||||
|
const float DIRECTIONAL_LIGHT_FACTOR = 0.3f;
|
||||||
|
|
||||||
BlocksRenderer::BlocksRenderer(
|
BlocksRenderer::BlocksRenderer(
|
||||||
size_t capacity,
|
size_t capacity,
|
||||||
@ -17,18 +18,18 @@ BlocksRenderer::BlocksRenderer(
|
|||||||
const ContentGfxCache& cache,
|
const ContentGfxCache& cache,
|
||||||
const EngineSettings& settings
|
const EngineSettings& settings
|
||||||
) : content(content),
|
) : content(content),
|
||||||
vertexBuffer(std::make_unique<float[]>(capacity * CHUNK_VERTEX_SIZE)),
|
vertexBuffer(std::make_unique<ChunkVertex[]>(capacity)),
|
||||||
indexBuffer(std::make_unique<int[]>(capacity)),
|
indexBuffer(std::make_unique<uint32_t[]>(capacity)),
|
||||||
|
vertexCount(0),
|
||||||
vertexOffset(0),
|
vertexOffset(0),
|
||||||
indexOffset(0),
|
indexCount(0),
|
||||||
indexSize(0),
|
|
||||||
capacity(capacity),
|
capacity(capacity),
|
||||||
cache(cache),
|
cache(cache),
|
||||||
settings(settings)
|
settings(settings)
|
||||||
{
|
{
|
||||||
voxelsBuffer = std::make_unique<VoxelsVolume>(
|
voxelsBuffer = std::make_unique<VoxelsVolume>(
|
||||||
CHUNK_W + voxelBufferPadding*2,
|
CHUNK_W + voxelBufferPadding*2,
|
||||||
CHUNK_H,
|
CHUNK_H,
|
||||||
CHUNK_D + voxelBufferPadding*2);
|
CHUNK_D + voxelBufferPadding*2);
|
||||||
blockDefsCache = content.getIndices()->blocks.getDefs();
|
blockDefsCache = content.getIndices()->blocks.getDefs();
|
||||||
}
|
}
|
||||||
@ -40,39 +41,31 @@ BlocksRenderer::~BlocksRenderer() {
|
|||||||
void BlocksRenderer::vertex(
|
void BlocksRenderer::vertex(
|
||||||
const glm::vec3& coord, float u, float v, const glm::vec4& light
|
const glm::vec3& coord, float u, float v, const glm::vec4& light
|
||||||
) {
|
) {
|
||||||
vertexBuffer[vertexOffset++] = coord.x;
|
|
||||||
vertexBuffer[vertexOffset++] = coord.y;
|
|
||||||
vertexBuffer[vertexOffset++] = coord.z;
|
|
||||||
|
|
||||||
vertexBuffer[vertexOffset++] = u;
|
vertexBuffer[vertexCount].position = coord;
|
||||||
vertexBuffer[vertexOffset++] = v;
|
|
||||||
|
|
||||||
union {
|
vertexBuffer[vertexCount].uv = {u,v};
|
||||||
float floating;
|
|
||||||
uint32_t integer;
|
|
||||||
} compressed;
|
|
||||||
|
|
||||||
compressed.integer = (static_cast<uint32_t>(light.r * 255) & 0xff) << 24;
|
vertexBuffer[vertexCount].color[0] = static_cast<uint8_t>(light.r * 255);
|
||||||
compressed.integer |= (static_cast<uint32_t>(light.g * 255) & 0xff) << 16;
|
vertexBuffer[vertexCount].color[1] = static_cast<uint8_t>(light.g * 255);
|
||||||
compressed.integer |= (static_cast<uint32_t>(light.b * 255) & 0xff) << 8;
|
vertexBuffer[vertexCount].color[2] = static_cast<uint8_t>(light.b * 255);
|
||||||
compressed.integer |= (static_cast<uint32_t>(light.a * 255) & 0xff);
|
vertexBuffer[vertexCount].color[3] = static_cast<uint8_t>(light.a * 255);
|
||||||
|
vertexCount++;
|
||||||
vertexBuffer[vertexOffset++] = compressed.floating;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlocksRenderer::index(int a, int b, int c, int d, int e, int f) {
|
void BlocksRenderer::index(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f) {
|
||||||
indexBuffer[indexSize++] = indexOffset + a;
|
indexBuffer[indexCount++] = static_cast<uint32_t>(vertexOffset + a);
|
||||||
indexBuffer[indexSize++] = indexOffset + b;
|
indexBuffer[indexCount++] = static_cast<uint32_t>(vertexOffset + b);
|
||||||
indexBuffer[indexSize++] = indexOffset + c;
|
indexBuffer[indexCount++] = static_cast<uint32_t>(vertexOffset + c);
|
||||||
indexBuffer[indexSize++] = indexOffset + d;
|
indexBuffer[indexCount++] = static_cast<uint32_t>(vertexOffset + d);
|
||||||
indexBuffer[indexSize++] = indexOffset + e;
|
indexBuffer[indexCount++] = static_cast<uint32_t>(vertexOffset + e);
|
||||||
indexBuffer[indexSize++] = indexOffset + f;
|
indexBuffer[indexCount++] = static_cast<uint32_t>(vertexOffset + f);
|
||||||
indexOffset += 4;
|
vertexOffset += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Add face with precalculated lights
|
/// @brief Add face with precalculated lights
|
||||||
void BlocksRenderer::face(
|
void BlocksRenderer::face(
|
||||||
const glm::vec3& coord,
|
const glm::vec3& coord,
|
||||||
float w, float h, float d,
|
float w, float h, float d,
|
||||||
const glm::vec3& axisX,
|
const glm::vec3& axisX,
|
||||||
const glm::vec3& axisY,
|
const glm::vec3& axisY,
|
||||||
@ -81,7 +74,7 @@ void BlocksRenderer::face(
|
|||||||
const glm::vec4(&lights)[4],
|
const glm::vec4(&lights)[4],
|
||||||
const glm::vec4& tint
|
const glm::vec4& tint
|
||||||
) {
|
) {
|
||||||
if (vertexOffset + CHUNK_VERTEX_SIZE * 4 > capacity) {
|
if (vertexCount + 4 >= capacity) {
|
||||||
overflow = true;
|
overflow = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -97,7 +90,7 @@ void BlocksRenderer::face(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BlocksRenderer::vertexAO(
|
void BlocksRenderer::vertexAO(
|
||||||
const glm::vec3& coord,
|
const glm::vec3& coord,
|
||||||
float u, float v,
|
float u, float v,
|
||||||
const glm::vec4& tint,
|
const glm::vec4& tint,
|
||||||
const glm::vec3& axisX,
|
const glm::vec3& axisX,
|
||||||
@ -121,7 +114,7 @@ void BlocksRenderer::faceAO(
|
|||||||
const UVRegion& region,
|
const UVRegion& region,
|
||||||
bool lights
|
bool lights
|
||||||
) {
|
) {
|
||||||
if (vertexOffset + CHUNK_VERTEX_SIZE * 4 > capacity) {
|
if (vertexCount + 4 >= capacity) {
|
||||||
overflow = true;
|
overflow = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -129,7 +122,7 @@ void BlocksRenderer::faceAO(
|
|||||||
float s = 0.5f;
|
float s = 0.5f;
|
||||||
if (lights) {
|
if (lights) {
|
||||||
float d = glm::dot(glm::normalize(Z), SUN_VECTOR);
|
float d = glm::dot(glm::normalize(Z), SUN_VECTOR);
|
||||||
d = 0.7f + d * 0.3f;
|
d = (1.0f - DIRECTIONAL_LIGHT_FACTOR) + d * DIRECTIONAL_LIGHT_FACTOR;
|
||||||
|
|
||||||
auto axisX = glm::normalize(X);
|
auto axisX = glm::normalize(X);
|
||||||
auto axisY = glm::normalize(Y);
|
auto axisY = glm::normalize(Y);
|
||||||
@ -159,7 +152,7 @@ void BlocksRenderer::face(
|
|||||||
glm::vec4 tint,
|
glm::vec4 tint,
|
||||||
bool lights
|
bool lights
|
||||||
) {
|
) {
|
||||||
if (vertexOffset + CHUNK_VERTEX_SIZE * 4 > capacity) {
|
if (vertexCount + 4 >= capacity) {
|
||||||
overflow = true;
|
overflow = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -167,7 +160,7 @@ void BlocksRenderer::face(
|
|||||||
float s = 0.5f;
|
float s = 0.5f;
|
||||||
if (lights) {
|
if (lights) {
|
||||||
float d = glm::dot(glm::normalize(Z), SUN_VECTOR);
|
float d = glm::dot(glm::normalize(Z), SUN_VECTOR);
|
||||||
d = 0.7f + d * 0.3f;
|
d = (1.0f - DIRECTIONAL_LIGHT_FACTOR) + d * DIRECTIONAL_LIGHT_FACTOR;
|
||||||
tint *= d;
|
tint *= d;
|
||||||
}
|
}
|
||||||
vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint);
|
vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint);
|
||||||
@ -178,10 +171,10 @@ void BlocksRenderer::face(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BlocksRenderer::blockXSprite(
|
void BlocksRenderer::blockXSprite(
|
||||||
int x, int y, int z,
|
int x, int y, int z,
|
||||||
const glm::vec3& size,
|
const glm::vec3& size,
|
||||||
const UVRegion& texface1,
|
const UVRegion& texface1,
|
||||||
const UVRegion& texface2,
|
const UVRegion& texface2,
|
||||||
float spread
|
float spread
|
||||||
) {
|
) {
|
||||||
glm::vec4 lights1[] {
|
glm::vec4 lights1[] {
|
||||||
@ -207,12 +200,12 @@ void BlocksRenderer::blockXSprite(
|
|||||||
|
|
||||||
face({x + xs, y, z + zs}, w, size.y, 0, {-1, 0, 1}, {0, 1, 0}, glm::vec3(),
|
face({x + xs, y, z + zs}, w, size.y, 0, {-1, 0, 1}, {0, 1, 0}, glm::vec3(),
|
||||||
texface1, lights2, tint);
|
texface1, lights2, tint);
|
||||||
face({x + xs, y, z + zs}, w, size.y, 0, {1, 0, 1}, {0, 1, 0}, glm::vec3(),
|
face({x + xs, y, z + zs}, w, size.y, 0, {1, 0, 1}, {0, 1, 0}, glm::vec3(),
|
||||||
texface1, lights1, tint);
|
texface1, lights1, tint);
|
||||||
|
|
||||||
face({x + xs, y, z + zs}, w, size.y, 0, {-1, 0, -1}, {0, 1, 0}, glm::vec3(),
|
face({x + xs, y, z + zs}, w, size.y, 0, {-1, 0, -1}, {0, 1, 0}, glm::vec3(),
|
||||||
texface2, lights2, tint);
|
texface2, lights2, tint);
|
||||||
face({x + xs, y, z + zs}, w, size.y, 0, {1, 0, -1}, {0, 1, 0}, glm::vec3(),
|
face({x + xs, y, z + zs}, w, size.y, 0, {1, 0, -1}, {0, 1, 0}, glm::vec3(),
|
||||||
texface2, lights1, tint);
|
texface2, lights1, tint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,8 +214,8 @@ void BlocksRenderer::blockXSprite(
|
|||||||
/// @brief AABB blocks render method
|
/// @brief AABB blocks render method
|
||||||
void BlocksRenderer::blockAABB(
|
void BlocksRenderer::blockAABB(
|
||||||
const glm::ivec3& icoord,
|
const glm::ivec3& icoord,
|
||||||
const UVRegion(&texfaces)[6],
|
const UVRegion(&texfaces)[6],
|
||||||
const Block* block,
|
const Block* block,
|
||||||
ubyte rotation,
|
ubyte rotation,
|
||||||
bool lights,
|
bool lights,
|
||||||
bool ao
|
bool ao
|
||||||
@ -249,7 +242,7 @@ void BlocksRenderer::blockAABB(
|
|||||||
orient.transform(hitbox);
|
orient.transform(hitbox);
|
||||||
}
|
}
|
||||||
coord -= glm::vec3(0.5f) - hitbox.center();
|
coord -= glm::vec3(0.5f) - hitbox.center();
|
||||||
|
|
||||||
if (ao) {
|
if (ao) {
|
||||||
faceAO(coord, X*size.x, Y*size.y, Z*size.z, texfaces[5], lights); // north
|
faceAO(coord, X*size.x, Y*size.y, Z*size.z, texfaces[5], lights); // north
|
||||||
faceAO(coord, -X*size.x, Y*size.y, -Z*size.z, texfaces[4], lights); // south
|
faceAO(coord, -X*size.x, Y*size.y, -Z*size.z, texfaces[4], lights); // south
|
||||||
@ -272,6 +265,19 @@ void BlocksRenderer::blockAABB(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_aligned(const glm::vec3& v, float e = 1e-6f) {
|
||||||
|
if (std::abs(v.y) < e && std::abs(v.z) < e && std::abs(v.x) > e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (std::abs(v.x) < e && std::abs(v.z) < e && std::abs(v.y) > e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (std::abs(v.x) < e && std::abs(v.y) < e && std::abs(v.z) > e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void BlocksRenderer::blockCustomModel(
|
void BlocksRenderer::blockCustomModel(
|
||||||
const glm::ivec3& icoord, const Block* block, ubyte rotation, bool lights, bool ao
|
const glm::ivec3& icoord, const Block* block, ubyte rotation, bool lights, bool ao
|
||||||
) {
|
) {
|
||||||
@ -289,32 +295,44 @@ void BlocksRenderer::blockCustomModel(
|
|||||||
|
|
||||||
const auto& model = cache.getModel(block->rt.id);
|
const auto& model = cache.getModel(block->rt.id);
|
||||||
for (const auto& mesh : model.meshes) {
|
for (const auto& mesh : model.meshes) {
|
||||||
if (vertexOffset + CHUNK_VERTEX_SIZE * mesh.vertices.size() > capacity) {
|
if (vertexCount + mesh.vertices.size() >= capacity) {
|
||||||
overflow = true;
|
overflow = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int triangle = 0; triangle < mesh.vertices.size() / 3; triangle++) {
|
for (int triangle = 0; triangle < mesh.vertices.size() / 3; triangle++) {
|
||||||
auto r = mesh.vertices[triangle * 3 + (triangle % 2) * 2].coord -
|
auto r = mesh.vertices[triangle * 3 + (triangle % 2) * 2].coord -
|
||||||
mesh.vertices[triangle * 3 + 1].coord;
|
mesh.vertices[triangle * 3 + 1].coord;
|
||||||
|
r = r.x * X + r.y * Y + r.z * Z;
|
||||||
r = glm::normalize(r);
|
r = glm::normalize(r);
|
||||||
|
|
||||||
|
const auto& v0 = mesh.vertices[triangle * 3];
|
||||||
|
auto n = v0.normal.x * X + v0.normal.y * Y + v0.normal.z * Z;
|
||||||
|
|
||||||
|
if (!isOpen(glm::floor(coord + n * 1e-4f), *block) && is_aligned(n)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float d = glm::dot(n, SUN_VECTOR);
|
||||||
|
d = (1.0f - DIRECTIONAL_LIGHT_FACTOR) + d * DIRECTIONAL_LIGHT_FACTOR;
|
||||||
|
glm::vec3 t = glm::cross(r, n);
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
const auto& vertex = mesh.vertices[triangle * 3 + i];
|
const auto& vertex = mesh.vertices[triangle * 3 + i];
|
||||||
auto n = vertex.normal.x * X + vertex.normal.y * Y +
|
|
||||||
vertex.normal.z * Z;
|
|
||||||
float d = glm::dot(n, SUN_VECTOR);
|
|
||||||
d = 0.8f + d * 0.2f;
|
|
||||||
const auto& vcoord = vertex.coord - 0.5f;
|
const auto& vcoord = vertex.coord - 0.5f;
|
||||||
vertexAO(
|
|
||||||
|
glm::vec4 aoColor {1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
if (ao) {
|
||||||
|
auto p = coord + vcoord.x * X + vcoord.y * Y +
|
||||||
|
vcoord.z * Z + r * 0.5f + t * 0.5f + n * 0.5f;
|
||||||
|
aoColor = pickSoftLight(p.x, p.y, p.z, glm::ivec3(r), glm::ivec3(t));
|
||||||
|
}
|
||||||
|
this->vertex(
|
||||||
coord + vcoord.x * X + vcoord.y * Y + vcoord.z * Z,
|
coord + vcoord.x * X + vcoord.y * Y + vcoord.z * Z,
|
||||||
vertex.uv.x,
|
vertex.uv.x,
|
||||||
vertex.uv.y,
|
vertex.uv.y,
|
||||||
glm::vec4(d, d, d, d),
|
glm::vec4(d, d, d, d) * aoColor
|
||||||
glm::cross(r, n),
|
|
||||||
r,
|
|
||||||
n
|
|
||||||
);
|
);
|
||||||
indexBuffer[indexSize++] = indexOffset++;
|
indexBuffer[indexCount++] = vertexOffset++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -322,9 +340,9 @@ void BlocksRenderer::blockCustomModel(
|
|||||||
|
|
||||||
/* Fastest solid shaded blocks render method */
|
/* Fastest solid shaded blocks render method */
|
||||||
void BlocksRenderer::blockCube(
|
void BlocksRenderer::blockCube(
|
||||||
const glm::ivec3& coord,
|
const glm::ivec3& coord,
|
||||||
const UVRegion(&texfaces)[6],
|
const UVRegion(&texfaces)[6],
|
||||||
const Block& block,
|
const Block& block,
|
||||||
blockstate states,
|
blockstate states,
|
||||||
bool lights,
|
bool lights,
|
||||||
bool ao
|
bool ao
|
||||||
@ -340,7 +358,7 @@ void BlocksRenderer::blockCube(
|
|||||||
Y = orient.axes[1];
|
Y = orient.axes[1];
|
||||||
Z = orient.axes[2];
|
Z = orient.axes[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ao) {
|
if (ao) {
|
||||||
if (isOpen(coord + Z, block)) {
|
if (isOpen(coord + Z, block)) {
|
||||||
faceAO(coord, X, Y, Z, texfaces[5], lights);
|
faceAO(coord, X, Y, Z, texfaces[5], lights);
|
||||||
@ -383,8 +401,8 @@ void BlocksRenderer::blockCube(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BlocksRenderer::isOpenForLight(int x, int y, int z) const {
|
bool BlocksRenderer::isOpenForLight(int x, int y, int z) const {
|
||||||
blockid_t id = voxelsBuffer->pickBlockId(chunk->x * CHUNK_W + x,
|
blockid_t id = voxelsBuffer->pickBlockId(chunk->x * CHUNK_W + x,
|
||||||
y,
|
y,
|
||||||
chunk->z * CHUNK_D + z);
|
chunk->z * CHUNK_D + z);
|
||||||
if (id == BLOCK_VOID) {
|
if (id == BLOCK_VOID) {
|
||||||
return false;
|
return false;
|
||||||
@ -398,7 +416,7 @@ bool BlocksRenderer::isOpenForLight(int x, int y, int z) const {
|
|||||||
|
|
||||||
glm::vec4 BlocksRenderer::pickLight(int x, int y, int z) const {
|
glm::vec4 BlocksRenderer::pickLight(int x, int y, int z) const {
|
||||||
if (isOpenForLight(x, y, z)) {
|
if (isOpenForLight(x, y, z)) {
|
||||||
light_t light = voxelsBuffer->pickLight(chunk->x * CHUNK_W + x, y,
|
light_t light = voxelsBuffer->pickLight(chunk->x * CHUNK_W + x, y,
|
||||||
chunk->z * CHUNK_D + z);
|
chunk->z * CHUNK_D + z);
|
||||||
return glm::vec4(Lightmap::extract(light, 0),
|
return glm::vec4(Lightmap::extract(light, 0),
|
||||||
Lightmap::extract(light, 1),
|
Lightmap::extract(light, 1),
|
||||||
@ -426,8 +444,8 @@ glm::vec4 BlocksRenderer::pickSoftLight(
|
|||||||
float x, float y, float z, const glm::ivec3& right, const glm::ivec3& up
|
float x, float y, float z, const glm::ivec3& right, const glm::ivec3& up
|
||||||
) const {
|
) const {
|
||||||
return pickSoftLight({
|
return pickSoftLight({
|
||||||
static_cast<int>(std::round(x)),
|
static_cast<int>(std::round(x)),
|
||||||
static_cast<int>(std::round(y)),
|
static_cast<int>(std::round(y)),
|
||||||
static_cast<int>(std::round(z))},
|
static_cast<int>(std::round(z))},
|
||||||
right, up);
|
right, up);
|
||||||
}
|
}
|
||||||
@ -460,23 +478,23 @@ void BlocksRenderer::render(
|
|||||||
int x = i % CHUNK_W;
|
int x = i % CHUNK_W;
|
||||||
int y = i / (CHUNK_D * CHUNK_W);
|
int y = i / (CHUNK_D * CHUNK_W);
|
||||||
int z = (i / CHUNK_D) % CHUNK_W;
|
int z = (i / CHUNK_D) % CHUNK_W;
|
||||||
switch (def.model) {
|
switch (def.model.type) {
|
||||||
case BlockModel::block:
|
case BlockModelType::BLOCK:
|
||||||
blockCube({x, y, z}, texfaces, def, vox.state, !def.shadeless,
|
blockCube({x, y, z}, texfaces, def, vox.state, !def.shadeless,
|
||||||
def.ambientOcclusion);
|
def.ambientOcclusion);
|
||||||
break;
|
break;
|
||||||
case BlockModel::xsprite: {
|
case BlockModelType::XSPRITE: {
|
||||||
blockXSprite(x, y, z, glm::vec3(1.0f),
|
blockXSprite(x, y, z, glm::vec3(1.0f),
|
||||||
texfaces[FACE_MX], texfaces[FACE_MZ], 1.0f);
|
texfaces[FACE_MX], texfaces[FACE_MZ], 1.0f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BlockModel::aabb: {
|
case BlockModelType::AABB: {
|
||||||
blockAABB({x, y, z}, texfaces, &def, vox.state.rotation,
|
blockAABB({x, y, z}, texfaces, &def, vox.state.rotation,
|
||||||
!def.shadeless, def.ambientOcclusion);
|
!def.shadeless, def.ambientOcclusion);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BlockModel::custom: {
|
case BlockModelType::CUSTOM: {
|
||||||
blockCustomModel({x, y, z}, &def, vox.state.rotation,
|
blockCustomModel({x, y, z}, &def, vox.state.rotation,
|
||||||
!def.shadeless, def.ambientOcclusion);
|
!def.shadeless, def.ambientOcclusion);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -523,30 +541,30 @@ SortingMeshData BlocksRenderer::renderTranslucent(
|
|||||||
int x = i % CHUNK_W;
|
int x = i % CHUNK_W;
|
||||||
int y = i / (CHUNK_D * CHUNK_W);
|
int y = i / (CHUNK_D * CHUNK_W);
|
||||||
int z = (i / CHUNK_D) % CHUNK_W;
|
int z = (i / CHUNK_D) % CHUNK_W;
|
||||||
switch (def.model) {
|
switch (def.model.type) {
|
||||||
case BlockModel::block:
|
case BlockModelType::BLOCK:
|
||||||
blockCube({x, y, z}, texfaces, def, vox.state, !def.shadeless,
|
blockCube({x, y, z}, texfaces, def, vox.state, !def.shadeless,
|
||||||
def.ambientOcclusion);
|
def.ambientOcclusion);
|
||||||
break;
|
break;
|
||||||
case BlockModel::xsprite: {
|
case BlockModelType::XSPRITE: {
|
||||||
blockXSprite(x, y, z, glm::vec3(1.0f),
|
blockXSprite(x, y, z, glm::vec3(1.0f),
|
||||||
texfaces[FACE_MX], texfaces[FACE_MZ], 1.0f);
|
texfaces[FACE_MX], texfaces[FACE_MZ], 1.0f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BlockModel::aabb: {
|
case BlockModelType::AABB: {
|
||||||
blockAABB({x, y, z}, texfaces, &def, vox.state.rotation,
|
blockAABB({x, y, z}, texfaces, &def, vox.state.rotation,
|
||||||
!def.shadeless, def.ambientOcclusion);
|
!def.shadeless, def.ambientOcclusion);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BlockModel::custom: {
|
case BlockModelType::CUSTOM: {
|
||||||
blockCustomModel({x, y, z}, &def, vox.state.rotation,
|
blockCustomModel({x, y, z}, &def, vox.state.rotation,
|
||||||
!def.shadeless, def.ambientOcclusion);
|
!def.shadeless, def.ambientOcclusion);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (vertexOffset == 0) {
|
if (vertexCount == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SortingMeshEntry entry {
|
SortingMeshEntry entry {
|
||||||
@ -555,50 +573,50 @@ SortingMeshData BlocksRenderer::renderTranslucent(
|
|||||||
y + 0.5f,
|
y + 0.5f,
|
||||||
z + chunk->z * CHUNK_D + 0.5f
|
z + chunk->z * CHUNK_D + 0.5f
|
||||||
),
|
),
|
||||||
util::Buffer<float>(indexSize * CHUNK_VERTEX_SIZE), 0};
|
util::Buffer<ChunkVertex>(indexCount), 0};
|
||||||
|
|
||||||
totalSize += entry.vertexData.size();
|
totalSize += entry.vertexData.size();
|
||||||
|
|
||||||
for (int j = 0; j < indexSize; j++) {
|
for (int j = 0; j < indexCount; j++) {
|
||||||
std::memcpy(
|
std::memcpy(
|
||||||
entry.vertexData.data() + j * CHUNK_VERTEX_SIZE,
|
entry.vertexData.data() + j,
|
||||||
vertexBuffer.get() + indexBuffer[j] * CHUNK_VERTEX_SIZE,
|
vertexBuffer.get() + indexBuffer[j],
|
||||||
sizeof(float) * CHUNK_VERTEX_SIZE
|
sizeof(ChunkVertex)
|
||||||
);
|
);
|
||||||
float& vx = entry.vertexData[j * CHUNK_VERTEX_SIZE + 0];
|
ChunkVertex& vertex = entry.vertexData[j];
|
||||||
float& vy = entry.vertexData[j * CHUNK_VERTEX_SIZE + 1];
|
|
||||||
float& vz = entry.vertexData[j * CHUNK_VERTEX_SIZE + 2];
|
|
||||||
|
|
||||||
if (!aabbInit) {
|
if (!aabbInit) {
|
||||||
aabbInit = true;
|
aabbInit = true;
|
||||||
aabb.a = aabb.b = {vx, vy, vz};
|
aabb.a = aabb.b = vertex.position;
|
||||||
} else {
|
} else {
|
||||||
aabb.addPoint(glm::vec3(vx, vy, vz));
|
aabb.addPoint(vertex.position);
|
||||||
}
|
}
|
||||||
vx += chunk->x * CHUNK_W + 0.5f;
|
|
||||||
vy += 0.5f;
|
vertex.position.x += chunk->x * CHUNK_W + 0.5f;
|
||||||
vz += chunk->z * CHUNK_D + 0.5f;
|
vertex.position.y += 0.5f;
|
||||||
|
vertex.position.z += chunk->z * CHUNK_D + 0.5f;
|
||||||
}
|
}
|
||||||
sortingMesh.entries.push_back(std::move(entry));
|
sortingMesh.entries.push_back(std::move(entry));
|
||||||
vertexOffset = 0;
|
vertexCount = 0;
|
||||||
indexOffset = indexSize = 0;
|
vertexOffset = indexCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// additional powerful optimization
|
// additional powerful optimization
|
||||||
auto size = aabb.size();
|
auto size = aabb.size();
|
||||||
if ((size.y < 0.01f || size.x < 0.01f || size.z < 0.01f) &&
|
if ((size.y < 0.01f || size.x < 0.01f || size.z < 0.01f) &&
|
||||||
sortingMesh.entries.size() > 1) {
|
sortingMesh.entries.size() > 1) {
|
||||||
SortingMeshEntry newEntry {
|
SortingMeshEntry newEntry {
|
||||||
sortingMesh.entries[0].position,
|
sortingMesh.entries[0].position,
|
||||||
util::Buffer<float>(totalSize),
|
util::Buffer<ChunkVertex>(totalSize),
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
for (const auto& entry : sortingMesh.entries) {
|
for (const auto& entry : sortingMesh.entries) {
|
||||||
std::memcpy(
|
std::memcpy(
|
||||||
newEntry.vertexData.data() + offset,
|
newEntry.vertexData.data() + offset,
|
||||||
entry.vertexData.data(), entry.vertexData.size() * sizeof(float)
|
entry.vertexData.data(),
|
||||||
|
entry.vertexData.size() * sizeof(ChunkVertex)
|
||||||
);
|
);
|
||||||
offset += entry.vertexData.size();
|
offset += entry.vertexData.size();
|
||||||
}
|
}
|
||||||
@ -630,7 +648,7 @@ void BlocksRenderer::build(const Chunk* chunk, const Chunks* chunks) {
|
|||||||
const voxel& vox = voxels[i];
|
const voxel& vox = voxels[i];
|
||||||
blockid_t id = vox.id;
|
blockid_t id = vox.id;
|
||||||
const auto& def = *blockDefsCache[id];
|
const auto& def = *blockDefsCache[id];
|
||||||
|
|
||||||
if (beginEnds[def.drawGroup][0] == 0) {
|
if (beginEnds[def.drawGroup][0] == 0) {
|
||||||
beginEnds[def.drawGroup][0] = i+1;
|
beginEnds[def.drawGroup][0] = i+1;
|
||||||
}
|
}
|
||||||
@ -639,36 +657,37 @@ void BlocksRenderer::build(const Chunk* chunk, const Chunks* chunks) {
|
|||||||
cancelled = false;
|
cancelled = false;
|
||||||
|
|
||||||
overflow = false;
|
overflow = false;
|
||||||
vertexOffset = 0;
|
vertexCount = 0;
|
||||||
indexOffset = indexSize = 0;
|
vertexOffset = indexCount = 0;
|
||||||
|
|
||||||
sortingMesh = renderTranslucent(voxels, beginEnds);
|
sortingMesh = renderTranslucent(voxels, beginEnds);
|
||||||
|
|
||||||
overflow = false;
|
overflow = false;
|
||||||
|
vertexCount = 0;
|
||||||
vertexOffset = 0;
|
vertexOffset = 0;
|
||||||
indexOffset = indexSize = 0;
|
indexCount = 0;
|
||||||
|
|
||||||
render(voxels, beginEnds);
|
render(voxels, beginEnds);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkMeshData BlocksRenderer::createMesh() {
|
ChunkMeshData BlocksRenderer::createMesh() {
|
||||||
return ChunkMeshData {
|
return ChunkMeshData{
|
||||||
MeshData(
|
MeshData(
|
||||||
util::Buffer<float>(vertexBuffer.get(), vertexOffset),
|
util::Buffer(vertexBuffer.get(), vertexCount),
|
||||||
util::Buffer<int>(indexBuffer.get(), indexSize),
|
util::Buffer(indexBuffer.get(), indexCount),
|
||||||
util::Buffer<VertexAttribute>(
|
util::Buffer(
|
||||||
CHUNK_VATTRS, sizeof(CHUNK_VATTRS) / sizeof(VertexAttribute)
|
ChunkVertex::ATTRIBUTES, sizeof(ChunkVertex::ATTRIBUTES) / sizeof(VertexAttribute)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
std::move(sortingMesh)};
|
std::move(sortingMesh)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkMesh BlocksRenderer::render(const Chunk* chunk, const Chunks* chunks) {
|
ChunkMesh BlocksRenderer::render(const Chunk *chunk, const Chunks *chunks) {
|
||||||
build(chunk, chunks);
|
build(chunk, chunks);
|
||||||
|
|
||||||
size_t vcount = vertexOffset / CHUNK_VERTEX_SIZE;
|
return ChunkMesh{std::make_unique<Mesh<ChunkVertex>>(
|
||||||
return ChunkMesh{std::make_unique<Mesh>(
|
vertexBuffer.get(), vertexCount, indexBuffer.get(), indexCount
|
||||||
vertexBuffer.get(), vcount, indexBuffer.get(), indexSize, CHUNK_VATTRS
|
|
||||||
), std::move(sortingMesh)};
|
), std::move(sortingMesh)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include "voxels/voxel.hpp"
|
#include "voxels/voxel.hpp"
|
||||||
@ -10,28 +8,27 @@
|
|||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
#include "voxels/Chunk.hpp"
|
#include "voxels/Chunk.hpp"
|
||||||
#include "voxels/VoxelsVolume.hpp"
|
#include "voxels/VoxelsVolume.hpp"
|
||||||
#include "graphics/core/MeshData.hpp"
|
|
||||||
#include "maths/util.hpp"
|
#include "maths/util.hpp"
|
||||||
#include "commons.hpp"
|
#include "commons.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
|
||||||
|
template<typename VertexStructure> class Mesh;
|
||||||
class Content;
|
class Content;
|
||||||
class Mesh;
|
|
||||||
class Block;
|
class Block;
|
||||||
class Chunk;
|
class Chunk;
|
||||||
class Chunks;
|
class Chunks;
|
||||||
class VoxelsVolume;
|
class VoxelsVolume;
|
||||||
class Chunks;
|
|
||||||
class ContentGfxCache;
|
class ContentGfxCache;
|
||||||
struct UVRegion;
|
struct UVRegion;
|
||||||
|
|
||||||
class BlocksRenderer {
|
class BlocksRenderer {
|
||||||
static const glm::vec3 SUN_VECTOR;
|
static const glm::vec3 SUN_VECTOR;
|
||||||
const Content& content;
|
const Content& content;
|
||||||
std::unique_ptr<float[]> vertexBuffer;
|
std::unique_ptr<ChunkVertex[]> vertexBuffer;
|
||||||
std::unique_ptr<int[]> indexBuffer;
|
std::unique_ptr<uint32_t[]> indexBuffer;
|
||||||
|
size_t vertexCount;
|
||||||
size_t vertexOffset;
|
size_t vertexOffset;
|
||||||
size_t indexOffset, indexSize;
|
size_t indexCount;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
int voxelBufferPadding = 2;
|
int voxelBufferPadding = 2;
|
||||||
bool overflow = false;
|
bool overflow = false;
|
||||||
@ -48,7 +45,7 @@ class BlocksRenderer {
|
|||||||
SortingMeshData sortingMesh;
|
SortingMeshData sortingMesh;
|
||||||
|
|
||||||
void vertex(const glm::vec3& coord, float u, float v, const glm::vec4& light);
|
void vertex(const glm::vec3& coord, float u, float v, const glm::vec4& light);
|
||||||
void index(int a, int b, int c, int d, int e, int f);
|
void index(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f);
|
||||||
|
|
||||||
void vertexAO(
|
void vertexAO(
|
||||||
const glm::vec3& coord, float u, float v,
|
const glm::vec3& coord, float u, float v,
|
||||||
|
|||||||
@ -74,7 +74,7 @@ ChunksRenderer::ChunksRenderer(
|
|||||||
if (!result.cancelled) {
|
if (!result.cancelled) {
|
||||||
auto meshData = std::move(result.meshData);
|
auto meshData = std::move(result.meshData);
|
||||||
meshes[result.key] = ChunkMesh {
|
meshes[result.key] = ChunkMesh {
|
||||||
std::make_unique<Mesh>(meshData.mesh),
|
std::make_unique<Mesh<ChunkVertex>>(meshData.mesh),
|
||||||
std::move(meshData.sortingMesh)};
|
std::move(meshData.sortingMesh)};
|
||||||
}
|
}
|
||||||
inwork.erase(result.key);
|
inwork.erase(result.key);
|
||||||
@ -92,7 +92,7 @@ ChunksRenderer::ChunksRenderer(
|
|||||||
ChunksRenderer::~ChunksRenderer() {
|
ChunksRenderer::~ChunksRenderer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Mesh* ChunksRenderer::render(
|
const Mesh<ChunkVertex>* ChunksRenderer::render(
|
||||||
const std::shared_ptr<Chunk>& chunk, bool important
|
const std::shared_ptr<Chunk>& chunk, bool important
|
||||||
) {
|
) {
|
||||||
chunk->flags.modified = false;
|
chunk->flags.modified = false;
|
||||||
@ -125,7 +125,7 @@ void ChunksRenderer::clear() {
|
|||||||
threadPool.clearQueue();
|
threadPool.clearQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Mesh* ChunksRenderer::getOrRender(
|
const Mesh<ChunkVertex>* ChunksRenderer::getOrRender(
|
||||||
const std::shared_ptr<Chunk>& chunk, bool important
|
const std::shared_ptr<Chunk>& chunk, bool important
|
||||||
) {
|
) {
|
||||||
auto found = meshes.find(glm::ivec2(chunk->x, chunk->z));
|
auto found = meshes.find(glm::ivec2(chunk->x, chunk->z));
|
||||||
@ -142,7 +142,7 @@ void ChunksRenderer::update() {
|
|||||||
threadPool.update();
|
threadPool.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Mesh* ChunksRenderer::retrieveChunk(
|
const Mesh<ChunkVertex>* ChunksRenderer::retrieveChunk(
|
||||||
size_t index, const Camera& camera, Shader& shader, bool culling
|
size_t index, const Camera& camera, Shader& shader, bool culling
|
||||||
) {
|
) {
|
||||||
auto chunk = chunks.getChunks()[index];
|
auto chunk = chunks.getChunks()[index];
|
||||||
@ -234,14 +234,14 @@ void ChunksRenderer::drawChunks(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void write_sorting_mesh_entries(
|
static inline void write_sorting_mesh_entries(
|
||||||
float* buffer, const std::vector<SortingMeshEntry>& chunkEntries
|
ChunkVertex* buffer, const std::vector<SortingMeshEntry>& chunkEntries
|
||||||
) {
|
) {
|
||||||
for (const auto& entry : chunkEntries) {
|
for (const auto& entry : chunkEntries) {
|
||||||
const auto& vertexData = entry.vertexData;
|
const auto& vertexData = entry.vertexData;
|
||||||
std::memcpy(
|
std::memcpy(
|
||||||
buffer,
|
buffer,
|
||||||
vertexData.data(),
|
vertexData.data(),
|
||||||
vertexData.size() * sizeof(float)
|
vertexData.size() * sizeof(ChunkVertex)
|
||||||
);
|
);
|
||||||
buffer += vertexData.size();
|
buffer += vertexData.size();
|
||||||
}
|
}
|
||||||
@ -288,10 +288,8 @@ void ChunksRenderer::drawSortedMeshes(const Camera& camera, Shader& shader) {
|
|||||||
if (chunkEntries.size() == 1) {
|
if (chunkEntries.size() == 1) {
|
||||||
auto& entry = chunkEntries.at(0);
|
auto& entry = chunkEntries.at(0);
|
||||||
if (found->second.sortedMesh == nullptr) {
|
if (found->second.sortedMesh == nullptr) {
|
||||||
found->second.sortedMesh = std::make_unique<Mesh>(
|
found->second.sortedMesh = std::make_unique<Mesh<ChunkVertex>>(
|
||||||
entry.vertexData.data(),
|
entry.vertexData.data(), entry.vertexData.size()
|
||||||
entry.vertexData.size() / CHUNK_VERTEX_SIZE,
|
|
||||||
CHUNK_VATTRS
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
found->second.sortedMesh->draw();
|
found->second.sortedMesh->draw();
|
||||||
@ -310,13 +308,13 @@ void ChunksRenderer::drawSortedMeshes(const Camera& camera, Shader& shader) {
|
|||||||
size += entry.vertexData.size();
|
size += entry.vertexData.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
static util::Buffer<float> buffer;
|
static util::Buffer<ChunkVertex> buffer;
|
||||||
if (buffer.size() < size) {
|
if (buffer.size() < size) {
|
||||||
buffer = util::Buffer<float>(size);
|
buffer = util::Buffer<ChunkVertex>(size);
|
||||||
}
|
}
|
||||||
write_sorting_mesh_entries(buffer.data(), chunkEntries);
|
write_sorting_mesh_entries(buffer.data(), chunkEntries);
|
||||||
found->second.sortedMesh = std::make_unique<Mesh>(
|
found->second.sortedMesh = std::make_unique<Mesh<ChunkVertex>>(
|
||||||
buffer.data(), size / CHUNK_VERTEX_SIZE, CHUNK_VATTRS
|
buffer.data(), size
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
found->second.sortedMesh->draw();
|
found->second.sortedMesh->draw();
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@ -9,12 +8,10 @@
|
|||||||
#define GLM_ENABLE_EXPERIMENTAL
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
#include <glm/gtx/hash.hpp>
|
#include <glm/gtx/hash.hpp>
|
||||||
|
|
||||||
#include "voxels/Block.hpp"
|
|
||||||
#include "util/ThreadPool.hpp"
|
#include "util/ThreadPool.hpp"
|
||||||
#include "graphics/core/MeshData.hpp"
|
|
||||||
#include "commons.hpp"
|
#include "commons.hpp"
|
||||||
|
|
||||||
class Mesh;
|
template<typename VertexStructure> class Mesh;
|
||||||
class Chunk;
|
class Chunk;
|
||||||
class Level;
|
class Level;
|
||||||
class Camera;
|
class Camera;
|
||||||
@ -52,7 +49,7 @@ class ChunksRenderer {
|
|||||||
std::unordered_map<glm::ivec2, bool> inwork;
|
std::unordered_map<glm::ivec2, bool> inwork;
|
||||||
std::vector<ChunksSortEntry> indices;
|
std::vector<ChunksSortEntry> indices;
|
||||||
util::ThreadPool<std::shared_ptr<Chunk>, RendererResult> threadPool;
|
util::ThreadPool<std::shared_ptr<Chunk>, RendererResult> threadPool;
|
||||||
const Mesh* retrieveChunk(
|
const Mesh<ChunkVertex>* retrieveChunk(
|
||||||
size_t index, const Camera& camera, Shader& shader, bool culling
|
size_t index, const Camera& camera, Shader& shader, bool culling
|
||||||
);
|
);
|
||||||
public:
|
public:
|
||||||
@ -66,13 +63,13 @@ public:
|
|||||||
);
|
);
|
||||||
virtual ~ChunksRenderer();
|
virtual ~ChunksRenderer();
|
||||||
|
|
||||||
const Mesh* render(
|
const Mesh<ChunkVertex>* render(
|
||||||
const std::shared_ptr<Chunk>& chunk, bool important
|
const std::shared_ptr<Chunk>& chunk, bool important
|
||||||
);
|
);
|
||||||
void unload(const Chunk* chunk);
|
void unload(const Chunk* chunk);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
const Mesh* getOrRender(
|
const Mesh<ChunkVertex>* getOrRender(
|
||||||
const std::shared_ptr<Chunk>& chunk, bool important
|
const std::shared_ptr<Chunk>& chunk, bool important
|
||||||
);
|
);
|
||||||
void drawChunks(const Camera& camera, Shader& shader);
|
void drawChunks(const Camera& camera, Shader& shader);
|
||||||
|
|||||||
@ -6,18 +6,15 @@
|
|||||||
#include "voxels/Chunks.hpp"
|
#include "voxels/Chunks.hpp"
|
||||||
#include "voxels/Chunk.hpp"
|
#include "voxels/Chunk.hpp"
|
||||||
|
|
||||||
static const VertexAttribute attrs[] = {
|
|
||||||
{3}, {2}, {3}, {1}, {0}
|
|
||||||
};
|
|
||||||
|
|
||||||
MainBatch::MainBatch(size_t capacity)
|
MainBatch::MainBatch(size_t capacity)
|
||||||
: buffer(std::make_unique<float[]>(capacity * VERTEX_SIZE)),
|
: buffer(std::make_unique<MainBatchVertex[]>(capacity)),
|
||||||
capacity(capacity),
|
capacity(capacity),
|
||||||
index(0),
|
index(0),
|
||||||
mesh(std::make_unique<Mesh>(buffer.get(), 0, attrs)) {
|
mesh(std::make_unique<Mesh<MainBatchVertex>>(buffer.get(), 0)) {
|
||||||
|
|
||||||
const ubyte pixels[] = {
|
const ubyte pixels[] = {
|
||||||
255, 255, 255, 255,
|
255, 255, 255, 255,
|
||||||
};
|
};
|
||||||
ImageData image(ImageFormat::rgba8888, 1, 1, pixels);
|
ImageData image(ImageFormat::rgba8888, 1, 1, pixels);
|
||||||
blank = Texture::from(&image);
|
blank = Texture::from(&image);
|
||||||
@ -25,7 +22,7 @@ MainBatch::MainBatch(size_t capacity)
|
|||||||
|
|
||||||
MainBatch::~MainBatch() = default;
|
MainBatch::~MainBatch() = default;
|
||||||
|
|
||||||
void MainBatch::setTexture(const Texture* texture) {
|
void MainBatch::setTexture(const Texture *texture) {
|
||||||
if (texture == nullptr) {
|
if (texture == nullptr) {
|
||||||
texture = blank.get();
|
texture = blank.get();
|
||||||
}
|
}
|
||||||
@ -33,10 +30,10 @@ void MainBatch::setTexture(const Texture* texture) {
|
|||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
this->texture = texture;
|
this->texture = texture;
|
||||||
region = UVRegion {0.0f, 0.0f, 1.0f, 1.0f};
|
region = UVRegion{0.0f, 0.0f, 1.0f, 1.0f};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainBatch::setTexture(const Texture* texture, const UVRegion& region) {
|
void MainBatch::setTexture(const Texture *texture, const UVRegion ®ion) {
|
||||||
setTexture(texture);
|
setTexture(texture);
|
||||||
this->region = region;
|
this->region = region;
|
||||||
}
|
}
|
||||||
@ -49,7 +46,7 @@ void MainBatch::flush() {
|
|||||||
texture = blank.get();
|
texture = blank.get();
|
||||||
}
|
}
|
||||||
texture->bind();
|
texture->bind();
|
||||||
mesh->reload(buffer.get(), index / VERTEX_SIZE);
|
mesh->reload(buffer.get(), index);
|
||||||
mesh->draw();
|
mesh->draw();
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
@ -60,76 +57,76 @@ void MainBatch::begin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainBatch::prepare(int vertices) {
|
void MainBatch::prepare(int vertices) {
|
||||||
if (index + VERTEX_SIZE * vertices > capacity * VERTEX_SIZE) {
|
if (index * vertices > capacity) {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec4 MainBatch::sampleLight(
|
glm::vec4 MainBatch::sampleLight(
|
||||||
const glm::vec3& pos, const Chunks& chunks, bool backlight
|
const glm::vec3 &pos, const Chunks &chunks, bool backlight
|
||||||
) {
|
) {
|
||||||
light_t light = chunks.getLight(
|
light_t light = chunks.getLight(
|
||||||
std::floor(pos.x),
|
std::floor(pos.x),
|
||||||
std::floor(std::min(CHUNK_H-1.0f, pos.y)),
|
std::floor(std::min(CHUNK_H - 1.0f, pos.y)),
|
||||||
std::floor(pos.z));
|
std::floor(pos.z));
|
||||||
light_t minIntensity = backlight ? 1 : 0;
|
light_t minIntensity = backlight ? 1 : 0;
|
||||||
return glm::vec4(
|
return {
|
||||||
glm::max(Lightmap::extract(light, 0), minIntensity) / 15.0f,
|
(float) glm::max(Lightmap::extract(light, 0), minIntensity) / 15.0f,
|
||||||
glm::max(Lightmap::extract(light, 1), minIntensity) / 15.0f,
|
(float) glm::max(Lightmap::extract(light, 1), minIntensity) / 15.0f,
|
||||||
glm::max(Lightmap::extract(light, 2), minIntensity) / 15.0f,
|
(float) glm::max(Lightmap::extract(light, 2), minIntensity) / 15.0f,
|
||||||
glm::max(Lightmap::extract(light, 3), minIntensity) / 15.0f
|
(float) glm::max(Lightmap::extract(light, 3), minIntensity) / 15.0f
|
||||||
);
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline glm::vec4 do_tint(float value) {
|
inline glm::vec4 do_tint(float value) {
|
||||||
return glm::vec4(value, value, value, 1.0f);
|
return {value, value, value, 1.0f};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainBatch::cube(
|
void MainBatch::cube(
|
||||||
const glm::vec3& coord,
|
const glm::vec3 &coord,
|
||||||
const glm::vec3& size,
|
const glm::vec3 &size,
|
||||||
const UVRegion(&texfaces)[6],
|
const UVRegion(&texfaces)[6],
|
||||||
const glm::vec4& tint,
|
const glm::vec4 &tint,
|
||||||
bool shading
|
bool shading
|
||||||
) {
|
) {
|
||||||
const glm::vec3 X(1.0f, 0.0f, 0.0f);
|
const glm::vec3 X(1.0f, 0.0f, 0.0f);
|
||||||
const glm::vec3 Y(0.0f, 1.0f, 0.0f);
|
const glm::vec3 Y(0.0f, 1.0f, 0.0f);
|
||||||
const glm::vec3 Z(0.0f, 0.0f, 1.0f);
|
const glm::vec3 Z(0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
quad(
|
quad(
|
||||||
coord + Z * size.z * 0.5f,
|
coord + Z * size.z * 0.5f,
|
||||||
X, Y, glm::vec2(size.x, size.y),
|
X, Y, glm::vec2(size.x, size.y),
|
||||||
(shading ? do_tint(0.8) * tint : tint),
|
(shading ? do_tint(0.8) * tint : tint),
|
||||||
glm::vec3(1.0f), texfaces[5]
|
glm::vec3(1.0f), texfaces[5]
|
||||||
);
|
);
|
||||||
quad(
|
quad(
|
||||||
coord - Z * size.z * 0.5f,
|
coord - Z * size.z * 0.5f,
|
||||||
-X, Y, glm::vec2(size.x, size.y),
|
-X, Y, glm::vec2(size.x, size.y),
|
||||||
(shading ? do_tint(0.9f) * tint : tint),
|
(shading ? do_tint(0.9f) * tint : tint),
|
||||||
glm::vec3(1.0f), texfaces[4]
|
glm::vec3(1.0f), texfaces[4]
|
||||||
);
|
);
|
||||||
quad(
|
quad(
|
||||||
coord + Y * size.y * 0.5f,
|
coord + Y * size.y * 0.5f,
|
||||||
-X, Z, glm::vec2(size.x, size.z),
|
-X, Z, glm::vec2(size.x, size.z),
|
||||||
(shading ? do_tint(1.0f) * tint : tint),
|
(shading ? do_tint(1.0f) * tint : tint),
|
||||||
glm::vec3(1.0f), texfaces[3]
|
glm::vec3(1.0f), texfaces[3]
|
||||||
);
|
);
|
||||||
quad(
|
quad(
|
||||||
coord - Y * size.y * 0.5f,
|
coord - Y * size.y * 0.5f,
|
||||||
X, Z, glm::vec2(size.x, size.z),
|
X, Z, glm::vec2(size.x, size.z),
|
||||||
(shading ? do_tint(0.7f) * tint : tint),
|
(shading ? do_tint(0.7f) * tint : tint),
|
||||||
glm::vec3(1.0f), texfaces[2]
|
glm::vec3(1.0f), texfaces[2]
|
||||||
);
|
);
|
||||||
quad(
|
quad(
|
||||||
coord + X * size.x * 0.5f,
|
coord + X * size.x * 0.5f,
|
||||||
-Z, Y, glm::vec2(size.z, size.y),
|
-Z, Y, glm::vec2(size.z, size.y),
|
||||||
(shading ? do_tint(0.8f) * tint : tint),
|
(shading ? do_tint(0.8f) * tint : tint),
|
||||||
glm::vec3(1.0f), texfaces[1]
|
glm::vec3(1.0f), texfaces[1]
|
||||||
);
|
);
|
||||||
quad(
|
quad(
|
||||||
coord - X * size.x * 0.5f,
|
coord - X * size.x * 0.5f,
|
||||||
Z, Y, glm::vec2(size.z, size.y),
|
Z, Y, glm::vec2(size.z, size.y),
|
||||||
(shading ? do_tint(0.9f) * tint : tint),
|
(shading ? do_tint(0.9f) * tint : tint),
|
||||||
glm::vec3(1.0f), texfaces[1]
|
glm::vec3(1.0f), texfaces[1]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,30 +1,46 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "maths/UVRegion.hpp"
|
#include "maths/UVRegion.hpp"
|
||||||
|
#include "graphics/core/MeshData.hpp"
|
||||||
|
|
||||||
|
template<typename VertexStructure>
|
||||||
class Mesh;
|
class Mesh;
|
||||||
class Texture;
|
class Texture;
|
||||||
class Chunks;
|
class Chunks;
|
||||||
|
|
||||||
|
struct MainBatchVertex {
|
||||||
|
glm::vec3 position;
|
||||||
|
glm::vec2 uv;
|
||||||
|
glm::vec3 tint;
|
||||||
|
std::array<uint8_t,4> color;
|
||||||
|
|
||||||
|
static constexpr VertexAttribute ATTRIBUTES[] = {
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 3},
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 2},
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 3},
|
||||||
|
{VertexAttribute::Type::UNSIGNED_BYTE, true, 4},
|
||||||
|
{{}, 0}};
|
||||||
|
};
|
||||||
|
|
||||||
class MainBatch {
|
class MainBatch {
|
||||||
std::unique_ptr<float[]> const buffer;
|
std::unique_ptr<MainBatchVertex[]> const buffer;
|
||||||
size_t const capacity;
|
size_t const capacity;
|
||||||
size_t index;
|
size_t index;
|
||||||
|
|
||||||
UVRegion region {0.0f, 0.0f, 1.0f, 1.0f};
|
UVRegion region {0.0f, 0.0f, 1.0f, 1.0f};
|
||||||
|
|
||||||
std::unique_ptr<Mesh> mesh;
|
std::unique_ptr<Mesh<MainBatchVertex>> mesh;
|
||||||
std::unique_ptr<Texture> blank;
|
std::unique_ptr<Texture> blank;
|
||||||
|
|
||||||
const Texture* texture = nullptr;
|
const Texture* texture = nullptr;
|
||||||
public:
|
public:
|
||||||
/// xyz, uv, color, compressed lights
|
/// xyz, uv, color, compressed lights
|
||||||
static inline constexpr uint VERTEX_SIZE = 9;
|
|
||||||
|
|
||||||
MainBatch(size_t capacity);
|
MainBatch(size_t capacity);
|
||||||
|
|
||||||
@ -47,27 +63,16 @@ public:
|
|||||||
const glm::vec4& light,
|
const glm::vec4& light,
|
||||||
const glm::vec3& tint
|
const glm::vec3& tint
|
||||||
) {
|
) {
|
||||||
float* buffer = this->buffer.get();
|
MainBatchVertex* buffer = this->buffer.get();
|
||||||
buffer[index++] = pos.x;
|
buffer[index].position = pos;
|
||||||
buffer[index++] = pos.y;
|
buffer[index].uv = {uv.x * region.getWidth() + region.u1,uv.y * region.getHeight() + region.v1};
|
||||||
buffer[index++] = pos.z;
|
buffer[index].tint = tint;
|
||||||
buffer[index++] = uv.x * region.getWidth() + region.u1;
|
|
||||||
buffer[index++] = uv.y * region.getHeight() + region.v1;
|
|
||||||
buffer[index++] = tint.x;
|
|
||||||
buffer[index++] = tint.y;
|
|
||||||
buffer[index++] = tint.z;
|
|
||||||
|
|
||||||
union {
|
buffer[index].color[0] = static_cast<uint8_t>(light.r * 255);
|
||||||
float floating;
|
buffer[index].color[1] = static_cast<uint8_t>(light.g * 255);
|
||||||
uint32_t integer;
|
buffer[index].color[2] = static_cast<uint8_t>(light.b * 255);
|
||||||
} compressed;
|
buffer[index].color[3] = static_cast<uint8_t>(light.a * 255);
|
||||||
|
index++;
|
||||||
compressed.integer = (static_cast<uint32_t>(light.r * 255) & 0xff) << 24;
|
|
||||||
compressed.integer |= (static_cast<uint32_t>(light.g * 255) & 0xff) << 16;
|
|
||||||
compressed.integer |= (static_cast<uint32_t>(light.b * 255) & 0xff) << 8;
|
|
||||||
compressed.integer |= (static_cast<uint32_t>(light.a * 255) & 0xff);
|
|
||||||
|
|
||||||
buffer[index++] = compressed.floating;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void quad(
|
inline void quad(
|
||||||
|
|||||||
@ -1,14 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "maths/UVRegion.hpp"
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
class Mesh;
|
template<typename VertexStructure> class Mesh;
|
||||||
class Texture;
|
class Texture;
|
||||||
class Chunks;
|
class Chunks;
|
||||||
class Assets;
|
class Assets;
|
||||||
|
|||||||
@ -50,16 +50,16 @@ static inline UVRegion get_region_for(
|
|||||||
|
|
||||||
void ModelsGenerator::prepare(Content& content, Assets& assets) {
|
void ModelsGenerator::prepare(Content& content, Assets& assets) {
|
||||||
for (auto& [name, def] : content.blocks.getDefs()) {
|
for (auto& [name, def] : content.blocks.getDefs()) {
|
||||||
if (def->model == BlockModel::custom && def->modelName.empty()) {
|
if (def->model.type == BlockModelType::CUSTOM && def->model.name.empty()) {
|
||||||
assets.store(
|
assets.store(
|
||||||
std::make_unique<model::Model>(
|
std::make_unique<model::Model>(
|
||||||
loadCustomBlockModel(
|
loadCustomBlockModel(
|
||||||
def->customModelRaw, assets, !def->shadeless
|
def->model.customRaw, assets, !def->shadeless
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
name + ".model"
|
name + ".model"
|
||||||
);
|
);
|
||||||
def->modelName = def->name + ".model";
|
def->model.name = def->name + ".model";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto& [name, def] : content.items.getDefs()) {
|
for (auto& [name, def] : content.items.getDefs()) {
|
||||||
@ -74,7 +74,7 @@ void ModelsGenerator::prepare(Content& content, Assets& assets) {
|
|||||||
|
|
||||||
model::Model ModelsGenerator::fromCustom(
|
model::Model ModelsGenerator::fromCustom(
|
||||||
const Assets& assets,
|
const Assets& assets,
|
||||||
const std::vector<BoxModel>& modelBoxes,
|
const std::vector<AABB>& modelBoxes,
|
||||||
const std::vector<std::string>& modelTextures,
|
const std::vector<std::string>& modelTextures,
|
||||||
const std::vector<glm::vec3>& points,
|
const std::vector<glm::vec3>& points,
|
||||||
bool lighting
|
bool lighting
|
||||||
@ -95,32 +95,30 @@ model::Model ModelsGenerator::fromCustom(
|
|||||||
modelBoxes[i].center(), modelBoxes[i].size() * 0.5f, boxtexfaces
|
modelBoxes[i].center(), modelBoxes[i].size() * 0.5f, boxtexfaces
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
glm::vec3 norm {0, 1, 0};
|
|
||||||
for (size_t i = 0; i < points.size() / 4; i++) {
|
for (size_t i = 0; i < points.size() / 4; i++) {
|
||||||
auto texture = modelTextures[modelBoxes.size() * 6 + i];
|
auto texture = modelTextures[modelBoxes.size() * 6 + i];
|
||||||
|
|
||||||
|
const glm::vec3& v0 = points[i * 4];
|
||||||
|
const glm::vec3& v1 = points[i * 4 + 1];
|
||||||
|
const glm::vec3& v2 = points[i * 4 + 2];
|
||||||
|
const glm::vec3& v3 = points[i * 4 + 3];
|
||||||
|
|
||||||
|
glm::vec3 edge1 = v1 - v0;
|
||||||
|
glm::vec3 edge2 = v2 - v0;
|
||||||
|
|
||||||
|
glm::vec3 norm = glm::cross(edge1, edge2);
|
||||||
|
norm = glm::normalize(norm);
|
||||||
|
|
||||||
auto& mesh = model.addMesh(texture);
|
auto& mesh = model.addMesh(texture);
|
||||||
mesh.lighting = lighting;
|
mesh.lighting = lighting;
|
||||||
|
|
||||||
auto reg = get_region_for(texture, assets);
|
auto reg = get_region_for(texture, assets);
|
||||||
mesh.vertices.push_back(
|
mesh.vertices.push_back({v0, glm::vec2(reg.u1, reg.v1), norm});
|
||||||
{points[i * 4 + 0], glm::vec2(reg.u1, reg.v1), norm}
|
mesh.vertices.push_back({v1, glm::vec2(reg.u2, reg.v1), norm});
|
||||||
);
|
mesh.vertices.push_back({v2, glm::vec2(reg.u2, reg.v2), norm});
|
||||||
mesh.vertices.push_back(
|
mesh.vertices.push_back({v0, glm::vec2(reg.u1, reg.v1), norm});
|
||||||
{points[i * 4 + 1], glm::vec2(reg.u2, reg.v1), norm}
|
mesh.vertices.push_back({v2, glm::vec2(reg.u2, reg.v2), norm});
|
||||||
);
|
mesh.vertices.push_back({v3, glm::vec2(reg.u1, reg.v2), norm});
|
||||||
mesh.vertices.push_back(
|
|
||||||
{points[i * 4 + 2], glm::vec2(reg.u2, reg.v2), norm}
|
|
||||||
);
|
|
||||||
mesh.vertices.push_back(
|
|
||||||
{points[i * 4 + 0], glm::vec2(reg.u1, reg.v1), norm}
|
|
||||||
);
|
|
||||||
mesh.vertices.push_back(
|
|
||||||
{points[i * 4 + 2], glm::vec2(reg.u2, reg.v2), norm}
|
|
||||||
);
|
|
||||||
mesh.vertices.push_back(
|
|
||||||
{points[i * 4 + 3], glm::vec2(reg.u1, reg.v2), norm}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
@ -131,12 +129,12 @@ model::Model ModelsGenerator::generate(
|
|||||||
if (def.iconType == ItemIconType::BLOCK) {
|
if (def.iconType == ItemIconType::BLOCK) {
|
||||||
auto model = assets.require<model::Model>("block");
|
auto model = assets.require<model::Model>("block");
|
||||||
const auto& blockDef = content.blocks.require(def.icon);
|
const auto& blockDef = content.blocks.require(def.icon);
|
||||||
if (blockDef.model == BlockModel::xsprite) {
|
if (blockDef.model.type == BlockModelType::XSPRITE) {
|
||||||
return create_flat_model(
|
return create_flat_model(
|
||||||
"blocks:" + blockDef.textureFaces.at(0), assets
|
"blocks:" + blockDef.textureFaces.at(0), assets
|
||||||
);
|
);
|
||||||
} else if (blockDef.model == BlockModel::custom) {
|
} else if (blockDef.model.type == BlockModelType::CUSTOM) {
|
||||||
model = assets.require<model::Model>(blockDef.modelName);
|
model = assets.require<model::Model>(blockDef.model.name);
|
||||||
for (auto& mesh : model.meshes) {
|
for (auto& mesh : model.meshes) {
|
||||||
mesh.scale(glm::vec3(0.2f));
|
mesh.scale(glm::vec3(0.2f));
|
||||||
}
|
}
|
||||||
@ -144,8 +142,8 @@ model::Model ModelsGenerator::generate(
|
|||||||
}
|
}
|
||||||
for (auto& mesh : model.meshes) {
|
for (auto& mesh : model.meshes) {
|
||||||
mesh.lighting = !blockDef.shadeless;
|
mesh.lighting = !blockDef.shadeless;
|
||||||
switch (blockDef.model) {
|
switch (blockDef.model.type) {
|
||||||
case BlockModel::aabb: {
|
case BlockModelType::AABB: {
|
||||||
glm::vec3 size = blockDef.hitboxes.at(0).size();
|
glm::vec3 size = blockDef.hitboxes.at(0).size();
|
||||||
float m = glm::max(size.x, glm::max(size.y, size.z));
|
float m = glm::max(size.x, glm::max(size.y, size.z));
|
||||||
m = glm::min(1.0f, m);
|
m = glm::min(1.0f, m);
|
||||||
|
|||||||
@ -24,10 +24,10 @@
|
|||||||
const int STARS_COUNT = 3000;
|
const int STARS_COUNT = 3000;
|
||||||
const int STARS_SEED = 632;
|
const int STARS_SEED = 632;
|
||||||
|
|
||||||
Skybox::Skybox(uint size, Shader& shader)
|
Skybox::Skybox(uint size, Shader& shader)
|
||||||
: size(size),
|
: size(size),
|
||||||
shader(shader),
|
shader(shader),
|
||||||
batch3d(std::make_unique<Batch3D>(4096))
|
batch3d(std::make_unique<Batch3D>(4096))
|
||||||
{
|
{
|
||||||
auto cubemap = std::make_unique<Cubemap>(size, size, ImageFormat::rgb888);
|
auto cubemap = std::make_unique<Cubemap>(size, size, ImageFormat::rgb888);
|
||||||
|
|
||||||
@ -35,12 +35,16 @@ Skybox::Skybox(uint size, Shader& shader)
|
|||||||
glGenFramebuffers(1, &fboid);
|
glGenFramebuffers(1, &fboid);
|
||||||
fbo = std::make_unique<Framebuffer>(fboid, 0, std::move(cubemap));
|
fbo = std::make_unique<Framebuffer>(fboid, 0, std::move(cubemap));
|
||||||
|
|
||||||
float vertices[] {
|
SkyboxVertex vertices[]{
|
||||||
-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
|
{{-1.0f, -1.0f}},
|
||||||
-1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f
|
{{-1.0f, 1.0f}},
|
||||||
|
{{1.0f, 1.0f}},
|
||||||
|
{{-1.0f, -1.0f}},
|
||||||
|
{{1.0f, 1.0f}},
|
||||||
|
{{1.0f, -1.0f}}
|
||||||
};
|
};
|
||||||
VertexAttribute attrs[] {{2}, {0}};
|
|
||||||
mesh = std::make_unique<Mesh>(vertices, 6, attrs);
|
mesh = std::make_unique<Mesh<SkyboxVertex>>(vertices, 6);
|
||||||
|
|
||||||
sprites.push_back(skysprite {
|
sprites.push_back(skysprite {
|
||||||
"misc/moon",
|
"misc/moon",
|
||||||
@ -95,11 +99,11 @@ void Skybox::drawStars(float angle, float opacity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Skybox::draw(
|
void Skybox::draw(
|
||||||
const DrawContext& pctx,
|
const DrawContext& pctx,
|
||||||
const Camera& camera,
|
const Camera& camera,
|
||||||
const Assets& assets,
|
const Assets& assets,
|
||||||
float daytime,
|
float daytime,
|
||||||
float fog)
|
float fog)
|
||||||
{
|
{
|
||||||
const glm::uvec2& viewport = pctx.getViewport();
|
const glm::uvec2& viewport = pctx.getViewport();
|
||||||
|
|
||||||
@ -116,7 +120,7 @@ void Skybox::draw(
|
|||||||
|
|
||||||
float angle = daytime * glm::pi<float>() * 2.0f;
|
float angle = daytime * glm::pi<float>() * 2.0f;
|
||||||
float opacity = glm::pow(1.0f-fog, 7.0f);
|
float opacity = glm::pow(1.0f-fog, 7.0f);
|
||||||
|
|
||||||
for (auto& sprite : sprites) {
|
for (auto& sprite : sprites) {
|
||||||
batch3d->texture(assets.get<Texture>(sprite.texture));
|
batch3d->texture(assets.get<Texture>(sprite.texture));
|
||||||
|
|
||||||
@ -129,7 +133,7 @@ void Skybox::draw(
|
|||||||
if (!sprite.emissive) {
|
if (!sprite.emissive) {
|
||||||
tint *= 0.6f+std::cos(angle)*0.4;
|
tint *= 0.6f+std::cos(angle)*0.4;
|
||||||
}
|
}
|
||||||
batch3d->sprite(pos, glm::vec3(0, 0, 1),
|
batch3d->sprite(pos, glm::vec3(0, 0, 1),
|
||||||
up, 1, 1, UVRegion(), tint);
|
up, 1, 1, UVRegion(), tint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +157,7 @@ void Skybox::refresh(const DrawContext& pctx, float t, float mie, uint quality)
|
|||||||
cubemap->bind();
|
cubemap->bind();
|
||||||
shader.use();
|
shader.use();
|
||||||
t *= glm::pi<float>()*2.0f;
|
t *= glm::pi<float>()*2.0f;
|
||||||
|
|
||||||
lightDir = glm::normalize(glm::vec3(sin(t), -cos(t), 0.0f));
|
lightDir = glm::normalize(glm::vec3(sin(t), -cos(t), 0.0f));
|
||||||
shader.uniform1i("u_quality", quality);
|
shader.uniform1i("u_quality", quality);
|
||||||
shader.uniform1f("u_mie", mie);
|
shader.uniform1f("u_mie", mie);
|
||||||
@ -171,7 +175,7 @@ void Skybox::refresh(const DrawContext& pctx, float t, float mie, uint quality)
|
|||||||
}
|
}
|
||||||
prevMie = mie;
|
prevMie = mie;
|
||||||
prevT = t;
|
prevT = t;
|
||||||
|
|
||||||
cubemap->unbind();
|
cubemap->unbind();
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
}
|
}
|
||||||
@ -190,7 +194,7 @@ void Skybox::refreshFace(uint face, Cubemap* cubemap) {
|
|||||||
{0.0f, 1.0f, 0.0f},
|
{0.0f, 1.0f, 0.0f},
|
||||||
{0.0f, 1.0f, 0.0f},
|
{0.0f, 1.0f, 0.0f},
|
||||||
{0.0f, 0.0f, -1.0f},
|
{0.0f, 0.0f, -1.0f},
|
||||||
|
|
||||||
{0.0f, 0.0f, 1.0f},
|
{0.0f, 0.0f, 1.0f},
|
||||||
{0.0f, 1.0f, 0.0f},
|
{0.0f, 1.0f, 0.0f},
|
||||||
{0.0f, 1.0f, 0.0f},
|
{0.0f, 1.0f, 0.0f},
|
||||||
@ -200,7 +204,7 @@ void Skybox::refreshFace(uint face, Cubemap* cubemap) {
|
|||||||
{1.0f, 0.0f, 0.0f},
|
{1.0f, 0.0f, 0.0f},
|
||||||
{-1.0f, 0.0f, 0.0f},
|
{-1.0f, 0.0f, 0.0f},
|
||||||
{0.0f, -1.0f, 0.0f},
|
{0.0f, -1.0f, 0.0f},
|
||||||
|
|
||||||
{0.0f, 1.0f, 0.0f},
|
{0.0f, 1.0f, 0.0f},
|
||||||
{0.0f, 0.0f, -1.0f},
|
{0.0f, 0.0f, -1.0f},
|
||||||
{0.0f, 0.0f, 1.0f},
|
{0.0f, 0.0f, 1.0f},
|
||||||
|
|||||||
@ -6,17 +6,25 @@
|
|||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "maths/fastmaths.hpp"
|
#include "maths/fastmaths.hpp"
|
||||||
|
#include "graphics/core/MeshData.hpp"
|
||||||
|
|
||||||
class Mesh;
|
template<typename VertexStructure> class Mesh;
|
||||||
class Shader;
|
class Shader;
|
||||||
class Assets;
|
class Assets;
|
||||||
class Camera;
|
class Camera;
|
||||||
class Batch3D;
|
class Batch3D;
|
||||||
class Shader;
|
|
||||||
class Cubemap;
|
class Cubemap;
|
||||||
class Framebuffer;
|
class Framebuffer;
|
||||||
class DrawContext;
|
class DrawContext;
|
||||||
|
|
||||||
|
struct SkyboxVertex {
|
||||||
|
glm::vec2 position;
|
||||||
|
|
||||||
|
static constexpr VertexAttribute ATTRIBUTES[] {
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 2},
|
||||||
|
{{}, 0}};
|
||||||
|
};
|
||||||
|
|
||||||
struct skysprite {
|
struct skysprite {
|
||||||
std::string texture;
|
std::string texture;
|
||||||
float phase;
|
float phase;
|
||||||
@ -32,7 +40,7 @@ class Skybox {
|
|||||||
FastRandom random;
|
FastRandom random;
|
||||||
glm::vec3 lightDir;
|
glm::vec3 lightDir;
|
||||||
|
|
||||||
std::unique_ptr<Mesh> mesh;
|
std::unique_ptr<Mesh<SkyboxVertex>> mesh;
|
||||||
std::unique_ptr<Batch3D> batch3d;
|
std::unique_ptr<Batch3D> batch3d;
|
||||||
std::vector<skysprite> sprites;
|
std::vector<skysprite> sprites;
|
||||||
int frameid = 0;
|
int frameid = 0;
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#include "WorldRenderer.hpp"
|
#include "WorldRenderer.hpp"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -119,6 +118,7 @@ void WorldRenderer::setupWorldShader(
|
|||||||
shader.uniform1f("u_gamma", settings.graphics.gamma.get());
|
shader.uniform1f("u_gamma", settings.graphics.gamma.get());
|
||||||
shader.uniform1f("u_fogFactor", fogFactor);
|
shader.uniform1f("u_fogFactor", fogFactor);
|
||||||
shader.uniform1f("u_fogCurve", settings.graphics.fogCurve.get());
|
shader.uniform1f("u_fogCurve", settings.graphics.fogCurve.get());
|
||||||
|
shader.uniform1i("u_debugLights", lightsDebug);
|
||||||
shader.uniform1f("u_weatherFogOpacity", weather.fogOpacity());
|
shader.uniform1f("u_weatherFogOpacity", weather.fogOpacity());
|
||||||
shader.uniform1f("u_weatherFogDencity", weather.fogDencity());
|
shader.uniform1f("u_weatherFogDencity", weather.fogDencity());
|
||||||
shader.uniform1f("u_weatherFogCurve", weather.fogCurve());
|
shader.uniform1f("u_weatherFogCurve", weather.fogCurve());
|
||||||
@ -443,6 +443,10 @@ void WorldRenderer::setDebug(bool flag) {
|
|||||||
debug = flag;
|
debug = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldRenderer::toggleLightsDebug() {
|
||||||
|
lightsDebug = !lightsDebug;
|
||||||
|
}
|
||||||
|
|
||||||
Weather& WorldRenderer::getWeather() {
|
Weather& WorldRenderer::getWeather() {
|
||||||
return weather;
|
return weather;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,6 +48,7 @@ class WorldRenderer {
|
|||||||
|
|
||||||
float timer = 0.0f;
|
float timer = 0.0f;
|
||||||
bool debug = false;
|
bool debug = false;
|
||||||
|
bool lightsDebug = false;
|
||||||
|
|
||||||
/// @brief Render block selection lines
|
/// @brief Render block selection lines
|
||||||
void renderBlockSelection();
|
void renderBlockSelection();
|
||||||
@ -107,5 +108,7 @@ public:
|
|||||||
|
|
||||||
void setDebug(bool flag);
|
void setDebug(bool flag);
|
||||||
|
|
||||||
|
void toggleLightsDebug();
|
||||||
|
|
||||||
Weather& getWeather();
|
Weather& getWeather();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,25 +1,36 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <glm/vec2.hpp>
|
||||||
#include <glm/vec3.hpp>
|
#include <glm/vec3.hpp>
|
||||||
|
|
||||||
#include "graphics/core/MeshData.hpp"
|
#include "graphics/core/MeshData.hpp"
|
||||||
#include "util/Buffer.hpp"
|
#include "util/Buffer.hpp"
|
||||||
|
|
||||||
/// @brief Chunk mesh vertex attributes
|
/// @brief Chunk mesh vertex format
|
||||||
inline const VertexAttribute CHUNK_VATTRS[]{ {3}, {2}, {1}, {0} };
|
struct ChunkVertex {
|
||||||
/// @brief Chunk mesh vertex size divided by sizeof(float)
|
glm::vec3 position;
|
||||||
inline constexpr int CHUNK_VERTEX_SIZE = 6;
|
glm::vec2 uv;
|
||||||
|
std::array<uint8_t, 4> color;
|
||||||
|
|
||||||
|
static constexpr VertexAttribute ATTRIBUTES[] = {
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 3},
|
||||||
|
{VertexAttribute::Type::FLOAT, false, 2},
|
||||||
|
{VertexAttribute::Type::UNSIGNED_BYTE, true, 4},
|
||||||
|
{{}, 0}};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename VertexStructure>
|
||||||
class Mesh;
|
class Mesh;
|
||||||
|
|
||||||
struct SortingMeshEntry {
|
struct SortingMeshEntry {
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
util::Buffer<float> vertexData;
|
util::Buffer<ChunkVertex> vertexData;
|
||||||
long long distance;
|
long long distance;
|
||||||
|
|
||||||
inline bool operator<(const SortingMeshEntry& o) const noexcept {
|
inline bool operator<(const SortingMeshEntry &o) const noexcept {
|
||||||
return distance > o.distance;
|
return distance > o.distance;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -29,12 +40,12 @@ struct SortingMeshData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ChunkMeshData {
|
struct ChunkMeshData {
|
||||||
MeshData mesh;
|
MeshData<ChunkVertex> mesh;
|
||||||
SortingMeshData sortingMesh;
|
SortingMeshData sortingMesh;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ChunkMesh {
|
struct ChunkMesh {
|
||||||
std::unique_ptr<Mesh> mesh;
|
std::unique_ptr<Mesh<ChunkVertex> > mesh;
|
||||||
SortingMeshData sortingMeshData;
|
SortingMeshData sortingMeshData;
|
||||||
std::unique_ptr<Mesh> sortedMesh = nullptr;
|
std::unique_ptr<Mesh<ChunkVertex> > sortedMesh = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -312,7 +312,7 @@ static int l_get_textures(lua::State* L) {
|
|||||||
|
|
||||||
static int l_get_model(lua::State* L) {
|
static int l_get_model(lua::State* L) {
|
||||||
if (auto def = require_block(L)) {
|
if (auto def = require_block(L)) {
|
||||||
return lua::pushlstring(L, BlockModelMeta.getName(def->model));
|
return lua::pushlstring(L, BlockModelTypeMeta.getName(def->model.type));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -143,7 +143,6 @@ void Block::cloneTo(Block& dst) {
|
|||||||
if (particles) {
|
if (particles) {
|
||||||
dst.particles = std::make_unique<ParticlesPreset>(*particles);
|
dst.particles = std::make_unique<ParticlesPreset>(*particles);
|
||||||
}
|
}
|
||||||
dst.customModelRaw = customModelRaw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::set<std::string, std::less<>> RESERVED_BLOCK_FIELDS {
|
static std::set<std::string, std::less<>> RESERVED_BLOCK_FIELDS {
|
||||||
|
|||||||
@ -81,25 +81,35 @@ struct BlockRotProfile {
|
|||||||
static inline std::string PANE_NAME = "pane";
|
static inline std::string PANE_NAME = "pane";
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class BlockModel {
|
enum class BlockModelType {
|
||||||
/// @brief invisible
|
/// @brief invisible
|
||||||
none,
|
NONE,
|
||||||
/// @brief default cube shape
|
/// @brief default cube shape
|
||||||
block,
|
BLOCK,
|
||||||
/// @brief X-shape (grass)
|
/// @brief X-shape (grass)
|
||||||
xsprite,
|
XSPRITE,
|
||||||
/// @brief box shape sized as block hitbox
|
/// @brief box shape sized as block hitbox
|
||||||
aabb,
|
AABB,
|
||||||
/// @brief custom model defined in json
|
/// @brief custom model defined in json
|
||||||
custom
|
CUSTOM
|
||||||
};
|
};
|
||||||
|
|
||||||
VC_ENUM_METADATA(BlockModel)
|
struct BlockModel {
|
||||||
{"none", BlockModel::none},
|
BlockModelType type = BlockModelType::BLOCK;
|
||||||
{"block", BlockModel::block},
|
|
||||||
{"X", BlockModel::xsprite},
|
/// @brief Custom model raw data
|
||||||
{"aabb", BlockModel::aabb},
|
dv::value customRaw = nullptr;
|
||||||
{"custom", BlockModel::custom},
|
|
||||||
|
/// @brief Custom model name (generated or an asset)
|
||||||
|
std::string name = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
VC_ENUM_METADATA(BlockModelType)
|
||||||
|
{"none", BlockModelType::NONE},
|
||||||
|
{"block", BlockModelType::BLOCK},
|
||||||
|
{"X", BlockModelType::XSPRITE},
|
||||||
|
{"aabb", BlockModelType::AABB},
|
||||||
|
{"custom", BlockModelType::CUSTOM},
|
||||||
VC_ENUM_END
|
VC_ENUM_END
|
||||||
|
|
||||||
enum class CullingMode {
|
enum class CullingMode {
|
||||||
@ -114,8 +124,6 @@ VC_ENUM_METADATA(CullingMode)
|
|||||||
{"disabled", CullingMode::DISABLED},
|
{"disabled", CullingMode::DISABLED},
|
||||||
VC_ENUM_END
|
VC_ENUM_END
|
||||||
|
|
||||||
using BoxModel = AABB;
|
|
||||||
|
|
||||||
/// @brief Common kit of block properties applied to groups of blocks
|
/// @brief Common kit of block properties applied to groups of blocks
|
||||||
struct BlockMaterial : Serializable {
|
struct BlockMaterial : Serializable {
|
||||||
std::string name;
|
std::string name;
|
||||||
@ -154,13 +162,8 @@ public:
|
|||||||
/// @brief Influences visible block sides for transparent blocks
|
/// @brief Influences visible block sides for transparent blocks
|
||||||
uint8_t drawGroup = 0;
|
uint8_t drawGroup = 0;
|
||||||
|
|
||||||
/// @brief Block model type
|
/// @brief Block model
|
||||||
BlockModel model = BlockModel::block;
|
BlockModel model {};
|
||||||
|
|
||||||
/// @brief Custom model raw data
|
|
||||||
dv::value customModelRaw = nullptr;
|
|
||||||
|
|
||||||
std::string modelName = "";
|
|
||||||
|
|
||||||
/// @brief Culling mode
|
/// @brief Culling mode
|
||||||
CullingMode culling = CullingMode::DEFAULT;
|
CullingMode culling = CullingMode::DEFAULT;
|
||||||
|
|||||||
@ -10,7 +10,6 @@
|
|||||||
#include "coders/byte_utils.hpp"
|
#include "coders/byte_utils.hpp"
|
||||||
#include "content/Content.hpp"
|
#include "content/Content.hpp"
|
||||||
#include "world/files/WorldFiles.hpp"
|
#include "world/files/WorldFiles.hpp"
|
||||||
#include "graphics/core/Mesh.hpp"
|
|
||||||
#include "lighting/Lightmap.hpp"
|
#include "lighting/Lightmap.hpp"
|
||||||
#include "maths/aabb.hpp"
|
#include "maths/aabb.hpp"
|
||||||
#include "maths/rays.hpp"
|
#include "maths/rays.hpp"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user