Commit 3b4e9fd9 authored by Shu's avatar Shu 🍠
Browse files

Entities instancing

parent 4066bf90
......@@ -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")
\ No newline at end of file
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")
\ No newline at end of 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
......
......@@ -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
}
}
\ No newline at end of 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
......
......@@ -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>
......
......@@ -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
......
/**
* \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;
}
\ No newline at end of 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();
......
#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;
}
\ No newline at end of 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();