mirror of
https://github.com/Ttanasart-pt/Pixel-Composer.git
synced 2025-02-15 22:55:13 +01:00
199 lines
6.8 KiB
Text
199 lines
6.8 KiB
Text
/// @macro {Real} Size of the SSAO noise texture. Must be the same as in shaders!
|
|
/// @private
|
|
#macro __BBMOD_SSAO_NOISE_TEXTURE_SIZE 4
|
|
|
|
/// @macro {Real} The size of SSAO sampling kernel. The higher the better quality,
|
|
/// but lower performance. Must be the same as in shaders!
|
|
/// @private
|
|
#macro __BBMOD_SSAO_KERNEL_SIZE 8
|
|
|
|
/// @var {Id.Sprite}
|
|
/// @private
|
|
global.__bbmodSSAONoise = __bbmod_ssao_make_noise(__BBMOD_SSAO_NOISE_TEXTURE_SIZE);
|
|
|
|
/// @var {Array<Real>}
|
|
/// @private
|
|
global.__bbmodSSAOKernel = __bbmod_ssao_create_kernel(__BBMOD_SSAO_KERNEL_SIZE);
|
|
|
|
/// @func __bbmod_ssao_make_noise(_size)
|
|
///
|
|
/// @desc Creates a sprite containing a random noise for the SSAO.
|
|
///
|
|
/// @param {Real} _size The size of the sprite.
|
|
///
|
|
/// @return {Id.Sprite} The created noise sprite.
|
|
///
|
|
/// @private
|
|
function __bbmod_ssao_make_noise(_size)
|
|
{
|
|
var _seed = random_get_seed();
|
|
randomize();
|
|
var _sur = surface_create(_size, _size);
|
|
surface_set_target(_sur);
|
|
draw_clear(0);
|
|
var _dir = 0;
|
|
var _dirStep = 180 / (_size * _size);
|
|
for (var i = 0; i < _size; ++i)
|
|
{
|
|
for (var j = 0; j < _size; ++j)
|
|
{
|
|
var _col = make_colour_rgb(
|
|
(dcos(_dir) * 0.5 + 0.5) * 255,
|
|
(dsin(_dir) * 0.5 + 0.5) * 255,
|
|
0);
|
|
draw_point_colour(i, j, _col);
|
|
_dir += _dirStep;
|
|
}
|
|
}
|
|
surface_reset_target();
|
|
random_set_seed(_seed);
|
|
var _sprite = sprite_create_from_surface(
|
|
_sur, 0, 0, _size, _size, false, false, 0, 0);
|
|
surface_free(_sur);
|
|
return _sprite;
|
|
}
|
|
|
|
/// @func __bbmod_ssao_create_kernel(_size)
|
|
///
|
|
/// @desc Generates a kernel of random vectors to be used for the SSAO.
|
|
///
|
|
/// @param {Real} _size Number of vectors in the kernel.
|
|
///
|
|
/// @return {Array} The created kernel as
|
|
/// `[v1X, v1Y, v1Z, v2X, v2Y, v2Z, ..., vnX, vnY, vnZ]`.
|
|
///
|
|
/// @private
|
|
function __bbmod_ssao_create_kernel(_size)
|
|
{
|
|
var _seed = random_get_seed();
|
|
randomize();
|
|
var _kernel = array_create(_size * 2, 0.0);
|
|
var _dir = 0;
|
|
var _dirStep = 360 / _size;
|
|
for (var i = _size - 1; i >= 0; --i)
|
|
{
|
|
var _len = (i + 1) / _size;
|
|
_kernel[i * 2 + 0] = lengthdir_x(_len, _dir);
|
|
_kernel[i * 2 + 1] = lengthdir_y(_len, _dir);
|
|
_dir += _dirStep;
|
|
}
|
|
random_set_seed(_seed);
|
|
return _kernel;
|
|
}
|
|
|
|
/// @func bbmod_ssao_draw(_radius, _power, _angleBias, _depthRange, _surSsao, _surWork, _surDepth, _matProj, _clipFar[, _selfOcclusionBias[, _blurDepthRange]])
|
|
///
|
|
/// @desc Renders SSAO into the `_surSsao` surface.
|
|
///
|
|
/// @param {Real} _radius Screen-space radius of the occlusion effect.
|
|
/// @param {Real} _power Strength of the occlusion effect. Should be greater
|
|
/// than 0.
|
|
/// @param {Real} _angleBias Angle bias in radians.
|
|
/// @param {Real} _depthRange Maximum depth difference of samples.
|
|
/// @param {Id.Surface} _surSsao The surface to draw the SSAO to.
|
|
/// @param {Id.Surface} _surWork A working surface used for blurring the SSAO.
|
|
/// Must have the same size as `_surSsao`!
|
|
/// @param {Id.Surface} _surDepth G-buffer surface.
|
|
/// @param {Array<Real>} _matProj The projection matrix used when rendering the
|
|
/// scene.
|
|
/// @param {Real} _clipFar Distance to the far clipping plane (same as in the
|
|
/// projection used when rendering the scene).
|
|
/// @param {Real} [_selfOcclusionBias] Defaults to 0.01. Increase to fix
|
|
/// self-occlusion.
|
|
/// @param {Real} [_blurDepthRange] Maximum depth difference over which can be SSAO samples
|
|
/// blurred. Defaults to 2.
|
|
function bbmod_ssao_draw(
|
|
_radius,
|
|
_power,
|
|
_angleBias,
|
|
_depthRange,
|
|
_surSsao,
|
|
_surWork,
|
|
_surDepth,
|
|
_matProj,
|
|
_clipFar,
|
|
_selfOcclusionBias=0.01,
|
|
_blurDepthRange=2.0)
|
|
{
|
|
static _uTexNoise = shader_get_sampler_index(BBMOD_ShSSAO, "u_texNoise");
|
|
static _uTexel = shader_get_uniform(BBMOD_ShSSAO, "u_vTexel");
|
|
static _uClipFar = shader_get_uniform(BBMOD_ShSSAO, "u_fClipFar");
|
|
static _uTanAspect = shader_get_uniform(BBMOD_ShSSAO, "u_vTanAspect");
|
|
static _uSampleKernel = shader_get_uniform(BBMOD_ShSSAO, "u_vSampleKernel");
|
|
static _uRadius = shader_get_uniform(BBMOD_ShSSAO, "u_fRadius");
|
|
static _uPower = shader_get_uniform(BBMOD_ShSSAO, "u_fPower");
|
|
static _uNoiseScale = shader_get_uniform(BBMOD_ShSSAO, "u_vNoiseScale");
|
|
static _uAngleBias = shader_get_uniform(BBMOD_ShSSAO, "u_fAngleBias");
|
|
static _uDepthRange = shader_get_uniform(BBMOD_ShSSAO, "u_fDepthRange");
|
|
static _uSelfOcclusionBias = shader_get_uniform(BBMOD_ShSSAO, "u_fSelfOcclusionBias");
|
|
static _uBlurTexel = shader_get_uniform(BBMOD_ShSSAOBlur, "u_vTexel");
|
|
static _uBlurTexDepth = shader_get_sampler_index(BBMOD_ShSSAOBlur, "u_texDepth");
|
|
static _uBlurClipFar = shader_get_uniform(BBMOD_ShSSAOBlur, "u_fClipFar");
|
|
static _uBlurDepthRange = shader_get_uniform(BBMOD_ShSSAOBlur, "u_fDepthRange");
|
|
|
|
var _tanAspect = (_matProj[11] == 0.0)
|
|
? [1.0, -1.0] // Ortho
|
|
: [1.0 / _matProj[0], -1.0 / _matProj[5]]; // Perspective
|
|
var _width = surface_get_width(_surSsao);
|
|
var _height = surface_get_height(_surSsao);
|
|
|
|
gpu_push_state();
|
|
gpu_set_tex_repeat(false);
|
|
|
|
static _cam = camera_create();
|
|
camera_set_view_size(_cam, _width, _height);
|
|
|
|
gpu_set_tex_filter(false);
|
|
|
|
surface_set_target(_surSsao);
|
|
camera_apply(_cam);
|
|
matrix_set(matrix_world, matrix_build_identity());
|
|
draw_clear(c_white);
|
|
shader_set(BBMOD_ShSSAO);
|
|
texture_set_stage(_uTexNoise, sprite_get_texture(global.__bbmodSSAONoise, 0));
|
|
gpu_set_texrepeat_ext(_uTexNoise, true);
|
|
shader_set_uniform_f(_uTexel, 1.0 / _width, 1.0 / _height);
|
|
shader_set_uniform_f(_uClipFar, _clipFar);
|
|
shader_set_uniform_f_array(_uTanAspect, _tanAspect);
|
|
shader_set_uniform_f_array(_uSampleKernel, global.__bbmodSSAOKernel);
|
|
shader_set_uniform_f(_uRadius, _radius);
|
|
shader_set_uniform_f(_uPower, _power);
|
|
shader_set_uniform_f(_uNoiseScale,
|
|
_width / __BBMOD_SSAO_NOISE_TEXTURE_SIZE,
|
|
_height / __BBMOD_SSAO_NOISE_TEXTURE_SIZE);
|
|
shader_set_uniform_f(_uAngleBias, _angleBias);
|
|
shader_set_uniform_f(_uDepthRange, _depthRange);
|
|
shader_set_uniform_f(_uSelfOcclusionBias, _selfOcclusionBias);
|
|
draw_surface_stretched(_surDepth, 0, 0, _width, _height);
|
|
shader_reset();
|
|
surface_reset_target();
|
|
|
|
gpu_set_tex_filter(true);
|
|
|
|
shader_set(BBMOD_ShSSAOBlur);
|
|
shader_set_uniform_f(_uBlurTexel, 1.0 / _width, 0.0);
|
|
shader_set_uniform_f(_uBlurClipFar, _clipFar);
|
|
texture_set_stage(_uBlurTexDepth, surface_get_texture(_surDepth));
|
|
gpu_set_tex_filter_ext(_uBlurTexDepth, false);
|
|
shader_set_uniform_f(_uBlurDepthRange, _blurDepthRange);
|
|
|
|
surface_set_target(_surWork);
|
|
camera_apply(_cam);
|
|
matrix_set(matrix_world, matrix_build_identity());
|
|
draw_clear(0);
|
|
shader_set_uniform_f(_uBlurTexel, 1.0 / _width, 0.0);
|
|
draw_surface(_surSsao, 0, 0);
|
|
surface_reset_target();
|
|
|
|
surface_set_target(_surSsao);
|
|
camera_apply(_cam);
|
|
matrix_set(matrix_world, matrix_build_identity());
|
|
draw_clear(0);
|
|
shader_set_uniform_f(_uBlurTexel, 0.0, 1.0 / _height);
|
|
draw_surface(_surWork, 0, 0);
|
|
surface_reset_target();
|
|
|
|
shader_reset();
|
|
|
|
gpu_pop_state();
|
|
}
|