enhanced 2d drawables

This commit is contained in:
2026-01-08 13:08:14 -06:00
parent 1ed5562650
commit dec26f6b41
6 changed files with 83 additions and 25 deletions

View File

@@ -219,7 +219,7 @@ function _batch_drawables(drawables) {
if (d.type == 'sprite') {
var tex = d.texture || d.image
var mat = d.material || default_mat
var mat = d.material || {blend: 'alpha', sampler: d.filter || 'nearest'}
if (current && current.type == 'sprite_batch' && current.texture == tex && _mat_eq(current.material, mat)) {
current.sprites.push(d)
@@ -232,9 +232,12 @@ function _batch_drawables(drawables) {
var tex = d.texture || d.image
var mat = d.material || default_mat
var particles = d.particles || []
var emitter_opacity = d.opacity != null ? d.opacity : 1
var emitter_tint = d.tint || {r: 1, g: 1, b: 1, a: 1}
for (var p = 0; p < particles.length; p++) {
var part = particles[p]
var pc = part.color || {r: 1, g: 1, b: 1, a: 1}
var sprite = {
type: 'sprite',
pos: part.pos,
@@ -242,7 +245,9 @@ function _batch_drawables(drawables) {
height: (d.height || 16) * (part.scale || 1),
anchor_x: 0.5,
anchor_y: 0.5,
color: part.color || {r: 1, g: 1, b: 1, a: 1}
color: pc,
opacity: emitter_opacity,
tint: emitter_tint
}
if (current && current.type == 'sprite_batch' && current.texture == tex && _mat_eq(current.material, mat)) {
@@ -259,6 +264,8 @@ function _batch_drawables(drawables) {
var tile_h = d.tile_height || 1
var off_x = d.offset_x || 0
var off_y = d.offset_y || 0
var tilemap_opacity = d.opacity != null ? d.opacity : 1
var tilemap_tint = d.tint || {r: 1, g: 1, b: 1, a: 1}
for (var x = 0; x < tiles.length; x++) {
if (!tiles[x]) continue
@@ -278,7 +285,9 @@ function _batch_drawables(drawables) {
height: tile_h,
anchor_x: 0.5,
anchor_y: 0.5,
color: {r: 1, g: 1, b: 1, a: 1}
color: {r: 1, g: 1, b: 1, a: 1},
opacity: tilemap_opacity,
tint: tilemap_tint
}
// Batching

View File

@@ -123,7 +123,9 @@ var factory = function(props) {
plane: 'default',
layer: 0,
groups: [],
particles: []
particles: [],
opacity: 1,
tint: {r: 1, g: 1, b: 1, a: 1}
}
var data = {}

View File

@@ -803,6 +803,14 @@ function _build_sprite_vertices(sprites, camera) {
var ay = s.anchor_y || 0
var c = s.color || white
// Apply tint and opacity
var tint = s.tint || white
var opacity = s.opacity != null ? s.opacity : 1
var final_r = c.r * tint.r
var final_g = c.g * tint.g
var final_b = c.b * tint.b
var final_a = c.a * (tint.a != null ? tint.a : 1) * opacity
// Apply anchor
var x = px - w * ax
var y = py - h * ay
@@ -812,6 +820,33 @@ function _build_sprite_vertices(sprites, camera) {
var v0 = s.uv_rect ? s.uv_rect.y : 0
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
// Apply UV transform (offset, scale, rotate)
var uv = s.uv
if (uv) {
var uv_off = uv.offset || {x: 0, y: 0}
var uv_scale = uv.scale || {x: 1, y: 1}
// Apply scale and offset to UVs
u0 = u0 * uv_scale.x + uv_off.x
v0 = v0 * uv_scale.y + uv_off.y
u1 = u1 * uv_scale.x + uv_off.x
v1 = v1 * uv_scale.y + uv_off.y
}
// Apply flip
var flip = s.flip
if (flip) {
if (flip.x) {
var tmp = u0
u0 = u1
u1 = tmp
}
if (flip.y) {
var tmp = v0
v0 = v1
v1 = tmp
}
}
// Quad vertices (bottom-left, bottom-right, top-right, top-left)
// v0: bottom-left
@@ -819,40 +854,40 @@ function _build_sprite_vertices(sprites, camera) {
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)
vertex_data.wf(final_r)
vertex_data.wf(final_g)
vertex_data.wf(final_b)
vertex_data.wf(final_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)
vertex_data.wf(final_r)
vertex_data.wf(final_g)
vertex_data.wf(final_b)
vertex_data.wf(final_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)
vertex_data.wf(final_r)
vertex_data.wf(final_g)
vertex_data.wf(final_b)
vertex_data.wf(final_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)
vertex_data.wf(final_r)
vertex_data.wf(final_g)
vertex_data.wf(final_b)
vertex_data.wf(final_a)
// Indices (two triangles)
index_data.w16(vertex_count + 0)
@@ -1274,12 +1309,14 @@ function _flush_draws(cmd_buffer, pass, draws, camera, target) {
// Sprite batch handling
var tex_path = draw.texture || '_white'
var blend = draw.material ? draw.material.blend : 'alpha'
var sampler = draw.material ? draw.material.sampler : 'nearest'
// Check if we can append to current batch
if (current_batch &&
current_batch.type == 'sprites' &&
current_batch.texture_path == tex_path &&
current_batch.blend == blend) {
current_batch.blend == blend &&
current_batch.sampler == sampler) {
// Append sprites
if (draw.geometry && draw.geometry.sprites) {
@@ -1296,6 +1333,7 @@ function _flush_draws(cmd_buffer, pass, draws, camera, target) {
type: 'sprites',
texture_path: tex_path,
blend: blend,
sampler: sampler,
sprites: []
}
@@ -1359,11 +1397,14 @@ function _render_batch(cmd_buffer, pass, batch, camera, target) {
// Select pipeline
var pipeline = batch.blend == 'add' ? _pipelines.sprite_add : _pipelines.sprite_alpha
// Select sampler based on filter
var sampler = (batch.sampler == 'linear') ? _sampler_linear : _sampler_nearest
// Draw
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_nearest}])
pass.bind_fragment_samplers(0, [{texture: tex, sampler: sampler}])
cmd_buffer.push_vertex_uniform_data(0, proj)
pass.draw_indexed(geom.index_count, 1, 0, 0, 0)
}

View File

@@ -47,11 +47,13 @@ return function(props) {
height: 1,
anchor_x: 0,
anchor_y: 0,
flip_x: false,
flip_y: false,
flip: {x: false, y: false},
rotation: 0,
color: {r: 1, g: 1, b: 1, a: 1},
opacity: 1,
tint: {r: 1, g: 1, b: 1, a: 1},
filter: 'nearest',
uv: {offset: {x: 0, y: 0}, scale: {x: 1, y: 1}, rotate: 0},
plane: 'default',
layer: 0,
groups: [],

View File

@@ -35,6 +35,8 @@ return function(props) {
font: "fonts/dos",
size: 16,
color: {r: 1, g: 1, b: 1, a: 1},
opacity: 1,
tint: {r: 1, g: 1, b: 1, a: 1},
mode: null,
sdf: null,
outline_width: null,

View File

@@ -49,7 +49,9 @@ return function(props) {
layer: 0,
groups: [],
tile_width: 1,
tile_height: 1
tile_height: 1,
opacity: 1,
tint: {r: 1, g: 1, b: 1, a: 1}
}
var data = {}