109 lines
4.4 KiB
C++
109 lines
4.4 KiB
C++
/*
|
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
*/
|
|
|
|
#include <nostalgia/core/consts.hpp>
|
|
#include "tilesheetpixelgrid.hpp"
|
|
|
|
namespace nostalgia::core {
|
|
|
|
void TileSheetGrid::setPixelSizeMod(float sm) noexcept {
|
|
m_pixelSizeMod = sm;
|
|
}
|
|
|
|
ox::Error TileSheetGrid::buildShader() noexcept {
|
|
const auto pixelLineVshad = ox::sfmt(VShad, glutils::GlslVersion);
|
|
const auto pixelLineFshad = ox::sfmt(FShad, glutils::GlslVersion);
|
|
const auto pixelLineGshad = ox::sfmt(GShad, glutils::GlslVersion);
|
|
return glutils::buildShaderProgram(pixelLineVshad, pixelLineFshad, pixelLineGshad).moveTo(&m_shader);
|
|
}
|
|
|
|
void TileSheetGrid::draw(bool update, const geo::Vec2 &scroll) noexcept {
|
|
glLineWidth(3 * m_pixelSizeMod * 0.5f);
|
|
glUseProgram(m_shader);
|
|
glBindVertexArray(m_bufferSet.vao);
|
|
if (update) {
|
|
glutils::sendVbo(m_bufferSet);
|
|
}
|
|
const auto uniformScroll = glGetUniformLocation(m_shader, "gScroll");
|
|
glUniform2f(uniformScroll, scroll.x, scroll.y);
|
|
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(m_bufferSet.vertices.size() / VertexVboRowLength));
|
|
}
|
|
|
|
void TileSheetGrid::initBufferSet(const geo::Vec2 &paneSize, const TileSheet &img) noexcept {
|
|
// vao
|
|
m_bufferSet.vao = glutils::generateVertexArrayObject();
|
|
glBindVertexArray(m_bufferSet.vao);
|
|
// vbo
|
|
m_bufferSet.vbo = glutils::generateBuffer();
|
|
setBufferObjects(paneSize, img, &m_bufferSet);
|
|
glutils::sendVbo(m_bufferSet);
|
|
// vbo layout
|
|
const auto pt1Attr = static_cast<GLuint>(glGetAttribLocation(m_shader, "vPt1"));
|
|
glEnableVertexAttribArray(pt1Attr);
|
|
glVertexAttribPointer(pt1Attr, 2, GL_FLOAT, GL_FALSE, VertexVboRowLength * sizeof(float), nullptr);
|
|
const auto pt2Attr = static_cast<GLuint>(glGetAttribLocation(m_shader, "vPt2"));
|
|
glEnableVertexAttribArray(pt2Attr);
|
|
glVertexAttribPointer(pt2Attr, 2, GL_FLOAT, GL_FALSE, VertexVboRowLength * sizeof(float),
|
|
reinterpret_cast<void*>(2 * sizeof(float)));
|
|
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*>(4 * sizeof(float)));
|
|
}
|
|
|
|
void TileSheetGrid::setBufferObject(geo::Point pt1, geo::Point pt2, Color32 c, float *vbo, const geo::Vec2 &pixSize) noexcept {
|
|
const auto x1 = static_cast<float>(pt1.x) * pixSize.x - 1.f;
|
|
const auto y1 = 1.f - static_cast<float>(pt1.y) * pixSize.y;
|
|
const auto x2 = static_cast<float>(pt2.x) * pixSize.x - 1.f;
|
|
const auto y2 = 1.f - static_cast<float>(pt2.y) * pixSize.y;
|
|
// don't worry, this memcpy gets optimized to something much more ideal
|
|
const float vertices[VertexVboLength] = {x1, y1, x2, y2, redf(c), greenf(c), bluef(c)};
|
|
memcpy(vbo, vertices, sizeof(vertices));
|
|
}
|
|
|
|
void TileSheetGrid::setBufferObjects(const geo::Vec2 &paneSize, const TileSheet &img, glutils::BufferSet *bg) noexcept {
|
|
const auto pixSize = pixelSize(paneSize);
|
|
const auto set = [bg, pixSize](unsigned i, geo::Point pt1, geo::Point pt2, Color32 c) {
|
|
const auto vbo = &bg->vertices[i * VertexVboLength];
|
|
setBufferObject(pt1, pt2, c, vbo, pixSize);
|
|
};
|
|
// set buffer length
|
|
const auto width = img.columns() * TileWidth;
|
|
const auto height = img.rows() * TileHeight;
|
|
const auto pixelCnt = static_cast<unsigned>(width * height);
|
|
const auto tileCnt = static_cast<unsigned>(img.columns() * img.rows());
|
|
m_bufferSet.vertices.resize((tileCnt + pixelCnt) * VertexVboLength);
|
|
// set buffer
|
|
auto i = 0ull;
|
|
// pixel outlines
|
|
constexpr auto pixOutlineColor = color32(0.4431f, 0.4901f, 0.4941f);
|
|
for (auto x = 0; x < img.columns() * TileWidth + 1; ++x) {
|
|
set(i, {x, 0}, {x, img.rows() * TileHeight}, pixOutlineColor);
|
|
++i;
|
|
}
|
|
for (auto y = 0; y < img.rows() * TileHeight + 1; ++y) {
|
|
set(i, {0, y}, {img.columns() * TileWidth, y}, pixOutlineColor);
|
|
++i;
|
|
}
|
|
// tile outlines
|
|
constexpr auto tileOutlineColor = color32(0.f, 0.f, 0.f);
|
|
for (auto x = 0; x < img.columns() * TileWidth + 1; x += TileWidth) {
|
|
set(i, {x, 0}, {x, img.rows() * TileHeight}, tileOutlineColor);
|
|
++i;
|
|
}
|
|
for (auto y = 0; y < img.rows() * TileHeight + 1; y += TileHeight) {
|
|
set(i, {0, y}, {img.columns() * TileWidth, y}, tileOutlineColor);
|
|
++i;
|
|
}
|
|
}
|
|
|
|
geo::Vec2 TileSheetGrid::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};
|
|
}
|
|
|
|
}
|