yupplemayham/YuppleMayham/src/graphics/instancedraw.cpp
2025-01-28 16:07:58 -05:00

129 lines
4.1 KiB
C++

#include "graphics/instancedraw.h"
#include "graphics/texture.h"
#include <glad/glad.h>
#include <iostream>
TileTextureInstance::TileTextureInstance(const char* texturePath)
{
texture = new Texture();
texture->loadTexture(texturePath);
if (texture)
setup();
}
TileTextureInstance::TileTextureInstance(const std::vector<const char*> texturePaths)
{
textures = new TextureArray();
if (textures->loadTextures(texturePaths))
setup();
}
void TileTextureInstance::setup()
{
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &instanceVBO);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(InstanceData) * MAX_INSTANCES, nullptr, GL_DYNAMIC_DRAW);
// tileIndex instanceData layout position 2
glVertexAttribIPointer(2, 1, GL_INT, sizeof(InstanceData), (void*)(offsetof(InstanceData, tileIndex)));
glEnableVertexAttribArray(2);
glVertexAttribDivisor(2, 1);
// textureIndex instanceData layout position 3 -> We are using multiple textures to hold each tileset
glVertexAttribIPointer(3, 1, GL_INT, sizeof(InstanceData), (void*)(offsetof(InstanceData, textureIndex)));
glEnableVertexAttribArray(3);
glVertexAttribDivisor(3, 1);
// tilesPerRow instanceData layout position 4, This is needed since we are supporting multiple tilesets
// of different sizes
glVertexAttribIPointer(4, 1, GL_INT, sizeof(InstanceData), (void*)(offsetof(InstanceData, tilesPerRow)));
glEnableVertexAttribArray(4);
glVertexAttribDivisor(4, 1);
// startID instanceData layout position 5
glVertexAttribIPointer(5, 1, GL_INT, sizeof(InstanceData), (void*)(offsetof(InstanceData, startID)));
glEnableVertexAttribArray(5);
glVertexAttribDivisor(5, 1);
// originalSize instanceData layout position 6
glVertexAttribPointer(6, 2, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (void*)(offsetof(InstanceData, originalSize)));
glEnableVertexAttribArray(6);
glVertexAttribDivisor(6, 1);
// modelMatrix instanceData as 4 vec 4s (a 4x4 matrix) layout head position 7
for (int i = 0; i < 4; i++)
{
glVertexAttribPointer(7 + i, 4, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (void*)(offsetof(InstanceData, modelMatrix) + (sizeof(glm::vec4) * i)));
glEnableVertexAttribArray(7 + i);
glVertexAttribDivisor(7 + i, 1);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void TileTextureInstance::updateInstanceData(const std::vector<InstanceData>& instanceData)
{
if (instanceData.empty())
return;
numOfInstances = instanceData.size();
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
InstanceData* instances = (InstanceData*)glMapBufferRange(GL_ARRAY_BUFFER, 0,
sizeof(InstanceData) * instanceData.size(),
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
if (!instances)
return;
if (instances)
{
std::memcpy(instances, instanceData.data(), sizeof(InstanceData) * instanceData.size());
glUnmapBuffer(GL_ARRAY_BUFFER);
}
/*
for (int i = 0; i < instanceData.size(); i++)
{
instances[i].modelMatrix = instanceData[i].modelMatrix;
instances[i].originalSize = instanceData[i].originalSize;
instances[i].tileIndex = instanceData[i].tileIndex;
instances[i].textureIndex = instanceData[i].textureIndex;
instances[i].tilesPerRow = instanceData[i].tilesPerRow;
instances[i].startID = instanceData[i].startID;
}
*/
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void TileTextureInstance::draw()
{
// bind textures
if (texture)
texture->bind();
else if (textures)
textures->bind();
glBindVertexArray(VAO);
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr, numOfInstances);
glBindVertexArray(0);
}