Skip to content

Instantly share code, notes, and snippets.

@Journeyman1337
Last active November 7, 2021 22:27
Show Gist options
  • Save Journeyman1337/2b2f2ce7c2f23b616ae4f6209e44765e to your computer and use it in GitHub Desktop.
Save Journeyman1337/2b2f2ce7c2f23b616ae4f6209e44765e to your computer and use it in GitHub Desktop.
#version 330
uniform sampler2D Atlas;
in vec2 UV;
in vec4 FG;
in vec4 BG;
out vec4 FragColor;
void main()
{
vec4 c = texture(Atlas, UV);
c = mix(BG, FG * vec4(c.rgb, 1.0), c.a);
FragColor = c;
}
#define RLH_IMPLEMENTATION
#include "roguelike.h"
#include "raylib.h"
#include <stdlib.h>
#define MAX_COLUMNS 20
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int tiles_tall = 80;
const int tiles_wide = 100;
const int tile_dimensions = 8;
const int w_width = tiles_tall * tile_dimensions;
const int w_height = tiles_wide * tile_dimensions;
Image loadedimage = LoadImage("cp_8x8_rgba_bg_alpha.png");
InitWindow(w_width, w_height, "rlh test");
rlhrenderercreateinfo_s create_info = { 0 };
create_info.ScreenTilesTall = tiles_tall;
create_info.ScreenTilesWide = tiles_wide;
create_info.SheetImage = loadedimage;
create_info.FontmapSTPQ = malloc(sizeof(float) * 256 * 4);
float uvtilesize = 1.0f / 16;
float* stpq = malloc(sizeof(float) * 256 * 4);
{
size_t i = 0;
for (float y = 0; y < 16; y++)
{
for (float x = 0; x < 16; x++)
{
for (int q = 0; q < 4; q++)
{
switch (q)
{
case 0:
stpq[i++] = uvtilesize * x;
break;
case 1:
stpq[i++] = uvtilesize * x + uvtilesize;
break;
case 2:
stpq[i++] = uvtilesize * y;
break;
case 3:
stpq[i++] = uvtilesize * y + uvtilesize;
break;
}
}
}
}
}
rlhrenderer_h renderer = rlhCreateRenderer(create_info);
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update tiles
for (int x = 0; x < tiles_wide; x++)
{
for (int y = 0; y < tiles_tall; y++)
{
rlhSetRendererData(renderer, x, y, (rlhglyph_t)x, WHITE, BLACK);
}
}
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(BLACK);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
free(stpq);
return 0;
}
/*
MIT License
Copyright (c) 2020 Daniel Valcour
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <raylib.h>
#include <stdint.h>
typedef float rlhfloat_t;
typedef uint8_t rlhbyte_t;
typedef uint8_t rlhbool_t;
typedef uint32_t rlhuint_t;
typedef uint16_t rlhglyph_t;
typedef size_t rlhsize_t;
typedef uint32_t rlhenum_t;
typedef struct rlhrenderer_s;
typedef struct rlhrenderer_s* rlhrenderer_h;
typedef struct rlhrenderercreateinfo_s
{
rlhsize_t ScreenTilesWide;
rlhsize_t ScreenTilesTall;
Image SheetImage;
rlhfloat_t* FontmapSTPQ;
} rlhrenderercreateinfo_s;
#define RLH_FAILURE 0
#define RLH_SUCCESS 1
#define RLH_FALSE 0
#define RLH_TRUE 1
void rlhSetRendererData(rlhrenderer_h renderer, rlhsize_t x, rlhsize_t y, rlhglyph_t ch, Color fg, Color bg);
void rlhClearRendererData(rlhrenderer_h renderer);
#ifndef RLH_IMPLEMENTATION
extern RlhRenderer* (*rlhCreateRendererGL)(RlhRendererCreateInfo rendererCreateInfo);
extern void (*rlhBindRendererGL)(RlhRenderer* renderer);
extern void (*rlhResizeRendererGL)(RlhRenderer* renderer, rlh_size_t screen_tiles_wide, rlh_size_t screen_tiles_tall);
extern void (*rlhTransformRendererGL)(RlhRenderer* renderer, rlh_float_t* matrix4x4);
extern void (*rlhDrawRendererGL)(RlhRenderer* renderer);
extern void (*rlhDestroyRendererGL)(RlhRenderer* renderer);
#endif
#ifdef RLH_IMPLEMENTATION
rlhrenderer_h rlhCreateRenderer(rlhrenderercreateinfo_s rendererCreateInfo);
void rlhDestroyRenderer(rlhrenderer_h renderer);
void rlhBindRenderer(rlhrenderer_h renderer);
void rlhResizeRenderer(rlhrenderer_h renderer, rlhsize_t screen_tiles_wide, rlhsize_t screen_tiles_tall);
void rlhTransformRenderer(rlhrenderer_h renderer, rlhfloat_t* matrix);
void rlhDrawRendererOpnegl33(rlhrenderer_h renderer);
typedef struct rlhrenderer_s
{
rlhsize_t SheetWidth;
rlhsize_t SheetHeight;
rlhsize_t SpriteCount;
Texture2D RayTexture;
rlhfloat_t* FontmapSTPQ;
rlhsize_t TilesWide;
rlhsize_t TilesTall;
rlhbool_t LargeSparseWide;
rlhbool_t LargeSparseTall;
rlhsize_t TileDataSize;
rlhsize_t TileCount;
rlhsize_t ReservedTileCount;
rlhbyte_t* Data;
}rlhrenderer_s;
void rlhSetRendererData(rlhrenderer_h renderer, rlhsize_t x, rlhsize_t y, rlhglyph_t ch, Color fg, Color bg)
{
if (renderer->TileCount > renderer->ReservedTileCount)
{
rlhsize_t new_tile_count = renderer->ReservedTileCount * 2;
rlhbyte_t* new_data_ptr = (rlhbyte_t*)realloc(renderer->Data, new_tile_count * renderer->TileDataSize);
if (new_data_ptr == NULL)
{
//TODO err out of memory
return;
}
renderer->Data = new_data_ptr;
}
size_t index = renderer->TileCount * renderer->TileDataSize;
renderer->Data[index++] = x & 0xff;
if (renderer->LargeSparseWide)
{
renderer->Data[index++] = (x >> 8) & 0xff;
}
renderer->Data[index++] = y & 0xff;
if (renderer->LargeSparseTall)
{
renderer->Data[index++] = (y >> 8) & 0xff;
}
renderer->Data[index++] = (ch) & 0xff;
renderer->Data[index++] = (ch >> 8) & 0xff;
renderer->Data[index++] = fg.r;
renderer->Data[index++] = fg.g;
renderer->Data[index++] = fg.b;
renderer->Data[index++] = bg.r;
renderer->Data[index++] = bg.g;
renderer->Data[index] = bg.b;
renderer->TileCount++;
}
rlhsize_t rlhRendererGetTileCount(rlhrenderer_h renderer)
{
return renderer->TileCount;
}
void rlhClearRendererData(rlhrenderer_h renderer)
{
renderer->TileCount = 0;
}
inline rlhrenderer_h createRenderer(rlhrenderercreateinfo_s rendererCreateInfo)
{
rlhrenderer_h renderer = (rlhrenderer_h)malloc(sizeof(rlhrenderer_s));
renderer->TilesTall = rendererCreateInfo.ScreenTilesTall;
renderer->TilesWide = rendererCreateInfo.ScreenTilesWide;
renderer->RayTexture = LoadTextureFromImage(rendererCreateInfo.SheetImage);
for (size_t i = 0; i < renderer->SheetWidth * renderer->SheetHeight * (rlhsize_t)4; i++)
{
renderer->SheetRGBA[i] = rendererCreateInfo.SheetRGBA[i];
}
renderer->FontmapSTPQ = (rlhfloat_t*)malloc(sizeof(rlhfloat_t) * renderer->SpriteCount * (rlhsize_t)4);
if (!flip_y)
{
for (size_t i = 0; i < renderer->SpriteCount * (size_t)4; i++)
{
renderer->FontmapSTPQ[i] = rendererCreateInfo.FontmapSTPQ[i];
}
}
else
{
for (size_t i = 0; i < renderer->SpriteCount * (size_t)4; i++)
{
if (i % 4 == 2)
{
renderer->FontmapSTPQ[i] = rendererCreateInfo.FontmapSTPQ[i + 1];
}
else if (i % 4 == 3)
{
renderer->FontmapSTPQ[i] = rendererCreateInfo.FontmapSTPQ[i - 1];
}
else
{
renderer->FontmapSTPQ[i] = rendererCreateInfo.FontmapSTPQ[i];
}
}
}
renderer->Data = (rlhbyte_t*)malloc(sizeof(rlhbyte_t) * renderer->TilesWide * renderer->TilesTall * (rlhsize_t)8);
rlhClearRendererData(renderer);
return renderer;
}
@INGRAINED_HEADER_VARS@
const GLfloat kScreenMatrix[16] =
{
2.0f, 0.0f, 0.0f, -1.0f,
0.0f, -2.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
RlhRenderer* rlhCreateRenderer(RlhRendererCreateInfo rendererCreateInfo)
{
RlhRenderer* renderer = createRendererCommon(rendererCreateInfo, RLH_TRUE);
{
int gl_vertex_shader, gl_fragment_shader;
gl_vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(gl_vertex_shader, 1, &vertex_shader_source, nullptr);
glCompileShader(gl_vertex_shader);
gl_fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(gl_fragment_shader, 1, &fragment_shader_source, nullptr);
glCompileShader(gl_fragment_shader);
renderer->Program = glCreateProgram();
glAttachShader(renderer->Program, gl_vertex_shader);
glAttachShader(renderer->Program, gl_fragment_shader);
glLinkProgram(renderer->Program);
glDetachShader(renderer->Program, gl_vertex_shader);
glDetachShader(renderer->Program, gl_fragment_shader);
glDeleteShader(gl_vertex_shader);
glDeleteShader(gl_fragment_shader);
}
glGenVertexArrays(1, &renderer->VAO);
glGenTextures(1, &renderer->SheetTEX);
glBindTexture(GL_TEXTURE_2D, renderer->SheetTEX);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, renderer->SheetWidth, renderer->SheetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, renderer->SheetRGBA);
glGenBuffers(1, &renderer->FontmapBUF);
glBindBuffer(GL_TEXTURE_BUFFER, renderer->FontmapBUF);
glBufferData(GL_TEXTURE_BUFFER, (rlh_size_t)renderer->SpriteCount * (rlh_size_t)4 * sizeof(float), renderer->FontmapSTPQ, GL_STATIC_DRAW);
glGenTextures(1, &renderer->FontmapTEX);
glBindTexture(GL_TEXTURE_BUFFER, renderer->FontmapTEX);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, renderer->FontmapBUF);
glGenBuffers(1, &renderer->DataBUF);
glBindBuffer(GL_TEXTURE_BUFFER, renderer->DataBUF);
glBufferData(GL_TEXTURE_BUFFER, (rlh_size_t)renderer->TilesTall * (rlh_size_t)renderer->TilesWide * (sizeof(uint16_t) + ((rlh_size_t)2 * sizeof(uint8_t))), renderer->Data, GL_DYNAMIC_DRAW);
glGenTextures(1, &renderer->DataTEX);
glBindTexture(GL_TEXTURE_BUFFER, renderer->DataTEX);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R8UI, renderer->DataBUF);
glBindVertexArray(renderer->VAO);
glUseProgram(renderer->Program);
glUniform2i(glGetUniformLocation(renderer->Program, "dimensions"), renderer->TilesWide, renderer->TilesTall);
glUniform1i(glGetUniformLocation(renderer->Program, "sheet"), 0);
glUniform1i(glGetUniformLocation(renderer->Program, "fontmap"), 1);
glUniform1i(glGetUniformLocation(renderer->Program, "data"), 2);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, renderer->SheetTEX);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_BUFFER, renderer->FontmapTEX);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_BUFFER, renderer->DataTEX);
glUniformMatrix4fv(glGetUniformLocation(renderer->Program, "matrix"), 1, false, &kScreenMatrix[0]);
return renderer;
}
void rlhDestroyRenderer(RlhRenderer* renderer)
{
free(renderer->Data);
free(renderer->SheetRGBA);
free(renderer->FontmapSTPQ);
glDeleteVertexArrays(1, &renderer->VAO);
glDeleteProgram(renderer->Program);
glDeleteBuffers(1, &renderer->DataBUF);
glDeleteBuffers(1, &renderer->FontmapBUF);
glDeleteTextures(1, &renderer->DataTEX);
glDeleteTextures(1, &renderer->FontmapTEX);
glDeleteTextures(1, &renderer->SheetTEX);
renderer->SheetHeight = 0;
renderer->SheetWidth = 0;
renderer->SpriteCount = 0;
}
void rlhBindRenderer(RlhRenderer* renderer)
{
sBOUND = renderer;
glBindVertexArray(renderer->VAO);
glUseProgram(renderer->Program);
}
void rlhResizeRenderer(RlhRenderer* renderer, rlh_size_t screen_tiles_wide, rlh_size_t screen_tiles_tall)
{
if (renderer->TilesWide != screen_tiles_wide && renderer->TilesTall != screen_tiles_tall)
{
if (sAUTOBIND && sBOUND != renderer)
{
rlhBindRendererGL(renderer);
}
renderer->TilesWide = screen_tiles_wide;
renderer->TilesTall = screen_tiles_tall;
glUniform2i(glGetUniformLocation(renderer->Program, "dimensions"), renderer->TilesWide, renderer->TilesTall);
free(renderer->Data);
renderer->Data = (rlh_byte_t*)malloc(sizeof(rlh_byte_t) * renderer->TilesWide * renderer->TilesTall * (rlh_size_t)8);
rlhClearRendererData(renderer);
}
}
void rlhTransformRenderer(RlhRenderer* renderer, rlh_float_t* matrix)
{
matrix[5] *= -1.0f;
matrix[7] *= -1.0f;
if (sAUTOBIND && sBOUND != renderer)
{
rlhBindRendererGL(renderer);
}
glUniformMatrix4fv(glGetUniformLocation(renderer->Program, "matrix"), 1, false, matrix);
}
void rlhDrawRendererOpnegl33(RlhRenderer* renderer)
{
if (sAUTOBIND && sBOUND != renderer)
{
rlhBindRendererGL(renderer);
}
glBindBuffer(GL_TEXTURE_BUFFER, renderer->DataBUF);
glBufferData(GL_TEXTURE_BUFFER, (rlh_size_t)renderer->TilesWide * (rlh_size_t)renderer->TilesTall * (rlh_size_t)8, renderer->Data, GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLES, 0, renderer->TilesWide * renderer->TilesTall * (rlh_size_t)6);
}
#endif
#ifdef __cplusplus
}
#endif
#version 330
uniform ivec2 ScreenTileDimensions; //dimensions of the batch
uniform vec2 TileScreenspaceDimensions;
uniform ivec2 SheetTileDimensions;
uniform vec2 SheetTileUVDimensions;
uniform bool HasLargeXCoordinate; //if this is sparse and the x positions are two bytes instead of one
uniform bool HasLargeYCoordinate; //if this is sparse and the y positions ar etwo bytes instead of one
uniform int TileByteSize; //size of a single tile in the data array in bytes
uniform usamplerBuffer Data; //batch data buffer.
uniform samplerBuffer Fontmap; //the coordinate uv buffer if not uv grid
uniform mat4 Matrix; //transform matrix for entire batch
uniform uvec2 ViewportPixelDimensions; //the pixel dimensions of the viewport.
uniform uvec2 TilePixelDimensions; //the dimensions of each tile in pixels.
out vec2 UV; //uv texture position
out vec4 FG; //foreground color
out vec4 BG; //background color
vec2 getVertexUV(int ch, int tile_vertex)
{
vec4 uv_square = texelFetch(Fontmap, ch);
vec2 vert_uvs[6] = vec2[](uv_square.sp, uv_square.sq, uv_square.tq, uv_square.sp, uv_square.tq, uv_square.tp);
vec2 uv = vert_uvs[tile_vertex];
return uv;
}
getVertexPosition(int tile, int tile_vertex, inout int buffer_offset)
{
uint tile_x = texelFetch(Data, buffer_offset).r;
buffer_offset += 1;
if (HasLargeXCoordinate)
{
tile_x += texelFetch(Data, buffer_offset).r * 256u;
buffer_offset += 1;
}
uint tile_y = texelFetch(Data, buffer_offset).r;
buffer_offset += 1;
if (HasLargeYCoordinate)
{
tile_y += texelFetch(Data, buffer_offset).r * 256u;
buffer_offset += 1;
}
float tile_lx = float(tile_x) * TileScreenspaceDimensions.x;
float tile_by = float(tile_y) * TileScreenspaceDimensions.y;
float tile_rx = tile_lx + TileScreenspaceDimensions.x;
float tile_ty = tile_by + TileScreenspaceDimensions.y;
vec4 position_square = vec4(tile_lx, tile_rx, tile_ty, tile_by);
vec2 vert_positions[6] = vec2[](position_square.sp, position_square.sq, position_square.tq, position_square.sp, position_square.tq, position_square.tp);
vec2 position = vert_positions[tile_vertex];
return vec4(position, 0.0, 1.0) * Matrix;
}
vec4 getColor32(inout int buffer_offset)
{
float r = float(texelFetch(Data, buffer_offset).r) / 255.0;
buffer_offset += 1;
float g = float(texelFetch(Data, buffer_offset).r) / 255.0;
buffer_offset += 1;
float b = float(texelFetch(Data, buffer_offset).r) / 255.0;
buffer_offset += 1;
float a = float(texelFetch(Data, buffer_offset).r) / 255.0;
buffer_offset += 1;
return vec4(r, g, b, 1);
}
int getGlyph16(inout int buffer_offset)
{
int glyph = int(texelFetch(Data, buffer_offset).r);
buffer_offset += 1;
glyph += int(texelFetch(Data, buffer_offset).r * 256u);
buffer_offset += 1;
return glyph;
}
void main()
{
int tile = gl_VertexID / 6;
int tile_vertex = gl_VertexID % 6;
int buffer_offset = TileByteSize * tile;
gl_Position = getVertexPosition(tile, tile_vertex, buffer_offset);
int glyph = getGlyph16(buffer_offset);
UV = getVertexUV(glyph, tile_vertex);
FG = getColor32(buffer_offset);
BG = getColor32(buffer_offset);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment