Dicewars-Siedler/src/engine/renderer/WorldSpriteRenderer.cpp
2026-02-15 10:08:02 +01:00

101 lines
3.2 KiB
C++

//
// Created by sebastian on 14.02.26.
//
#include "WorldSpriteRenderer.h"
#include <vector>
#include "../layer/entities/Camera.h"
#include "../toolbox/MathUtils.h"
#include "glm/ext/matrix_transform.hpp"
#include "loader/Loader.h"
WorldSpriteRenderer::WorldSpriteRenderer(const glm::mat4& projectionMatrix) : projectionMatrix(projectionMatrix) {
std::vector<float> positions = {
-0.5f, 0.5f, 0.0f, // oben links
-0.5f, -0.5f, 0.0f, // unten links
0.5f, 0.5f, 0.0f, // oben rechts
0.5f, -0.5f, 0.0f // unten rechts
};
std::vector<float> uvs = {
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
std::vector<int> indices = {
0, 1, 2,
2, 1, 3
};
quadModel = std::make_unique<RawModel>(Loader::instance().loadToVAO(positions, uvs, indices));
}
void WorldSpriteRenderer::prepare(const Camera &camera) {
glm::mat4 viewMatrix = MathUtils::createViewMatrix(camera);
glm::mat4 projectionViewMatrix = projectionMatrix * viewMatrix;
worldSpriteShader.start();
worldSpriteShader.loadProjectionViewMatrix(projectionViewMatrix);
}
void WorldSpriteRenderer::render(std::unordered_map<ModelTexture*, std::vector<WorldSpriteRenderingData>> worldSprites, const Camera &camera) {
glDepthMask(false);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (auto& batch : worldSprites) {
glBindTexture(GL_TEXTURE_2D, batch.first->getTextureID());
for (auto& sprite : batch.second) {
glm::mat4 model = buildWorldSpriteMatrix(*sprite.worldSpriteTransform, *sprite.worldSpriteComponent, camera);
worldSpriteShader.loadModelMatrix(model);
worldSpriteShader.loadAlpha(sprite.worldSpriteComponent->alpha);
glBindVertexArray(quadModel->vaoID);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawElements(GL_TRIANGLES, quadModel->vertexCount, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindVertexArray(0);
}
}
glDepthMask(true);
glDisable(GL_BLEND);
}
void WorldSpriteRenderer::finalize() {
worldSpriteShader.stop();
}
glm::mat4 WorldSpriteRenderer::buildWorldSpriteMatrix(const TransformComponent &objectTransform,
const WorldSpriteComponent &worldSpriteComponent,
const Camera &camera
) {
glm::vec3 worldPos = objectTransform.position + worldSpriteComponent.offset;
auto model = glm::identity<glm::mat4>();
//Transform
model = glm::translate(model, worldPos);
//Billboard (nur y Achse)
if (worldSpriteComponent.billboard) {
glm::vec3 camPos = camera.getPosition();
glm::vec3 direction = camPos - worldPos;
direction.y = 0.0f;
direction = glm::normalize(direction);
float angle = std::atan2(direction.x, direction.z);
model = glm::rotate(model, angle, glm::vec3(0, 1, 0));
}
//Scale
model = glm::scale(model, glm::vec3(worldSpriteComponent.scale.x, worldSpriteComponent.scale.y, 1.0f));
return model;
}