diff options
author | davidovski <david@davidovski.xyz> | 2023-04-23 03:13:02 +0100 |
---|---|---|
committer | davidovski <david@davidovski.xyz> | 2023-04-23 03:13:02 +0100 |
commit | bb3034a4cb0f793e31608ebee4eff2ef8c1f8379 (patch) | |
tree | 5f5bddfc45bf75a0be004cdf6de1a05e7cb351dd |
Pass tilemap to shader
-rw-r--r-- | Makefile | 15 | ||||
-rw-r--r-- | README.md | 8 | ||||
-rw-r--r-- | tiled.c | 90 | ||||
-rw-r--r-- | tiled.glsl | 57 | ||||
-rw-r--r-- | tiles.png | bin | 0 -> 875 bytes |
5 files changed, 170 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2a5ece6 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +PROG=tiled +CC=gcc +FLAGS=-lm -lraylib + +.DEFAULT_GOAL := build + +install: ${PROG} + cp ${PROG} ${PREFIX}/bin/ + +build: ${PROG}.c + ${CC} ${PROG}.c -o ${PROG} ${FLAGS} + +clean: ${PROG} + rm ${PROG} + diff --git a/README.md b/README.md new file mode 100644 index 0000000..dde036b --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# Tiled Rendering + +Experimenting with rendering a tilemap using shaders + +## Requirements + +- C Compiler +- raylib @@ -0,0 +1,90 @@ +#include <raylib.h> + +#define SCREEN_W 1280 +#define SCREEN_H 720 + +#define MAP_W 4 +#define MAP_H 4 + +const int tilemap[MAP_H][MAP_W] = { + {0, 0, 0, 0}, + {0, 0, 3, 3}, + {3, 3, 1, 1}, + {1, 1, 2, 2} +}; + + +int main() { + InitWindow(SCREEN_W, SCREEN_H, "tiled"); + + Shader shader = LoadShader(0, "tiled.glsl"); + + RenderTexture2D target = LoadRenderTexture(SCREEN_W, SCREEN_H); + + float resolution[2] = {SCREEN_W, SCREEN_H}; + float offset[2] = {0, 0}; + float zoom = 1.0f; + Texture atlas = LoadTexture("tiles.png"); + // size of the tile atlas grid in tiles + int atlasSize[2] = {2, 2}; + + int resolutionLoc = GetShaderLocation(shader, "resolution"); + int locationLoc = GetShaderLocation(shader, "offset"); + int zoomLoc = GetShaderLocation(shader, "zoom"); + int atlasSizeLoc = GetShaderLocation(shader, "atlasSize"); + + int tilemapLoc[MAP_W][MAP_H]= {}; + for (int x = 0; x < MAP_W; x++) { + for (int y = 0; y < MAP_H; y++) { + tilemapLoc[y][x] = GetShaderLocation(shader, TextFormat("tilemap[%d][%d]", y, x)); + } + } + + + int textureLoc = GetShaderLocation(shader, "texture1"); + + while (!WindowShouldClose()) { + if (IsKeyDown(KEY_UP)) offset[1] += zoom * 0.01f; + if (IsKeyDown(KEY_DOWN)) offset[1] -= zoom * 0.01f; + if (IsKeyDown(KEY_RIGHT)) offset[0] -= zoom * 0.01f; + if (IsKeyDown(KEY_LEFT)) offset[0] += zoom * 0.01f; + + if (IsKeyDown(KEY_W)) zoom -= zoom * 0.01f; + if (IsKeyDown(KEY_S)) zoom += zoom * 0.01f; + + SetShaderValue(shader, resolutionLoc, resolution, SHADER_UNIFORM_VEC2); + SetShaderValue(shader, locationLoc, &offset, SHADER_UNIFORM_VEC2); + SetShaderValue(shader, zoomLoc, &zoom, SHADER_UNIFORM_FLOAT); + SetShaderValue(shader, atlasSizeLoc, &atlasSize, SHADER_UNIFORM_IVEC2); + for (int x = 0; x < MAP_W; x++) { + for (int y = 0; y < MAP_H; y++) { + SetShaderValue(shader, tilemapLoc[y][x], &tilemap[y][x], SHADER_UNIFORM_INT); + } + } + + BeginDrawing(); + + ClearBackground(LIGHTGRAY); + + BeginTextureMode(target); + DrawRectangle(0, 0, SCREEN_W, SCREEN_H, BLACK); + EndTextureMode(); + + BeginShaderMode(shader); + SetShaderValueTexture(shader, textureLoc, atlas); + + // draw the base image to texture0 + DrawTexture(target.texture, 0, 0, WHITE); + EndShaderMode(); + + EndDrawing(); + } + + UnloadShader(shader); + UnloadRenderTexture(target); + UnloadTexture(atlas); + + CloseWindow(); + + return 0; +} diff --git a/tiled.glsl b/tiled.glsl new file mode 100644 index 0000000..2a0e5d9 --- /dev/null +++ b/tiled.glsl @@ -0,0 +1,57 @@ +#version 430 +precision highp float; + +in vec3 vertexPos; +in vec2 fragTexCoord; +in vec4 fragColor; + +uniform sampler2D texture0; +uniform sampler2D texture1; + +uniform vec2 resolution; +uniform vec2 offset; +uniform float zoom; +uniform ivec2 atlasSize; +uniform int tilemap[4][4]; + +out vec4 finalColor; + +ivec2 calcTileOffset(int tileIndex) { + tileIndex -= 1; + int x = tileIndex % atlasSize.x; + int y = (tileIndex - x) / atlasSize.y; + return ivec2(x, y); +} + +vec4 tile(vec2 coords, int tileIndex) { + ivec2 texSize = textureSize(texture1, 1); + + // for now just render the first tile + + + vec2 tileSize = texSize / atlasSize; + + if (tileIndex == 0 + || coords.x > tileSize.x + || coords.x < 0 + || coords.y > tileSize.y + || coords.y < 0) { + return vec4(0.0f, 0.0f, 0.0f, 0.0f); + } else { + ivec2 tileOffset = calcTileOffset(tileIndex); + vec2 texCoords = coords + (tileOffset*tileSize); + texCoords /= texSize; + + return texture(texture1, texCoords); + } +} + +void main() { + vec2 uv = fragTexCoord; + uv.x *= resolution.x / resolution.y; + + uv *= zoom; + uv -= offset; + + finalColor = tile(uv, tilemap[2][2]); +} diff --git a/tiles.png b/tiles.png Binary files differnew file mode 100644 index 0000000..3a86dc4 --- /dev/null +++ b/tiles.png |