@ -73,11 +73,17 @@ function draw(state, context) {
@@ -73,11 +73,17 @@ function draw(state, context) {
bvh _clip ( state , context ) ;
const segment _count = geometry _write _instances ( state , context ) ;
const dynamic _segment _count = context . dynamic _segment _count ;
const dynamic _stroke _count = context . dynamic _stroke _count ;
// "Static" data upload
gl . bindBuffer ( gl . ARRAY _BUFFER , buffers [ 'b_instance' ] ) ;
gl . bufferData ( gl . ARRAY _BUFFER , context . instance _data _points . size * 4 + context . instance _data _ids . size * 4 , gl . STREAM _DRAW ) ;
gl . bufferSubData ( gl . ARRAY _BUFFER , 0 , tv _data ( context . instance _data _points ) ) ;
gl . bufferSubData ( gl . ARRAY _BUFFER , context . instance _data _points . size * 4 , tv _data ( context . instance _data _ids ) ) ;
gl . bindTexture ( gl . TEXTURE _2D , context . textures [ 'stroke_data' ] ) ;
// TODO: this is stable data, only upload new strokes as they arrive
upload _square _rgba16ui _texture ( gl , context . stroke _data , config . stroke _texture _size ) ;
gl . uniform2f ( locations [ 'u_res' ] , context . canvas . width , context . canvas . height ) ;
gl . uniform2f ( locations [ 'u_scale' ] , state . canvas . zoom , state . canvas . zoom ) ;
@ -91,7 +97,7 @@ function draw(state, context) {
@@ -91,7 +97,7 @@ function draw(state, context) {
gl . enableVertexAttribArray ( locations [ 'a_b' ] ) ;
gl . enableVertexAttribArray ( locations [ 'a_stroke_id' ] ) ;
// Points (a, b) and stroke ids are not stored in separate cpu buffers so that points can be resued
// Points (a, b) and stroke ids are stored in separate cpu buffers so that points can be reused (look at stride and offset values)
gl . vertexAttribPointer ( locations [ 'a_a' ] , 2 , gl . FLOAT , false , 2 * 4 , 0 ) ;
gl . vertexAttribPointer ( locations [ 'a_b' ] , 2 , gl . FLOAT , false , 2 * 4 , 2 * 4 ) ;
gl . vertexAttribIPointer ( locations [ 'a_stroke_id' ] , 1 , gl . INT , 4 , context . instance _data _points . size * 4 ) ;
@ -99,81 +105,47 @@ function draw(state, context) {
@@ -99,81 +105,47 @@ function draw(state, context) {
gl . vertexAttribDivisor ( locations [ 'a_a' ] , 1 ) ;
gl . vertexAttribDivisor ( locations [ 'a_b' ] , 1 ) ;
gl . vertexAttribDivisor ( locations [ 'a_stroke_id' ] , 1 ) ;
gl . bindTexture ( gl . TEXTURE _2D , context . textures [ 'stroke_data' ] ) ;
// TODO: this is stable data, only upload new strokes as they arrive
upload _square _rgba16ui _texture ( gl , context . stroke _data , config . stroke _texture _size ) ;
gl . activeTexture ( gl . TEXTURE0 ) ;
gl . drawArraysInstanced ( gl . TRIANGLES , 0 , 6 , segment _count ) ; // TODO: based on clipping results
document . getElementById ( 'debug-stats' ) . innerHTML = `
< span > Segments onscreen : $ { segment _count } < / s p a n >
< span > Canvas offset : ( $ { state . canvas . offset . x } , $ { state . canvas . offset . y } ) < / s p a n >
< span > Canvas zoom : $ { Math . round ( state . canvas . zoom * 100000 ) / 100000 } < / s p a n > ` ;
/ *
// Dynamic data (stroke previews that are currently in progress)
const dynamic _points = context . dynamic _serializer . offset / config . bytes _per _point ;
if ( dynamic _points > 0 ) {
gl . drawBuffers ( [ gl . BACK ] ) ;
locations = context . locations [ 'sdf' ] . main ;
gl . useProgram ( context . programs [ 'sdf' ] . main ) ;
gl . uniform2f ( locations [ 'u_res' ] , context . canvas . width , context . canvas . height ) ;
gl . uniform2f ( locations [ 'u_scale' ] , state . canvas . zoom , state . canvas . zoom ) ;
gl . uniform2f ( locations [ 'u_translation' ] , state . canvas . offset . x , state . canvas . offset . y ) ;
gl . uniform1i ( locations [ 'u_stroke_count' ] , state . stroke _count ) ;
gl . uniform1i ( locations [ 'u_debug_mode' ] , state . debug . red ) ;
gl . clear ( gl . DEPTH _BUFFER _BIT ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , buffers [ 'b_packed_dynamic' ] ) ;
gl . bindBuffer ( gl . ELEMENT _ARRAY _BUFFER , buffers [ 'b_packed_dynamic_index' ] ) ;
gl . enableVertexAttribArray ( locations [ 'a_pos' ] ) ;
gl . enableVertexAttribArray ( locations [ 'a_line' ] ) ;
gl . enableVertexAttribArray ( locations [ 'a_color' ] ) ;
gl . enableVertexAttribArray ( locations [ 'a_stroke_id' ] ) ;
// Static draw (everything already bound)
gl . drawArraysInstanced ( gl . TRIANGLES , 0 , 6 , segment _count ) ;
// Dynamic strokes should be drawn above static strokes
gl . clear ( gl . DEPTH _BUFFER _BIT ) ;
gl . vertexAttribPointer ( locations [ 'a_pos' ] , 3 , gl . FLOAT , false , config . bytes _per _point , 0 ) ;
gl . vertexAttribPointer ( locations [ 'a_line' ] , 4 , gl . FLOAT , false , config . bytes _per _point , 4 * 3 ) ;
gl . vertexAttribPointer ( locations [ 'a_color' ] , 3 , gl . UNSIGNED _BYTE , true , config . bytes _per _point , 4 * 3 + 4 * 4 ) ;
gl . vertexAttribIPointer ( locations [ 'a_stroke_id' ] , 1 , gl . INT , config . bytes _per _point , 4 * 3 + 4 * 4 + 4 ) ;
// Dynamic draw (strokes currently being drawn)
gl . uniform1i ( locations [ 'u_stroke_count' ] , dynamic _stroke _count ) ;
gl . uniform1i ( locations [ 'u_stroke_data' ] , 0 ) ;
gl . uniform1i ( locations [ 'u_stroke_texture_size' ] , config . dynamic _stroke _texture _size ) ;
gl . bindBuffer ( gl . ARRAY _BUFFER , buffers [ 'b_dynamic_instance' ] ) ;
const dynamic _indices = [ ] ;
let base = 0 ;
// Dynamic data upload
gl . bufferData ( gl . ARRAY _BUFFER , context . dynamic _instance _points . size * 4 + context . dynamic _instance _ids . size * 4 , gl . STREAM _DRAW ) ;
gl . bufferSubData ( gl . ARRAY _BUFFER , 0 , tv _data ( context . dynamic _instance _points ) ) ;
gl . bufferSubData ( gl . ARRAY _BUFFER , context . dynamic _instance _points . size * 4 , tv _data ( context . dynamic _instance _ids ) ) ;
gl . bindTexture ( gl . TEXTURE _2D , context . textures [ 'dynamic_stroke_data' ] ) ;
upload _square _rgba16ui _texture ( gl , context . dynamic _stroke _data , config . dynamic _stroke _texture _size ) ;
for ( const player _id in state . players ) {
// player has the same data as their current stroke: points, color, width
const player = state . players [ player _id ] ;
if ( player . points . length > 1 ) {
for ( let i = 0 ; i < player . points . length - 1 ; ++ i ) {
dynamic _indices . push ( base + 0 ) ;
dynamic _indices . push ( base + 1 ) ;
dynamic _indices . push ( base + 2 ) ;
dynamic _indices . push ( base + 3 ) ;
dynamic _indices . push ( base + 2 ) ;
dynamic _indices . push ( base + 1 ) ;
gl . enableVertexAttribArray ( locations [ 'a_a' ] ) ;
gl . enableVertexAttribArray ( locations [ 'a_b' ] ) ;
gl . enableVertexAttribArray ( locations [ 'a_stroke_id' ] ) ;
// Points (a, b) and stroke ids are stored in separate cpu buffers so that points can be reused (look at stride and offset values)
gl . vertexAttribPointer ( locations [ 'a_a' ] , 2 , gl . FLOAT , false , 2 * 4 , 0 ) ;
gl . vertexAttribPointer ( locations [ 'a_b' ] , 2 , gl . FLOAT , false , 2 * 4 , 2 * 4 ) ;
gl . vertexAttribIPointer ( locations [ 'a_stroke_id' ] , 1 , gl . INT , 4 , context . dynamic _instance _points . size * 4 ) ;
base += 4 ;
}
}
}
gl . vertexAttribDivisor ( locations [ 'a_a' ] , 1 ) ;
gl . vertexAttribDivisor ( locations [ 'a_b' ] , 1 ) ;
gl . vertexAttribDivisor ( locations [ 'a_stroke_id' ] , 1 ) ;
gl . drawArraysInstanced ( gl . TRIANGLES , 0 , 6 , dynamic _segment _count ) ;
if ( context . need _dynamic _upload ) {
gl . bufferData ( gl . ARRAY _BUFFER , new Uint8Array ( context . dynamic _serializer . buffer , 0 , context . dynamic _serializer . offset ) , gl . DYNAMIC _DRAW ) ;
gl . bufferData ( gl . ELEMENT _ARRAY _BUFFER , new Uint32Array ( dynamic _indices ) , gl . DYNAMIC _DRAW ) ;
context . need _dynamic _upload = false ;
}
document . getElementById ( 'debug-stats' ) . innerHTML = `
< span > Segments onscreen : $ { segment _count } < / s p a n >
< span > Canvas offset : ( $ { state . canvas . offset . x } , $ { state . canvas . offset . y } ) < / s p a n >
< span > Canvas zoom : $ { Math . round ( state . canvas . zoom * 100000 ) / 100000 } < / s p a n > ` ;
gl . drawElements ( gl . TRIANGLES , dynamic _indices . length , gl . UNSIGNED _INT , 0 ) ;
}
* /
if ( context . gpu _timer _ext ) {
gl . endQuery ( context . gpu _timer _ext . TIME _ELAPSED _EXT ) ;