Pixel-Composer/scripts/BBMOD_PostProcessor/BBMOD_PostProcessor.gml
2023-04-23 16:47:33 +02:00

174 lines
5.4 KiB
Text

/// @func BBMOD_PostProcessor()
///
/// @extends BBMOD_Class
///
/// @desc Handles post-processing effects like color grading, chromatic aberration,
/// grayscale effect, vignette and anti-aliasing.
function BBMOD_PostProcessor()
: BBMOD_Class() constructor
{
BBMOD_CLASS_GENERATED_BODY;
static Class_destroy = destroy;
/// @var {Id.Surface}
/// @private
__surPostProcess = noone;
/// @var {Bool} If `true` then the post-processor is enabled. Default value
/// is `true`.
Enabled = true;
/// @var {Pointer.Texture} The lookup table texture used for color grading.
/// @note Post-processing must be enabled for this to have any effect!
/// @see BBMOD_Renderer.EnablePostProcessing
ColorGradingLUT = sprite_get_texture(BBMOD_SprColorGradingLUT, 0);
/// @var {Real} The strength of the chromatic aberration effect. Use 0 to
/// disable the effect. Defaults to 0.
/// @note Post-processing must be enabled for this to have any effect!
/// @see BBMOD_Renderer.EnablePostProcessing
ChromaticAberration = 0.0;
/// @var {Real} Chromatic aberration offsets for RGB channels. Defaults to
/// `(-1, 0, 1)`.
/// @note Post-processing must be enabled for this to have any effect!
/// @see BBMOD_Renderer.EnablePostProcessing
ChromaticAberrationOffset = new BBMOD_Vec3(-1.0, 0.0, 1.0);
/// @var {Real} The strength of the grayscale effect. Use values in range 0..1,
/// where 0 means the original color and 1 means grayscale. Defaults to 0.
/// @note Post-processing must be enabled for this to have any effect!
/// @see BBMOD_Renderer.EnablePostProcessing
Grayscale = 0.0;
/// @var {Real} The strength of the vignette effect. Defaults to 0.
/// @note Post-processing must be enabled for this to have any effect!
/// @see BBMOD_Renderer.EnablePostProcessing
Vignette = 0.0;
/// @var {Real} The color of the vignette effect. Defaults to `c_black`.
/// @note Post-processing must be enabled for this to have any effect!
/// @see BBMOD_Renderer.EnablePostProcessing
VignetteColor = c_black;
/// @var {Real} Antialiasing technique to use. Use values from
/// {@link BBMOD_EAntialiasing}. Defaults to {@link BBMOD_EAntialiasing.None}.
Antialiasing = BBMOD_EAntialiasing.None;
/// @func draw(_surface, _x, _y)
///
/// @desc If enabled, draws a surface with post-processing applied, otherwise
/// draws the original surface.
///
/// @param {Id.Surface} _surface The surface to draw with post-processing
/// applied.
/// @param {Real} _x The X position to draw the surface at.
/// @param {Real} _y The Y position to draw the surface at.
///
/// @return {Struct.BBMOD_PostProcessor} Returns `self`.
///
/// @see BBMOD_PostProcessor.Enabled
static draw = function (_surface, _x, _y) {
if (!Enabled)
{
draw_surface(_surface, _x, _y);
return self;
}
var _world = matrix_get(matrix_world);
var _width = surface_get_width(_surface);
var _height = surface_get_height(_surface);
var _texelWidth = 1.0 / _width;
var _texelHeight = 1.0 / _height;
var _surFinal = _surface;
gpu_push_state();
gpu_set_tex_filter(true);
gpu_set_tex_repeat(false);
gpu_set_blendenable(false);
////////////////////////////////////////////////////////////////////
// Do post-processing
if (Antialiasing != BBMOD_EAntialiasing.None)
{
// If anti-aliasing is enabled, we need to do post-processing in
// another surface...
__surPostProcess = bbmod_surface_check(__surPostProcess, _width, _height);
surface_set_target(__surPostProcess);
matrix_set(matrix_world, matrix_build_identity());
}
var _shader = BBMOD_ShPostProcess;
shader_set(_shader);
texture_set_stage(
shader_get_sampler_index(_shader, "u_texLut"),
ColorGradingLUT);
shader_set_uniform_f(
shader_get_uniform(_shader, "u_vTexel"),
_texelWidth, _texelHeight);
shader_set_uniform_f(
shader_get_uniform(_shader, "u_vOffset"),
ChromaticAberrationOffset.X,
ChromaticAberrationOffset.Y,
ChromaticAberrationOffset.Z);
shader_set_uniform_f(
shader_get_uniform(_shader, "u_fDistortion"),
ChromaticAberration);
shader_set_uniform_f(
shader_get_uniform(_shader, "u_fGrayscale"),
Grayscale);
shader_set_uniform_f(
shader_get_uniform(_shader, "u_fVignette"),
Vignette);
shader_set_uniform_f(
shader_get_uniform(_shader, "u_vVignetteColor"),
color_get_red(VignetteColor) / 255.0,
color_get_green(VignetteColor) / 255.0,
color_get_blue(VignetteColor) / 255.0);
draw_surface(
_surface,
(Antialiasing == BBMOD_EAntialiasing.None) ? _x : 0,
(Antialiasing == BBMOD_EAntialiasing.None) ? _y : 0);
shader_reset();
if (Antialiasing != BBMOD_EAntialiasing.None)
{
// Reset surface...
surface_reset_target();
matrix_set(matrix_world, _world);
_surFinal = __surPostProcess;
}
////////////////////////////////////////////////////////////////////
// Apply anti-aliasing to the final surface
if (Antialiasing == BBMOD_EAntialiasing.FXAA)
{
var _shader = BBMOD_ShFXAA;
shader_set(_shader);
shader_set_uniform_f(
shader_get_uniform(_shader, "u_vTexelVS"),
_texelWidth, _texelHeight);
shader_set_uniform_f(
shader_get_uniform(_shader, "u_vTexelPS"),
_texelWidth, _texelHeight);
draw_surface(_surFinal, _x, _y);
shader_reset();
}
gpu_pop_state();
return self;
};
static destroy = function () {
Class_destroy();
if (surface_exists(__surPostProcess))
{
surface_free(__surPostProcess);
}
return undefined;
};
}