1
0
Fork 0

Entities instancing

This commit is contained in:
May B. 2020-08-30 18:35:45 +02:00
parent 4066bf90b9
commit 3b4e9fd940
36 changed files with 397 additions and 340 deletions

View File

@ -81,4 +81,15 @@ target_include_directories(zstd_sampler PRIVATE "include/FastNoiseSIMD" "include
add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/content/zstd.dict"
COMMAND "${CMAKE_BINARY_DIR}/zstd_sampler" DEPENDS zstd_sampler)
add_custom_target(generate_dictionary DEPENDS "${CMAKE_BINARY_DIR}/content/zstd.dict")
add_custom_target(generate_dictionary DEPENDS "${CMAKE_BINARY_DIR}/content/zstd.dict")
# Builtin models
file(GLOB_RECURSE MCT_SOURCES "src/model_contouring.cpp" "src/*/*.cpp")
add_executable(model_contouring EXCLUDE_FROM_ALL ${MCT_SOURCES} ${INCLUDE_SOURCES})
target_compile_features(model_contouring PUBLIC cxx_std_17)
target_link_libraries(model_contouring ${LINKED_LIBS})
target_include_directories(model_contouring PRIVATE ${INCLUDE_LIBS})
add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/content/model.ivb"
COMMAND "${CMAKE_BINARY_DIR}/model_contouring" DEPENDS model_contouring)
add_custom_target(render_models DEPENDS "${CMAKE_BINARY_DIR}/content/model.ivb")

View File

@ -18,7 +18,7 @@
- [x] Edition
- [~] Entity
- [x] Basic
- [ ] Instanced
- [x] Instanced
- https://learnopengl.com/Advanced-OpenGL/Instancing
- [ ] Inheritance
- [ ] ECS
@ -34,7 +34,7 @@
- [ ] Corrected Normals
- [ ] Surface curvature
- [ ] Curvature avare frustum
- [ ] Sphere
- [x] Sphere
- [ ] Healpix
- [ ] Surface features
- [ ] Biomes

View File

@ -172,4 +172,7 @@ void main() {
color = mix(color, pow(FogColor, vec3(2.2)), clamp(ratio, 0, 1));
#endif
color = pow(color, vec3(1.0 / 2.2));
if(color.r > 1 || color.g > 1 || color.b > 1) {
color = vec3(1, 0, 0); //TODO: bloom
}
}

View File

