All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.earth.worldwind.layer.starfield.StarFieldProgram.kt Maven / Gradle / Ivy

package earth.worldwind.layer.starfield

import earth.worldwind.draw.DrawContext
import earth.worldwind.geom.Matrix4
import earth.worldwind.render.program.AbstractShaderProgram
import earth.worldwind.util.kgl.GL_TEXTURE0
import earth.worldwind.util.kgl.KglUniformLocation

/**
 * StarFieldProgram is a GLSL program that draws points representing stars.
 */
open class StarFieldProgram : AbstractShaderProgram() {
    override var programSources = arrayOf(
        """
            //.x = declination
            //.y = right ascension
            //.z = point size
            //.w = magnitude
            attribute vec4 vertexPoint;

            uniform mat4 mvpMatrix;
            /* number of days (positive or negative) since Greenwich noon, Terrestrial Time, on 1 January 2000 (J2000.0) */
            uniform float numDays;
            uniform vec2 magnitudeRange;

            varying float magnitudeWeight;

            /* normalizes an angle between 0.0 and 359.0 */
            float normalizeAngle(float angle) {
               float angleDivisions = angle / 360.0;
               return 360.0 * (angleDivisions - floor(angleDivisions));
            }

            /* transforms declination and right ascension in cartesian coordinates */
            vec3 computePosition(float dec, float ra) {
               float GMST = normalizeAngle(280.46061837 + 360.98564736629 * numDays);
               float GHA = normalizeAngle(GMST - ra);
               float lon = -GHA + 360.0 * step(180.0, GHA);
               float latRad = radians(dec);
               float lonRad = radians(lon);
               float radCosLat = cos(latRad);
               return vec3(radCosLat * sin(lonRad), sin(latRad), radCosLat * cos(lonRad));
            }

            /* normalizes a value between 0.0 and 1.0 */
            float normalizeScalar(float value, float minValue, float maxValue){
               return (value - minValue) / (maxValue - minValue);
            }

            void main() {
               vec3 vertexPosition = computePosition(vertexPoint.x, vertexPoint.y);
               gl_Position = mvpMatrix * vec4(vertexPosition.xyz, 1.0);
               gl_Position.z = gl_Position.w - 0.00001;
               gl_PointSize = vertexPoint.z;
               magnitudeWeight = normalizeScalar(vertexPoint.w, magnitudeRange.x, magnitudeRange.y);
            }
        """.trimIndent(),
        """
            precision mediump float;

            uniform sampler2D textureSampler;
            uniform int textureEnabled;

            varying float magnitudeWeight;

            const vec4 white = vec4(1.0, 1.0, 1.0, 1.0);
            const vec4 grey = vec4(0.5, 0.5, 0.5, 1.0);

            void main() {
               if (textureEnabled == 1) {
                   gl_FragColor = texture2D(textureSampler, gl_PointCoord);
               }
               else {
            /* paint the starts in shades of grey, where the brightest star is white and the dimmest star is grey */
                   gl_FragColor = mix(white, grey, magnitudeWeight);
               }
            }
        """.trimIndent()
    )
    override val attribBindings = arrayOf("vertexPoint")
    protected var mvpMatrixId = KglUniformLocation.NONE
    protected var numDaysId = KglUniformLocation.NONE
    protected var magnitudeRangeId = KglUniformLocation.NONE
    protected var textureUnitId = KglUniformLocation.NONE
    protected var textureEnabledId = KglUniformLocation.NONE
    private val array = FloatArray(16)

    override fun initProgram(dc: DrawContext) {
        super.initProgram(dc)
        mvpMatrixId = gl.getUniformLocation(program, "mvpMatrix");
        numDaysId = gl.getUniformLocation(program, "numDays");
        magnitudeRangeId = gl.getUniformLocation(program, "magnitudeRange");
        textureUnitId = gl.getUniformLocation(program, "textureSampler");
        textureEnabledId = gl.getUniformLocation(program, "textureEnabled");
    }

    /**
     * Loads the specified matrix as the value of this program's 'mvpMatrix' uniform variable.
     *
     * @param matrix The matrix to load.
     */
    fun loadModelviewProjection(matrix: Matrix4) {
        // Don't bother testing whether mvpMatrix has changed, the common case is to load a different matrix.
        matrix.transposeToArray(array, 0)
        gl.uniformMatrix4fv(mvpMatrixId, 1, false, array, 0)
    }

    /**
     * Loads the specified number as the value of this program's 'numDays' uniform variable.
     *
     * @param numDays The number of days (positive or negative) since Greenwich noon, Terrestrial Time,
     * on 1 January 2000 (J2000.0)
     */
    fun loadNumDays(numDays: Float) = gl.uniform1f(numDaysId, numDays)

    /**
     * Loads the specified numbers as the value of this program's 'magnitudeRange' uniform variable.
     *
     * @param minMag Minimal magnitude
     * @param maxMag Maximal magnitude
     */
    fun loadMagnitudeRange(minMag: Float, maxMag: Float) = gl.uniform2f(magnitudeRangeId, minMag, maxMag)

    /**
     * Loads the specified number as the value of this program's 'textureSampler' uniform variable.
     *
     * @param unit The texture unit.
     */
    fun loadTextureUnit(unit: Int) = gl.uniform1i(textureUnitId, unit - GL_TEXTURE0);

    /**
     * Loads the specified boolean as the value of this program's 'textureEnabledLocation' uniform variable.
     *
     * @param value Texture enabled
     */
    fun loadTextureEnabled(value: Boolean) = gl.uniform1i(textureEnabledId, if (value) 1 else 0)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy