[BGM Shader] Batching improvements
Make it easier to change framebuffer size
This commit is contained in:
parent
87739d57f4
commit
313872f115
|
@ -3,9 +3,8 @@
|
|||
// Unfortunately, this loses type-checking on [0.0, 1.0] vs [0,255] etc. so a lot of this will involve comments declaring ranges.
|
||||
shader_type canvas_item;
|
||||
render_mode blend_premul_alpha;
|
||||
const int INT_TEX_SIZE = 4096;
|
||||
const float TEX_SIZE = 4096.0;
|
||||
const float UV_QUANTIZE = TEX_SIZE;
|
||||
uniform int INT_TEX_WIDTH = 4096;
|
||||
uniform vec2 TEX_SIZE = vec2(4096.0, 4096.0);
|
||||
// I feel like these magic numbers are a bit more intuitive in hex
|
||||
const float x00FF = float(0x00FF); // 255.0
|
||||
const float x0100 = float(0x0100); // 256.0
|
||||
|
@ -60,16 +59,16 @@ vec2 pack_float_to_int16(float value) {
|
|||
return vec2(LSB, MSB);
|
||||
}
|
||||
|
||||
vec4 test_writeback(sampler2D tex, vec2 uv) {
|
||||
// Test importing and exporting the samples,
|
||||
// and exporting a value derived from the UV
|
||||
vec4 output;
|
||||
float sample_1 = rescale_int16(unpack_int16(texture(tex, uv).xw));
|
||||
float sample_2 = rescale_int16(dot(trunc(uv*TEX_SIZE), vec2(1.0, TEX_SIZE)));
|
||||
output.xy = pack_float_to_int16(sample_1);
|
||||
output.zw = pack_float_to_int16(sample_2);
|
||||
return output;
|
||||
}
|
||||
// vec4 test_writeback(sampler2D tex, vec2 uv) {
|
||||
// // Test importing and exporting the samples,
|
||||
// // and exporting a value derived from the UV
|
||||
// vec4 output;
|
||||
// float sample_1 = rescale_int16(unpack_int16(texture(tex, uv).xw));
|
||||
// float sample_2 = rescale_int16(dot(trunc(uv*TEX_SIZE), vec2(1.0, TEX_SIZE)));
|
||||
// output.xy = pack_float_to_int16(sample_1);
|
||||
// output.zw = pack_float_to_int16(sample_2);
|
||||
// return output;
|
||||
// }
|
||||
|
||||
|
||||
// ============================================================= LOGIC =============================================================
|
||||
|
@ -153,7 +152,6 @@ float get_instrument_sample(float instrument_index, float note, float t) {
|
|||
const int NUM_CHANNELS = 8;
|
||||
const int MAX_CHANNEL_NOTE_EVENTS = 2048;
|
||||
const int NUM_CHANNEL_NOTE_PROBES = 11; // log2(MAX_CHANNEL_NOTE_EVENTS)
|
||||
// uniform sampler2D midi_events : hint_normal;
|
||||
uniform vec2 midi_events_size = vec2(2048.0, 32.0);
|
||||
vec4 get_midi_texel(sampler2D tex, float x, float y) {
|
||||
return texture(tex, vec2(x, y)/midi_events_size).xyzw;
|
||||
|
@ -211,8 +209,8 @@ vec4 render_song(sampler2D tex, int smp) {
|
|||
void fragment() {
|
||||
// GLES2
|
||||
vec2 uv = vec2(UV.x, 1.0-UV.y);
|
||||
// uv = (trunc(uv*UV_QUANTIZE)+0.5)/UV_QUANTIZE;
|
||||
// uv = (trunc(uv*TEX_SIZE)+0.5)/TEX_SIZE;
|
||||
// COLOR.xyzw = test_writeback(TEXTURE, uv);
|
||||
ivec2 xy = ivec2(trunc(uv*TEX_SIZE));
|
||||
COLOR.xyzw = render_song(TEXTURE, xy.x + (xy.y*INT_TEX_SIZE));
|
||||
COLOR.xyzw = render_song(TEXTURE, xy.x + (xy.y*INT_TEX_WIDTH));
|
||||
}
|
||||
|
|
|
@ -4,8 +4,9 @@ const INPUT_TEX_WIDTH := 2048
|
|||
const INPUT_FORMAT := Image.FORMAT_RGBA8 # Image.FORMAT_LA8
|
||||
const INPUT_BYTES_PER_TEXEL := 4 # 2
|
||||
const OUTPUT_BYTES_PER_TEXEL := 4
|
||||
const OUTPUT_WIDTH := 4096
|
||||
const OUTPUT_HEIGHT := 4096
|
||||
const OUTPUT_FRAMEBUFFER_SIZE := Vector2(4096, 4096)
|
||||
const OUTPUT_WIDTH := int(OUTPUT_FRAMEBUFFER_SIZE.x)
|
||||
const OUTPUT_HEIGHT := int(OUTPUT_FRAMEBUFFER_SIZE.y)
|
||||
const QUAD_COLOR := PoolColorArray([Color.white, Color.white, Color.white, Color.white])
|
||||
var viewport: Viewport
|
||||
var render_queue: Array # of Images
|
||||
|
@ -21,19 +22,27 @@ func _ready() -> void:
|
|||
self.waiting_for_viewport = []
|
||||
self.done_first_draw = false
|
||||
self.current_textures = []
|
||||
self.get_parent().size = OUTPUT_FRAMEBUFFER_SIZE
|
||||
self.material.set_shader_param('OUTPUT_FRAMEBUFFER_SIZE', OUTPUT_FRAMEBUFFER_SIZE)
|
||||
self.material.set_shader_param('INT_OUTPUT_WIDTH', OUTPUT_WIDTH)
|
||||
|
||||
func push_image(img: Image, uv_rows: int = 4096, desc: String = '') -> void:
|
||||
self.render_queue.append([img, uv_rows, desc])
|
||||
func push_image(img: Image, target_samples: int = -1, desc: String = '') -> void:
|
||||
var target_rows = ceil(target_samples/float(OUTPUT_WIDTH))
|
||||
if target_samples <= 0:
|
||||
target_rows = int(img.get_size().y)
|
||||
self.render_queue.append([img, target_rows, desc])
|
||||
|
||||
func push_bytes(data: PoolByteArray, uv_rows: int = 4096, desc: String = '') -> void:
|
||||
# print(data.subarray(0, 15))
|
||||
func push_bytes(data: PoolByteArray, target_samples: int = -1, desc: String = '') -> void:
|
||||
var rows = int(pow(2, ceil(log((len(data)/INPUT_BYTES_PER_TEXEL) / INPUT_TEX_WIDTH)/log(2))))
|
||||
var target_length = rows * INPUT_BYTES_PER_TEXEL * INPUT_FORMAT
|
||||
while len(data) < target_length: # This is inefficient, but this function should be called with pre-padded data anyway
|
||||
data.append(0)
|
||||
var image := Image.new()
|
||||
image.create_from_data(INPUT_TEX_WIDTH, rows, false, INPUT_FORMAT, data)
|
||||
self.render_queue.append([image, uv_rows, desc])
|
||||
var target_rows = ceil(target_samples/float(OUTPUT_WIDTH))
|
||||
if target_samples <= 0:
|
||||
target_rows = rows
|
||||
self.render_queue.append([image, target_rows, desc])
|
||||
|
||||
func _process(_delta) -> void:
|
||||
update()
|
||||
|
@ -67,11 +76,10 @@ func _draw() -> void:
|
|||
self.current_textures.append(ImageTexture.new())
|
||||
var tex: ImageTexture = self.current_textures[i]
|
||||
tex.create_from_image(image_and_uv_rows_and_desc[0], 0)
|
||||
# self.material.set_shader_param('midi_events', tex)
|
||||
self.material.set_shader_param('midi_events_size', tex.get_size())
|
||||
var y_top: int = OUTPUT_HEIGHT - rows_drawn
|
||||
var y_bot: int = y_top + draw_rows
|
||||
var uv_inv_v: float = 1 - (draw_rows / float(OUTPUT_WIDTH))
|
||||
var uv_inv_v: float = 1 - (draw_rows / OUTPUT_FRAMEBUFFER_SIZE.y)
|
||||
var uvs := PoolVector2Array([Vector2(0, uv_inv_v), Vector2(1, uv_inv_v), Vector2(1, 1), Vector2(0, 1)])
|
||||
var points := PoolVector2Array([Vector2(0, y_top), Vector2(OUTPUT_WIDTH, y_top), Vector2(OUTPUT_WIDTH, y_bot), Vector2(0, y_bot)])
|
||||
draw_primitive(points, QUAD_COLOR, uvs, tex)
|
||||
|
|
|
@ -180,14 +180,13 @@ func queue_prerender_bgm(bgm_id: int) -> void:
|
|||
var data = data_and_target_time_and_loops[0]
|
||||
var target_time = data_and_target_time_and_loops[1]
|
||||
var target_samples = target_time * 32000
|
||||
var target_rows = ceil(target_samples/4096.0)
|
||||
var bgm_key := 'BGM%02d'%bgm_id
|
||||
audio_renderer.push_bytes(data, target_rows, bgm_key)
|
||||
audio_renderer.push_bytes(data, target_samples, bgm_key)
|
||||
self.prerendered_bgm_start_and_end_loops[bgm_key] = data_and_target_time_and_loops[2]
|
||||
|
||||
|
||||
|
||||
func render_all_bgm(bgms_to_render: int = 64) -> void:
|
||||
func render_all_bgm(bgms_to_render: int = 70) -> void:
|
||||
self.initialize_instrument_texture()
|
||||
for bgm_id in bgms_to_render:
|
||||
self.queue_prerender_bgm(bgm_id)
|
||||
|
@ -199,6 +198,7 @@ func render_all_bgm(bgms_to_render: int = 64) -> void:
|
|||
const save_prerendered_audio := false
|
||||
func _get_prerendered_audio():
|
||||
audio_renderer.get_result()
|
||||
var tracks_rendered := ''
|
||||
while audio_renderer.result_queue:
|
||||
var result = audio_renderer.result_queue.pop_front()
|
||||
var desc = result[0]
|
||||
|
@ -216,11 +216,13 @@ func _get_prerendered_audio():
|
|||
var error = rendered_audio.save_to_wav('output/rendered_%s.wav'%desc)
|
||||
print('@%dms - Saved render of %s (error code %s)' % [get_ms(), desc, globals.ERROR_CODE_STRINGS[error]])
|
||||
else:
|
||||
print('@%dms - Rendered %s without saving' % [get_ms(), desc])
|
||||
# print('@%dms - Rendered %s without saving' % [get_ms(), desc])
|
||||
tracks_rendered = '%s, %s'%[tracks_rendered, desc]
|
||||
if self.queued_bgm_playback == desc:
|
||||
self.audio_player.stream = rendered_audio
|
||||
self.audio_player.play()
|
||||
self.queued_bgm_playback = ''
|
||||
print('@%dms - Rendered %s without saving' % [get_ms(), tracks_rendered.right(2)])
|
||||
|
||||
|
||||
func get_shader_test_pattern() -> PoolByteArray:
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
[sub_resource type="ShaderMaterial" id=2]
|
||||
shader = ExtResource( 4 )
|
||||
shader_param/INT_TEX_WIDTH = 4096
|
||||
shader_param/TEX_SIZE = Vector2( 4096, 4096 )
|
||||
shader_param/instrument_samples_size = Vector2( 2048, 128 )
|
||||
shader_param/reference_note = 71.0
|
||||
shader_param/output_mixrate = 32000.0
|
||||
|
|
Loading…
Reference in New Issue