@ -39,7 +39,6 @@ void main() {
gl_Position = gl_in[i].gl_Position;
gs.Position_modelspace = vs_in[i].Position_modelspace;
gs.FaceNormal_modelspace = vs_in[i].FaceNormal_modelspace;
gs.FaceNormal_worldspace = vs_in[i].FaceNormal_worldspace;
gs.Textures[i] = vs_in[i].Texture;
switch(int(mod(i,3))) {
@ -57,8 +56,11 @@ void main() {
break;
};
#ifdef PBR
gs.FaceNormal_worldspace = vs_in[i].FaceNormal_worldspace;
gs.EyeDirection_cameraspace = vs_in[i].EyeDirection_cameraspace;
gs.LightDirection_cameraspace = vs_in[i].LightDirection_cameraspace;
#endif
#ifdef SHADOW
gs.ShadowCoord = vs_in[i].ShadowCoord;
#endif

View File

@ -18,7 +18,11 @@ out VertexData {
#endif
} vs;
#ifdef INSTANCED
layout(location = 6) in mat4 Model;
#else
uniform mat4 Model;
#endif
uniform mat4 View;
uniform mat4 Proj;

View File

@ -8,7 +8,6 @@ inline void optimize_fetch(buffer::ShortIndexed::Data& out) {
out.vertices.resize(vertex_count, buffer::PackedVertexData(0, 0, 0, 0, 0, 0, 0));
}
//TODO: quantize half-float / 8-10 int
//MAYBE: when networking meshopt_encodeVertexBuffer
template<typename I>

View File

@ -14,9 +14,6 @@
#include "render/UI.hpp"
#include "control/InputMap.hpp" //TODO: add options
#include "render/pass/ColorProgram.hpp"
#include "render/buffer/Colored.hpp"
#include "state.h"
#include "data/math.hpp"
@ -56,40 +53,11 @@ int main(int /*unused*/, char */*unused*/[]){
Camera camera(&player, options.camera);
auto *renderer = new Renderer(options.renderer);
renderer->LightInvDir = glm::vec3(-0.5f, 2, -2);
renderer->LightInvDir = glm::normalize(glm::vec3(-.5f, 2, -2));
UI::setup(window);
GLuint aimTexture = pass::Program::loadTexture("ui/Aim", false);
auto *lookProgram = new pass::ColorProgram();
buffer::Colored lookBuffer(GL_LINES, 24, {
glm::vec3(0, 0, 0), glm::vec3(0, 0, 1),
glm::vec3(0, 0, 1), glm::vec3(0, 1, 1),
glm::vec3(0, 1, 1), glm::vec3(0, 1, 0),
glm::vec3(0, 1, 0), glm::vec3(0, 0, 0),
glm::vec3(1, 0, 0), glm::vec3(1, 0, 1),
glm::vec3(1, 0, 1), glm::vec3(1, 1, 1),
glm::vec3(1, 1, 1), glm::vec3(1, 1, 0),
glm::vec3(1, 1, 0), glm::vec3(1, 0, 0),
glm::vec3(0, 0, 0), glm::vec3(1, 0, 0),
glm::vec3(0, 0, 1), glm::vec3(1, 0, 1),
glm::vec3(0, 1, 1), glm::vec3(1, 1, 1),
glm::vec3(0, 1, 0), glm::vec3(1, 1, 0),
}, {
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
});
#if TRACY_ENABLE
LOG("Profiling !");
#endif
@ -119,6 +87,7 @@ int main(int /*unused*/, char */*unused*/[]){
}
camera.update();
renderer->lookFrom(camera);
renderer->LightInvDir = glm::vec3(glm::rotate(glm::mat4(1), deltaTime * .1f, glm::vec3(1, .5, .1)) * glm::vec4(renderer->LightInvDir, 0));
{
const auto ray_result = world.raycast(camera.getRay() * options.voxel_density);
@ -165,7 +134,7 @@ int main(int /*unused*/, char */*unused*/[]){
glClearColor(options.renderer.clear_color.x, options.renderer.clear_color.y, options.renderer.clear_color.z, options.renderer.clear_color.w);
}
if(actions && UI::Actions::RendererSharders) {
renderer->reloadShaders(options.renderer.main);
renderer->reloadShaders(options.renderer.voxel);
}
if(actions && UI::Actions::RendererTextures) {
renderer->reloadTextures(options.renderer.textures, options.renderer.mipMapLOD);
@ -189,8 +158,7 @@ int main(int /*unused*/, char */*unused*/[]){
{ // Rendering
ZoneScopedN("Render");
TracyGpuZone("Render");
auto pass = renderer->getPass();
pass.start();
renderer->beginFrame();
reports.models_count = 0;
reports.tris_count = 0;
@ -200,11 +168,12 @@ int main(int /*unused*/, char */*unused*/[]){
}
const auto offset = state.position.raw_as_long();
{ // Chunks
const auto pass = renderer->beginWorldPass();
const auto draw = [&](glm::mat4 model, buffer::Abstract *const buffer, const contouring::Abstract::area_info &area, const voxel_pos &pos) {
renderer->SphereProj = glm::vec4(pos, std::get<1>(area));
renderer->Curvature = std::get<2>(area);
reports.models_count++;
reports.tris_count += buffer->draw(pass.setup(model));
reports.tris_count += buffer->draw(pass(model));
};
if (options.culling > 0) {
std::vector<glm::vec3> occlusion;
@ -225,50 +194,19 @@ int main(int /*unused*/, char */*unused*/[]){
}
}
{ // Entities
lookProgram->useIt();
lookProgram->start(renderer);
const auto draw = [&](const std::vector<glm::mat4>& models, buffer::Abstract *const) {
const auto pass = renderer->beginEntityPass();
const auto draw = [&](const std::vector<glm::mat4>& models, buffer::Abstract *const buffer) {
reports.models_count += models.size();
reports.tris_count += models.size() * 24; // FIXME: get from buffer
//instancedProgram->setMatrices(&models[batch * BATCH_SIZE]);
/*
unsigned int instanceVBO;
glGenBuffers(1, &instanceVBO);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * BATCH_SIZE, &translations[0], GL_STATIC_DRAW); //MAYBE: only rewrite only count
glBindBuffer(GL_ARRAY_BUFFER, 0);
*/
/*
constexpr std::size_t vec4Size = sizeof(glm::vec4);
constexpr auto location = 6;
glEnableVertexAttribArray(location+0);
glVertexAttribPointer(location+0, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (void*)0);
glEnableVertexAttribArray(location+1);
glVertexAttribPointer(location+1, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (void*)(1 * vec4Size));
glEnableVertexAttribArray(location+2);
glVertexAttribPointer(location+2, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (void*)(2 * vec4Size));
glEnableVertexAttribArray(location+3);
glVertexAttribPointer(location+3, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (void*)(3 * vec4Size));
glVertexAttribDivisor(location+0, 1);
glVertexAttribDivisor(location+1, 1);
glVertexAttribDivisor(location+2, 1);
glVertexAttribDivisor(location+3, 1);
*/
//glDrawArraysInstanced(GL_TRIANGLES, 0, 6, count);
for (size_t offset = 0; offset < models.size(); offset++) //TODO: instansiate
lookBuffer.draw(lookProgram->setup(renderer, models[offset]));
reports.tris_count += buffer->draw(pass(models));
};
world.getEntitiesModels(draw, frustum, offset, options.voxel_density);
}
if(state.look_at.has_value()) { // Indicator
lookProgram->useIt();
lookProgram->start(renderer);
const auto model = glm::scale(glm::translate(glm::scale(glm::mat4(1), 1.f / glm::vec3(options.voxel_density)), glm::vec3(state.look_at.value().pos.second + state.look_at.value().offset - offset * glm::llvec3(options.voxel_density)) - glm::vec3(.5 + options.tool.radius)), glm::vec3(1 + options.tool.radius * 2));
reports.models_count++;
reports.tris_count += lookBuffer.draw(lookProgram->setup(renderer, model));
reports.tris_count += renderer->drawIndicatorCube(model);
}
renderer->postProcess();
renderer->endFrame();
UI::render();
}
@ -294,7 +232,6 @@ int main(int /*unused*/, char */*unused*/[]){
glfwWindowShouldClose(window) == 0);
UI::unload();
delete lookProgram;
delete renderer;
// Close OpenGL window and terminate GLFW

52
src/model_contouring.cpp Normal file
View File

@ -0,0 +1,52 @@
/**
* \file model_contouring.cpp
* \brief Generate entities vertices
* \author Maelys Bois
* \version 0.0.1
*
* Generate ShortIndexed::Data for manually defined chunks.
*/
#include <fstream>
#include "world/generator.hpp"
#include "world/Chunk.hpp"
#include "contouring/FlatDualMC.hpp"
class Contouring: public contouring::FlatDualMC {
public:
Contouring() : FlatDualMC("iso = 0.1\nkeep_distance = 2\nload_distance = 1\nlod_levels = [ false, false, false, false, true ]\nlod_quality = 0.0\nlod_strength = 0.15\nmanifold = true\nreordering = true\ntransparency = true") { }
void render(const std::shared_ptr<world::Chunk>& chunk, buffer::LodShortIndexed::LodData& out) const {
contouring::surrounding::corners surround = {
chunk, world::EMPTY_CHUNK, world::EMPTY_CHUNK, world::EMPTY_CHUNK,
world::EMPTY_CHUNK, world::EMPTY_CHUNK, world::EMPTY_CHUNK, world::EMPTY_CHUNK
};
std::vector<buffer::VertexData> tmp;
FlatDualMC::render(surround, out, tmp);
}
};
/// Entry point
int main(int /*unused*/, char * /*unused*/[])
{
const auto generator = world::generator::load(world::generator::Void::Params());
const auto chunk = std::make_shared<world::Chunk>(chunk_pos(0), generator);
//TODO: load from file
for (auto x = 1; x <= 6; x++) {
for (auto y = 1; y <= 6; y++) {
for (auto z = 1; z <= 6; z++) {
chunk->setAt(chunk_voxel_pos(x, y, z), world::Voxel(z >= 4 ? world::materials::ROCK : world::materials::GRASS, world::Voxel::DENSITY_MAX));
}}}
buffer::LodShortIndexed::LodData data;
Contouring ct = Contouring();
ct.render(chunk, data);
assert(data.second.size() == 1 && "Must contain a single lod");
data.first.indices.resize(data.second.front()); //Discard full res
std::ofstream out("content/model.ivb");
data.first.serialize(out);
out.close();
return 0;
}

View File

@ -3,13 +3,41 @@
#include "../world/materials.hpp"
#include "../control/Camera.hpp"
Renderer::Renderer(const Renderer::options& options) {
Renderer::Renderer(const Renderer::options& options):
IndicatorCubeBuffer(GL_LINES, 24, {
glm::vec3(0, 0, 0), glm::vec3(0, 0, 1),
glm::vec3(0, 0, 1), glm::vec3(0, 1, 1),
glm::vec3(0, 1, 1), glm::vec3(0, 1, 0),
glm::vec3(0, 1, 0), glm::vec3(0, 0, 0),
glm::vec3(1, 0, 0), glm::vec3(1, 0, 1),
glm::vec3(1, 0, 1), glm::vec3(1, 1, 1),
glm::vec3(1, 1, 1), glm::vec3(1, 1, 0),
glm::vec3(1, 1, 0), glm::vec3(1, 0, 0),
glm::vec3(0, 0, 0), glm::vec3(1, 0, 0),
glm::vec3(0, 0, 1), glm::vec3(1, 0, 1),
glm::vec3(0, 1, 1), glm::vec3(1, 1, 1),
glm::vec3(0, 1, 0), glm::vec3(1, 1, 0),
}, {
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
}) {
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
MainPass = new pass::MainProgram(options.main);
SkyPass = new pass::SkyProgram();
reloadShaders(options.voxel);
SkyPass = std::make_unique<pass::SkyProgram>();
SkyEnable = options.skybox;
IndicatorPass = std::make_unique<pass::ColorProgram>();
FogColor = glm::vec3(options.clear_color.x, options.clear_color.y, options.clear_color.z);
loadTextures(options.textures, options.mipMapLOD);
@ -17,24 +45,43 @@ Renderer::Renderer(const Renderer::options& options) {
Renderer::~Renderer() {
unloadTextures();
delete MainPass;
delete SkyPass;
glDeleteVertexArrays(1, &VertexArrayID);
}
pass::Context Renderer::getPass() {
void Renderer::beginFrame() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
return pass::Context(this, MainPass);
}
void Renderer::postProcess() {
std::function<buffer::params(glm::mat4)> Renderer::beginWorldPass() {
WorldPass->useIt();
WorldPass->start(this);
return [&](glm::mat4 model) {
return WorldPass->setup(this, model);
};
}
std::function<buffer::params(const std::vector<glm::mat4> &)> Renderer::beginEntityPass() {
EntityPass->useIt();
EntityPass->start(this);
return [&](const std::vector<glm::mat4>& models) {
return EntityPass->setup(this, models);
};
}
size_t Renderer::drawIndicatorCube(glm::mat4 model) {
IndicatorPass->useIt();
return IndicatorCubeBuffer.draw(IndicatorPass->setup(this, model));
}
void Renderer::endFrame() {
if(SkyEnable) {
SkyPass->draw(this);
}
}
void Renderer::reloadShaders(const pass::MainProgram::options& options) {
delete MainPass;
MainPass = new pass::MainProgram(options);
void Renderer::reloadShaders(const pass::VoxelProgram::options& options) {
WorldPass = std::make_unique<pass::WorldProgram>(options);
EntityPass = std::make_unique<pass::EntityProgram>(options);
}
void Renderer::reloadTextures(const std::string& texturePath, float mipMapLOD) {
unloadTextures();

View File

@ -1,9 +1,13 @@
#pragma once
#include <functional>
#include <memory>
#include <GL/glew.h>
#include "pass/Context.hpp"
#include "pass/MainProgram.hpp"
#include "pass/WorldProgram.hpp"
#include "pass/EntityProgram.hpp"
#include "pass/SkyProgram.hpp"
#include "pass/ColorProgram.hpp"
#include "buffer/Colored.hpp"
class Camera;
/// Handle rendering passes and params
@ -11,8 +15,8 @@ class Renderer {
public:
/// Rendering options
struct options {
/// Main pass
pass::MainProgram::options main;
/// Voxel passes
pass::VoxelProgram::options voxel;
/// Display skybox
bool skybox = true;
/// Display only wires
@ -64,21 +68,30 @@ public:
return Skybox;
}
/// Get main pass with context
pass::Context getPass();
/// Start new frame and setup
void beginFrame();
/// Get started world program
std::function<buffer::params(glm::mat4)> beginWorldPass();
/// Get started entity program
std::function<buffer::params(const std::vector<glm::mat4>&)> beginEntityPass();
/// Draw cube indicator
size_t drawIndicatorCube(glm::mat4 model);
/// Apply postprocessing
void postProcess();
void endFrame();
/// Apply camera matrices
void lookFrom(const Camera&);
void reloadShaders(const pass::MainProgram::options &);
void reloadShaders(const pass::VoxelProgram::options &);
void reloadTextures(const std::string &, float mipMapLOD = 0);
private:
GLuint VertexArrayID;
pass::MainProgram *MainPass;
pass::SkyProgram *SkyPass;
std::unique_ptr<pass::WorldProgram> WorldPass;
std::unique_ptr<pass::EntityProgram> EntityPass;
std::unique_ptr<pass::SkyProgram> SkyPass;
std::unique_ptr<pass::ColorProgram> IndicatorPass;
buffer::Colored IndicatorCubeBuffer;
glm::mat4 ProjectionMatrix;
glm::mat4 ViewMatrix;

View File

@ -71,29 +71,29 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
{
bool changeRenderer = false;
changeRenderer |= ImGui::Checkbox("PBR", &options.renderer.main.pbr);
changeRenderer |= ImGui::Checkbox("PBR", &options.renderer.voxel.pbr);
ImGui::SameLine();
changeRenderer |= ImGui::Checkbox("Triplanar", &options.renderer.main.triplanar);
changeRenderer |= ImGui::Checkbox("Triplanar", &options.renderer.voxel.triplanar);
changeRenderer |= ImGui::Checkbox("Geometry", &options.renderer.main.geometry);
changeRenderer |= ImGui::Checkbox("Geometry", &options.renderer.voxel.geometry);
ImGui::SameLine();
if(options.renderer.main.geometry) {
changeRenderer |= ImGui::Checkbox("Blend", &options.renderer.main.blend);
if(options.renderer.voxel.geometry) {
changeRenderer |= ImGui::Checkbox("Blend", &options.renderer.voxel.blend);
} else {
ImGui::TextDisabled("Blend");
}
changeRenderer |= ImGui::Checkbox("Curvature", &options.renderer.main.curvature);
changeRenderer |= ImGui::Checkbox("Curvature", &options.renderer.voxel.curvature);
ImGui::SameLine();
if(options.renderer.main.curvature) {
changeRenderer |= ImGui::Checkbox("Depth", &options.renderer.main.curv_depth);
if(options.renderer.voxel.curvature) {
changeRenderer |= ImGui::Checkbox("Depth", &options.renderer.voxel.curv_depth);
if(ImGui::IsItemHovered())
ImGui::SetTooltip("Planets may look way bigger than expected without it");
} else {
ImGui::TextDisabled("Depth");
}
changeRenderer |= ImGui::Checkbox("Fog", &options.renderer.main.fog);
changeRenderer |= ImGui::Checkbox("Fog", &options.renderer.voxel.fog);
ImGui::SameLine();
ImGui::Checkbox("Skybox", &options.renderer.skybox);
if (changeRenderer) {

View File

@ -8,6 +8,7 @@ namespace buffer {
struct params {
/// Bind only vertices positions
bool vertexOnly;
/// Draw instanced model
size_t instances = 1;
};

View File

@ -18,14 +18,18 @@ uint Colored::draw(params params) {
} else {
enableAllAttribs();
}
glDrawArrays(Shape, 0, ElementCount);
if (params.instances == 1) {
glDrawArrays(Shape, 0, ElementCount);
} else {
glDrawArraysInstanced(Shape, 0, ElementCount, params.instances);
}
if (params.vertexOnly) {
disableVertexAttrib();
} else {
disableAllAttribs();
}
return ElementCount;
return ElementCount * params.instances;
}
void Colored::enableAllAttribs() {

View File

@ -18,12 +18,16 @@ uint LodShortIndexed::draw(buffer::params params) {
const auto start = getOffset(level);
const auto end = getOffset(level+1);
const auto count = end - start;
glDrawElements(Shape, count, GL_UNSIGNED_SHORT, (void *)(start*sizeof(GLushort)));
if (params.instances == 1) {
glDrawElements(Shape, count, GL_UNSIGNED_SHORT, (void *)(start*sizeof(GLushort)));
} else {
glDrawElementsInstanced(Shape, count, GL_UNSIGNED_SHORT, (void *)(start*sizeof(GLushort)), params.instances);
}
if(params.vertexOnly) {
disableVertexAttrib();
} else {
disableAllAttribs();
}
return count;
return count * params.instances;
}

View File

@ -6,6 +6,28 @@
using namespace buffer;
ShortIndexed::Data::Data(const std::vector<PackedVertexData> &vs, const std::vector<GLushort> &indices): indices(indices), vertices(vs) { }
ShortIndexed::Data::Data(std::ifstream& in) {
{
size_t i_size;
in.read(reinterpret_cast<char *>(&i_size), sizeof(i_size));
indices.resize(i_size);
in.read(reinterpret_cast<char *>(indices.data()), sizeof(GLushort) * i_size);
}
size_t v_size;
in.read(reinterpret_cast<char *>(&v_size), sizeof(v_size));
vertices.resize(v_size, PackedVertexData(0, 0, 0, 0, 0, 0, 0, 0));
in.read(reinterpret_cast<char *>(vertices.data()), sizeof(buffer::PackedVertexData) * v_size);
}
void ShortIndexed::Data::serialize(std::ofstream& out) {
{
size_t i_size = indices.size();
out.write(reinterpret_cast<char *>(&i_size), sizeof(i_size));
out.write(reinterpret_cast<char *>(indices.data()), sizeof(GLushort) * i_size);
}
size_t v_size = vertices.size();
out.write(reinterpret_cast<char *>(&v_size), sizeof(v_size));
out.write(reinterpret_cast<char *>(vertices.data()), sizeof(buffer::PackedVertexData) * v_size);
}
void ShortIndexed::Data::index(const std::vector<PackedVertexData>& vs) {
indexVBO(vs, indices, vertices);
}
@ -78,14 +100,18 @@ uint ShortIndexed::draw(buffer::params params) {
enableAllAttribs();
}
enableIndex();
glDrawElements(Shape, IndexSize, GL_UNSIGNED_SHORT, (void *)0);
if (params.instances == 1) {
glDrawElements(Shape, IndexSize, GL_UNSIGNED_SHORT, (void *)0);
} else {
glDrawElementsInstanced(Shape, IndexSize, GL_UNSIGNED_SHORT, (void *)0, params.instances);
}
if(params.vertexOnly) {
disableVertexAttrib();
} else {
disableAllAttribs();
}
return IndexSize;
return IndexSize * params.instances;
}
void ShortIndexed::setData(const ShortIndexed::Data& data) {

View File

@ -3,6 +3,7 @@
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <vector>
#include <fstream>
#include "Abstract.hpp"
#include "VertexData.hpp"
@ -19,6 +20,7 @@ namespace buffer {
Data() { }
Data(const std::vector<PackedVertexData> &vertices, const std::vector<GLushort> &indices);
Data(const std::vector<PackedVertexData> &vertices) { index(vertices); }
Data(std::ifstream &in);
void index(const std::vector<PackedVertexData> &vertices);
bool empty() const {
@ -28,6 +30,8 @@ namespace buffer {
indices.clear();
vertices.clear();
}
void serialize(std::ofstream &out);
};
ShortIndexed(GLenum shape, const typename std::vector<PackedVertexData> &vertices);

View File

@ -20,7 +20,6 @@ ColorProgram::~ColorProgram() { }
std::string ColorProgram::getName() const {
return "Color";
}
void ColorProgram::start(Renderer *) { }
buffer::params ColorProgram::setup(Renderer *renderer, glm::mat4 modelMatrix) {
const auto mvp = renderer->getProjectionMatrix() * renderer->getViewMatrix() * modelMatrix;
setMVP(&mvp[0][0]);

View File

@ -9,10 +9,10 @@ namespace pass {
ColorProgram();
~ColorProgram();
std::string getName() const override;
void start(Renderer *) override;
buffer::params setup(Renderer *, glm::mat4 modelMatrix) override;
buffer::params setup(Renderer *, glm::mat4 modelMatrix);
protected:
std::string getName() const override;
void setMVP(const GLfloat *matrix);
private:

View File

@ -1,15 +0,0 @@
#include "Context.hpp"
#include "../Renderer.hpp"
using namespace pass;
Context::Context(Renderer* Renderer, Program *Program):
renderer(Renderer), program(Program) { }
void Context::start() {
program->useIt();
program->start(renderer);
}
buffer::params Context::setup(glm::mat4 modelMatrix) {
return program->setup(renderer, modelMatrix);
}

View File

@ -1,23 +0,0 @@
#pragma once
#include "../buffer/Abstract.hpp"
#include <glm/glm.hpp>
class Renderer;
namespace pass {
class Program;
/// Program execution container
struct Context {
public:
Context(Renderer *Renderer, Program *Program);
/// Prepare for multiple draw
void start();
/// Prepare for specific draw
buffer::params setup(glm::mat4 modelMatrix);
private:
Renderer *renderer;
Program *program;
};
}

View File

@ -0,0 +1,45 @@
#include "EntityProgram.hpp"
#include "../Renderer.hpp"
using namespace pass;
EntityProgram::EntityProgram(const EntityProgram::options& opts): VoxelProgram(opts, {"INSTANCED"}) {
ModelsBufferID = 0;
}
EntityProgram::~EntityProgram() { }
buffer::params EntityProgram::setup(Renderer *renderer, const std::vector<glm::mat4>& modelsMatrices) {
setModels(&modelsMatrices[0][0][0], modelsMatrices.size());
auto params = VoxelProgram::setup(renderer);
params.instances = modelsMatrices.size();
return params;
}
void EntityProgram::setModels(const GLfloat *matrices, size_t count) {
if (ModelsBufferID != 0) { //MAYBE: writable buffer
glDeleteBuffers(1, &ModelsBufferID);
}
glGenBuffers(1, &ModelsBufferID);
glBindBuffer(GL_ARRAY_BUFFER, ModelsBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * count, matrices, GL_STATIC_DRAW);
glEnableVertexAttribArray(LOCATION + 0);
glVertexAttribPointer(LOCATION + 0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(glm::vec4), (void *)0);
glVertexAttribDivisor(LOCATION + 0, 1);
glEnableVertexAttribArray(LOCATION + 1);
glVertexAttribPointer(LOCATION + 1, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(glm::vec4), (void *)(1 * sizeof(glm::vec4)));
glVertexAttribDivisor(LOCATION + 1, 1);
glEnableVertexAttribArray(LOCATION + 2);
glVertexAttribPointer(LOCATION + 2, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(glm::vec4), (void *)(2 * sizeof(glm::vec4)));
glVertexAttribDivisor(LOCATION + 2, 1);
glEnableVertexAttribArray(LOCATION + 3);
glVertexAttribPointer(LOCATION + 3, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(glm::vec4), (void *)(3 * sizeof(glm::vec4)));
glVertexAttribDivisor(LOCATION + 3, 1);
}
void EntityProgram::disable() {
glDisableVertexAttribArray(LOCATION + 0);
glDisableVertexAttribArray(LOCATION + 1);
glDisableVertexAttribArray(LOCATION + 2);
glDisableVertexAttribArray(LOCATION + 3);
}

View File

@ -0,0 +1,23 @@
#pragma once
#include "VoxelProgram.hpp"
namespace pass {
/// Instanced voxels pass
class EntityProgram: public VoxelProgram {
public:
EntityProgram(const options &opts);
~EntityProgram();
static constexpr auto LOCATION = 6;
buffer::params setup(Renderer *, const std::vector<glm::mat4> &modelsMatrices);
void disable();
protected:
void setModels(const GLfloat *matrices, size_t count);
private:
GLuint ModelsBufferID;
};
}

View File

@ -69,7 +69,4 @@ GLuint Program::loadTextureCube(const std::string &name) {
std::transform(faces.begin(), faces.end(), paths.begin(),
[name](const std::string &face) -> std::string { return TEXTURES_DIR + name + ".cube." + face + ".dds"; });
return loadDDSCube(paths);
}
GLuint Program::loadRawTexture(const std::string& name) {
return loadBMP_custom(name.c_str());
}

View File

@ -18,21 +18,18 @@ namespace pass {
/// Bind program
void useIt();
virtual std::string getName() const = 0;
/// Prepare for multiple draw
virtual void start(Renderer*) = 0;
/// Prepare for specific draw
virtual buffer::params setup(Renderer*, glm::mat4 modelMatrix) = 0;
static GLuint loadTexture(const std::string &name, bool linear = true);
static GLuint loadRawTexture(const std::string &name);
static GLuint loadTextureArray(const std::vector<std::string> &names, const std::string &suffix = "", float mipMapLOD = 0);
static GLuint loadTextureCube(const std::string &name);
protected:
/// Get shaders name prefix
virtual std::string getName() const = 0;
Shader *loadShader(GLenum type, const std::vector<std::string> &flags = {});
void load(const std::vector<Shader *> &shaders);
virtual Shader *loadShader(GLenum type, const std::vector<std::string> &flags = {});
GLuint ProgramID;
};
}

View File

@ -72,13 +72,13 @@ void SkyProgram::start(Renderer *renderer) {
bindTexture(renderer->getSkyTexture());
}
buffer::params SkyProgram::setup(Renderer *, glm::mat4) {
buffer::params SkyProgram::setup() {
return buffer::params{.vertexOnly = true};
}
void SkyProgram::draw(Renderer *renderer) {
useIt();
start(renderer);
CubeBuffer.draw(setup(renderer, glm::mat4(1)));
CubeBuffer.draw(setup());
}
void SkyProgram::setView(const GLfloat *matrix) {

View File

@ -10,13 +10,14 @@ namespace pass {
SkyProgram();
~SkyProgram();
std::string getName() const override;
void start(Renderer *) override;
buffer::params setup(Renderer *, glm::mat4 modelMatrix) override;
void start(Renderer *);
buffer::params setup();
/// Direct draw using internal buffer
void draw(Renderer *);
protected:
std::string getName() const override;
void setView(const GLfloat *matrix);
void setProjection(const GLfloat *matrix);

View File

@ -9,8 +9,8 @@ namespace pass {
UIProgram();
~UIProgram();
protected:
std::string getName() const override;
void bindTexture(GLuint textureID);
private:

View File

@ -1,12 +1,11 @@
#include "MainProgram.hpp"
#include "VoxelProgram.hpp"
#include "../Renderer.hpp"
using namespace pass;
MainProgram::MainProgram(const MainProgram::options& opts): Program() {
VoxelProgram::VoxelProgram(const VoxelProgram::options& opts, std::vector<std::string> flags): Program() {
std::vector<std::string> flags;
if(opts.pbr)
flags.emplace_back("PBR");
if(opts.triplanar)
@ -31,7 +30,6 @@ MainProgram::MainProgram(const MainProgram::options& opts): Program() {
shaders.push_back(loadShader(GL_GEOMETRY_SHADER, flags));
load(shaders);
ModelMatrixID = glGetUniformLocation(ProgramID, "Model");
ViewMatrixID = glGetUniformLocation(ProgramID, "View");
ProjMatrixID = glGetUniformLocation(ProgramID, "Proj");
@ -41,19 +39,19 @@ MainProgram::MainProgram(const MainProgram::options& opts): Program() {
LightInvDirID = glGetUniformLocation(ProgramID, "LightInvDirection_worldspace");
FogDepthID = glGetUniformLocation(ProgramID, "FogDepth");
FogDepthID = glGetUniformLocation(ProgramID, "FogDepth"); //MAYBE: merge as vec4
FogColorID = glGetUniformLocation(ProgramID, "FogColor");
SphereProjID = glGetUniformLocation(ProgramID, "SphereProj");
CurvatureID = glGetUniformLocation(ProgramID, "Curvature");
}
MainProgram::~MainProgram() { }
VoxelProgram::~VoxelProgram() { }
std::string MainProgram::getName() const {
return "Main";
std::string VoxelProgram::getName() const {
return "Voxel";
}
void MainProgram::start(Renderer *renderer) {
void VoxelProgram::start(Renderer *renderer) {
bindTexture(renderer->getTextureAtlas());
bindNormal(renderer->getNormalAtlas());
bindHOS(renderer->getHOSAtlas());
@ -62,50 +60,46 @@ void MainProgram::start(Renderer *renderer) {
setView(&renderer->getViewMatrix()[0][0]);
setProj(&renderer->getProjectionMatrix()[0][0]);
}
buffer::params MainProgram::setup(Renderer *renderer, glm::mat4 modelMatrix) {
setModel(&modelMatrix[0][0]);
buffer::params VoxelProgram::setup(Renderer *renderer) {
setSphereProj(&renderer->SphereProj[0]);
setCurvature(renderer->Curvature);
return buffer::params{.vertexOnly = false};
}
void MainProgram::setProj(const GLfloat *matrix) {
void VoxelProgram::setProj(const GLfloat *matrix) {
glUniformMatrix4fv(ProjMatrixID, 1, GL_FALSE, matrix);
}
void MainProgram::setModel(const GLfloat *matrix) {
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, matrix);
}
void MainProgram::setView(const GLfloat *matrix) {
void VoxelProgram::setView(const GLfloat *matrix) {
glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, matrix);
}
void MainProgram::bindTexture(GLuint textureID) {
void VoxelProgram::bindTexture(GLuint textureID) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, textureID);
glUniform1i(TextureID, 0);
}
void MainProgram::bindNormal(GLuint textureID) {
void VoxelProgram::bindNormal(GLuint textureID) {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D_ARRAY, textureID);
glUniform1i(NormalID, 1);
}
void MainProgram::bindHOS(GLuint textureID) {
void VoxelProgram::bindHOS(GLuint textureID) {
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D_ARRAY, textureID);
glUniform1i(HOSID, 2);
}
void MainProgram::setLightInvDir(const GLfloat *pos) {
void VoxelProgram::setLightInvDir(const GLfloat *pos) {
glUniform3fv(LightInvDirID, 1, pos);
}
void MainProgram::setFog(const GLfloat *color, const GLfloat depth) {
void VoxelProgram::setFog(const GLfloat *color, const GLfloat depth) {
glUniform3fv(FogColorID, 1, color);
glUniform1f(FogDepthID, depth);
}
void MainProgram::setSphereProj(const GLfloat *posRad) {
void VoxelProgram::setSphereProj(const GLfloat *posRad) {
glUniform4fv(SphereProjID, 1, posRad);
}
void MainProgram::setCurvature(GLfloat ratio) {
void VoxelProgram::setCurvature(GLfloat ratio) {
glUniform1f(CurvatureID, ratio);
}

View File

@ -3,8 +3,8 @@
#include "Program.hpp"
namespace pass {
/// World voxels pass
class MainProgram: public Program {
/// Abstract voxels pass
class VoxelProgram: public Program {
public:
/// Pass options
struct options {
@ -24,14 +24,15 @@ namespace pass {
bool curv_depth = true;
};
MainProgram(const options &opts);
~MainProgram();
VoxelProgram(const options &opts, std::vector<std::string> flags = {});
~VoxelProgram();
void start(Renderer *);
protected:
buffer::params setup(Renderer *);
std::string getName() const override;
void start(Renderer *) override;
buffer::params setup(Renderer *, glm::mat4 modelMatrix) override;
void setModel(const GLfloat *matrix);
void setView(const GLfloat *matrix);
void setProj(const GLfloat *matrix);
@ -46,7 +47,6 @@ namespace pass {
void setCurvature(GLfloat ratio);
private:
GLuint ModelMatrixID;
GLuint ViewMatrixID;
GLuint ProjMatrixID;

View File

@ -0,0 +1,21 @@
#include "WorldProgram.hpp"
#include "../Renderer.hpp"
using namespace pass;
WorldProgram::WorldProgram(const WorldProgram::options& opts): VoxelProgram(opts) {
ModelMatrixID = glGetUniformLocation(ProgramID, "Model");
}
WorldProgram::~WorldProgram() { }
buffer::params WorldProgram::setup(Renderer *renderer, glm::mat4 modelMatrix) {
setModel(&modelMatrix[0][0]);
return VoxelProgram::setup(renderer);
}
void WorldProgram::setModel(const GLfloat *matrix) {
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, matrix);
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "VoxelProgram.hpp"
namespace pass {
/// Unique voxels pass
class WorldProgram: public VoxelProgram {
public:
WorldProgram(const options &opts);
~WorldProgram();
buffer::params setup(Renderer *, glm::mat4 modelMatrix);
protected:
void setModel(const GLfloat *matrix);
private:
GLuint ModelMatrixID;
};
}

View File

@ -11,120 +11,6 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
GLuint loadBMP_custom(const char * imagepath){
printf("Reading image %s\n", imagepath);
// Data read from the header of the BMP file
unsigned char header[54];
unsigned int dataPos;
unsigned int imageSize;
unsigned int width, height;
// Actual RGB data
unsigned char * data;
// Open the file
FILE * file = fopen(imagepath,"rb");
if (!file){
printf("%s could not be opened.\n", imagepath);
getchar();
return 0;
}
// Read the header, i.e. the 54 first bytes
// If less than 54 bytes are read, problem
if ( fread(header, 1, 54, file)!=54 ){
printf("Not a correct BMP file\n");
fclose(file);
return 0;
}
// A BMP files always begins with "BM"
if ( header[0]!='B' || header[1]!='M' ){
printf("Not a correct BMP file\n");
fclose(file);
return 0;
}
// Make sure this is a 24bpp file
if ( *(int*)&(header[0x1E])!=0 ) {printf("Not a correct BMP file\n"); fclose(file); return 0;}
if ( *(int*)&(header[0x1C])!=24 ) {printf("Not a correct BMP file\n"); fclose(file); return 0;}
// Read the information about the image
dataPos = *(int*)&(header[0x0A]);
imageSize = *(int*)&(header[0x22]);
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
// Some BMP files are misformatted, guess missing information
if (imageSize==0) imageSize=width*height*3; // 3 : one byte for each Red, Green and Blue component
if (dataPos==0) dataPos=54; // The BMP header is done that way
// Create a buffer
data = new unsigned char [imageSize];
// Read the actual data from the file into the buffer
fread(data,1,imageSize,file);
// Everything is in memory now, the file can be closed.
fclose (file);
// Create one OpenGL texture
GLuint textureID;
glGenTextures(1, &textureID);
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, textureID);
// Give the image to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
// OpenGL has now copied the data. Free our own version
delete [] data;
// Poor filtering, or ...
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// ... nice trilinear filtering ...
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// ... which requires mipmaps. Generate them automatically.
glGenerateMipmap(GL_TEXTURE_2D);
// Return the ID of the texture we just created
return textureID;
}
// Since GLFW 3, glfwLoadTexture2D() has been removed. You have to use another texture loading library,
// or do it yourself (just like loadBMP_custom and loadDDS)
//GLuint loadTGA_glfw(const char * imagepath){
//
// // Create one OpenGL texture
// GLuint textureID;
// glGenTextures(1, &textureID);
//
// // "Bind" the newly created texture : all future texture functions will modify this texture
// glBindTexture(GL_TEXTURE_2D, textureID);
//
// // Read the file, call glTexImage2D with the right parameters
// glfwLoadTexture2D(imagepath, 0);
//
// // Nice trilinear filtering.
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// glGenerateMipmap(GL_TEXTURE_2D);
//
// // Return the ID of the texture we just created
// return textureID;
//}
#define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII
#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
#define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII

View File

@ -1,18 +1,12 @@
#ifndef TEXTURE_HPP
#define TEXTURE_HPP
#pragma once
#include <string.h>
#include <vector>
#include <array>
// Load a .BMP file using our custom loader
GLuint loadBMP_custom(const char * imagepath);
// Load a .DDS file using GLFW's own loader
GLuint loadDDS(const std::string& imagepath, bool linear = true);
// Load a list of .DDS files
GLuint loadDDSArray(const std::vector<std::string> &imagepaths, float mipMapLOD = 0);
// Load a .DDS cubemap
GLuint loadDDSCube(const std::array<std::string, 6> &imagepaths);
#endif

View File

@ -39,11 +39,11 @@ struct options {
renderer.textures = config["render"]["textures"].value_or(renderer.textures);
renderer.mipMapLOD = config["render"]["texture_quality"].value_or(renderer.mipMapLOD);
renderer.main.pbr = config["render"]["pbr"].value_or(renderer.main.pbr);
renderer.main.triplanar = config["render"]["triplanar"].value_or(renderer.main.triplanar);
renderer.main.geometry = config["render"]["geometry"].value_or(renderer.main.geometry);
renderer.main.blend = config["render"]["blend"].value_or(renderer.main.blend);
renderer.main.fog = config["render"]["fog"].value_or(renderer.main.fog);
renderer.voxel.pbr = config["render"]["pbr"].value_or(renderer.voxel.pbr);
renderer.voxel.triplanar = config["render"]["triplanar"].value_or(renderer.voxel.triplanar);
renderer.voxel.geometry = config["render"]["geometry"].value_or(renderer.voxel.geometry);
renderer.voxel.blend = config["render"]["blend"].value_or(renderer.voxel.blend);
renderer.voxel.fog = config["render"]["fog"].value_or(renderer.voxel.fog);
const std::string fog = config["render"]["fog_color"].value_or(std::string{"#000000"});
renderer.clear_color = fromHex(fog);
renderer.skybox = config["render"]["skybox"].value_or(renderer.skybox);
@ -91,11 +91,11 @@ struct options {
config.insert_or_assign("render", toml::table({
{"textures", renderer.textures},
{"texture_quality", renderer.mipMapLOD},
{"pbr", renderer.main.pbr},
{"triplanar", renderer.main.triplanar},
{"geometry", renderer.main.geometry},
{"blend", renderer.main.blend},
{"fog", renderer.main.fog},
{"pbr", renderer.voxel.pbr},
{"triplanar", renderer.voxel.triplanar},
{"geometry", renderer.voxel.geometry},
{"blend", renderer.voxel.blend},
{"fog", renderer.voxel.fog},
{"fog_color", toHexa(renderer.clear_color)},
{"skybox", renderer.skybox}
}));

View File

@ -7,6 +7,8 @@
#include "../contouring/Dummy.hpp"
#include "Chunk.hpp"
#include "../render/buffer/ShortIndexed.hpp"
using namespace world;
const auto AREAS_FILE = "/areas.idx";
@ -56,7 +58,16 @@ Universe::Universe(const Universe::options &options): dicts("content/zstd.dict"
index.close();
}
entities.emplace(nullptr, glm::vec3(1), glm::vec3(2)); //TODO: use contouring to load models
{
std::ifstream ivb("content/model.ivb");
if(ivb.good()) {
buffer::ShortIndexed::Data data(ivb);
entities.emplace(new buffer::ShortIndexed(GL_TRIANGLES, data), glm::vec3(1), glm::vec3(2));
} else {
LOG_E("No model file!!! Please run render_models");
}
ivb.close();
}
// Workers
for (size_t i = 0; i < std::thread::hardware_concurrency() / 2 - 1; i++) {

View File

@ -105,7 +105,7 @@ namespace world::generator {
if (heightRatio >= 0) {
return Voxel(materials::AIR, (heightRatio < params.surface_roughness) * Voxel::DENSITY_MAX);
} else {
return Voxel(materials::WATER, Voxel::DENSITY_MAX);
return Voxel(materials::WATER, std::clamp(-heightRatio * params.height, 0.f, 1.f) * Voxel::DENSITY_MAX);
}
}
}();
@ -113,7 +113,7 @@ namespace world::generator {
}
private:
static constexpr PlanetShape shape = PS;
static constexpr voxel_pos::value_type getHeight(const voxel_pos &p) {
static constexpr glm::f64 getHeight(const voxel_pos &p) {
if constexpr(shape == PlanetShape::Cube) {
return glm::max_axis(glm::abs(p));
} else {