Pixel-Composer/scripts/node_custom_shader/node_custom_shader.gml

276 lines
No EOL
7.2 KiB
Text

#region shader cache
globalvar SHADER_CACHE;
SHADER_CACHE = {};
function shader_compile_vs(file) {
if(struct_has(SHADER_CACHE, file)) return SHADER_CACHE[$ file];
var _sh = d3d11_shader_compile_vs(file, "main", "vs_4_0");
SHADER_CACHE[$ file] = _sh;
return _sh;
}
function shader_compile_ps(file) {
if(struct_has(SHADER_CACHE, file)) return SHADER_CACHE[$ file];
var _sh = d3d11_shader_compile_ps(file, "main", "ps_4_0");
SHADER_CACHE[$ file] = _sh;
return _sh;
}
#endregion
function __Custom_Shader() constructor {
shader_vs = noone;
shader_fs = noone;
static compile = function(vs, fs) {
shader_vs = shader_compile_vs(vs);
if(!d3d11_shader_exists(shader_vs)) noti_warning(d3d11_get_error_string());
shader_fs = shader_compile_ps(fs);
if(!d3d11_shader_exists(shader_fs)) noti_warning(d3d11_get_error_string());
return self;
}
static isValid = function() { return d3d11_shader_exists(shader_vs) && d3d11_shader_exists(shader_fs); }
static setUniforms = function(uniforms, _reg) {
d3d11_cbuffer_begin();
var _buffer = buffer_create(1, buffer_grow, 1);
var _sample = 1;
var _cbSize = 0;
for( var i = 0, n = array_length(uniforms); i < n; i++ ) {
var _unif = uniforms[i];
var _utype = _unif.type;
var _value = _unif.value;
switch(_utype) {
case "float" : // u_float
d3d11_cbuffer_add_float(1);
_cbSize++;
buffer_write(_buffer, buffer_f32, _value);
break;
case "int" : // u_int
d3d11_cbuffer_add_int(1);
_cbSize++;
buffer_write(_buffer, buffer_s32, _value);
break;
case "vec2" : // u_vec2
case "vec3" : // u_vec3
case "vec4" : // u_vec4
case "mat3" : // u_mat3
case "mat4" : // u_mat4
if(is_array(_value)) {
d3d11_cbuffer_add_float(array_length(_value));
_cbSize += array_length(_value);
for( var j = 0, m = array_length(_value); j < m; j++ )
buffer_write(_buffer, buffer_f32, _value[j]);
}
break;
case "surface" : // u_sampler2D
if(is_surface(_value))
d3d11_texture_set_stage_ps(_sample, surface_get_texture(_value));
_sample++;
break;
case "color" : // u_vec4 color
d3d11_cbuffer_add_float(4);
_cbSize += 4;
var _clr = colToVec4(_value);
buffer_write(_buffer, buffer_f32, _clr[0]);
buffer_write(_buffer, buffer_f32, _clr[1]);
buffer_write(_buffer, buffer_f32, _clr[2]);
buffer_write(_buffer, buffer_f32, _clr[3]);
break;
}
}
d3d11_cbuffer_add_float(4 - _cbSize % 4);
var cbuff = d3d11_cbuffer_end();
d3d11_cbuffer_update(cbuff, _buffer);
buffer_delete(_buffer);
d3d11_shader_set_cbuffer_ps(_reg, cbuff);
}
static set = function() {
d3d11_shader_override_vs(shader_vs);
d3d11_shader_override_ps(shader_fs);
}
static reset = function() {
d3d11_shader_override_vs(-1);
d3d11_shader_override_ps(-1);
}
static drawSurface = function(surface) {
matrix_set(matrix_world, matrix_build(0, 0, 0, 0, 0, 0, surface_get_width_safe(surface), surface_get_height_safe(surface), 1));
vertex_submit(global.HLSL_VB_PLANE, pr_trianglestrip, surface_get_texture(surface));
matrix_set(matrix_world, matrix_build_identity());
}
static drawEmpty = function(sw, sh) {
matrix_set(matrix_world, matrix_build(0, 0, 0, 0, 0, 0, sw, sh, 1));
vertex_submit(global.HLSL_VB_PLANE, pr_trianglestrip, -1);
matrix_set(matrix_world, matrix_build_identity());
}
}
function Node_Custom_Shader(_x, _y, _group = noone, _param = {}) : Node_Custom(_x, _y, _group, _param) constructor {
multipass = false;
shader = noone;
uniform = [];
shaders = [];
uniformMap = {};
surface_index = noone;
dimension_index = noone;
texfilter = "none";
attribute_surface_depth();
static onParseInfo = function() {
multipass = struct_has(node_info, "passes");
texfilter = node_info[$ "texfilter"] ?? "none";
for( var i = 0, n = array_length(node_info.inputs); i < n; i++ ) {
var _input = inputs[i];
var _info = node_info.inputs[i];
var _type = _info.type;
var _flag = _info[$ "flag"];
var _unif = _info[$ "uniform"];
if(_flag == "SURFACE_IN") {
_input.setVisible(true, true);
surface_index = i;
} else if(_flag == "DIMENSION") {
dimension_index = i;
}
if(_unif != undefined) {
if(multipass) uniformMap[$ _unif] = { type: _type, index: i };
else array_push(uniform, { type: _type, index: i });
}
}
if(multipass) {
for( var i = 0, n = array_length(node_info.passes); i < n; i++ ) {
var _pass = node_info.passes[i];
shaders[i] = {
shader: new __Custom_Shader().compile($"{sourceDir}/{_pass.shader_vs}", $"{sourceDir}/{_pass.shader_fs}"),
uniforms: _pass.uniforms
}
}
temp_surface = array_create(n, 0);
} else {
shader = new __Custom_Shader().compile($"{sourceDir}/{node_info.shader_vs}", $"{sourceDir}/{node_info.shader_fs}");
}
}
static processData = function(_output, _data, _output_index, _array_index = 0) {
var _surf = noone;
var sw = 0;
var sh = 0;
if(surface_index != noone) {
_surf = _data[surface_index];
if(!is_surface(_surf)) return _output;
sw = surface_get_width_safe(_surf);
sh = surface_get_height_safe(_surf);
}
if(dimension_index != noone) {
var _dim = _data[dimension_index];
sw = _dim[0];
sh = _dim[1];
}
if(sw == 0 || sh == 0) return _output;
_output = surface_verify(_output, sw, sh, attrDepth());
if(multipass) {
var _draw = _surf;
for( var i = 0, n = array_length(shaders); i < n; i++ ) {
temp_surface[i] = surface_verify(temp_surface[i], sw, sh, attrDepth());
var _sh = shaders[i];
var _shader = _sh.shader;
var _uniform = _sh.uniforms;
if(!_shader.isValid()) continue;
for( var j = 0, m = array_length(_uniform); j < m; j++ ) {
var _n = _uniform[j].name;
if(struct_has(uniformMap, _n)) _uniform[j].value = _data[uniformMap[$ _n].index];
}
surface_set_target(temp_surface[i]);
DRAW_CLEAR
_shader.set();
_shader.setUniforms(_uniform, 10)
_shader.setUniforms([{ type: "vec2", value: [sw, sh] }], 4)
gpu_set_tex_filter(texfilter == "linear");
if(is_surface(_draw)) _shader.drawSurface(_draw);
else _shader.drawEmpty(sw, sh);
gpu_set_tex_filter(false);
_shader.reset();
surface_reset_target();
_draw = temp_surface[i];
}
surface_set_shader(_output);
draw_surface(temp_surface[n - 1], 0, 0);
surface_reset_shader();
return _output;
}
if(!shader.isValid()) return _output;
for( var i = 0, n = array_length(uniform); i < n; i++ )
uniform[i].value = _data[uniform[i].index];
surface_set_target(_output);
DRAW_CLEAR
shader.set();
shader.setUniforms(uniform, 10)
shader.setUniforms([{ type: "vec2", value: [sw, sh] }], 4)
gpu_set_tex_filter(texfilter == "linear");
if(is_surface(_surf)) shader.drawSurface(_surf);
else shader.drawEmpty(sw, sh);
gpu_set_tex_filter(false);
shader.reset();
surface_reset_target();
return _output;
}
}