Skip to content

Commit

Permalink
Add opacity support to Placemarks, Paths, Ellipses, Polygons, Surface…
Browse files Browse the repository at this point in the history
…Images and Labels. (#40)
  • Loading branch information
GuzulFromUkraine authored Sep 28, 2023
1 parent 5596d43 commit 727adfa
Show file tree
Hide file tree
Showing 13 changed files with 64 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ open class DrawShapeState internal constructor() {
var enableDepthWrite = true
var depthOffset = 0.0
protected val color = Color()
protected var opacity = 1.0f
protected var lineWidth = 1f
protected var texture: Texture? = null
protected val texCoordMatrix = Matrix3()
Expand All @@ -40,6 +41,7 @@ open class DrawShapeState internal constructor() {
enableDepthTest = true
depthOffset = 0.0
color.set(1f, 1f, 1f, 1f)
opacity = 1.0f
lineWidth = 1f
texture = null
texCoordMatrix.setToIdentity()
Expand All @@ -51,6 +53,8 @@ open class DrawShapeState internal constructor() {

fun color(color: Color) = apply { this.color.copy(color) }

fun opacity(opacity: Float) = apply { this.opacity = opacity }

fun lineWidth(width: Float) = apply { lineWidth = width }

fun texture(texture: Texture?) = apply { this.texture = texture }
Expand All @@ -69,6 +73,7 @@ open class DrawShapeState internal constructor() {
prim.type = type
prim.offset = offset
prim.color.copy(color)
prim.opacity = opacity
prim.lineWidth = lineWidth
prim.texture = texture
prim.texCoordMatrix.copy(texCoordMatrix)
Expand All @@ -82,6 +87,7 @@ open class DrawShapeState internal constructor() {
var type = 0
var offset = 0
val color = Color()
var opacity = 1.0f
var lineWidth = 0f
var texture: Texture? = null
val texCoordMatrix = Matrix3()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ open class DrawableLines protected constructor(): Drawable {
var vertexPoints: FloatBufferObject? = null
val mvpMatrix = Matrix4()
val color = Color()
var opacity = 1.0f
var lineWidth = 1f
var enableDepthTest = true
var program: BasicShaderProgram? = null
Expand Down Expand Up @@ -51,6 +52,9 @@ open class DrawableLines protected constructor(): Drawable {
// Use the leader's color.
program.loadColor(color)

// Use the leader's opacity.
program.loadOpacity(opacity)

// Use the leader's modelview-projection matrix.
program.loadModelviewProjection(mvpMatrix)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import kotlin.jvm.JvmStatic
open class DrawableScreenTexture protected constructor(): Drawable {
val unitSquareTransform = Matrix4()
val color = Color()
var opacity = 1.0f
var enableDepthTest = true
var program: BasicShaderProgram? = null
var texture: Texture? = null
Expand Down Expand Up @@ -76,6 +77,7 @@ open class DrawableScreenTexture protected constructor(): Drawable {

// Use the drawable's color.
program.loadColor(drawable.color)
program.loadOpacity(drawable.opacity)

// Attempt to bind the drawable's texture, configuring the shader program appropriately if there is no texture
// or if the texture failed to bind.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ open class DrawableShape protected constructor(): Drawable {
for (idx in 0 until drawState.primCount) {
val prim = drawState.prims[idx]
program.loadColor(prim.color)
program.loadOpacity(prim.opacity)
if (prim.texture?.bindTexture(dc) == true) {
program.loadTexCoordMatrix(prim.texCoordMatrix)
program.enableTexture(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import kotlin.jvm.JvmStatic
open class DrawableSurfaceTexture protected constructor(): Drawable {
val sector = Sector()
val color = Color()
var opacity = 1.0f
val texCoordMatrix = Matrix3()
var texture: Texture? = null
var program: SurfaceTextureProgram? = null
Expand All @@ -31,6 +32,7 @@ open class DrawableSurfaceTexture protected constructor(): Drawable {
) = apply {
if (sector != null) this.sector.copy(sector) else this.sector.setEmpty()
this.color.set(1f, 1f, 1f, 1f)
this.opacity = 1f
if (texCoordMatrix != null) this.texCoordMatrix.copy(texCoordMatrix) else this.texCoordMatrix.setToIdentity()
this.texture = texture
this.program = program
Expand Down Expand Up @@ -124,6 +126,9 @@ open class DrawableSurfaceTexture protected constructor(): Drawable {
// Use the surface texture's RGBA color.
program.loadColor(texture.color)

// Use the surface texture's opacity.
program.loadOpacity(texture.opacity)

// Draw the terrain as triangles.
terrain.drawTriangles(dc)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ open class BasicShaderProgram : AbstractShaderProgram() {
uniform bool enablePickMode;
uniform bool enableTexture;
uniform vec4 color;
uniform float opacity;
uniform sampler2D texSampler;
varying vec2 texCoord;
Expand All @@ -47,10 +48,10 @@ open class BasicShaderProgram : AbstractShaderProgram() {
gl_FragColor = color * texMask;
} else if (!enablePickMode && enableTexture) {
/* Modulate the RGBA color with the 2D texture's RGBA color. */
gl_FragColor = color * texture2D(texSampler, texCoord);
gl_FragColor = color * texture2D(texSampler, texCoord) * opacity;
} else {
/* Return the RGBA color as-is. */
gl_FragColor = color;
gl_FragColor = color * opacity;
}
}
""".trimIndent()
Expand All @@ -62,12 +63,14 @@ open class BasicShaderProgram : AbstractShaderProgram() {
protected val mvpMatrix = Matrix4()
protected val texCoordMatrix = Matrix3()
protected val color = Color()
protected var opacity = 1.0f
protected var enablePickModeId = KglUniformLocation.NONE
protected var enableTextureId = KglUniformLocation.NONE
protected var mvpMatrixId = KglUniformLocation.NONE
protected var texCoordMatrixId = KglUniformLocation.NONE
protected var texSamplerId = KglUniformLocation.NONE
protected var colorId = KglUniformLocation.NONE
protected var opacityId = KglUniformLocation.NONE
private val array = FloatArray(16)

override fun initProgram(dc: DrawContext) {
Expand All @@ -85,6 +88,8 @@ open class BasicShaderProgram : AbstractShaderProgram() {
colorId = gl.getUniformLocation(program, "color")
val alpha = color.alpha
gl.uniform4f(colorId, color.red * alpha, color.green * alpha, color.blue * alpha, alpha)
opacityId = gl.getUniformLocation(program, "opacity")
gl.uniform1f(opacityId, opacity)
texSamplerId = gl.getUniformLocation(program, "texSampler")
gl.uniform1i(texSamplerId, 0) // GL_TEXTURE0
}
Expand Down Expand Up @@ -124,4 +129,11 @@ open class BasicShaderProgram : AbstractShaderProgram() {
gl.uniform4f(colorId, color.red * alpha, color.green * alpha, color.blue * alpha, alpha)
}
}

fun loadOpacity(opacity: Float) {
if (this.opacity != opacity) {
this.opacity = opacity
gl.uniform1f(opacityId, opacity)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ open class SurfaceTextureProgram : AbstractShaderProgram() {
uniform bool enablePickMode;
uniform bool enableTexture;
uniform vec4 color;
uniform float opacity;
uniform sampler2D texSampler;
varying vec2 texCoord;
Expand All @@ -65,10 +66,10 @@ open class SurfaceTextureProgram : AbstractShaderProgram() {
} else if (!enablePickMode && enableTexture) {
/* Using the first texture coordinate, modulate the RGBA color with the 2D texture's RGBA color. Finally,
modulate by the tile mask to suppress fragments outside the surface tile. */
gl_FragColor = color * texture2D(texSampler, texCoord) * tileMask;
gl_FragColor = color * texture2D(texSampler, texCoord) * opacity * tileMask;
} else {
/* Modulate the RGBA color by the tile mask to suppress fragments outside the surface tile. */
gl_FragColor = color * tileMask;
gl_FragColor = color * opacity * tileMask;
}
}
""".trimIndent()
Expand All @@ -83,9 +84,11 @@ open class SurfaceTextureProgram : AbstractShaderProgram() {
protected var texCoordMatrixId = KglUniformLocation.NONE
protected var texSamplerId = KglUniformLocation.NONE
protected var colorId = KglUniformLocation.NONE
protected var opacityId = KglUniformLocation.NONE
private val mvpMatrixArray = FloatArray(16)
private val texCoordMatrixArray = FloatArray(9 * 2)
private val color = Color()
private var opacity = 1.0f

override fun initProgram(dc: DrawContext) {
super.initProgram(dc)
Expand All @@ -103,6 +106,8 @@ open class SurfaceTextureProgram : AbstractShaderProgram() {
colorId = gl.getUniformLocation(program, "color")
color.set(1f, 1f, 1f, 1f) // opaque white
gl.uniform4f(colorId, color.red, color.green, color.blue, color.alpha)
opacityId = gl.getUniformLocation(program, "opacity")
gl.uniform1f(opacityId, opacity)
texSamplerId = gl.getUniformLocation(program, "texSampler")
gl.uniform1i(texSamplerId, 0) // GL_TEXTURE0
}
Expand All @@ -123,10 +128,17 @@ open class SurfaceTextureProgram : AbstractShaderProgram() {
}

fun loadColor(color: Color) {
if (this.color != color) { // suppress unnecessary writes to GLSL uniform variables
if (this.color != color) {
this.color.copy(color)
val a: Float = color.alpha
gl.uniform4f(colorId, color.red * a, color.green * a, color.blue * a, a)
val alpha = color.alpha
gl.uniform4f(colorId, color.red * alpha, color.green * alpha, color.blue * alpha, alpha)
}
}

fun loadOpacity(opacity: Float) {
if (this.opacity != opacity) {
this.opacity = opacity
gl.uniform1f(opacityId, opacity)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ open class Ellipse @JvmOverloads constructor(

// Configure the drawable to display the shape's interior.
drawState.color(if (rc.isPickMode) pickColor else activeAttributes.interiorColor)
drawState.opacity(if (rc.isPickMode) 1f else rc.currentLayer.opacity)
drawState.texCoordAttrib(2 /*size*/, 12 /*offset in bytes*/)
val top = drawState.elementBuffer!!.ranges[TOP_RANGE]!!
drawState.drawElements(GL_TRIANGLE_STRIP, top.length, GL_UNSIGNED_SHORT, top.lower * 2 /*offset*/)
Expand All @@ -336,13 +337,15 @@ open class Ellipse @JvmOverloads constructor(

// Configure the drawable to display the shape's outline.
drawState.color(if (rc.isPickMode) pickColor else activeAttributes.outlineColor)
drawState.opacity(if (rc.isPickMode) 1f else rc.currentLayer.opacity)
drawState.lineWidth(activeAttributes.outlineWidth)
drawState.texCoordAttrib(1 /*size*/, 20 /*offset in bytes*/)
val outline = drawState.elementBuffer!!.ranges[OUTLINE_RANGE]!!
drawState.drawElements(GL_LINE_LOOP, outline.length, GL_UNSIGNED_SHORT, outline.lower * 2 /*offset*/)
if (activeAttributes.isDrawVerticals && isExtrude) {
val side = drawState.elementBuffer!!.ranges[SIDE_RANGE]!!
drawState.color(if (rc.isPickMode) pickColor else activeAttributes.outlineColor)
drawState.opacity(if (rc.isPickMode) 1f else rc.currentLayer.opacity)
drawState.lineWidth(activeAttributes.outlineWidth)
drawState.texture(null)
drawState.drawElements(GL_LINES, side.length, GL_UNSIGNED_SHORT, side.lower * 2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,7 @@ open class Label @JvmOverloads constructor(
val drawableCount = rc.drawableCount
if (rc.isPickMode) {
renderData.pickedObjectId = rc.nextPickedObjectId()
PickedObject.identifierToUniqueColor(
renderData.pickedObjectId, renderData.pickColor
)
PickedObject.identifierToUniqueColor(renderData.pickedObjectId, renderData.pickColor)
}

// Enqueue drawables for processing on the OpenGL thread.
Expand Down Expand Up @@ -200,6 +198,7 @@ open class Label @JvmOverloads constructor(
// in the texture's color.
if (rc.isPickMode) drawable.color.copy(renderData.pickColor)
else drawable.color.set(1f, 1f, 1f, 1f)
drawable.opacity = if (rc.isPickMode) 1f else rc.currentLayer.opacity
drawable.texture = texture
drawable.enableDepthTest = activeAttributes.isDepthTest

Expand Down
3 changes: 3 additions & 0 deletions worldwind/src/commonMain/kotlin/earth/worldwind/shape/Path.kt
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ open class Path @JvmOverloads constructor(
// drawn indirectly offscreen framebuffer appear thinner when sampled as a texture.
if (activeAttributes.isDrawOutline) {
drawState.color(if (rc.isPickMode) pickColor else activeAttributes.outlineColor)
drawState.opacity(if (rc.isPickMode) 1f else rc.currentLayer.opacity)
drawState.lineWidth(activeAttributes.outlineWidth + if (isSurfaceShape) 0.5f else 0f)
drawState.drawElements(
GL_LINE_STRIP, outlineElements.size,
Expand All @@ -128,6 +129,7 @@ open class Path @JvmOverloads constructor(
// Configure the drawable to display the shape's extruded verticals.
if (activeAttributes.isDrawOutline && activeAttributes.isDrawVerticals && isExtrude) {
drawState.color(if (rc.isPickMode) pickColor else activeAttributes.outlineColor)
drawState.opacity(if (rc.isPickMode) 1f else rc.currentLayer.opacity)
drawState.lineWidth(activeAttributes.outlineWidth)
drawState.drawElements(
GL_LINES, verticalElements.size,
Expand All @@ -138,6 +140,7 @@ open class Path @JvmOverloads constructor(
// Configure the drawable to display the shape's extruded interior.
if (activeAttributes.isDrawInterior && isExtrude) {
drawState.color(if (rc.isPickMode) pickColor else activeAttributes.interiorColor)
drawState.opacity(if (rc.isPickMode) 1f else rc.currentLayer.opacity)
drawState.drawElements(
GL_TRIANGLE_STRIP, interiorElements.size,
GL_UNSIGNED_INT, 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ open class Placemark @JvmOverloads constructor(
// the active attributes' image source and its associated tex coord transform. If the texture is not specified
// or not available, draw a simple colored square.
drawable.color.copy(if (rc.isPickMode) pickColor else activeAttributes.imageColor)
drawable.opacity = if (rc.isPickMode) 1f else rc.currentLayer.opacity
drawable.texture = activeTexture
drawable.enableDepthTest = activeAttributes.isDepthTest
}
Expand All @@ -437,6 +438,7 @@ open class Placemark @JvmOverloads constructor(
// color for drawing, specifying white for normal drawing ensures the color multiplication in the shader results
// in the texture's color.
if (rc.isPickMode) drawable.color.copy(pickColor) else drawable.color.set(1f, 1f, 1f, 1f)
drawable.opacity = if (rc.isPickMode) 1f else rc.currentLayer.opacity
drawable.texture = labelTexture
drawable.enableDepthTest = activeAttributes.labelAttributes.isDepthTest
}
Expand Down Expand Up @@ -475,6 +477,7 @@ open class Placemark @JvmOverloads constructor(
// Configure the drawable according to the placemark's active leader attributes. Use a color appropriate for the
// pick mode. When picking use a unique color associated with the picked object ID.
drawable.color.copy(if (rc.isPickMode) pickColor else activeAttributes.leaderAttributes.outlineColor)
drawable.opacity = if (rc.isPickMode) 1f else rc.currentLayer.opacity
drawable.lineWidth = activeAttributes.leaderAttributes.outlineWidth
drawable.enableDepthTest = activeAttributes.leaderAttributes.isDepthTest
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ open class Polygon @JvmOverloads constructor(

// Configure the drawable to display the shape's interior top.
drawState.color(if (rc.isPickMode) pickColor else activeAttributes.interiorColor)
drawState.opacity(if (rc.isPickMode) 1f else rc.currentLayer.opacity)
drawState.texCoordAttrib(2 /*size*/, 12 /*offset in bytes*/)
drawState.drawElements(GL_TRIANGLES, topElements.size, GL_UNSIGNED_INT, 0 /*offset*/)

Expand All @@ -228,6 +229,7 @@ open class Polygon @JvmOverloads constructor(

// Configure the drawable to display the shape's outline.
drawState.color(if (rc.isPickMode) pickColor else activeAttributes.outlineColor)
drawState.opacity(if (rc.isPickMode) 1f else rc.currentLayer.opacity)
drawState.lineWidth(activeAttributes.outlineWidth)
drawState.texCoordAttrib(1 /*size*/, 20 /*offset in bytes*/)
drawState.drawElements(
Expand All @@ -238,6 +240,7 @@ open class Polygon @JvmOverloads constructor(
// Configure the drawable to display the shape's extruded verticals.
if (activeAttributes.isDrawVerticals && isExtrude) {
drawState.color(if (rc.isPickMode) pickColor else activeAttributes.outlineColor)
drawState.opacity(if (rc.isPickMode) 1f else rc.currentLayer.opacity)
drawState.lineWidth(activeAttributes.outlineWidth)
drawState.texture(null)
drawState.drawElements(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ open class SurfaceImage(sector: Sector, var imageSource: ImageSource): AbstractS
val program = getShaderProgram(rc)
val pool = rc.getDrawablePool<DrawableSurfaceTexture>()
val drawable = DrawableSurfaceTexture.obtain(pool).set(program, sector, texture, texture.coordTransform)
drawable.opacity = if (rc.isPickMode) 1f else rc.currentLayer.opacity
rc.offerSurfaceDrawable(drawable, 0.0 /*z-order*/)

// Enqueue a picked object that associates the drawable surface texture with this surface image.
Expand Down

0 comments on commit 727adfa

Please sign in to comment.