#pragma once #include "hd2d/GL.h" #include "hd2d/Texture.h" #include #include #include #include namespace hd2d { // How a material id maps onto layers of the terrain texture array. struct TerrainMaterial { int topFirst = 0, topCount = 1; // layers picked per tile for top faces int accentFirst = 0, accentCount = 0; // occasional variation layers float accentChance = 0.0f; // probability a tile uses an accent layer int sideFirst = 0, sideCount = 1; // layers for cliff faces below this tile int lipLayer = -1; // layer for an overhang strip atop cliff faces (-1 = none) }; // Tile-based diorama terrain: every tile has an integer height level and a // material. Top faces are drawn with organically jittered material borders // at pixel granularity; height differences produce textured cliff faces. class Terrain { public: static constexpr int kMaxMaterials = 8; void init(int width, int depth, float levelHeight = 0.5f); int width() const { return w_; } int depth() const { return d_; } float levelHeight() const { return levelHeight_; } bool inBounds(int x, int z) const { return x >= 0 && z >= 0 && x < w_ && z < d_; } int level(int x, int z) const; uint8_t material(int x, int z) const; void setLevel(int x, int z, int level); void setMaterial(int x, int z, uint8_t mat); float heightAt(float x, float z) const; // top surface height of tile under (x, z) // Cliff faces at the map border extend down to this level (diorama base). int baseLevel = -6; std::array materials{}; // (Re)builds GPU mesh + material map after edits. void build(); void draw() const; void bindMaterialMap(GLuint unit) const { glBindTextureUnit(unit, matTex_); } TextureArray textures; // pixel-art material layers, all same size private: int w_ = 0, d_ = 0; float levelHeight_ = 0.5f; std::vector levels_; std::vector mats_; GLuint vao_ = 0, vbo_ = 0, ibo_ = 0, matTex_ = 0; GLsizei indexCount_ = 0; }; } // namespace hd2d