Skip to content

Commit

Permalink
library: surface settint + setalpha api
Browse files Browse the repository at this point in the history
  • Loading branch information
Adamcake committed Dec 7, 2024
1 parent 9f91b35 commit 216115a
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 1 deletion.
27 changes: 27 additions & 0 deletions src/library/doc/doc.texi
Original file line number Diff line number Diff line change
Expand Up @@ -1064,6 +1064,33 @@ mysurface:drawtowindow(mywindow, 0, 0, 100, 100, 0, 0, 1920, 1080)
@end verbatim
@end example

@node surface-settint
@subsection settint

Sets the "tint" this surface will be drawn with when drawing it to the
screen or to another surface. These values are in the range [0.0 - 1.0]
and are multiplied with the red, green and blue channels of the image,
so values less than 1.0 will darken the image. The defaults are all 1.0.

@example lua
@verbatim
mysurface:settint(red, green, blue)
@end verbatim
@end example

@node surface-setalpha
@subsection setalpha

Sets the alpha transparency this surface will be drawn with when drawing
it to the screen or to another surface. The value is in the range [0.0 -
1.0] where 0.0 is invisible and 1.0 is fully opaque. The default is 1.0.

@example lua
@verbatim
mysurface:setalpha(0.5)
@end verbatim
@end example

@node objects-buffer
@section Buffer

Expand Down
42 changes: 41 additions & 1 deletion src/library/gl.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ static GLint program_direct_screen_sampler;
static GLint program_direct_screen_d_xywh;
static GLint program_direct_screen_s_xywh;
static GLint program_direct_screen_src_wh_dest_wh;
static GLint program_direct_screen_rgba;
static GLuint program_direct_surface;
static GLint program_direct_surface_sampler;
static GLint program_direct_surface_d_xywh;
static GLint program_direct_surface_s_xywh;
static GLint program_direct_surface_src_wh_dest_wh;
static GLint program_direct_surface_rgba;
static GLuint program_region;
static GLint program_region_xywh;
static GLint program_region_dest_wh;
Expand Down Expand Up @@ -70,8 +72,9 @@ static const GLchar program_direct_fs[] = GLSLHEADER
"uniform sampler2D tex;"
"uniform ivec4 s_xywh;"
"uniform ivec4 src_wh_dest_wh;"
"uniform vec4 rgba;"
"void main() {"
"col = texture(tex, ((vPos * s_xywh.pq) + s_xywh.st) / src_wh_dest_wh.st);"
"col = texture(tex, ((vPos * s_xywh.pq) + s_xywh.st) / src_wh_dest_wh.st) * clamp(rgba, 0.0, 1.0);"
"}";

