add lua 'pixel' drawing api

This commit is contained in:
Zack Buhman 2026-03-19 13:01:51 -05:00
parent a5a304bcae
commit 50a747934d
14 changed files with 356 additions and 15 deletions

View File

@ -45,6 +45,8 @@ OBJS = \
src/collada/effect.o \
src/collada/node_state.o \
src/collada/animate.o \
src/lua_api.o \
src/pixel_line_art.o \
data/scenes/ship20/ship20.o \
data/scenes/noodle/noodle.o \
data/scenes/shadow_test/shadow_test.o \

View File

@ -64,5 +64,5 @@ namespace font {
void load_fonts(font * const fonts, font_desc const * const descs, int length);
int best_font(font_desc const * const descs, int length);
void draw_start(font const& font, unsigned int vertex_array_object, unsigned int index_buffer);
void draw_string(font const& font, char const * const s, int x, int y);
int draw_string(font const& font, char const * const s, int x, int y);
}

18
include/lua_api.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
int draw_font_start();
int draw_font(int font_ix, char const * text, int x, int y);
void draw_line_quad_start();
void draw_line(int x1, int y1, int x2, int y2);
void draw_set_color(float r, float g, float b);
void draw_quad(int x1, int y1, int x2, int y2,
int x3, int y3, int x4, int y4);
#ifdef __cplusplus
}
#endif

12
include/pixel_line_art.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
namespace pixel_line_art {
void load();
void draw_line_quad_start();
void draw_line(int x1, int y1, int x2, int y2);
void draw_set_color(float r, float g, float b);
void draw_quad(int x1, int y1, int x2, int y2,
int x3, int y3, int x4, int y4);
}

View File

@ -6,6 +6,8 @@ extern "C" {
void load(const char * source_path);
void draw();
void love2d_state_load();
void love2d_state_restore();
void update_keyboard(int up, int down, int left, int right,
int w, int s, int a, int d,
int t, int g, int f, int h,

105
main.lua
View File

@ -23,6 +23,15 @@ void update_joystick(int joystick_index,
int leftshoulder, int rightshoulder,
int start);
void update(float time);
int draw_font_start();
int draw_font(int font_ix, char const * text, int x, int y);
void draw_line_quad_start();
void draw_line(int x1, int y1, int x2, int y2);
void draw_set_color(float r, float g, float b);
void draw_quad(int x1, int y1, int x2, int y2,
int x3, int y3, int x4, int y4);
]]
local source_path = love.filesystem.getSource()
test = ffi.load(source_path .. "/test.so")
@ -88,11 +97,97 @@ local draw = function()
test.draw()
end
local nico_draw = function()
----------------------------------------------------------------------
-- font drawing
----------------------------------------------------------------------
-- call "draw_font_start()" prior each "group" of "draw_font()" calls
--
-- a "group" of draw_font() calls are back-to-back/consecutive,
-- with no non-font drawing between them.
--
-- For example:
local font_ix = test.draw_font_start()
local x = 512
local y = 50
y = y + test.draw_font(font_ix, "lua test", x, y)
y = y + test.draw_font(font_ix, "cool", x, y)
-- note that "font_ix" is the current "best font" as calculated
-- from the current window size, and might change next frame if the
-- window is resized.
--
-- Any of this of course could be changed to match your precise
-- requirements.
----------------------------------------------------------------------
-- line drawing
----------------------------------------------------------------------
-- call "draw_line_quad_start()" prior to each "group" of
-- "draw_line()" or "draw_quad()" calls
--
-- a "group" of draw_line()/draw_quad() calls are
-- back-to-back/consecutive, with no non-line/quad drawing between
-- them.
--
-- For example:
test.draw_line_quad_start()
test.draw_set_color(1.0, 0.0, 0.0) -- r, g, b (0.0 to 1.0)
test.draw_line(0, 0, 1024, 1024) -- x1, y1, x2, y2
test.draw_line(700, 300, 400, 500)
test.draw_set_color(0.0, 1.0, 0.0)
test.draw_line(700, 300, 400, 700)
-- x1, y1, x2, y2,
-- x3, y3, x4, y4,
--
-- vertices must be specified In "counter clockwise" order, as in:
--
-- 2──1
-- │ │ valid (counter clockwise)
-- 3──4
--
-- these can also be rotated, as in:
--
-- 3
-- ╱ ╲
-- 4 2 valid (counter clockwise)
-- ╲ ╱
-- 1
--
-- however "mirroring" is not valid, as in:
--
-- 1──2
-- │ │ not valid (clockwise)
-- 4──3
--
test.draw_set_color(0.0, 0.0, 1.0)
test.draw_quad(
600, 600, -- top right
500, 600, -- top left
500, 700, -- bottom left
600, 700 -- bottom right
)
test.draw_set_color(0.0, 0.5, 1.0)
test.draw_quad(
900, 900, -- bottom
950, 850, -- right
900, 800, -- top
850, 850 -- left
)
-- If you want to draw a large number of lines or quads in bulk
-- (e.g: 10,000+ lines/quads per frame), this interface might not be good
-- enough, and we should discuss this in more detail.
end
function love.run()
init()
--love.timer.step()
return function()
love.event.pump()
for name, a,b,c,d,e,f,g,h in love.event.poll() do
@ -109,7 +204,6 @@ function love.run()
width, height, flags = love.window.getMode()
test.update_window(width, height)
--local dt = love.timer.step()
local time = love.timer.getTime()
update(time)
@ -121,10 +215,9 @@ function love.run()
test.update_mouse(x, y)
end
nico_draw()
love.graphics.present()
love.timer.sleep(0.001)
--love.timer.sleep(0.1)
--local fps = love.timer.getFPS( )
--print(fps)
end
end

