Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draw call batching for Paths #81

Open
wants to merge 49 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
0c532ef
Move color and line width attributes to vertex data
Jul 28, 2024
8c5c017
Embed collor and width data for lines in polygons and elipses
Jul 28, 2024
5e67e19
Added Static lines, pass vertexBuffer with it's attributes to Drawabl…
Jul 31, 2024
6485dba
Testing StaticPath on Polygon, Path, Labels example
Aug 4, 2024
0d8509b
Fix zero size vertex attributes
Aug 5, 2024
76e2425
Add vertex color and line width mode to shader and revert related cha…
Aug 6, 2024
40ec59f
Created VertexState class to encapsulate buffers and arguments bindin…
Aug 7, 2024
d3966c8
Fixing comments
Aug 8, 2024
c34c4e7
Make VertexAttrib immutable
Aug 8, 2024
b3d08bb
Make VertexAttrib immutable
Aug 8, 2024
3b4332c
First commit for PickColor caching
Aug 14, 2024
4a2ffb0
Add pickColorBuffer for LinesBatch, restore paths highlight functiona…
Aug 17, 2024
db16dfb
Refactor vertexArray recreation for LinesBatch, use LineBatch only fo…
Aug 17, 2024
4c8bc6d
Rename vars, restore names for highways in PathsPolygonsLabelsActivit…
Aug 18, 2024
7f994fc
Add LineBatchesContainer to RenderableLayer to intercept Path rendera…
Aug 25, 2024
90e1913
Dead code elimination and cleanup after previous commit
Aug 25, 2024
bee3d27
Fix freeBatches adding logic, renaming some variables, forcing reset …
Aug 25, 2024
8032078
Remove reliance on AbstractShape render for Paths that has been batched
Aug 25, 2024
1ce3caf
Restore interface
Aug 25, 2024
57c5a5c
Renaming classes
Aug 27, 2024
3e4431e
Delete PickColorIdList, revert to previous pickColor logic, added off…
Sep 5, 2024
200eb69
Fix pickColor for LineSet
Sep 5, 2024
71a4a14
Added LineSetAttributes class, created a map translating attributes t…
Sep 6, 2024
f049a5d
Moving batch determination logic to AbstractShape, code cleanup
Sep 6, 2024
b722563
Address comments related to shader version, move VertexState to separ…
Sep 6, 2024
3cf43d9
Add attributesHash to AbstractShape to determine when attributes have…
Sep 8, 2024
800ab20
Fix LineSet vertices generation
Sep 11, 2024
8f4d756
Renaming classes
Oct 7, 2024
805b764
Fix after rename
Oct 7, 2024
54d1ddc
Add interface to abstract batching of renderables
Oct 7, 2024
3179759
Fix batch removal
Oct 7, 2024
0b987fe
Refactor coed to move batching to the Shape code
Oct 7, 2024
193f920
Fix batch recreation
Oct 9, 2024
38949b8
Disable batching for parts of composite shapes
Oct 9, 2024
f219af9
Change batchRenderers var to val
Oct 10, 2024
df41ee9
Batch paths managed by tacticalGraphics class
Oct 11, 2024
73eb7fb
Cleanup shapes on tactical graphics removal
Oct 11, 2024
8c76595
Remove shapes from batches according to lifetime
Oct 13, 2024
cd6dc5d
Fix texcoords for batched paths
Oct 13, 2024
59159ca
Fix batched shapes removal
Oct 13, 2024
5fc6296
Remove unneeded code for examples
Oct 13, 2024
af5a5bc
Use long for frameIndex
Oct 14, 2024
88b5635
Revert tactical graphics changes
Oct 14, 2024
d16b1aa
Fix comments
Oct 14, 2024
173ee16
Add TODO comments
Oct 14, 2024
0457bb0
Fix graticules rendering
Oct 16, 2024
14360f9
Remove cast
Oct 16, 2024
5e4d065
Disable batching for tactical graphics that has outline
Oct 16, 2024
9531a7d
Disable for pollygons and paths in tactical graphics
Oct 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions worldwind/src/commonMain/kotlin/earth/worldwind/WorldWind.kt
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ open class WorldWind @JvmOverloads constructor(
private val scratchProjection = Matrix4()
private val scratchPoint = Vec3()
private val scratchRay = Line()
private var frameIndex = 0L
IOTRFAFH marked this conversation as resolved.
Show resolved Hide resolved

init {
// Initialize default camera location based on user time zone
Expand Down Expand Up @@ -444,6 +445,7 @@ open class WorldWind @JvmOverloads constructor(
)
rc.renderResourceCache = renderResourceCache
rc.verticalExaggeration = verticalExaggeration
rc.frameIndex = frameIndex
rc.densityFactor = densityFactor
rc.atmosphereAltitude = atmosphereAltitude
rc.globeState = globe.state
Expand Down Expand Up @@ -494,6 +496,8 @@ open class WorldWind @JvmOverloads constructor(
// Reset the render context's state in preparation for the next frame.
rc.reset()

++frameIndex
IOTRFAFH marked this conversation as resolved.
Show resolved Hide resolved

return isRedrawRequested
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ import earth.worldwind.geom.Vec3
import earth.worldwind.render.Color
import earth.worldwind.render.Texture
import earth.worldwind.render.buffer.AbstractBufferObject
import earth.worldwind.render.buffer.FloatBufferObject
import earth.worldwind.render.program.TriangleShaderProgram
import earth.worldwind.render.VertexState

open class DrawShapeState internal constructor() {
companion object {
const val MAX_DRAW_ELEMENTS = 4
}

var program: TriangleShaderProgram? = null
var vertexBuffer: FloatBufferObject? = null
var elementBuffer: AbstractBufferObject? = null
val vertexOrigin = Vec3()
var vertexStride = 0
Expand All @@ -23,32 +22,34 @@ open class DrawShapeState internal constructor() {
var enableDepthWrite = true
var depthOffset = 0.0
var isLine = false
var isStatic = false
val vertexState = VertexState()
var pickIdOffset = 0
protected val color = Color()
protected var opacity = 1.0f
protected var lineWidth = 1f
protected var texture: Texture? = null
protected val texCoordMatrix = Matrix3()
private val texCoordAttrib = VertexAttrib()
internal var primCount = 0
internal val prims = Array(MAX_DRAW_ELEMENTS) { DrawElements() }

open fun reset() {
program = null
vertexBuffer = null
vertexState.reset()
elementBuffer = null
vertexOrigin.set(0.0, 0.0, 0.0)
vertexStride = 0
enableCullFace = true
enableDepthTest = true
isLine = false
isStatic = false
depthOffset = 0.0
color.set(1f, 1f, 1f, 1f)
pickIdOffset = 0
opacity = 1.0f
lineWidth = 1f
texture = null
texCoordMatrix.setToIdentity()
texCoordAttrib.size = 0
texCoordAttrib.offset = 0
primCount = 0
for (idx in 0 until MAX_DRAW_ELEMENTS) prims[idx].texture = null
}
Expand All @@ -63,11 +64,6 @@ open class DrawShapeState internal constructor() {

fun texCoordMatrix(matrix: Matrix3) = apply { texCoordMatrix.copy(matrix) }

fun texCoordAttrib(size: Int, offset: Int) = apply {
texCoordAttrib.size = size
texCoordAttrib.offset = offset
}

open fun drawElements(mode: Int, count: Int, type: Int, offset: Int) {
val prim = prims[primCount++]
prim.mode = mode
Expand All @@ -79,8 +75,6 @@ open class DrawShapeState internal constructor() {
prim.lineWidth = lineWidth
prim.texture = texture
prim.texCoordMatrix.copy(texCoordMatrix)
prim.texCoordAttrib.size = texCoordAttrib.size
prim.texCoordAttrib.offset = texCoordAttrib.offset
}

internal open class DrawElements {
Expand All @@ -93,11 +87,5 @@ open class DrawShapeState internal constructor() {
var lineWidth = 0f
var texture: Texture? = null
val texCoordMatrix = Matrix3()
val texCoordAttrib = VertexAttrib()
}

internal open class VertexAttrib {
var size = 0
var offset = 0
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ open class DrawableLines protected constructor(): Drawable {
// Disable texturing.
program.enableTexture(false)

// Ensure program is in triangles mode
program.enableOneVertexMode(false)
// Ensure program is in lines mode
program.enableLinesMode(true)
program.enableVertexColorAndWidth(false)

// Use the leader's color.
program.loadColor(color)
Expand All @@ -75,8 +76,8 @@ open class DrawableLines protected constructor(): Drawable {
if (!enableDepthTest) dc.gl.disable(GL_DEPTH_TEST)

// Use the leader line as the vertex point attribute.
dc.gl.enableVertexAttribArray(1 /*value*/)
dc.gl.enableVertexAttribArray(2 /*value*/)
dc.gl.enableVertexAttribArray(1 /*pointB*/)
dc.gl.enableVertexAttribArray(2 /*pointC*/)

// Use the shape's vertex point attribute and vertex texture coordinate attribute.
dc.gl.vertexAttribPointer(0 /*pointA*/, 4, GL_FLOAT, false, 20, offset + 0)
Expand All @@ -89,7 +90,7 @@ open class DrawableLines protected constructor(): Drawable {
// Restore the default WorldWind OpenGL state.
if (!enableDepthTest) dc.gl.enable(GL_DEPTH_TEST)

dc.gl.disableVertexAttribArray(1 /*value*/)
dc.gl.disableVertexAttribArray(2 /*value*/)
dc.gl.disableVertexAttribArray(1 /*pointB*/)
dc.gl.disableVertexAttribArray(2 /*pointC*/)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import earth.worldwind.geom.Matrix4
import earth.worldwind.util.Pool
import earth.worldwind.util.kgl.GL_CULL_FACE
import earth.worldwind.util.kgl.GL_DEPTH_TEST
import earth.worldwind.util.kgl.GL_FLOAT
import earth.worldwind.util.kgl.GL_LINES
import earth.worldwind.util.kgl.GL_LINE_LOOP
import earth.worldwind.util.kgl.GL_LINE_STRIP
import earth.worldwind.util.kgl.GL_TEXTURE0
import kotlin.jvm.JvmStatic

Expand Down Expand Up @@ -32,7 +34,7 @@ open class DrawableShape protected constructor(): Drawable {
// TODO shape batching
val program = drawState.program ?: return // program unspecified
if (!program.useProgram(dc)) return // program failed to build
if (drawState.vertexBuffer?.bindBuffer(dc) != true) return // vertex buffer unspecified or failed to bind
if (!drawState.vertexState.bind(dc)) return
if (drawState.elementBuffer?.bindBuffer(dc) != true) return // element buffer unspecified or failed to bind

// Use the draw context's pick mode.
Expand All @@ -51,6 +53,7 @@ open class DrawableShape protected constructor(): Drawable {
drawState.vertexOrigin.z
)
program.loadModelviewProjection(mvpMatrix)
program.loadPickIdOffset(drawState.pickIdOffset)

// Disable triangle back face culling if requested.
if (!drawState.enableCullFace) dc.gl.disable(GL_CULL_FACE)
Expand All @@ -64,48 +67,30 @@ open class DrawableShape protected constructor(): Drawable {
// Make multi-texture unit 0 active.
dc.activeTextureUnit(GL_TEXTURE0)

// Use the shape's vertex point attribute and vertex texture coordinate attribute.
dc.gl.enableVertexAttribArray(1 /*vertexTexCoord*/)
dc.gl.enableVertexAttribArray(2 /*vertexTexCoord*/)
dc.gl.enableVertexAttribArray(3 /*vertexTexCoord*/)
program.enableLinesMode(drawState.isLine)
program.enableVertexColorAndWidth(drawState.isStatic)
if (drawState.isLine) program.loadScreen(
dc.viewport.width.toFloat(),
dc.viewport.height.toFloat()
)

if (drawState.isLine) {
program.enableOneVertexMode(false)
program.loadScreen(dc.viewport.width.toFloat(), dc.viewport.height.toFloat())
dc.gl.vertexAttribPointer(0 /*pointA*/, 4, GL_FLOAT, false, 20, 0)
dc.gl.vertexAttribPointer(1 /*pointB*/, 4, GL_FLOAT, false, 20, 40)
dc.gl.vertexAttribPointer(2 /*pointC*/, 4, GL_FLOAT, false, 20, 80)
dc.gl.vertexAttribPointer(3 /*texCoord*/, 1, GL_FLOAT, false, 20, 56)
} else {
program.enableOneVertexMode(true)
dc.gl.vertexAttribPointer(0 /*vertexPoint*/, 3, GL_FLOAT, false, drawState.vertexStride, 0)
dc.gl.vertexAttribPointer(1 /*vertexPoint*/, 3, GL_FLOAT, false, drawState.vertexStride, 0)
dc.gl.vertexAttribPointer(2 /*vertexPoint*/, 3, GL_FLOAT, false, drawState.vertexStride, 0)
}
// Draw the specified primitives.
for (idx in 0 until drawState.primCount) {
val prim = drawState.prims[idx]
program.loadColor(prim.color)
program.loadOpacity(prim.opacity)
if (!drawState.isStatic) {
program.loadColor(prim.color)
program.loadLineWidth(prim.lineWidth)
}
if (prim.texture?.bindTexture(dc) == true) {
program.loadTexCoordMatrix(prim.texCoordMatrix)
program.enableTexture(true)
} else {
program.enableTexture(false)
}
if (drawState.isLine) {
program.loadLineWidth(prim.lineWidth)
} else {
dc.gl.vertexAttribPointer(
3 /*vertexTexCoord*/,
prim.texCoordAttrib.size,
GL_FLOAT,
false,
drawState.vertexStride,
prim.texCoordAttrib.offset
)
dc.gl.lineWidth(prim.lineWidth)
}
if (prim.mode == GL_LINES || prim.mode == GL_LINE_STRIP || prim.mode == GL_LINE_LOOP) dc.gl.lineWidth(
prim.lineWidth
)
dc.gl.drawElements(prim.mode, prim.count, prim.type, prim.offset)
}

Expand All @@ -115,8 +100,6 @@ open class DrawableShape protected constructor(): Drawable {
if (!drawState.enableDepthWrite) dc.gl.depthMask(true)
dc.gl.lineWidth(1f)
dc.gl.enable(GL_CULL_FACE)
dc.gl.disableVertexAttribArray(1 /*vertexTexCoord*/)
dc.gl.disableVertexAttribArray(2 /*vertexTexCoord*/)
dc.gl.disableVertexAttribArray(3 /*vertexTexCoord*/)
drawState.vertexState.unbind(dc)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@ open class DrawableSurfaceShape protected constructor(): Drawable {
// Make multi-texture unit 0 active.
dc.activeTextureUnit(GL_TEXTURE0)

// Set up to use vertex tex coord attributes.
dc.gl.enableVertexAttribArray(1 /*vertexTexCoord*/)
dc.gl.enableVertexAttribArray(2 /*vertexTexCoord*/)
dc.gl.enableVertexAttribArray(3 /*vertexTexCoord*/)

// Accumulate shapes in the draw context's scratch list.
// TODO accumulate in a geospatial quadtree
val scratchList = dc.scratchList
Expand Down Expand Up @@ -75,10 +70,6 @@ open class DrawableSurfaceShape protected constructor(): Drawable {
} finally {
// Clear the accumulated shapes.
scratchList.clear()
// Restore the default WorldWind OpenGL state.
dc.gl.disableVertexAttribArray(1 /*vertexTexCoord*/)
dc.gl.disableVertexAttribArray(2 /*vertexTexCoord*/)
dc.gl.disableVertexAttribArray(3 /*vertexTexCoord*/)
}
}

Expand Down Expand Up @@ -124,9 +115,16 @@ open class DrawableSurfaceShape protected constructor(): Drawable {
// Get the shape.
val shape = element as DrawableSurfaceShape
if (shape.offset != terrain.offset || !shape.sector.intersectsOrNextTo(terrainSector)) continue
if (shape.drawState.vertexBuffer?.bindBuffer(dc) != true) continue // vertex buffer unspecified or failed to bind
if (!shape.drawState.vertexState.bind(dc)) continue
if (shape.drawState.elementBuffer?.bindBuffer(dc) != true) continue // element buffer unspecified or failed to bind

program.enableLinesMode(shape.drawState.isLine)
program.enableVertexColorAndWidth(shape.drawState.isStatic)
if (shape.drawState.isLine) program.loadScreen(
colorAttachment.width.toFloat(),
colorAttachment.height.toFloat()
)

// Transform local shape coordinates to texture fragments appropriate for the terrain sector.
mvpMatrix.copy(textureMvpMatrix)
mvpMatrix.multiplyByTranslation(
Expand All @@ -135,51 +133,32 @@ open class DrawableSurfaceShape protected constructor(): Drawable {
shape.drawState.vertexOrigin.z
)
program.loadModelviewProjection(mvpMatrix)
if (shape.drawState.isLine) {
program.enableOneVertexMode(false)
program.loadScreen(colorAttachment.width.toFloat(), colorAttachment.height.toFloat())

dc.gl.vertexAttribPointer(0 /*pointA*/, 4, GL_FLOAT, false, 20, 0)
dc.gl.vertexAttribPointer(1 /*pointB*/, 4, GL_FLOAT, false, 20, 40)
dc.gl.vertexAttribPointer(2 /*pointC*/, 4, GL_FLOAT, false, 20, 80)
dc.gl.vertexAttribPointer(3 /*vertexTexCoord*/, 1, GL_FLOAT, false, 20, 56)
} else {
program.enableOneVertexMode(true)

// Use the shape's vertex point attribute.
dc.gl.vertexAttribPointer(0 /*vertexPoint*/, 3, GL_FLOAT, false, shape.drawState.vertexStride, 0)
dc.gl.vertexAttribPointer(1 /*vertexPoint*/, 3, GL_FLOAT, false, shape.drawState.vertexStride, 0)
dc.gl.vertexAttribPointer(2 /*vertexPoint*/, 3, GL_FLOAT, false, shape.drawState.vertexStride, 0)
}
program.loadPickIdOffset(shape.drawState.pickIdOffset)

// Draw the specified primitives to the framebuffer texture.
for (primIdx in 0 until shape.drawState.primCount) {
val prim = shape.drawState.prims[primIdx]
program.loadColor(prim.color)
program.loadOpacity(prim.opacity)
if (!drawState.isStatic) {
program.loadColor(prim.color)
program.loadLineWidth(prim.lineWidth)
}
if (prim.texture?.bindTexture(dc) == true) {
program.loadTexCoordMatrix(prim.texCoordMatrix)
program.enableTexture(true)
} else {
program.enableTexture(false)
}
if (shape.drawState.isLine) {
program.loadLineWidth(prim.lineWidth)
} else {
dc.gl.vertexAttribPointer(
3 /*vertexTexCoord*/,
prim.texCoordAttrib.size,
GL_FLOAT,
false,
shape.drawState.vertexStride,
prim.texCoordAttrib.offset
)
dc.gl.lineWidth(prim.lineWidth)
}
if (prim.mode == GL_LINES || prim.mode == GL_LINE_STRIP || prim.mode == GL_LINE_LOOP) dc.gl.lineWidth(
prim.lineWidth
)
dc.gl.drawElements(prim.mode, prim.count, prim.type, prim.offset)
}

// Accumulate the number of shapes drawn into the texture.
shapeCount++

shape.drawState.vertexState.unbind(dc)
}
} finally {
// Restore the default WorldWind OpenGL state.
Expand All @@ -194,22 +173,24 @@ open class DrawableSurfaceShape protected constructor(): Drawable {
protected open fun drawTextureToTerrain(dc: DrawContext, terrain: DrawableTerrain) {
val program = drawState.program ?: return
try {
dc.gl.enableVertexAttribArray(3 /*vertexTexCoord*/)
if (!terrain.useVertexPointAttrib(dc, 0 /*vertexPoint*/)) return // terrain vertex attribute failed to bind
if (!terrain.useVertexPointAttrib(dc, 1 /*vertexPoint*/)) return // terrain vertex attribute failed to bind
if (!terrain.useVertexPointAttrib(dc, 2 /*vertexPoint*/)) return // terrain vertex attribute failed to bind
if (!terrain.useVertexTexCoordAttrib(dc, 3 /*vertexTexCoord*/)) return // terrain vertex attribute failed to bind

val colorAttachment = dc.scratchFramebuffer.getAttachedTexture(GL_COLOR_ATTACHMENT0)
if (!colorAttachment.bindTexture(dc)) return // framebuffer texture failed to bind

// Configure the program to draw texture fragments unmodified and aligned with the terrain.
// TODO consolidate pickMode and enableTexture into a single textureMode
// TODO it's confusing that pickMode must be disabled during surface shape render-to-texture
program.enableOneVertexMode(true)
program.enableLinesMode(false)
program.enableVertexColorAndWidth(false)
program.enablePickMode(false)
program.enableTexture(true)
program.loadTexCoordMatrix(identityMatrix3)
program.loadColor(color)
program.loadOpacity(opacity)
program.loadPickIdOffset(0)

// Use the draw context's modelview projection matrix, transformed to terrain local coordinates.
val terrainOrigin = terrain.vertexOrigin
Expand All @@ -220,6 +201,7 @@ open class DrawableSurfaceShape protected constructor(): Drawable {
// Draw the terrain as triangles.
terrain.drawTriangles(dc)
} finally {
dc.gl.disableVertexAttribArray(3 /*vertexTexCoord*/)
// Unbind color attachment texture to avoid feedback loop
dc.bindTexture(KglTexture.NONE)
}
Expand Down
Loading
Loading