// "region" program draws an outline of alternating black and white pixels on a rectangular region of the screen
Expand Down Expand Up @@ -129,6 +132,8 @@ static void _bolt_gl_plugin_surface_clear(void* userdata, double r, double g, do
static void _bolt_gl_plugin_surface_subimage(void* userdata, int x, int y, int w, int h, const void* pixels, uint8_t is_bgra);
static void _bolt_gl_plugin_surface_drawtoscreen(void* userdata, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh);
static void _bolt_gl_plugin_surface_drawtosurface(void* userdata, void* target, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh);
static void _bolt_gl_plugin_surface_set_tint(void* userdata, double r, double g, double b);
static void _bolt_gl_plugin_surface_set_alpha(void* userdata, double alpha);
static void _bolt_gl_plugin_draw_region_outline(void* userdata, int16_t x, int16_t y, uint16_t width, uint16_t height);
static void _bolt_gl_plugin_read_screen_pixels(uint32_t width, uint32_t height, void* data);
static void _bolt_gl_plugin_game_view_rect(int* x, int* y, int* w, int* h);
Expand Down Expand Up @@ -168,6 +173,7 @@ struct PluginSurfaceUserdata {
unsigned int height;
GLuint framebuffer;
GLuint renderbuffer;
GLfloat rgba[4];
};

struct PluginShaderUserdata {
Expand Down Expand Up @@ -622,9 +628,22 @@ static void _bolt_gl_load(void* (*GetProcAddress)(const char*)) {
INIT_GL_FUNC(MultiDrawElements)
INIT_GL_FUNC(ShaderSource)
INIT_GL_FUNC(TexStorage2D)
INIT_GL_FUNC(Uniform1f)
INIT_GL_FUNC(Uniform2f)
INIT_GL_FUNC(Uniform3f)
INIT_GL_FUNC(Uniform4f)
INIT_GL_FUNC(Uniform1fv)
INIT_GL_FUNC(Uniform2fv)
INIT_GL_FUNC(Uniform3fv)
INIT_GL_FUNC(Uniform4fv)
INIT_GL_FUNC(Uniform1i)
INIT_GL_FUNC(Uniform2i)
INIT_GL_FUNC(Uniform3i)
INIT_GL_FUNC(Uniform4i)
INIT_GL_FUNC(Uniform1iv)
INIT_GL_FUNC(Uniform2iv)
INIT_GL_FUNC(Uniform3iv)
INIT_GL_FUNC(Uniform4iv)
INIT_GL_FUNC(UniformMatrix4fv)
INIT_GL_FUNC(UnmapBuffer)
INIT_GL_FUNC(UseProgram)
Expand Down Expand Up @@ -664,6 +683,7 @@ static void _bolt_gl_init() {
program_direct_screen_d_xywh = gl.GetUniformLocation(program_direct_screen, "d_xywh");
program_direct_screen_s_xywh = gl.GetUniformLocation(program_direct_screen, "s_xywh");
program_direct_screen_src_wh_dest_wh = gl.GetUniformLocation(program_direct_screen, "src_wh_dest_wh");
program_direct_screen_rgba = gl.GetUniformLocation(program_direct_screen, "rgba");

program_direct_surface = gl.CreateProgram();
gl.AttachShader(program_direct_surface, direct_surface_vs);
Expand All @@ -673,6 +693,7 @@ static void _bolt_gl_init() {
program_direct_surface_d_xywh = gl.GetUniformLocation(program_direct_surface, "d_xywh");
program_direct_surface_s_xywh = gl.GetUniformLocation(program_direct_surface, "s_xywh");
program_direct_surface_src_wh_dest_wh = gl.GetUniformLocation(program_direct_surface, "src_wh_dest_wh");
program_direct_surface_rgba = gl.GetUniformLocation(program_direct_surface, "rgba");

gl.DetachShader(program_direct_screen, direct_screen_vs);
gl.DetachShader(program_direct_screen, direct_fs);
Expand Down Expand Up @@ -2118,6 +2139,9 @@ static void _bolt_gl_plugin_surface_init(struct SurfaceFunctions* functions, uns
struct GLContext* c = _bolt_context();
userdata->width = width;
userdata->height = height;
for (size_t i = 0; i < 4; i += 1) {
userdata->rgba[i] = 1.0;
}
_bolt_gl_surface_init_buffers(userdata);
if (data) {
lgl->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
Expand All @@ -2130,6 +2154,8 @@ static void _bolt_gl_plugin_surface_init(struct SurfaceFunctions* functions, uns
functions->subimage = _bolt_gl_plugin_surface_subimage;
functions->draw_to_screen = _bolt_gl_plugin_surface_drawtoscreen;
functions->draw_to_surface = _bolt_gl_plugin_surface_drawtosurface;
functions->set_tint = _bolt_gl_plugin_surface_set_tint;
functions->set_alpha = _bolt_gl_plugin_surface_set_alpha;

const struct GLTexture2D* original_tex = c->texture_units[c->active_texture];
lgl->BindTexture(GL_TEXTURE_2D, original_tex ? original_tex->id : 0);
Expand Down Expand Up @@ -2186,6 +2212,7 @@ static void _bolt_gl_plugin_surface_drawtoscreen(void* _userdata, int sx, int sy
gl.Uniform4i(program_direct_screen_d_xywh, dx, dy, dw, dh);
gl.Uniform4i(program_direct_screen_s_xywh, sx, sy, sw, sh);
gl.Uniform4i(program_direct_screen_src_wh_dest_wh, userdata->width, userdata->height, gl_width, gl_height);
gl.Uniform4fv(program_direct_screen_rgba, 1, userdata->rgba);
lgl->Viewport(0, 0, gl_width, gl_height);
lgl->Disable(GL_DEPTH_TEST);
lgl->Disable(GL_SCISSOR_TEST);
Expand Down Expand Up @@ -2220,6 +2247,7 @@ static void _bolt_gl_plugin_surface_drawtosurface(void* _userdata, void* _target
gl.Uniform4i(program_direct_surface_d_xywh, dx, dy, dw, dh);
gl.Uniform4i(program_direct_surface_s_xywh, sx, sy, sw, sh);
gl.Uniform4i(program_direct_surface_src_wh_dest_wh, userdata->width, userdata->height, target->width, target->height);
gl.Uniform4fv(program_direct_screen_rgba, 1, userdata->rgba);
lgl->Viewport(0, 0, target->width, target->height);
lgl->Disable(GL_DEPTH_TEST);
lgl->Disable(GL_SCISSOR_TEST);
Expand All @@ -2237,6 +2265,18 @@ static void _bolt_gl_plugin_surface_drawtosurface(void* _userdata, void* _target
gl.UseProgram(c->bound_program ? c->bound_program->id : 0);
}

static void _bolt_gl_plugin_surface_set_tint(void* userdata, double r, double g, double b) {
struct PluginSurfaceUserdata* surface = userdata;
surface->rgba[0] = (GLfloat)r;
surface->rgba[1] = (GLfloat)g;
surface->rgba[2] = (GLfloat)b;
}

static void _bolt_gl_plugin_surface_set_alpha(void* userdata, double alpha) {
struct PluginSurfaceUserdata* surface = userdata;
surface->rgba[3] = (GLfloat)alpha;
}

static void _bolt_gl_plugin_draw_region_outline(void* userdata, int16_t x, int16_t y, uint16_t width, uint16_t height) {
struct PluginSurfaceUserdata* target = userdata;
struct GLContext* c = _bolt_context();
Expand Down
13 changes: 13 additions & 0 deletions src/library/gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,22 @@ struct GLProcFunctions {
void (*MultiDrawElements)(GLenum, const GLsizei*, GLenum, const void* const*, GLsizei);
void (*ShaderSource)(GLuint, GLsizei, const GLchar**, const GLint*);
void (*TexStorage2D)(GLenum, GLsizei, GLenum, GLsizei, GLsizei);
void (*Uniform1f)(GLint, GLfloat);
void (*Uniform2f)(GLint, GLfloat, GLfloat);
void (*Uniform3f)(GLint, GLfloat, GLfloat, GLfloat);
void (*Uniform4f)(GLint, GLfloat, GLfloat, GLfloat, GLfloat);
void (*Uniform1fv)(GLint, GLsizei, const GLfloat*);
void (*Uniform2fv)(GLint, GLsizei, const GLfloat*);
void (*Uniform3fv)(GLint, GLsizei, const GLfloat*);
void (*Uniform4fv)(GLint, GLsizei, const GLfloat*);
void (*Uniform1i)(GLint, GLint);
void (*Uniform2i)(GLint, GLint, GLint);
void (*Uniform3i)(GLint, GLint, GLint, GLint);
void (*Uniform4i)(GLint, GLint, GLint, GLint, GLint);
void (*Uniform1iv)(GLint, GLsizei, const GLint*);
void (*Uniform2iv)(GLint, GLsizei, const GLint*);
void (*Uniform3iv)(GLint, GLsizei, const GLint*);
void (*Uniform4iv)(GLint, GLsizei, const GLint*);
void (*UniformMatrix4fv)(GLint, GLsizei, GLboolean, const GLfloat*);
GLboolean (*UnmapBuffer)(GLenum);
void (*UseProgram)(GLuint);
Expand Down
8 changes: 8 additions & 0 deletions src/library/plugin/plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,14 @@ struct SurfaceFunctions {
/// Draws a rectangle from the surface, indicated by sx,sy,sw,sh, to a rectangle on the target surface,
/// indicated by dx,dy,dw,dh. All values are in pixels.
void (*draw_to_surface)(void* userdata, void* target, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh);

/// Sets the tint this surface will be drawn with when calling draw_to_screen or draw_to_surface.
/// Values are in the range [0.0 - 1.0]. Defaults are 1.0.
void (*set_tint)(void* userdata, double r, double g, double b);

/// Sets the transparency this surface will be drawn with when calling draw_to_screen or draw_to_surface.
/// Value is in the range [0.0 - 1.0] with 0.0 being invisible and 1.0 being fully opaque. Default is 1.0.
void (*set_alpha)(void* userdata, double alpha);
};

/// Struct containing "vtable" callback information for shaders
Expand Down
18 changes: 18 additions & 0 deletions src/library/plugin/plugin_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,22 @@ static int api_surface_drawtowindow(lua_State* state) {
return 0;
}

static int api_surface_settint(lua_State* state) {
const struct SurfaceFunctions* functions = require_self_userdata(state, "settint");
const lua_Number r = luaL_checknumber(state, 2);
const lua_Number g = luaL_checknumber(state, 3);
const lua_Number b = luaL_checknumber(state, 4);
functions->set_tint(functions->userdata, r, g, b);
return 0;
}

static int api_surface_setalpha(lua_State* state) {
const struct SurfaceFunctions* functions = require_self_userdata(state, "setalpha");
const lua_Number alpha = luaL_checknumber(state, 2);
functions->set_alpha(functions->userdata, alpha);
return 0;
}

static int api_window_close(lua_State* state) {
struct EmbeddedWindow* window = require_self_userdata(state, "state");
window->is_deleted = true;
Expand Down Expand Up @@ -1841,6 +1857,8 @@ static struct ApiFuncTemplate surface_functions[] = {
BOLTFUNC(drawtoscreen, surface),
BOLTFUNC(drawtosurface, surface),
BOLTFUNC(drawtowindow, surface),
BOLTFUNC(settint, surface),
BOLTFUNC(setalpha, surface),
};

static struct ApiFuncTemplate window_functions[] = {
Expand Down

0 comments on commit 216115a

Please sign in to comment.