View File

@ -40,8 +40,8 @@ void main()
vec4 texture_color = texelFetch(TerrainSampler, coord, 0);
if (texture_color.w != 1.0) {
discard;
return;
//discard;
//return;
}
Position = fs_in.BlockPosition.xzy;

View File

@ -0,0 +1,10 @@
#version 430 core
out vec4 Color;
layout (location = 1) uniform vec3 BaseColor;
void main()
{
Color = vec4(BaseColor, 1);
}

View File

@ -0,0 +1,10 @@
#version 430 core
layout (location = 0) in vec2 Position;
layout (location = 0) uniform mat4 Transform;
void main()
{
gl_Position = Transform * vec4(Position, 0, 1);
}

View File

@ -123,8 +123,8 @@ namespace font {
inline static XMFLOAT4X4 glyph_transform(font const& font, int x, int y)
{
XMMATRIX transform =
XMMatrixScaling(font.desc->glyph_width, font.desc->glyph_height, 0)
XMMATRIX transform
= XMMatrixScaling(font.desc->glyph_width, font.desc->glyph_height, 0)
* XMMatrixTranslation(x, -y, 0)
* XMMatrixScaling(2.0f / window::width, 2.0f / window::height, 0)
* XMMatrixTranslation(-1, 1, 0);
@ -148,7 +148,7 @@ namespace font {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
}
void draw_string(font const& font, char const * const s, int x, int y)
int draw_string(font const& font, char const * const s, int x, int y)
{
int i = 0;
while (s[i] != 0) {
@ -164,5 +164,6 @@ namespace font {
x += font.desc->glyph_width;
}
return x;
}
}

View File

@ -81,7 +81,6 @@ namespace hud {
int font_ix = font::best_font(font::terminus, font::terminus_length);
font::font const& ter_best = terminus_fonts[font_ix];
font::draw_start(ter_best, empty_vertex_array_object, quad_index_buffer);
labeled_value<float>(buf, "fov: ", "%.3f", view::state.fov);

45
src/lua_api.cpp Normal file
View File

@ -0,0 +1,45 @@
#include "font.h"
#include "pixel_line_art.h"
#include "lua_api.h"
extern font::font * terminus_fonts;
extern unsigned int empty_vertex_array_object;
extern unsigned int quad_index_buffer;
int draw_font_start()
{
int font_ix = font::best_font(font::terminus, font::terminus_length);
font::font const& ter_best = terminus_fonts[font_ix];
font::draw_start(ter_best, empty_vertex_array_object, quad_index_buffer);
return font_ix;
}
int draw_font(int font_ix, char const * text, int x, int y)
{
font::font const& ter_best = terminus_fonts[font_ix];
font::draw_string(ter_best, text, x, y);
return ter_best.desc->glyph_height;
}
void draw_line_quad_start()
{
pixel_line_art::draw_line_quad_start();
}
void draw_line(int x1, int y1, int x2, int y2)
{
pixel_line_art::draw_line(x1, y1, x2, y2);
}
void draw_set_color(float r, float g, float b)
{
pixel_line_art::draw_set_color(r, g, b);
}
void draw_quad(int x1, int y1, int x2, int y2,
int x3, int y3, int x4, int y4)
{
pixel_line_art::draw_quad(x1, y1, x2, y2,
x3, y3, x4, y4);
}

138
src/pixel_line_art.cpp Normal file
View File

@ -0,0 +1,138 @@
#include "glad/gl.h"
#include "directxmath/directxmath.h"
#include <stdio.h>
#include "opengl.h"
#include "window.h"
#include "pixel_line_art.h"
extern unsigned int quad_index_buffer;
namespace pixel_line_art {
struct layout {
struct {
unsigned int position;
} attribute;
struct {
unsigned int transform;
unsigned int base_color;
} uniform;
};
const layout layout = {
.attribute = {
.position = 0,
},
.uniform = {
.transform = 0,
.base_color = 1,
},
};
static unsigned int program;
static unsigned int vertex_array_object;
static unsigned int per_vertex_buffer;
static int const per_vertex_size = (sizeof (float)) * 2;
static void load_program()
{
program = compile_from_files("shader/pixel_line_art.vert",
nullptr,
"shader/pixel_line_art.frag");
}
static void load_vertex_attributes()
{
glGenVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);
glVertexBindingDivisor(0, 0);
glEnableVertexAttribArray(layout.attribute.position);
glVertexAttribFormat(layout.attribute.position, 2, GL_FLOAT, GL_FALSE, 0);
glVertexAttribBinding(layout.attribute.position, 0);
glBindVertexArray(0);
}
static void load_per_vertex_buffer(int x1, int y1, int x2, int y2)
{
float vertex_data[] = {
(float)x1, (float)y1, (float)x2, (float)y2,
};
int vertex_data_size = (sizeof (vertex_data));
glBindBuffer(GL_ARRAY_BUFFER, per_vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, vertex_data_size, vertex_data, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
static void load_per_vertex_buffer2(int x1, int y1, int x2, int y2,
int x3, int y3, int x4, int y4)
{
float vertex_data[] = {
(float)x1, (float)y1, (float)x2, (float)y2,
(float)x3, (float)y3, (float)x4, (float)y4,
};
int vertex_data_size = (sizeof (vertex_data));
glBindBuffer(GL_ARRAY_BUFFER, per_vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, vertex_data_size, vertex_data, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void load()
{
load_program();
load_vertex_attributes();
glGenBuffers(1, &per_vertex_buffer);
}
static void set_transform(XMMATRIX const & transform)
{
XMFLOAT4X4 float_transform;
XMStoreFloat4x4(&float_transform, transform);
glUniformMatrix4fv(layout.uniform.transform, 1, false, (float *)&float_transform);
}
void draw_line_quad_start()
{
glUseProgram(program);
glBlendFunc(GL_ONE, GL_ZERO);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
glBindVertexArray(vertex_array_object);
glBindVertexBuffer(0, per_vertex_buffer, 0, per_vertex_size);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_index_buffer);
XMMATRIX transform
= XMMatrixScaling(2.0f / window::width, -2.0f / window::height, 0)
* XMMatrixTranslation(-1, 1, 0);
set_transform(transform);
}
void draw_line(int x1, int y1, int x2, int y2)
{
load_per_vertex_buffer(x1, y1, x2, y2);
glDrawArrays(GL_LINES, 0, 2);
}
void draw_quad(int x1, int y1, int x2, int y2,
int x3, int y3, int x4, int y4)
{
load_per_vertex_buffer2(x1, y1, x2, y2,
x3, y3, x4, y4);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, (void *)0);
}
void draw_set_color(float r, float g, float b)
{
glUniform3f(layout.uniform.base_color, r, g, b);
}
}

View File

@ -24,6 +24,7 @@
#include "collada/scene.h"
#include "collada/types.h"
#include "collada/instance_types.h"
#include "pixel_line_art.h"
#include "world/entry_table.h"
#include "world/world.h"
@ -88,7 +89,6 @@ void load_quad_index_buffer()
glGenBuffers(1, &quad_index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data_size, data, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
@ -119,6 +119,12 @@ void load(const char * source_path)
fprintf(stderr, "getproc %p\n", SDL_GL_GetProcAddress);
gladLoadGL((GLADloadfunc)SDL_GL_GetProcAddress);
//
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//////////////////////////////////////////////////////////////////////
// minecraft (drawing data)
//////////////////////////////////////////////////////////////////////
@ -140,6 +146,12 @@ void load(const char * source_path)
terminus_fonts = (font::font *)malloc((sizeof (font::font)) * font::terminus_length);
font::load_fonts(terminus_fonts, font::terminus, font::terminus_length);
//////////////////////////////////////////////////////////////////////
// pixel_line_art
//////////////////////////////////////////////////////////////////////
pixel_line_art::load();
//////////////////////////////////////////////////////////////////////
// quad
//////////////////////////////////////////////////////////////////////
@ -370,7 +382,6 @@ float mouse_block[3] = {};
void update_mouse(int x, int y)
{
printf("update mouse %d %d\n", x, y);
x = clamp(x, geometry_buffer_pnc.width);
y = clamp(y, geometry_buffer_pnc.height);