Created
June 21, 2025 11:23
-
-
Save JujuAdams/967bc94446d0ceec4a930e8b5f04cca0 to your computer and use it in GitHub Desktop.
surface_bbox
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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