113 lines
4.2 KiB
C++
113 lines
4.2 KiB
C++
/*
|
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
*/
|
|
|
|
#include <nostalgia/core/consts.hpp>
|
|
#include <nostalgia/core/ptidxconv.hpp>
|
|
#include "tilesheeteditormodel.hpp"
|
|
#include "tilesheetpixels.hpp"
|
|
|
|
namespace nostalgia::core {
|
|
|
|
TileSheetPixels::TileSheetPixels(TileSheetEditorModel *model) noexcept: m_model(model) {
|
|
}
|
|
|
|
void TileSheetPixels::setPixelSizeMod(float sm) noexcept {
|
|
m_pixelSizeMod = sm;
|
|
}
|
|
|
|
ox::Error TileSheetPixels::buildShader() noexcept {
|
|
const auto Vshad = ox::sfmt(VShad, glutils::GlslVersion);
|
|
const auto Fshad = ox::sfmt(FShad, glutils::GlslVersion);
|
|
return glutils::buildShaderProgram(Vshad, Fshad).moveTo(&m_shader);
|
|
}
|
|
|
|
void TileSheetPixels::draw(bool update, const geo::Vec2 &scroll) noexcept {
|
|
glUseProgram(m_shader);
|
|
glBindVertexArray(m_bufferSet.vao);
|
|
if (update) {
|
|
glutils::sendVbo(m_bufferSet);
|
|
}
|
|
const auto uniformScroll = glGetUniformLocation(m_shader, "vScroll");
|
|
glUniform2f(uniformScroll, scroll.x, scroll.y);
|
|
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_bufferSet.elements.size()), GL_UNSIGNED_INT, nullptr);
|
|
}
|
|
|
|
void TileSheetPixels::initBufferSet(const geo::Vec2 &paneSize) noexcept {
|
|
// vao
|
|
m_bufferSet.vao = glutils::generateVertexArrayObject();
|
|
glBindVertexArray(m_bufferSet.vao);
|
|
// vbo & ebo
|
|
m_bufferSet.vbo = glutils::generateBuffer();
|
|
m_bufferSet.ebo = glutils::generateBuffer();
|
|
setBufferObjects(paneSize);
|
|
glutils::sendVbo(m_bufferSet);
|
|
glutils::sendEbo(m_bufferSet);
|
|
// vbo layout
|
|
const auto posAttr = static_cast<GLuint>(glGetAttribLocation(m_shader, "vPosition"));
|
|
glEnableVertexAttribArray(posAttr);
|
|
glVertexAttribPointer(posAttr, 2, GL_FLOAT, GL_FALSE, VertexVboRowLength * sizeof(float), nullptr);
|
|
const auto colorAttr = static_cast<GLuint>(glGetAttribLocation(m_shader, "vColor"));
|
|
glEnableVertexAttribArray(colorAttr);
|
|
glVertexAttribPointer(colorAttr, 3, GL_FLOAT, GL_FALSE, VertexVboRowLength * sizeof(float),
|
|
reinterpret_cast<void*>(2 * sizeof(float)));
|
|
}
|
|
|
|
geo::Vec2 TileSheetPixels::pixelSize(const geo::Vec2 &paneSize) const noexcept {
|
|
const auto [sw, sh] = paneSize;
|
|
constexpr float ymod = 0.35f / 10.0f;
|
|
const auto xmod = ymod * sh / sw;
|
|
return {xmod * m_pixelSizeMod, ymod * m_pixelSizeMod};
|
|
}
|
|
|
|
void TileSheetPixels::setPixelBufferObject(const geo::Vec2 &paneSize, unsigned vertexRow, float x, float y, Color16 color, float *vbo, GLuint *ebo) const noexcept {
|
|
const auto [xmod, ymod] = pixelSize(paneSize);
|
|
x *= xmod;
|
|
y *= -ymod;
|
|
x -= 1.0f;
|
|
y += 1.0f - ymod;
|
|
const auto r = redf(color), g = greenf(color), b = bluef(color);
|
|
// don't worry, these memcpys gets optimized to something much more ideal
|
|
const float vertices[VertexVboLength] = {
|
|
x, y, r, g, b, // bottom left
|
|
x + xmod, y, r, g, b, // bottom right
|
|
x + xmod, y + ymod, r, g, b, // top right
|
|
x, y + ymod, r, g, b, // top left
|
|
};
|
|
memcpy(vbo, vertices, sizeof(vertices));
|
|
const GLuint elms[VertexEboLength] = {
|
|
vertexRow + 0, vertexRow + 1, vertexRow + 2,
|
|
vertexRow + 2, vertexRow + 3, vertexRow + 0,
|
|
};
|
|
memcpy(ebo, elms, sizeof(elms));
|
|
}
|
|
|
|
void TileSheetPixels::setBufferObjects(const geo::Vec2 &paneSize) noexcept {
|
|
// set buffer lengths
|
|
const auto subSheet = m_model->activeSubSheet();
|
|
const auto &pal = m_model->pal();
|
|
const auto width = subSheet->columns * TileWidth;
|
|
const auto height = subSheet->rows * TileHeight;
|
|
const auto pixels = static_cast<unsigned>(width * height);
|
|
m_bufferSet.vertices.resize(pixels * VertexVboLength);
|
|
m_bufferSet.elements.resize(pixels * VertexEboLength);
|
|
// set pixels
|
|
subSheet->walkPixels(m_model->img().bpp, [&](std::size_t i, uint8_t p) {
|
|
auto color = pal.colors[p];
|
|
const auto pt = idxToPt(static_cast<int>(i), subSheet->columns);
|
|
const auto fx = static_cast<float>(pt.x);
|
|
const auto fy = static_cast<float>(pt.y);
|
|
const auto vbo = &m_bufferSet.vertices[i * VertexVboLength];
|
|
const auto ebo = &m_bufferSet.elements[i * VertexEboLength];
|
|
if (m_model->pixelSelected(i)) {
|
|
const auto r = red16(color) / 2;
|
|
const auto g = (green16(color) + 20) / 2;
|
|
const auto b = (blue16(color) + 31) / 2;
|
|
color = color16(r, g, b);
|
|
}
|
|
setPixelBufferObject(paneSize, i * VertexVboRows, fx, fy, color, vbo, ebo);
|
|
});
|
|
}
|
|
|
|
}
|