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();

}
⚠️ **GitHub.com Fallback** ⚠️