mirror of
https://github.com/Ttanasart-pt/Pixel-Composer.git
synced 2025-02-16 07:05:14 +01:00
864 lines
25 KiB
Text
864 lines
25 KiB
Text
/// @func BBMOD_BaseRenderer()
|
|
///
|
|
/// @extends BBMOD_Class
|
|
///
|
|
/// @desc Base struct for renderers, which execute
|
|
/// [render commands](./BBMOD_RenderCommand.html) created with method
|
|
/// [render](./BBMOD_Model.render.html).
|
|
///
|
|
/// @see BBMOD_DefaultRenderer
|
|
function BBMOD_BaseRenderer()
|
|
: BBMOD_Class() constructor
|
|
{
|
|
BBMOD_CLASS_GENERATED_BODY;
|
|
|
|
static Class_destroy = destroy;
|
|
|
|
/// @var {Real} The X position of the renderer on the screen. Default value
|
|
/// is 0.
|
|
X = 0;
|
|
|
|
/// @var {Real} The Y position of the renderer on the screen. Default value
|
|
/// is 0.
|
|
Y = 0;
|
|
|
|
/// @var {Real} The width of the renderer on the screen. If `undefined` then
|
|
/// the window width is used. Default value is `undefined`.
|
|
Width = undefined;
|
|
|
|
/// @var {Real} The height of the renderer on the screen. If `undefined`
|
|
/// then the window height is used. Default value is `undefined`.
|
|
Height = undefined;
|
|
|
|
/// @var {Bool} If `true` then rendering of instance IDs into an off-screen
|
|
/// surface is enabled. This must be enabled if you would like to use method
|
|
/// {@link BBMOD_BaseRenderer.get_instance_id} for mouse-picking instances.
|
|
/// Default value is `false`.
|
|
RenderInstanceIDs = false;
|
|
|
|
/// @var {Id.Surface} Surface for rendering highlight of selected instances.
|
|
/// @private
|
|
__surInstanceHighlight = noone;
|
|
|
|
/// @var {Struct.BBMOD_Color} Outline color of instances selected by gizmo.
|
|
/// Default value is {@link BBMOD_C_ORANGE}.
|
|
/// @see BBMOD_BaseRenderer.Gizmo
|
|
InstanceHighlightColor = BBMOD_C_ORANGE;
|
|
|
|
/// @var {Bool} If `true` then edit mode is enabled. Default value is `false`.
|
|
EditMode = false;
|
|
|
|
/// @var {Bool} If `true` then mousepicking of gizmo and instances is enabled.
|
|
/// Default value is `true`.
|
|
/// @note This can be useful for example to disable mousepicking when the
|
|
/// mouse cursor is over UI.
|
|
EnableMousepick = true;
|
|
|
|
/// @var {Constant.MouseButton} The mouse button used to select instances when
|
|
/// edit mode is enabled. Default value is `mb_left`.
|
|
/// @see BBMOD_BaseRenderer.EditMode
|
|
ButtonSelect = mb_left;
|
|
|
|
/// @var {Constant.VirtualKey} The keyboard key used to add/remove instances
|
|
/// from multiple selection when edit mode is enabled. Default value is
|
|
/// `vk_shift`.
|
|
/// @see BBMOD_BaseRenderer.EditMode
|
|
KeyMultiSelect = vk_shift;
|
|
|
|
/// @var {Struct.BBMOD_Gizmo} A gizmo for transforming instances when
|
|
/// {@link BBMOD_BaseRenderer.EditMode} is enabled. This is by default `undefined`.
|
|
/// @see BBMOD_Gizmo
|
|
Gizmo = undefined;
|
|
|
|
/// @var {Id.Surface} A surface containing the gizmo. Used to enable
|
|
/// z-testing against itself, but ingoring the scene geometry.
|
|
/// @private
|
|
__surGizmo = noone;
|
|
|
|
/// @var {Id.Surface} Surface for mouse-picking the gizmo.
|
|
/// @private
|
|
__surSelect = noone;
|
|
|
|
/// @var {Array<Struct.BBMOD_IRenderable>} An array of renderable objects
|
|
/// and structs. These are automatically rendered in
|
|
/// {@link BBMOD_BaseRenderer.render}.
|
|
/// @readonly
|
|
/// @see BBMOD_BaseRenderer.add
|
|
/// @see BBMOD_BaseRenderer.remove
|
|
/// @see BBMOD_IRenderable
|
|
Renderables = [];
|
|
|
|
/// @var {Bool} Set to `true` to enable the `application_surface`.
|
|
/// Use method {@link BBMOD_BaseRenderer.present} to draw the
|
|
/// `application_surface` to the screen. Defaults to `false`.
|
|
UseAppSurface = false;
|
|
|
|
/// @var {Real} Resolution multiplier for the `application_surface`.
|
|
/// {@link BBMOD_BaseRenderer.UseAppSurface} must be enabled for this to
|
|
/// have any effect. Defaults to 1. Use lower values to improve framerate.
|
|
RenderScale = 1.0;
|
|
|
|
/// @var {Bool} Enables rendering into a shadowmap in the shadows render pass.
|
|
/// Defauls to `false`.
|
|
/// @see BBMOD_BaseRenderer.ShadowmapArea
|
|
/// @see BBMOD_BaseRenderer.ShadowmapResolution
|
|
EnableShadows = false;
|
|
|
|
/// @var {Id.Surface} The surface used for rendering the scene's depth from the
|
|
/// directional light's view.
|
|
/// @private
|
|
__surShadowmap = noone;
|
|
|
|
/// @var {Real} The area captured by the shadowmap. Defaults to 1024.
|
|
/// @obsolete This has been replaced with {@link BBMOD_DirectionalLight.ShadowmapArea}.
|
|
ShadowmapArea = 1024.
|
|
|
|
/// @var {Real} The resolution of the shadowmap surface. Must be power of 2.
|
|
/// Defaults to 4096.
|
|
/// @obsolete This has been replaced with {@link BBMOD_Light.ShadowmapResolution}.
|
|
ShadowmapResolution = 4096;
|
|
|
|
/// @var {Real} When rendering shadows, offsets vertex position by its normal
|
|
/// scaled by this value. Defaults to 1. Increasing the value can remove some
|
|
/// artifacts but using too high value could make the objects appear flying
|
|
/// above the ground.
|
|
ShadowmapNormalOffset = 1;
|
|
|
|
/// @var {Bool} Enables post-processing effects. Defaults to `false`. Enabling
|
|
/// this requires the [Post-processing submodule](./PostProcessingSubmodule.html)!
|
|
///
|
|
/// @note {@link BBMOD_BaseRenderer.UseAppSurface} must be enabled for this to
|
|
/// have any effect!
|
|
///
|
|
/// @obsolete Post-processing is now handled through
|
|
/// {@link BBMOD_BaseRenderer.PostProcessor}!
|
|
EnablePostProcessing = false;
|
|
|
|
/// @var {Struct.BBMOD_PostProcessor} Handles post-processing effects if
|
|
/// isn't `undefined` and {@link BBMOD_BaseRenderer.UseAppSurface} is enabled.
|
|
/// Default value is `undefined`.
|
|
/// @see BBMOD_PostProcessor
|
|
PostProcessor = undefined;
|
|
|
|
/// @var {Id.Surface}
|
|
/// @private
|
|
__surFinal = noone;
|
|
|
|
/// @func get_width()
|
|
///
|
|
/// @desc Retrieves the width of the renderer on the screen.
|
|
///
|
|
/// @return {Real} The width of the renderer on the screen.
|
|
static get_width = function () {
|
|
gml_pragma("forceinline");
|
|
return max((Width == undefined) ? window_get_width() : Width, 1);
|
|
};
|
|
|
|
/// @func get_height()
|
|
///
|
|
/// @desc Retrieves the height of the renderer on the screen.
|
|
///
|
|
/// @return {Real} The height of the renderer on the screen.
|
|
static get_height = function () {
|
|
gml_pragma("forceinline");
|
|
return max((Height == undefined) ? window_get_height() : Height, 1);
|
|
};
|
|
|
|
/// @func get_render_width()
|
|
///
|
|
/// @desc Retrieves the width of the renderer with
|
|
///
|
|
/// {@link BBMOD_BaseRenderer.RenderScale} applied.
|
|
///
|
|
/// @return {Real} The width of the renderer after `RenderScale` is applied.
|
|
static get_render_width = function () {
|
|
gml_pragma("forceinline");
|
|
return max(get_width() * RenderScale, 1);
|
|
};
|
|
|
|
/// @func get_render_height()
|
|
///
|
|
/// @desc Retrieves the height of the renderer with
|
|
/// {@link BBMOD_BaseRenderer.RenderScale} applied.
|
|
///
|
|
/// @return {Real} The height of the renderer after `RenderScale` is applied.
|
|
static get_render_height = function () {
|
|
gml_pragma("forceinline");
|
|
return max(get_height() * RenderScale, 1);
|
|
};
|
|
|
|
/// @func set_position(_x, _y)
|
|
///
|
|
/// @desc Changes the renderer's position on the screen.
|
|
///
|
|
/// @param {Real} _x The new X position on the screen.
|
|
/// @param {Real} _y The new Y position on the screen.
|
|
///
|
|
/// @return {Struct.BBMOD_BaseRenderer} Returns `self`.
|
|
static set_position = function (_x, _y) {
|
|
gml_pragma("forceinline");
|
|
X = _x;
|
|
Y = _y;
|
|
return self;
|
|
};
|
|
|
|
/// @func set_size(_width, _height)
|
|
///
|
|
/// @desc Changes the renderer's size on the screen.
|
|
///
|
|
/// @param {Real} _width The new width on the screen.
|
|
/// @param {Real} _height The new height on the screen.
|
|
///
|
|
/// @return {Struct.BBMOD_BaseRenderer} Returns `self`.
|
|
static set_size = function (_width, _height) {
|
|
gml_pragma("forceinline");
|
|
Width = _width;
|
|
Height = _height;
|
|
return self;
|
|
};
|
|
|
|
/// @func set_rectangle(_x, _y, _width, _height)
|
|
///
|
|
/// @desc Changes the renderer's position and size on the screen.
|
|
///
|
|
/// @param {Real} _x The new X position on the screen.
|
|
/// @param {Real} _y The new Y position on the screen.
|
|
/// @param {Real} _width The new width on the screen.
|
|
/// @param {Real} _height The new height on the screen.
|
|
///
|
|
/// @return {Struct.BBMOD_BaseRenderer} Returns `self`.
|
|
static set_rectangle = function (_x, _y, _width, _height) {
|
|
gml_pragma("forceinline");
|
|
set_position(_x, _y);
|
|
set_size(_width, _height);
|
|
return self;
|
|
};
|
|
|
|
/// @func select_gizmo(_screenX, _screenY)
|
|
///
|
|
/// @desc Tries to select a gizmo at given screen coordinates and
|
|
/// automatically changes its {@link BBMOD_Gizmo.EditAxis} and
|
|
/// {@link BBMOD_Gizmo.EditType} based on which part of the gizmo
|
|
/// was selected.
|
|
///
|
|
/// @param {Real} _screenX The X position on the screen.
|
|
/// @param {Real} _screenY The Y position on the screen.
|
|
///
|
|
/// @return {Bool} Returns `true` if the gizmo was selected.
|
|
///
|
|
/// @note {@link BBMOD_BaseRenderer.Gizmo} must be defined.
|
|
///
|
|
/// @private
|
|
static select_gizmo = function (_screenX, _screenY) {
|
|
_screenX = clamp(_screenX - X, 0, get_width()) * RenderScale;
|
|
_screenY = clamp(_screenY - Y, 0, get_height()) * RenderScale;
|
|
|
|
Gizmo.EditAxis = BBMOD_EEditAxis.None;
|
|
|
|
var _pixel = surface_getpixel_ext(__surSelect, _screenX, _screenY);
|
|
if (_pixel & $FF000000 == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var _blue = (_pixel >> 16) & 255;
|
|
var _green = (_pixel >> 8) & 255;
|
|
var _red = _pixel & 255;
|
|
var _value = max(_red, _green, _blue);
|
|
|
|
Gizmo.EditAxis = 0
|
|
| (BBMOD_EEditAxis.X * (_red > 0))
|
|
| (BBMOD_EEditAxis.Y * (_green > 0))
|
|
| (BBMOD_EEditAxis.Z * (_blue > 0));
|
|
|
|
Gizmo.EditType = ((_value == 255) ? BBMOD_EEditType.Position
|
|
: ((_value == 128) ? BBMOD_EEditType.Rotation
|
|
: BBMOD_EEditType.Scale));
|
|
|
|
return true;
|
|
};
|
|
|
|
/// @func get_instance_id(_screenX, _screenY)
|
|
///
|
|
/// @desc Retrieves an ID of an instance at given position on the screen.
|
|
///
|
|
/// @param {Real} _screenX The X position on the screen.
|
|
/// @param {Real} _screenY The Y position on the screen.
|
|
///
|
|
/// @return {Id.Instance} The ID of the instance or 0 if no instance was
|
|
/// found at the given position.
|
|
///
|
|
/// @note {@link BBMOD_BaseRenderer.RenderInstanceIDs} must be enabled.
|
|
static get_instance_id = function (_screenX, _screenY) {
|
|
gml_pragma("forceinline");
|
|
if (!surface_exists(__surSelect))
|
|
{
|
|
return 0;
|
|
}
|
|
_screenX = clamp(_screenX - X, 0, get_width()) * RenderScale;
|
|
_screenY = clamp(_screenY - Y, 0, get_height()) * RenderScale;
|
|
return surface_getpixel_ext(__surSelect, _screenX, _screenY);
|
|
};
|
|
|
|
/// @func add(_renderable)
|
|
///
|
|
/// @desc Adds a renderable object or struct to the renderer.
|
|
///
|
|
/// @param {Struct.BBMOD_IRenderable} _renderable The renderable object or
|
|
/// struct to add.
|
|
///
|
|
/// @return {Struct.BBMOD_BaseRenderer} Returns `self`.
|
|
///
|
|
/// @see BBMOD_BaseRenderer.remove
|
|
/// @see BBMOD_IRenderable
|
|
static add = function (_renderable) {
|
|
gml_pragma("forceinline");
|
|
array_push(Renderables, _renderable);
|
|
return self;
|
|
};
|
|
|
|
/// @func remove(_renderable)
|
|
///
|
|
/// @desc Removes a renderable object or a struct from the renderer.
|
|
///
|
|
/// @param {Struct.BBMOD_IRenderable} _renderable The renderable object or
|
|
/// struct to remove.
|
|
///
|
|
/// @return {Struct.BBMOD_BaseRenderer} Returns `self`.
|
|
///
|
|
/// @see BBMOD_BaseRenderer.add
|
|
/// @see BBMOD_IRenderable
|
|
static remove = function (_renderable) {
|
|
gml_pragma("forceinline");
|
|
for (var i = array_length(Renderables) - 1; i >= 0; --i)
|
|
{
|
|
if (Renderables[i] == _renderable)
|
|
{
|
|
array_delete(Renderables, i, 1);
|
|
}
|
|
}
|
|
return self;
|
|
};
|
|
|
|
/// @func update(_deltaTime)
|
|
///
|
|
/// @desc Updates the renderer. This should be called in the Step event.
|
|
///
|
|
/// @param {Real} _deltaTime How much time has passed since the last frame
|
|
/// (in microseconds).
|
|
///
|
|
/// @return {Struct.BBMOD_BaseRenderer} Returns `self`.
|
|
static update = function (_deltaTime) {
|
|
global.__bbmodRendererCurrent = self;
|
|
|
|
if (UseAppSurface)
|
|
{
|
|
application_surface_enable(true);
|
|
application_surface_draw_enable(false);
|
|
|
|
var _surfaceWidth = get_render_width();
|
|
var _surfaceHeight = get_render_height();
|
|
|
|
if (surface_exists(application_surface)
|
|
&& (surface_get_width(application_surface) != _surfaceWidth
|
|
|| surface_get_height(application_surface) != _surfaceHeight))
|
|
{
|
|
surface_resize(application_surface, _surfaceWidth, _surfaceHeight);
|
|
}
|
|
}
|
|
|
|
if (Gizmo && EditMode)
|
|
{
|
|
Gizmo.update(delta_time);
|
|
}
|
|
|
|
return self;
|
|
};
|
|
|
|
/// @func __render_shadowmap()
|
|
///
|
|
/// @desc Renders a shadowmap.
|
|
///
|
|
/// @note This modifies render pass and view and projection matrices and
|
|
/// for optimization reasons it does not reset them back! Make sure to do
|
|
/// that yourself in the calling function if needed.
|
|
///
|
|
/// @private
|
|
static __render_shadowmap = function () {
|
|
gml_pragma("forceinline");
|
|
|
|
static _renderQueues = bbmod_render_queues_get();
|
|
|
|
var _shadowCaster = undefined;
|
|
var _shadowCasterIndex = -1;
|
|
var _shadowmapMatrix;
|
|
var _shadowmapZFar;
|
|
|
|
if (EnableShadows)
|
|
{
|
|
var _light = bbmod_light_directional_get();
|
|
if (_light != undefined
|
|
&& _light.CastShadows
|
|
&& _light.__getZFar != undefined
|
|
&& _light.__getShadowmapMatrix != undefined)
|
|
{
|
|
// Directional light
|
|
_shadowCaster = _light;
|
|
_shadowmapMatrix = _light.__getShadowmapMatrix();
|
|
_shadowmapZFar = _light.__getZFar();
|
|
}
|
|
else
|
|
{
|
|
// Punctual lights
|
|
var i = 0;
|
|
repeat (array_length(global.__bbmodPunctualLights))
|
|
{
|
|
var _light = global.__bbmodPunctualLights[i];
|
|
if (_light.CastShadows
|
|
&& _light.__getZFar != undefined
|
|
&& _light.__getShadowmapMatrix != undefined)
|
|
{
|
|
_shadowCaster = _light;
|
|
_shadowCasterIndex = i;
|
|
_shadowmapMatrix = _light.__getShadowmapMatrix();
|
|
_shadowmapZFar = _light.__getZFar();
|
|
break;
|
|
}
|
|
++i;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_shadowCaster == undefined)
|
|
{
|
|
if (surface_exists(__surShadowmap))
|
|
{
|
|
surface_free(__surShadowmap);
|
|
__surShadowmap = noone;
|
|
}
|
|
// No shadow caster was found!!!
|
|
bbmod_shader_unset_global("bbmod_Shadowmap");
|
|
bbmod_shader_set_global_f("bbmod_ShadowmapEnableVS", 0.0);
|
|
bbmod_shader_set_global_f("bbmod_ShadowmapEnablePS", 0.0);
|
|
return;
|
|
}
|
|
|
|
bbmod_render_pass_set(BBMOD_ERenderPass.Shadows);
|
|
|
|
__surShadowmap = bbmod_surface_check(
|
|
__surShadowmap, _light.ShadowmapResolution, _light.ShadowmapResolution);
|
|
|
|
surface_set_target(__surShadowmap);
|
|
draw_clear(c_red);
|
|
matrix_set(matrix_view, _light.__getViewMatrix());
|
|
matrix_set(matrix_projection, _light.__getProjMatrix());
|
|
bbmod_shader_set_global_f("bbmod_ZFar", _light.__getZFar());
|
|
|
|
var _rqi = 0;
|
|
repeat (array_length(_renderQueues))
|
|
{
|
|
_renderQueues[_rqi++].submit();
|
|
}
|
|
|
|
surface_reset_target();
|
|
|
|
var _shadowmapTexture = surface_get_texture(__surShadowmap);
|
|
bbmod_shader_set_global_f("bbmod_ShadowmapEnableVS", 1.0);
|
|
bbmod_shader_set_global_f("bbmod_ShadowmapEnablePS", 1.0);
|
|
bbmod_shader_set_global_sampler("bbmod_Shadowmap", _shadowmapTexture);
|
|
bbmod_shader_set_global_sampler_mip_enable("bbmod_Shadowmap", true);
|
|
bbmod_shader_set_global_sampler_filter("bbmod_Shadowmap", true);
|
|
bbmod_shader_set_global_sampler_repeat("bbmod_Shadowmap", false);
|
|
bbmod_shader_set_global_f2("bbmod_ShadowmapTexel",
|
|
texture_get_texel_width(_shadowmapTexture),
|
|
texture_get_texel_height(_shadowmapTexture));
|
|
bbmod_shader_set_global_f("bbmod_ShadowmapArea", _shadowmapZFar);
|
|
bbmod_shader_set_global_f("bbmod_ShadowmapNormalOffset", ShadowmapNormalOffset);
|
|
bbmod_shader_set_global_matrix_array("bbmod_ShadowmapMatrix", _shadowmapMatrix);
|
|
bbmod_shader_set_global_f("bbmod_ShadowCasterIndex", _shadowCasterIndex);
|
|
};
|
|
|
|
/// @func __render_gizmo_and_instance_ids()
|
|
///
|
|
/// @desc Renders gizmo and instance IDs into dedicated surfaces.
|
|
///
|
|
/// @private
|
|
static __render_gizmo_and_instance_ids = function () {
|
|
static _renderQueues = bbmod_render_queues_get();
|
|
|
|
var _view = matrix_get(matrix_view);
|
|
var _projection = matrix_get(matrix_projection);
|
|
var _renderWidth = get_render_width();
|
|
var _renderHeight = get_render_height();
|
|
|
|
var _editMode = (EditMode && Gizmo);
|
|
var _mouseX = window_mouse_get_x();
|
|
var _mouseY = window_mouse_get_y();
|
|
var _mouseOver = (_mouseX >= X && _mouseX < X + get_width()
|
|
&& _mouseY >= Y && _mouseY < Y + get_height());
|
|
var _continueMousePick = EnableMousepick;
|
|
var _gizmoSize;
|
|
|
|
if (_editMode)
|
|
{
|
|
_gizmoSize = Gizmo.Size;
|
|
|
|
if (_projection[11] != 0.0)
|
|
{
|
|
Gizmo.Size = _gizmoSize
|
|
* Gizmo.Position.Sub(bbmod_camera_get_position()).Length() / 100.0;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// Gizmo select
|
|
if (_editMode
|
|
&& _continueMousePick
|
|
&& _mouseOver
|
|
&& mouse_check_button_pressed(Gizmo.ButtonDrag))
|
|
{
|
|
__surSelect = bbmod_surface_check(__surSelect, _renderWidth, _renderHeight);
|
|
surface_set_target(__surSelect);
|
|
draw_clear_alpha(0, 0.0);
|
|
matrix_set(matrix_view, _view);
|
|
matrix_set(matrix_projection, _projection);
|
|
Gizmo.submit(Gizmo.MaterialsSelect);
|
|
surface_reset_target();
|
|
|
|
if (select_gizmo(_mouseX, _mouseY))
|
|
{
|
|
Gizmo.IsEditing = true;
|
|
_continueMousePick = false;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// Instance IDs
|
|
var _mousePickInstance = (_editMode && _continueMousePick
|
|
&& _mouseOver && mouse_check_button_pressed(ButtonSelect));
|
|
|
|
if (_mousePickInstance || RenderInstanceIDs)
|
|
{
|
|
__surSelect = bbmod_surface_check(__surSelect, _renderWidth, _renderHeight);
|
|
|
|
surface_set_target(__surSelect);
|
|
draw_clear_alpha(0, 0.0);
|
|
matrix_set(matrix_view, _view);
|
|
matrix_set(matrix_projection, _projection);
|
|
|
|
bbmod_render_pass_set(BBMOD_ERenderPass.Id);
|
|
|
|
var _rqi = 0;
|
|
repeat (array_length(_renderQueues))
|
|
{
|
|
_renderQueues[_rqi++].submit();
|
|
}
|
|
|
|
surface_reset_target();
|
|
|
|
// Select instance
|
|
if (_mousePickInstance)
|
|
{
|
|
if (!keyboard_check(KeyMultiSelect))
|
|
{
|
|
Gizmo.clear_selection();
|
|
}
|
|
|
|
var _id = get_instance_id(_mouseX, _mouseY);
|
|
if (_id != 0)
|
|
{
|
|
Gizmo.toggle_select(_id).update_position();
|
|
Gizmo.Size = _gizmoSize
|
|
* Gizmo.Position.Sub(bbmod_camera_get_position()).Length() / 100.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_editMode && !ds_list_empty(Gizmo.Selected))
|
|
{
|
|
////////////////////////////////////////////////////////////////////
|
|
// Instance highlight
|
|
__surInstanceHighlight = bbmod_surface_check(
|
|
__surInstanceHighlight, _renderWidth, _renderHeight);
|
|
|
|
surface_set_target(__surInstanceHighlight);
|
|
draw_clear_alpha(0, 0.0);
|
|
|
|
matrix_set(matrix_view, _view);
|
|
matrix_set(matrix_projection, _projection);
|
|
|
|
bbmod_render_pass_set(BBMOD_ERenderPass.Id);
|
|
|
|
var _selectedInstances = Gizmo.Selected;
|
|
var _rqi = 0;
|
|
repeat (array_length(_renderQueues))
|
|
{
|
|
_renderQueues[_rqi++].submit(_selectedInstances);
|
|
}
|
|
|
|
surface_reset_target();
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Gizmo
|
|
bbmod_render_pass_set(BBMOD_ERenderPass.Forward);
|
|
|
|
__surGizmo = bbmod_surface_check(__surGizmo, _renderWidth, _renderHeight);
|
|
surface_set_target(__surGizmo);
|
|
draw_clear_alpha(0, 0.0);
|
|
matrix_set(matrix_view, _view);
|
|
matrix_set(matrix_projection, _projection);
|
|
Gizmo.submit();
|
|
surface_reset_target();
|
|
}
|
|
|
|
if (_editMode)
|
|
{
|
|
Gizmo.Size = _gizmoSize;
|
|
}
|
|
};
|
|
|
|
/// @func render(_clearQueues=true)
|
|
///
|
|
/// @desc Renders all added [renderables](./BBMOD_BaseRenderer.Renderables.html)
|
|
/// to the current render target.
|
|
///
|
|
/// @param {Bool} [_clearQueues] If true then all render queues are cleared
|
|
/// at the end of this method. Default value is `true`.
|
|
///
|
|
/// @return {Struct.BBMOD_BaseRenderer} Returns `self`.
|
|
static render = function (_clearQueues=true) {
|
|
global.__bbmodRendererCurrent = self;
|
|
|
|
static _renderQueues = bbmod_render_queues_get();
|
|
|
|
var _world = matrix_get(matrix_world);
|
|
var _view = matrix_get(matrix_view);
|
|
var _projection = matrix_get(matrix_projection);
|
|
|
|
var i = 0;
|
|
repeat (array_length(Renderables))
|
|
{
|
|
with (Renderables[i++])
|
|
{
|
|
render();
|
|
}
|
|
}
|
|
|
|
bbmod_material_reset();
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Edit mode
|
|
//
|
|
__render_gizmo_and_instance_ids();
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Shadow map
|
|
//
|
|
__render_shadowmap();
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Forward pass
|
|
//
|
|
bbmod_shader_set_global_f("bbmod_ZFar", bbmod_camera_get_zfar());
|
|
|
|
matrix_set(matrix_view, _view);
|
|
matrix_set(matrix_projection, _projection);
|
|
|
|
bbmod_render_pass_set(BBMOD_ERenderPass.Forward);
|
|
|
|
var _rqi = 0;
|
|
repeat (array_length(_renderQueues))
|
|
{
|
|
var _queue = _renderQueues[_rqi++].submit();
|
|
if (_clearQueues)
|
|
{
|
|
_queue.clear();
|
|
}
|
|
}
|
|
|
|
// Unset in case it gets destroyed when the room changes etc.
|
|
bbmod_shader_unset_global("bbmod_Shadowmap");
|
|
|
|
bbmod_material_reset();
|
|
|
|
matrix_set(matrix_world, _world);
|
|
return self;
|
|
};
|
|
|
|
/// @func present()
|
|
///
|
|
/// @desc Presents the rendered graphics on the screen, with post-processing
|
|
/// applied (if {@link BBMOD_BaseRenderer.PostProcessor} is defined).
|
|
///
|
|
/// @return {Struct.BBMOD_BaseRenderer} Returns `self`.
|
|
///
|
|
/// @note If {@link BBMOD_BaseRenderer.UseAppSurface} is `false`, then this only
|
|
/// draws the gizmo and selected instances.
|
|
static present = function () {
|
|
global.__bbmodRendererCurrent = self;
|
|
|
|
static _gpuState = undefined;
|
|
if (_gpuState == undefined)
|
|
{
|
|
gpu_push_state();
|
|
gpu_set_state(bbmod_gpu_get_default_state());
|
|
gpu_set_tex_filter(true);
|
|
gpu_set_tex_repeat(false);
|
|
gpu_set_blendenable(true);
|
|
_gpuState = gpu_get_state();
|
|
gpu_pop_state();
|
|
}
|
|
|
|
var _width = get_width();
|
|
var _height = get_height();
|
|
var _texelWidth = 1.0 / _width;
|
|
var _texelHeight = 1.0 / _height;
|
|
|
|
if (!UseAppSurface // Can't use post-processing even if it was defined
|
|
|| (PostProcessor == undefined || !PostProcessor.Enabled))
|
|
{
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Post-processing DISABLED
|
|
//
|
|
gpu_push_state();
|
|
gpu_set_state(_gpuState);
|
|
|
|
if (UseAppSurface)
|
|
{
|
|
gpu_set_blendenable(false);
|
|
draw_surface_stretched(application_surface, X, Y, _width, _height);
|
|
gpu_set_blendenable(true);
|
|
}
|
|
|
|
if (EditMode && Gizmo && !ds_list_empty(Gizmo.Selected))
|
|
{
|
|
////////////////////////////////////////////////////////////////
|
|
// Highlighted instances
|
|
if (!ds_list_empty(Gizmo.Selected)
|
|
&& surface_exists(__surInstanceHighlight))
|
|
{
|
|
var _shader = BBMOD_ShInstanceHighlight;
|
|
shader_set(_shader);
|
|
shader_set_uniform_f(shader_get_uniform(_shader, "u_vTexel"),
|
|
_texelWidth, _texelHeight);
|
|
shader_set_uniform_f(shader_get_uniform(_shader, "u_vColor"),
|
|
InstanceHighlightColor.Red / 255.0,
|
|
InstanceHighlightColor.Green / 255.0,
|
|
InstanceHighlightColor.Blue / 255.0,
|
|
InstanceHighlightColor.Alpha);
|
|
draw_surface_stretched(__surInstanceHighlight, X, Y, _width, _height);
|
|
shader_reset();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
// Gizmo
|
|
if (surface_exists(__surGizmo))
|
|
{
|
|
draw_surface_stretched(__surGizmo, X, Y, _width, _height);
|
|
}
|
|
}
|
|
|
|
gpu_pop_state();
|
|
}
|
|
else
|
|
{
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Post-processing ENABLED
|
|
//
|
|
var _world = matrix_get(matrix_world);
|
|
|
|
__surFinal = bbmod_surface_check(__surFinal, _width, _height);
|
|
|
|
gpu_push_state();
|
|
gpu_set_state(_gpuState);
|
|
|
|
surface_set_target(__surFinal);
|
|
matrix_set(matrix_world, matrix_build_identity());
|
|
|
|
draw_surface_stretched(application_surface, 0, 0, _width, _height);
|
|
|
|
if (EditMode && Gizmo && !ds_list_empty(Gizmo.Selected))
|
|
{
|
|
////////////////////////////////////////////////////////////////
|
|
// Highlighted instances
|
|
if (!ds_list_empty(Gizmo.Selected)
|
|
&& surface_exists(__surInstanceHighlight))
|
|
{
|
|
var _shader = BBMOD_ShInstanceHighlight;
|
|
shader_set(_shader);
|
|
shader_set_uniform_f(shader_get_uniform(_shader, "u_vTexel"),
|
|
_texelWidth, _texelHeight);
|
|
shader_set_uniform_f(shader_get_uniform(_shader, "u_vColor"),
|
|
InstanceHighlightColor.Red / 255.0,
|
|
InstanceHighlightColor.Green / 255.0,
|
|
InstanceHighlightColor.Blue / 255.0,
|
|
InstanceHighlightColor.Alpha);
|
|
draw_surface_stretched(__surInstanceHighlight, 0, 0, _width, _height);
|
|
shader_reset();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
// Gizmo
|
|
if (surface_exists(__surGizmo))
|
|
{
|
|
draw_surface_stretched(__surGizmo, 0, 0, _width, _height);
|
|
}
|
|
}
|
|
|
|
surface_reset_target();
|
|
matrix_set(matrix_world, _world);
|
|
gpu_pop_state();
|
|
|
|
PostProcessor.draw(__surFinal, X, Y);
|
|
}
|
|
|
|
return self;
|
|
};
|
|
|
|
static destroy = function () {
|
|
Class_destroy();
|
|
|
|
if (global.__bbmodRendererCurrent == self)
|
|
{
|
|
global.__bbmodRendererCurrent = undefined;
|
|
}
|
|
|
|
if (surface_exists(__surSelect))
|
|
{
|
|
surface_free(__surSelect);
|
|
}
|
|
|
|
if (surface_exists(__surInstanceHighlight))
|
|
{
|
|
surface_free(__surInstanceHighlight);
|
|
}
|
|
|
|
if (surface_exists(__surGizmo))
|
|
{
|
|
surface_free(__surGizmo);
|
|
}
|
|
|
|
if (surface_exists(__surShadowmap))
|
|
{
|
|
surface_free(__surShadowmap);
|
|
}
|
|
|
|
if (surface_exists(__surFinal))
|
|
{
|
|
surface_free(__surFinal);
|
|
}
|
|
|
|
if (UseAppSurface)
|
|
{
|
|
application_surface_enable(false);
|
|
application_surface_draw_enable(true);
|
|
}
|
|
|
|
return undefined;
|
|
};
|
|
}
|