commonMain.earth.worldwind.layer.atmosphere.AbstractAtmosphereProgram.kt Maven / Gradle / Ivy
package earth.worldwind.layer.atmosphere
import earth.worldwind.draw.DrawContext
import earth.worldwind.geom.Matrix3
import earth.worldwind.geom.Matrix4
import earth.worldwind.geom.Vec3
import earth.worldwind.render.program.AbstractShaderProgram
import earth.worldwind.util.kgl.KglUniformLocation
import kotlin.math.PI
import kotlin.math.pow
// TODO Correctly compute the atmosphere color for eye positions beneath the atmosphere
// TODO Test the effect of working in local coordinates (reference point) on the GLSL atmosphere programs
abstract class AbstractAtmosphereProgram: AbstractShaderProgram() {
protected var fragModeId = KglUniformLocation.NONE
protected var mvpMatrixId = KglUniformLocation.NONE
protected var texCoordMatrixId = KglUniformLocation.NONE
protected var texSamplerId = KglUniformLocation.NONE
protected var vertexOriginId = KglUniformLocation.NONE
protected var eyePointId = KglUniformLocation.NONE
protected var eyeMagnitudeId = KglUniformLocation.NONE
protected var eyeMagnitude2Id = KglUniformLocation.NONE
protected var lightDirectionId = KglUniformLocation.NONE
protected var invWavelengthId = KglUniformLocation.NONE
protected var atmosphereRadiusId = KglUniformLocation.NONE
protected var atmosphereRadius2Id = KglUniformLocation.NONE
protected var globeRadiusId = KglUniformLocation.NONE
protected var krESunId = KglUniformLocation.NONE
protected var kmESunId = KglUniformLocation.NONE
protected var kr4PIId = KglUniformLocation.NONE
protected var km4PIId = KglUniformLocation.NONE
protected var scaleId = KglUniformLocation.NONE
protected var scaleDepthId = KglUniformLocation.NONE
protected var scaleOverScaleDepthId = KglUniformLocation.NONE
protected var gId = KglUniformLocation.NONE
protected var g2Id = KglUniformLocation.NONE
protected var exposureId = KglUniformLocation.NONE
private val array = FloatArray(16)
/**
* Frag color indicates the atmospheric scattering color components written to the fragment color. Accepted values
* are [FRAGMODE_PRIMARY], [FRAGMODE_SECONDARY] and [FRAGMODE_PRIMARY_TEX_BLEND].
*/
enum class FragMode(val asInt : Int) {
PRIMARY(1),
SECONDARY(2),
PRIMARY_TEX_BLEND(3)
}
override fun initProgram(dc: DrawContext) {
super.initProgram(dc)
val invWavelength = Vec3(
1 / 0.650.pow(4.0), // 650 nm for red
1 / 0.570.pow(4.0), // 570 nm for green
1 / 0.475.pow(4.0) // 475 nm for blue
)
val kr = 0.0025 // Rayleigh scattering constant
val km = 0.0010 // Mie scattering constant
val eSun = 20.0 // Sun brightness constant
val g = -0.990 // The Mie phase asymmetry factor
val exposure = 2.0
fragModeId = gl.getUniformLocation(program, "fragMode")
gl.uniform1i(fragModeId, FragMode.PRIMARY.asInt)
mvpMatrixId = gl.getUniformLocation(program, "mvpMatrix")
Matrix4().transposeToArray(array, 0) // 4 x 4 identity matrix
gl.uniformMatrix4fv(mvpMatrixId, 1, false, array, 0)
texCoordMatrixId = gl.getUniformLocation(program, "texCoordMatrix")
Matrix3().transposeToArray(array, 0) // 3 x 3 identity matrix
gl.uniformMatrix3fv(texCoordMatrixId, 1, false, array, 0)
texSamplerId = gl.getUniformLocation(program, "texSampler")
gl.uniform1i(texSamplerId, 0) // GL_TEXTURE0
vertexOriginId = gl.getUniformLocation(program, "vertexOrigin")
array.fill(0f)
gl.uniform3fv(vertexOriginId, 1, array, 0)
eyePointId = gl.getUniformLocation(program, "eyePoint")
array.fill(0f)
gl.uniform3fv(eyePointId, 1, array, 0)
eyeMagnitudeId = gl.getUniformLocation(program, "eyeMagnitude")
gl.uniform1f(eyeMagnitudeId, 0f)
eyeMagnitude2Id = gl.getUniformLocation(program, "eyeMagnitude2")
gl.uniform1f(eyeMagnitude2Id, 0f)
lightDirectionId = gl.getUniformLocation(program, "lightDirection")
array.fill(0f)
gl.uniform3fv(lightDirectionId, 1, array, 0)
invWavelengthId = gl.getUniformLocation(program, "invWavelength")
invWavelength.toArray(array, 0)
gl.uniform3fv(invWavelengthId, 1, array, 0)
atmosphereRadiusId = gl.getUniformLocation(program, "atmosphereRadius")
atmosphereRadius2Id = gl.getUniformLocation(program, "atmosphereRadius2")
globeRadiusId = gl.getUniformLocation(program, "globeRadius")
krESunId = gl.getUniformLocation(program, "KrESun")
gl.uniform1f(krESunId, (kr * eSun).toFloat())
kmESunId = gl.getUniformLocation(program, "KmESun")
gl.uniform1f(kmESunId, (km * eSun).toFloat())
kr4PIId = gl.getUniformLocation(program, "Kr4PI")
gl.uniform1f(kr4PIId, (kr * 4 * PI).toFloat())
km4PIId = gl.getUniformLocation(program, "Km4PI")
gl.uniform1f(km4PIId, (km * 4 * PI).toFloat())
scaleId = gl.getUniformLocation(program, "scale")
scaleDepthId = gl.getUniformLocation(program, "scaleDepth")
scaleOverScaleDepthId = gl.getUniformLocation(program, "scaleOverScaleDepth")
gId = gl.getUniformLocation(program, "g")
gl.uniform1f(gId, g.toFloat())
g2Id = gl.getUniformLocation(program, "g2")
gl.uniform1f(g2Id, (g * g).toFloat())
exposureId = gl.getUniformLocation(program, "exposure")
gl.uniform1f(exposureId, exposure.toFloat())
}
fun loadFragMode(fragMode: FragMode) { gl.uniform1i(fragModeId, fragMode.asInt) }
fun loadModelviewProjection(matrix: Matrix4) {
matrix.transposeToArray(array, 0)
gl.uniformMatrix4fv(mvpMatrixId, 1, false, array, 0)
}
fun loadTexCoordMatrix(matrix: Matrix3) {
matrix.transposeToArray(array, 0)
gl.uniformMatrix3fv(texCoordMatrixId, 1, false, array, 0)
}
fun loadVertexOrigin(origin: Vec3) {
origin.toArray(array, 0)
gl.uniform3fv(vertexOriginId, 1, array, 0)
}
fun loadVertexOrigin(x: Double, y: Double, z: Double) {
gl.uniform3f(vertexOriginId, x.toFloat(), y.toFloat(), z.toFloat())
}
fun loadLightDirection(direction: Vec3) {
direction.toArray(array, 0)
gl.uniform3fv(lightDirectionId, 1, array, 0)
}
fun loadEyePoint(eyePoint: Vec3) {
eyePoint.toArray(array, 0)
gl.uniform3fv(eyePointId, 1, array, 0)
gl.uniform1f(eyeMagnitudeId, eyePoint.magnitude.toFloat())
gl.uniform1f(eyeMagnitude2Id, eyePoint.magnitudeSquared.toFloat())
}
fun loadAtmosphereParams(equatorialRadius: Double, atmosphereAltitude: Double) {
val rayleighScaleDepth = 0.25
val ar = equatorialRadius + atmosphereAltitude
gl.uniform1f(globeRadiusId, equatorialRadius.toFloat())
gl.uniform1f(atmosphereRadiusId, ar.toFloat())
gl.uniform1f(atmosphereRadius2Id, (ar * ar).toFloat())
gl.uniform1f(scaleId, (1 / atmosphereAltitude).toFloat())
gl.uniform1f(scaleDepthId, rayleighScaleDepth.toFloat())
gl.uniform1f(scaleOverScaleDepthId, (1 / atmosphereAltitude / rayleighScaleDepth).toFloat())
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy