GLint pos = uniformLoc("pos"); | GLint pos = uniformLoc("pos"); | ||||
GLint vertex = attribLoc("vertex"); | GLint vertex = attribLoc("vertex"); | ||||
GLint tileTex = uniformLoc("tileTex"); | GLint tileTex = uniformLoc("tileTex"); | ||||
GLint tileTexWidth = uniformLoc("tileTexWidth"); | |||||
GLint tileTexHeight = uniformLoc("tileTexHeight"); | |||||
GLint tileTexSize = uniformLoc("tileTexSize"); | |||||
GLint tiles = uniformLoc("tiles"); | GLint tiles = uniformLoc("tiles"); | ||||
GLuint vbo; | GLuint vbo; | ||||
glUniform1iv(state_->chunkProg.tiles, sizeof(tiles) / sizeof(*tiles), tiles); | glUniform1iv(state_->chunkProg.tiles, sizeof(tiles) / sizeof(*tiles), tiles); | ||||
glCheck(); | glCheck(); | ||||
glUniform1f(state_->chunkProg.tileTexWidth, | |||||
(float)(int)(state_->atlasTex.width() / SwanCommon::TILE_SIZE)); | |||||
glUniform1f(state_->chunkProg.tileTexHeight, | |||||
glUniform2f(state_->chunkProg.tileTexSize, | |||||
(float)(int)(state_->atlasTex.width() / SwanCommon::TILE_SIZE), | |||||
(float)(int)(state_->atlasTex.height() / SwanCommon::TILE_SIZE)); | (float)(int)(state_->atlasTex.height() / SwanCommon::TILE_SIZE)); | ||||
glCheck(); | glCheck(); | ||||
TileAtlas::TileAtlas(): state_(std::make_unique<AtlasState>()) { | TileAtlas::TileAtlas(): state_(std::make_unique<AtlasState>()) { | ||||
GLint size; | GLint size; | ||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size); | glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size); | ||||
state_->tilesPerLine = std::min(size / SwanCommon::TILE_SIZE, 8); | |||||
state_->tilesPerLine = std::min(size / SwanCommon::TILE_SIZE, 1024); | |||||
} | } | ||||
TileAtlas::~TileAtlas() = default; | TileAtlas::~TileAtlas() = default; | ||||
const unsigned char *bytes = (const unsigned char *)data; | const unsigned char *bytes = (const unsigned char *)data; | ||||
size_t x = tileId % state_->tilesPerLine; | size_t x = tileId % state_->tilesPerLine; | ||||
size_t y = tileId / state_->tilesPerLine; | size_t y = tileId / state_->tilesPerLine; | ||||
if (y >= state_->tilesPerLine) { | |||||
std::cerr << "Cygnet: Warning: Tile ID " << tileId << " too big for texture atlas\n"; | |||||
return; | |||||
} | |||||
std::cerr << "Tile " << tileId << " to " << x << ", " << y << '\n'; | |||||
if (state_->width <= x) { | if (state_->width <= x) { | ||||
state_->width = x + 1; | state_->width = x + 1; | ||||
size_t requiredSize = state_->tilesPerLine * SwanCommon::TILE_SIZE * | size_t requiredSize = state_->tilesPerLine * SwanCommon::TILE_SIZE * | ||||
state_->height * SwanCommon::TILE_SIZE * 4; | state_->height * SwanCommon::TILE_SIZE * 4; | ||||
state_->data.reserve(requiredSize); | |||||
state_->data.resize(requiredSize); | |||||
for (size_t ty = 0; ty < rows; ++ty) { | for (size_t ty = 0; ty < rows; ++ty) { | ||||
const unsigned char *src = bytes + ty * SwanCommon::TILE_SIZE * 4; | const unsigned char *src = bytes + ty * SwanCommon::TILE_SIZE * 4; |
varying vec2 v_tileCoord; | varying vec2 v_tileCoord; | ||||
uniform sampler2D tileTex; | uniform sampler2D tileTex; | ||||
uniform float tileTexWidth; | |||||
uniform float tileTexHeight; | |||||
uniform vec2 tileTexSize; | |||||
uniform int tiles[CHUNK_WIDTH * CHUNK_HEIGHT]; | uniform int tiles[CHUNK_WIDTH * CHUNK_HEIGHT]; | ||||
void main() { | void main() { | ||||
float tileX = floor(v_tileCoord.x); | |||||
float tileY = floor(-v_tileCoord.y); | |||||
int tileIndex = int(tileY * float(CHUNK_WIDTH) + tileX); | |||||
vec2 tilePos = floor(vec2(v_tileCoord.x, -v_tileCoord.y)); | |||||
int tileIndex = int(tilePos.y * float(CHUNK_WIDTH) + tilePos.x); | |||||
float tileID = float(tiles[tileIndex]); | float tileID = float(tiles[tileIndex]); | ||||
float atlasX = floor(mod(tileID, tileTexWidth)) + v_tileCoord.x - tileX; | |||||
float atlasY = floor(tileID / tileTexWidth) + (-v_tileCoord.y - tileY); | |||||
vec2 atlasPos = vec2( | |||||
tileID + v_tileCoord.x - tilePos.x, | |||||
floor(tileID / tileTexSize.x) + (-v_tileCoord.y - tilePos.y)); | |||||
float x = atlasX / tileTexWidth; | |||||
float y = atlasY / tileTexHeight; | |||||
gl_FragColor = texture2D(tileTex, vec2(x, y)); | |||||
gl_FragColor = texture2D(tileTex, fract(atlasPos / tileTexSize)); | |||||
} | } | ||||
)glsl"; | )glsl"; | ||||