scene
This commit is contained in:
185
sdl_gpu.cm
185
sdl_gpu.cm
@@ -787,8 +787,8 @@ function _build_sprite_vertices(sprites, camera) {
|
||||
var vertices_per_sprite = 4
|
||||
var indices_per_sprite = 6
|
||||
|
||||
var vertex_data = new blob_mod(sprites.length * vertices_per_sprite * floats_per_vertex * 32)
|
||||
var index_data = geometry.make_quad_indices(sprites.length)
|
||||
var vertex_data = new blob_mod(sprites.length * vertices_per_sprite * floats_per_vertex * 4)
|
||||
var index_data = new blob_mod(sprites.length * indices_per_sprite * 2)
|
||||
|
||||
var vertex_count = 0
|
||||
|
||||
@@ -813,9 +813,56 @@ function _build_sprite_vertices(sprites, camera) {
|
||||
var u1 = s.uv_rect ? (s.uv_rect.x + s.uv_rect.width) : 1
|
||||
var v1 = s.uv_rect ? (s.uv_rect.y + s.uv_rect.height) : 1
|
||||
|
||||
// call to implement
|
||||
var verts = geometry.sprite_vertices({x,y,w,h,u0,v0,u1,v1,c})
|
||||
vertex_data.write_blob(verts)
|
||||
// Quad vertices (bottom-left, bottom-right, top-right, top-left)
|
||||
// v0: bottom-left
|
||||
vertex_data.wf(x)
|
||||
vertex_data.wf(y)
|
||||
vertex_data.wf(u0)
|
||||
vertex_data.wf(v1) // Flip V
|
||||
vertex_data.wf(c.r)
|
||||
vertex_data.wf(c.g)
|
||||
vertex_data.wf(c.b)
|
||||
vertex_data.wf(c.a)
|
||||
|
||||
// v1: bottom-right
|
||||
vertex_data.wf(x + w)
|
||||
vertex_data.wf(y)
|
||||
vertex_data.wf(u1)
|
||||
vertex_data.wf(v1) // Flip V
|
||||
vertex_data.wf(c.r)
|
||||
vertex_data.wf(c.g)
|
||||
vertex_data.wf(c.b)
|
||||
vertex_data.wf(c.a)
|
||||
|
||||
// v2: top-right
|
||||
vertex_data.wf(x + w)
|
||||
vertex_data.wf(y + h)
|
||||
vertex_data.wf(u1)
|
||||
vertex_data.wf(v0) // Flip V
|
||||
vertex_data.wf(c.r)
|
||||
vertex_data.wf(c.g)
|
||||
vertex_data.wf(c.b)
|
||||
vertex_data.wf(c.a)
|
||||
|
||||
// v3: top-left
|
||||
vertex_data.wf(x)
|
||||
vertex_data.wf(y + h)
|
||||
vertex_data.wf(u0)
|
||||
vertex_data.wf(v0) // Flip V
|
||||
vertex_data.wf(c.r)
|
||||
vertex_data.wf(c.g)
|
||||
vertex_data.wf(c.b)
|
||||
vertex_data.wf(c.a)
|
||||
|
||||
// Indices (two triangles)
|
||||
index_data.w16(vertex_count + 0)
|
||||
index_data.w16(vertex_count + 1)
|
||||
index_data.w16(vertex_count + 2)
|
||||
index_data.w16(vertex_count + 0)
|
||||
index_data.w16(vertex_count + 2)
|
||||
index_data.w16(vertex_count + 3)
|
||||
|
||||
vertex_count += 4
|
||||
})
|
||||
|
||||
return {
|
||||
@@ -916,16 +963,16 @@ function _build_ortho_matrix(left, right, bottom, top, near, far) {
|
||||
}
|
||||
|
||||
function _build_camera_matrix(camera, target_width, target_height) {
|
||||
var pos = camera.pos || [0, 0]
|
||||
var pos = camera.pos || {x: 0, y: 0}
|
||||
var cam_width = camera.width || target_width
|
||||
var cam_height = camera.height || target_height
|
||||
var anchor = camera.anchor || [0.5, 0.5]
|
||||
|
||||
var left = pos[0] - cam_width * anchor[0]
|
||||
var right = pos[0] + cam_width * (1 - anchor[0])
|
||||
var bottom = pos[1] - cam_height * anchor[1]
|
||||
var top = pos[1] + cam_height * (1 - anchor[1])
|
||||
|
||||
var anchor = camera.anchor || {x: 0.5, y: 0.5}
|
||||
|
||||
var left = pos.x - cam_width * anchor.x
|
||||
var right = pos.x + cam_width * (1 - anchor.x)
|
||||
var bottom = pos.y - cam_height * anchor.y
|
||||
var top = pos.y + cam_height * (1 - anchor.y)
|
||||
|
||||
return _build_ortho_matrix(left, right, bottom, top, -1, 1)
|
||||
}
|
||||
|
||||
@@ -1068,7 +1115,11 @@ function _execute_commands(commands, window_size) {
|
||||
case 'draw_text':
|
||||
pending_draws.push(cmd)
|
||||
break
|
||||
|
||||
|
||||
case 'draw_texture_ref':
|
||||
pending_draws.push(cmd)
|
||||
break
|
||||
|
||||
case 'blit':
|
||||
// Flush pending draws first
|
||||
if (current_pass && pending_draws.length > 0) {
|
||||
@@ -1258,12 +1309,19 @@ function _flush_draws(cmd_buffer, pass, draws, camera, target) {
|
||||
// Flush current batch
|
||||
if (current_batch) _render_batch(cmd_buffer, pass, current_batch, camera, target)
|
||||
current_batch = null
|
||||
|
||||
|
||||
// Render text immediately
|
||||
_render_text(cmd_buffer, pass, draw.drawable, camera, target)
|
||||
} else if (draw.cmd == 'draw_texture_ref') {
|
||||
// Flush current batch
|
||||
if (current_batch) _render_batch(cmd_buffer, pass, current_batch, camera, target)
|
||||
current_batch = null
|
||||
|
||||
// Render pre-rendered effect texture
|
||||
_render_texture_ref(cmd_buffer, pass, draw.drawable, camera, target)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Flush final batch
|
||||
if (current_batch) _render_batch(cmd_buffer, pass, current_batch, camera, target)
|
||||
}
|
||||
@@ -1311,6 +1369,68 @@ function _render_batch(cmd_buffer, pass, batch, camera, target) {
|
||||
}
|
||||
}
|
||||
|
||||
// Render a pre-rendered texture from an effect group
|
||||
function _render_texture_ref(cmd_buffer, pass, drawable, camera, target) {
|
||||
var tex_target = drawable.texture_target
|
||||
if (!tex_target) return
|
||||
|
||||
// The texture_target is a compositor target reference - resolve it
|
||||
// It should have already been rendered to and we just need to blit it
|
||||
var pos = drawable.pos || {x: 0, y: 0}
|
||||
var width = drawable.width || target.width
|
||||
var height = drawable.height || target.height
|
||||
|
||||
// Build a single sprite for the texture reference
|
||||
var sprites = [{
|
||||
pos: pos,
|
||||
width: width,
|
||||
height: height,
|
||||
anchor_x: 0,
|
||||
anchor_y: 0,
|
||||
color: {r: 1, g: 1, b: 1, a: 1}
|
||||
}]
|
||||
|
||||
var geom = _build_sprite_vertices(sprites, camera)
|
||||
|
||||
// Upload geometry
|
||||
var vb_size = geom.vertices.length / 8
|
||||
var ib_size = geom.indices.length / 8
|
||||
|
||||
var vb = new gpu_mod.buffer(_gpu, {size: vb_size, vertex: true})
|
||||
var ib = new gpu_mod.buffer(_gpu, {size: ib_size, index: true})
|
||||
|
||||
var vb_transfer = new gpu_mod.transfer_buffer(_gpu, {size: vb_size, usage: "upload"})
|
||||
var ib_transfer = new gpu_mod.transfer_buffer(_gpu, {size: ib_size, usage: "upload"})
|
||||
|
||||
vb_transfer.copy_blob(_gpu, geom.vertices)
|
||||
ib_transfer.copy_blob(_gpu, geom.indices)
|
||||
|
||||
var copy_cmd = _gpu.acquire_cmd_buffer()
|
||||
var copy = copy_cmd.copy_pass()
|
||||
copy.upload_to_buffer({transfer_buffer: vb_transfer, offset: 0}, {buffer: vb, offset: 0, size: vb_size}, false)
|
||||
copy.upload_to_buffer({transfer_buffer: ib_transfer, offset: 0}, {buffer: ib, offset: 0, size: ib_size}, false)
|
||||
copy.end()
|
||||
copy_cmd.submit()
|
||||
|
||||
// Build camera matrix
|
||||
var proj = _build_camera_matrix(camera, target.width, target.height)
|
||||
|
||||
// Select pipeline based on blend mode
|
||||
var blend = drawable.blend || 'over'
|
||||
var pipeline = blend == 'add' ? _pipelines.sprite_add : _pipelines.sprite_alpha
|
||||
|
||||
// The texture_target has a .texture property from the target pool
|
||||
var tex = tex_target.texture || tex_target
|
||||
if (!tex) return
|
||||
|
||||
pass.bind_pipeline(pipeline)
|
||||
pass.bind_vertex_buffers(0, [{buffer: vb, offset: 0}])
|
||||
pass.bind_index_buffer({buffer: ib, offset: 0}, 16)
|
||||
pass.bind_fragment_samplers(0, [{texture: tex, sampler: _sampler_linear}])
|
||||
cmd_buffer.push_vertex_uniform_data(0, proj)
|
||||
pass.draw_indexed(geom.index_count, 1, 0, 0, 0)
|
||||
}
|
||||
|
||||
function _render_text(cmd_buffer, pass, drawable, camera, target) {
|
||||
// Get font - support mode tag: 'bitmap', 'sdf', 'msdf'
|
||||
var font_path = drawable.font
|
||||
@@ -1666,6 +1786,9 @@ function _do_shader_pass(cmd_buffer, cmd, get_swapchain_tex) {
|
||||
case 'accumulator':
|
||||
pipeline = _pipelines.accumulator
|
||||
break
|
||||
case 'mask':
|
||||
pipeline = _pipelines.mask
|
||||
break
|
||||
default:
|
||||
log.console(`sdl_gpu: Unknown shader: ${shader}`)
|
||||
return
|
||||
@@ -1762,7 +1885,7 @@ function _do_shader_pass(cmd_buffer, cmd, get_swapchain_tex) {
|
||||
|
||||
function _build_shader_uniforms(shader, uniforms) {
|
||||
var data = new blob_mod(64) // 16 floats max
|
||||
|
||||
|
||||
switch (shader) {
|
||||
case 'threshold':
|
||||
data.wf(uniforms.threshold || 0.8)
|
||||
@@ -1771,21 +1894,21 @@ function _build_shader_uniforms(shader, uniforms) {
|
||||
data.wf(0) // padding
|
||||
break
|
||||
case 'blur':
|
||||
var dir = uniforms.direction || [1, 0]
|
||||
var texel = uniforms.texel_size || [0.001, 0.001]
|
||||
data.wf(dir[0])
|
||||
data.wf(dir[1])
|
||||
data.wf(texel[0])
|
||||
data.wf(texel[1])
|
||||
var dir = uniforms.direction || {x: 1, y: 0}
|
||||
var texel = uniforms.texel_size || {x: 0.001, y: 0.001}
|
||||
data.wf(dir.x)
|
||||
data.wf(dir.y)
|
||||
data.wf(texel.x)
|
||||
data.wf(texel.y)
|
||||
break
|
||||
case 'crt':
|
||||
data.wf(uniforms.curvature || 0.1)
|
||||
data.wf(uniforms.scanline_intensity || 0.3)
|
||||
data.wf(uniforms.vignette || 0.2)
|
||||
data.wf(0) // padding
|
||||
var res = uniforms.resolution || [1280, 720]
|
||||
data.wf(res[0])
|
||||
data.wf(res[1])
|
||||
var res = uniforms.resolution || {width: 1280, height: 720}
|
||||
data.wf(res.width)
|
||||
data.wf(res.height)
|
||||
data.wf(0) // padding
|
||||
data.wf(0) // padding
|
||||
break
|
||||
@@ -1795,10 +1918,18 @@ function _build_shader_uniforms(shader, uniforms) {
|
||||
data.wf(0) // padding
|
||||
data.wf(0) // padding
|
||||
break
|
||||
case 'mask':
|
||||
// channel: 0=alpha, 1=luminance
|
||||
// invert: 0=normal, 1=inverted
|
||||
data.wf(uniforms.channel != null ? uniforms.channel : 0)
|
||||
data.wf(uniforms.invert != null ? uniforms.invert : 0)
|
||||
data.wf(0) // padding
|
||||
data.wf(0) // padding
|
||||
break
|
||||
default:
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
return stone(data)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user