Entities instancing
This commit is contained in:
parent
4066bf90b9
commit
3b4e9fd940
|
@ -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")
|
4
TODO.md
4
TODO.md
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
|
|
@ -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>
|
||||
|
|
85
src/main.cpp
85
src/main.cpp
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace buffer {
|
|||
struct params {
|
||||
/// Bind only vertices positions
|
||||
bool vertexOnly;
|
||||
/// Draw instanced model
|
||||
size_t instances = 1;
|
||||
};
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -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());
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ namespace pass {
|
|||
UIProgram();
|
||||
~UIProgram();
|
||||
|
||||
protected:
|
||||
std::string getName() const override;
|
||||
|
||||
void bindTexture(GLuint textureID);
|
||||
|
||||
private:
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
20
src/state.h
20
src/state.h
|
@ -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}
|
||||
}));
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue