Instancing - Goutch/HellbenderEngine GitHub Wiki
VertexShader.vert
#version 450
//binding=0 vertices
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec2 inTexCoord;
layout(location = 1) out vec2 fragTexCoord;
//binding=1 instanced
layout(location = 2) in mat4 inInstanceTransforms;
//uniforms
layout(binding = 0) uniform UniformBufferObject {
mat4 view;
mat4 projection;
} ubo;
void main() {
gl_Position = ubo.projection * ubo.view * inInstanceTransforms * vec4(inPosition, 1.0);
fragTexCoord = inTexCoord;
}
FragmentShader.frag
#version 450
layout(location = 0) out vec4 outColor;
layout(location = 1) in vec2 fragTexCoord;
void main() {
outColor=vec4(fragTexCoord,0.0,1.0);
}
main.cpp
#include "HBE.h"
using namespace HBE;
void onAppUpdate(float delta) {
//Shut down app if escape key is pressed
if (Input::getKeyDown(KEY::ESCAPE)) {
Application::quit();
}
//change vertical sync if V key is pressed
if (Input::getKeyDown(KEY::V)) {
Configs::setVerticalSync(!Configs::getVerticalSync());
}
}
void init() {
//-------------------RESOURCES CREATION--------------------------------------
ShaderInfo frag_info{SHADER_STAGE_FRAGMENT, "../../res/shaders/FragmentShader.frag"};
ShaderInfo vert_info{SHADER_STAGE_VERTEX, "../../res/shaders/VertexShader.vert"};
auto frag = Resources::createShader(frag_info, "frag");
auto vert = Resources::createShader(vert_info, "vert");
std::vector<VertexBindingInfo> binding_infos;
//vertex binding
binding_infos.emplace_back();
binding_infos[0].binding = 0;
binding_infos[0].size = sizeof(vec3) + sizeof(vec2);
//instance binding
binding_infos.emplace_back();
binding_infos[1].binding = 1;
binding_infos[1].size = sizeof(mat4);
binding_infos[1].flags = VERTEX_BINDING_FLAG_PER_INSTANCE |
VERTEX_BINDING_FLAG_FAST_WRITE |//Use host visible memory.
VERTEX_BINDING_FLAG_MULTIPLE_BUFFERS;//We are updating this binding every frame so we need multiple buffers.
GraphicPipelineInfo pipeline_info{};
pipeline_info.binding_infos = binding_infos.data();
pipeline_info.binding_info_count = binding_infos.size();
pipeline_info.fragement_shader = frag;
pipeline_info.vertex_shader = vert;
pipeline_info.flags = GRAPHIC_PIPELINE_FLAG_CULL_BACK;
auto pipeline = Resources::createGraphicPipeline(pipeline_info, "pipeline");
MeshInfo mesh_info{};
mesh_info.binding_infos = binding_infos.data();
mesh_info.binding_info_count = binding_infos.size();
mesh_info.flags = MESH_FLAG_NONE;
auto mesh = Resources::createMesh(mesh_info, "mesh");
Geometry::createCube(*mesh, 1, 1, 1, VERTEX_FLAG_UV);
//-------------------SCENE CREATION--------------------------------------
Scene &scene = *(new Scene());
Application::setScene(&scene, true);
Entity camera_entity = scene.createEntity("camera");
Camera &camera = camera_entity.attach<Camera>();
camera.render_target = Graphics::getDefaultRenderTarget();
camera_entity.attach<CameraController>();
scene.setCameraEntity(camera_entity);
int32_t range = 5; //10*10*10 = 1000 cubes
for (int i = -range; i < range; ++i) {
for (int j = -range; j < range; ++j) {
for (int k = -range; k < range; ++k) {
Entity cube_entity = scene.createEntity();
auto &renderer = cube_entity.attach<InstancedRenderer>();
renderer.pipeline = pipeline;
renderer.mesh = mesh;
cube_entity.get<Transform>().translate(vec3(i, j, k) * 2.0f);
}
}
}
}
int main() {
Application::init();
//-----------------------SETUP--------------------
Configs::setWindowTitle("Hellbender");
init();
//-----------------------EVENTS------------------
Application::onUpdate.subscribe(&onAppUpdate);
//-----------------------LOOP--------------------
Application::run();
//-----------------------CLEANUP------------------
Application::onUpdate.unsubscribe(&onAppUpdate);
//-----------------------TERMINATE------------------
Application::terminate();
}