Skip to content

Instantly share code, notes, and snippets.

@JujuAdams
Created June 21, 2025 11:23
Show Gist options
  • Select an option

  • Save JujuAdams/967bc94446d0ceec4a930e8b5f04cca0 to your computer and use it in GitHub Desktop.

Select an option

Save JujuAdams/967bc94446d0ceec4a930e8b5f04cca0 to your computer and use it in GitHub Desktop.
surface_bbox
// Feather disable all
/// @param surface
/// @param [threshold=0]
/// @param [left]
/// @param [top]
/// @param [width]
/// @param [height]
function surface_bbox(_surfaceIn, _threshold = 0, _leftIn = 0, _topIn = 0, _widthIn = surface_get_width(_surfaceIn), _heightIn = surface_get_height(_surfaceIn))
{
static _surface_bbox_shader_u_fThreshold = shader_get_uniform(__surface_bbox_shader, "u_fThreshold");
static _surfaceA = -1;
static _surfaceB = -1;
static _surfaceC = -1;
static _surfaceEnsure = function(_surface, _width, _height)
{
if (surface_exists(_surface) && ((surface_get_width(_surface) < _width) || (surface_get_height(_surface) < _height)))
{
surface_free(_surface);
}
if (not surface_exists(_surface))
{
_surface = surface_create(_width, _height, surface_rgba16float);
}
return _surface;
}
var _widthA = ceil(_widthIn/2);
var _heightA = ceil(_heightIn/2);
_surfaceA = _surfaceEnsure(_surfaceA, _widthA, _heightA);
_surfaceB = _surfaceEnsure(_surfaceB, ceil(_widthA/2), ceil(_heightA/2));
_surfaceC = _surfaceEnsure(_surfaceC, 1, 1);
surface_set_target(_surfaceB);
draw_clear_alpha(#ffffff, 1);
surface_reset_target();
surface_set_target(_surfaceA);
draw_clear_alpha(#ffffff, 1);
gpu_push_state();
gpu_set_tex_filter(false);
gpu_set_tex_repeat(false);
gpu_set_blendenable(true);
gpu_set_blendmode_ext(bm_one, bm_one);
gpu_set_blendequation(bm_eq_min);
gpu_set_ztestenable(false);
shader_set(__surface_bbox_shader);
shader_set_uniform_f(_surface_bbox_shader_u_fThreshold, _threshold);
var _widthRem = _widthIn - _widthA;
var _heightRem = _heightIn - _heightA;
draw_surface_part(_surfaceIn, _leftIn, _topIn, _widthA, _heightA, 0, 0);
draw_surface_part(_surfaceIn, _leftIn + _widthA, _topIn, _widthRem, _heightA, 0, 0);
draw_surface_part(_surfaceIn, _leftIn, _topIn + _heightA, _widthA, _heightRem, 0, 0);
draw_surface_part(_surfaceIn, _leftIn + _widthA, _topIn + _heightA, _widthRem, _heightRem, 0, 0);
shader_reset();
surface_reset_target();
var _iterations = ceil(max(logn(2, _widthIn), logn(2, _heightIn)));
if (_iterations < 2)
{
_surfaceFrom = _surfaceA;
}
else
{
var _widthFrom = _widthA;
var _heightFrom = _heightA;
var _surfaceFrom = _surfaceA;
var _surfaceTo = _surfaceB;
repeat(_iterations-1)
{
surface_set_target(_surfaceTo);
var _widthTo = ceil(_widthFrom/2);
var _heightTo = ceil(_heightFrom/2);
var _widthRem = _widthFrom - _widthTo;
var _heightRem = _heightFrom - _heightTo;
draw_surface_part(_surfaceFrom, 0, 0, _widthTo, _heightTo, 0, 0);
draw_surface_part(_surfaceFrom, _widthTo, 0, _widthRem, _heightTo, 0, 0);
draw_surface_part(_surfaceFrom, 0, _heightTo, _widthTo, _heightRem, 0, 0);
draw_surface_part(_surfaceFrom, _widthTo, _heightTo, _widthRem, _heightRem, 0, 0);
surface_reset_target();
var _temp = _surfaceFrom;
_surfaceFrom = _surfaceTo;
_surfaceTo = _temp;
_widthFrom = _widthTo;
_heightFrom = _heightTo;
}
}
gpu_pop_state();
surface_copy_part(_surfaceC, 0, 0, _surfaceFrom, 0, 0, 1, 1);
static _buffer = buffer_create(8, buffer_fixed, 1);
buffer_get_surface(_buffer, _surfaceC, 0);
buffer_seek(_buffer, buffer_seek_start, 0);
var _u0 = buffer_read(_buffer, buffer_f16);
var _v0 = buffer_read(_buffer, buffer_f16);
var _u1 = buffer_read(_buffer, buffer_f16);
var _v1 = buffer_read(_buffer, buffer_f16);
var _widthSurf = surface_get_width(_surfaceIn);
var _heightSurf = surface_get_height(_surfaceIn);
static _result = {
left: 0,
top: 0,
right: 0,
bottom: 0,
};
_result.left = floor(_widthSurf * _u0) - _leftIn;
_result.top = floor(_heightSurf * _v0) - _topIn;
_result.right = ceil(_widthSurf * (1 - _u1)) - _leftIn;
_result.bottom = ceil(_heightSurf * (1 - _v1)) - _topIn;
return _result;
}
///////
// __surface_bbox_shader vertex shader
///////
attribute vec3 in_Position;
attribute vec4 in_Colour;
attribute vec2 in_TextureCoord;
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
void main()
{
vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0);
gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
v_vColour = in_Colour;
v_vTexcoord = in_TextureCoord;
}
///////
// __surface_bbox_shader fragment shader
///////
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform float u_fThreshold;
void main()
{
if (texture2D(gm_BaseTexture, v_vTexcoord).a <= u_fThreshold)
{
gl_FragColor = vec4(1.0);
}
else
{
gl_FragColor = vec4(v_vTexcoord, 1.0 - v_vTexcoord);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment