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

jsMain.com.soywiz.kgl.KmlGlJsCanvas.kt Maven / Gradle / Ivy

There is a newer version: 4.0.10
Show newest version
// WARNING: File autogenerated DO NOT modify
// https://www.khronos.org/registry/OpenGL/api/GLES2/gl2.h
@file:Suppress("unused", "RedundantUnitReturnType", "PropertyName")

package com.soywiz.kgl

import com.soywiz.kmem.*
import org.w3c.dom.*
import org.khronos.webgl.*
import kotlin.math.*
import com.soywiz.korim.format.*
import com.soywiz.korim.bitmap.*
import com.soywiz.kmem.set
import com.soywiz.kmem.get
import com.soywiz.korio.lang.printStackTrace
import com.soywiz.korio.util.OS
import kotlinx.browser.document

// https://github.com/shrekshao/MoveWebGL1EngineToWebGL2/blob/master/Move-a-WebGL-1-Engine-To-WebGL-2-Blog-1.md
// https://webglstats.com/
// https://caniuse.com/#feat=webgl
class KmlGlJsCanvas(val canvas: HTMLCanvasElement, val glOpts: dynamic) : KmlGlWithExtensions() {
    var webglVersion = 1
    val gl = (null
            ?: canvas.getContext("webgl2", glOpts)?.also { webglVersion = 2 }
            ?: canvas.getContext("webgl", glOpts)
            ?: canvas.getContext("experimental-webgl", glOpts)
        ).unsafeCast()
        ?: run {
            try {
                document.body?.prepend((document.createElement("div") as HTMLElement).apply {
                    style.color = "red"
                    style.font = "30px Arial"
                    innerText = "Can't get webgl context. Running in an android emulator without cross-walk?"
                })
            } catch (e: Throwable) {
                e.printStackTrace()
            }
            error("Can't get webgl context")
        }
    private val items = arrayOfNulls(8 * 1024)
    private val freeList = (1 until items.size).reversed().toMutableList()
    private fun  T.alloc(): Int = run {
		if (this === null) return 0
		if (this.asDynamic().id === undefined) {
		    if (freeList.isEmpty()) error("KmlGlJsCanvas.freeList is empty. (Probably allocating lots of OpenGL objects without releasing them)")
		    val index = freeList.removeAt(freeList.size - 1)
            items[index] = this
            (this.asDynamic()).id = index
		}
        this.asDynamic().id.unsafeCast()
	}
	private fun  Int.get(): T? = if (this != 0) items[this].unsafeCast() else null
    private fun  Int.free(): T? = run { if (this != 0) { val out = items[this].unsafeCast(); freeList += this; items[this] = null; out } else { null } }

    override fun activeTexture(texture: Int): Unit = gl.activeTexture(texture)
    override fun attachShader(program: Int, shader: Int): Unit = gl.attachShader(program.get(), shader.get())
    override fun bindAttribLocation(program: Int, index: Int, name: String): Unit = gl.bindAttribLocation(program.get(), index, name)
    override fun bindBuffer(target: Int, buffer: Int): Unit = gl.bindBuffer(target, buffer.get())
    override fun bindFramebuffer(target: Int, framebuffer: Int): Unit = gl.bindFramebuffer(target, framebuffer.get())
    override fun bindRenderbuffer(target: Int, renderbuffer: Int): Unit = gl.bindRenderbuffer(target, renderbuffer.get())
    override fun bindTexture(target: Int, texture: Int): Unit = gl.bindTexture(target, texture.get())
    override fun blendColor(red: Float, green: Float, blue: Float, alpha: Float): Unit = gl.blendColor(red, green, blue, alpha)
    override fun blendEquation(mode: Int): Unit = gl.blendEquation(mode)
    override fun blendEquationSeparate(modeRGB: Int, modeAlpha: Int): Unit = gl.blendEquationSeparate(modeRGB, modeAlpha)
    override fun blendFunc(sfactor: Int, dfactor: Int): Unit = gl.blendFunc(sfactor, dfactor)
    override fun blendFuncSeparate(sfactorRGB: Int, dfactorRGB: Int, sfactorAlpha: Int, dfactorAlpha: Int): Unit = gl.blendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha)
    override fun bufferData(target: Int, size: Int, data: FBuffer, usage: Int): Unit = gl.bufferData(target, Uint8Array(data.arrayBuffer, 0, size), usage)
    override fun bufferSubData(target: Int, offset: Int, size: Int, data: FBuffer): Unit = gl.bufferSubData(target, offset, Uint8Array(data.arrayBuffer, 0, size))
    override fun checkFramebufferStatus(target: Int): Int = gl.checkFramebufferStatus(target)
    override fun clear(mask: Int): Unit = gl.clear(mask)
    override fun clearColor(red: Float, green: Float, blue: Float, alpha: Float): Unit = gl.clearColor(red, green, blue, alpha)
    override fun clearDepthf(d: Float): Unit = gl.clearDepth(d)
    override fun clearStencil(s: Int): Unit = gl.clearStencil(s)
    override fun colorMask(red: Boolean, green: Boolean, blue: Boolean, alpha: Boolean): Unit = gl.colorMask(red, green, blue, alpha)
    override fun compileShader(shader: Int): Unit = gl.compileShader(shader.get())
    override fun compressedTexImage2D(target: Int, level: Int, internalformat: Int, width: Int, height: Int, border: Int, imageSize: Int, data: FBuffer): Unit = gl.compressedTexImage2D(target, level, internalformat, width, height, border, data?.arrayByte)
    override fun compressedTexSubImage2D(target: Int, level: Int, xoffset: Int, yoffset: Int, width: Int, height: Int, format: Int, imageSize: Int, data: FBuffer): Unit = gl.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, data?.arrayByte)
    override fun copyTexImage2D(target: Int, level: Int, internalformat: Int, x: Int, y: Int, width: Int, height: Int, border: Int): Unit = gl.copyTexImage2D(target, level, internalformat, x, y, width, height, border)
    override fun copyTexSubImage2D(target: Int, level: Int, xoffset: Int, yoffset: Int, x: Int, y: Int, width: Int, height: Int): Unit = gl.copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height)
    override fun createProgram(): Int = gl.createProgram().alloc()
    override fun createShader(type: Int): Int = gl.createShader(type).alloc()
    override fun cullFace(mode: Int): Unit = gl.cullFace(mode)
    override fun deleteBuffers(n: Int, items: FBuffer): Unit = run { for (p in 0 until n) gl.deleteBuffer(items.arrayInt[p].free()) }
    override fun deleteFramebuffers(n: Int, items: FBuffer): Unit = run { for (p in 0 until n) gl.deleteFramebuffer(items.arrayInt[p].free()) }
    override fun deleteProgram(program: Int): Unit = gl.deleteProgram(program.get())
    override fun deleteRenderbuffers(n: Int, items: FBuffer): Unit = run { for (p in 0 until n) gl.deleteRenderbuffer(items.arrayInt[p].free()) }
    override fun deleteShader(shader: Int): Unit = gl.deleteShader(shader.get())
    override fun deleteTextures(n: Int, items: FBuffer): Unit = run { for (p in 0 until n) gl.deleteTexture(items.arrayInt[p].free()) }
    override fun depthFunc(func: Int): Unit = gl.depthFunc(func)
    override fun depthMask(flag: Boolean): Unit = gl.depthMask(flag)
    override fun depthRangef(n: Float, f: Float): Unit = gl.depthRange(n, f)
    override fun detachShader(program: Int, shader: Int): Unit = gl.detachShader(program.get(), shader.get())
    override fun disable(cap: Int): Unit = gl.disable(cap)
    override fun disableVertexAttribArray(index: Int): Unit = gl.disableVertexAttribArray(index)
    override fun drawArrays(mode: Int, first: Int, count: Int): Unit = gl.drawArrays(mode, first, count)
    override fun drawElements(mode: Int, count: Int, type: Int, indices: Int): Unit = gl.drawElements(mode, count, type, indices)
    override fun enable(cap: Int): Unit = gl.enable(cap)
    override fun enableVertexAttribArray(index: Int): Unit = gl.enableVertexAttribArray(index)
    override fun finish(): Unit = gl.finish()
    override fun flush(): Unit = gl.flush()
    override fun framebufferRenderbuffer(target: Int, attachment: Int, renderbuffertarget: Int, renderbuffer: Int): Unit = gl.framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer.get())
    override fun framebufferTexture2D(target: Int, attachment: Int, textarget: Int, texture: Int, level: Int): Unit = gl.framebufferTexture2D(target, attachment, textarget, texture.get(), level)
    override fun frontFace(mode: Int): Unit = gl.frontFace(mode)
    override fun genBuffers(n: Int, buffers: FBuffer): Unit = run { for (p in 0 until n) buffers.arrayInt[p] = gl.createBuffer().alloc() }
    override fun generateMipmap(target: Int): Unit = gl.generateMipmap(target)
    override fun genFramebuffers(n: Int, framebuffers: FBuffer): Unit = run { for (p in 0 until n) framebuffers.arrayInt[p] = gl.createFramebuffer().alloc() }
    override fun genRenderbuffers(n: Int, renderbuffers: FBuffer): Unit = run { for (p in 0 until n) renderbuffers.arrayInt[p] = gl.createRenderbuffer().alloc() }
    override fun genTextures(n: Int, textures: FBuffer): Unit = run { for (p in 0 until n) textures.arrayInt[p] = gl.createTexture().alloc() }
    override fun getActiveAttrib(program: Int, index: Int, bufSize: Int, length: FBuffer, size: FBuffer, type: FBuffer, name: FBuffer): Unit = run { val info = gl.getActiveAttrib(program.get(), index)!!; size.arrayInt[0] = info.size; type.arrayInt[0] = info.type; name.putAsciiString(info.name); length.arrayInt[0] = info.size + 1 }
    override fun getActiveUniform(program: Int, index: Int, bufSize: Int, length: FBuffer, size: FBuffer, type: FBuffer, name: FBuffer): Unit = run { val info = gl.getActiveUniform(program.get(), index)!!; size.arrayInt[0] = info.size; type.arrayInt[0] = info.type; name.putAsciiString(info.name); length.arrayInt[0] = info.size + 1 }
    override fun getAttachedShaders(program: Int, maxCount: Int, count: FBuffer, shaders: FBuffer): Unit = run { val ashaders = gl.getAttachedShaders(program.get())!!; count.arrayInt[0] = ashaders.size; for (n in 0 until min(maxCount, ashaders.size)) shaders.arrayInt[n] = ashaders[n].asDynamic().id.unsafeCast() }
    override fun getAttribLocation(program: Int, name: String): Int = gl.getAttribLocation(program.get(), name)
    override fun getUniformLocation(program: Int, name: String): Int = run { val prg = program.get().asDynamic(); if (prg.uniforms === undefined) prg.uniforms = js("({})"); if (prg.uniforms[name] === undefined) prg.uniforms[name] = gl.getUniformLocation(prg, name).alloc(); return prg.uniforms[name].unsafeCast() }
    override fun getBooleanv(pname: Int, data: FBuffer): Unit = run { data.arrayInt[0] = gl.getParameter(pname).unsafeCast() }
    override fun getBufferParameteriv(target: Int, pname: Int, params: FBuffer): Unit = run { params.arrayInt[0] = gl.getBufferParameter(target, pname).unsafeCast() }
    override fun getError(): Int = gl.getError()
    override fun getFloatv(pname: Int, data: FBuffer): Unit = run { data.arrayFloat[0] = gl.getParameter(pname).unsafeCast() }
    override fun getFramebufferAttachmentParameteriv(target: Int, attachment: Int, pname: Int, params: FBuffer): Unit = run { params.arrayInt[0] = gl.getFramebufferAttachmentParameter(target, attachment, pname).unsafeCast() }
    override fun getIntegerv(pname: Int, data: FBuffer): Unit = run { data.arrayInt[0] = gl.getParameter(pname).unsafeCast() }
    override fun getProgramInfoLog(program: Int, bufSize: Int, length: FBuffer, infoLog: FBuffer): Unit = run { val str = gl.getProgramInfoLog(program.get()) ?: ""; length.arrayInt[0] = str.length; infoLog.putAsciiString(str) }
    override fun getRenderbufferParameteriv(target: Int, pname: Int, params: FBuffer): Unit = run { params.arrayInt[0] = gl.getRenderbufferParameter(target, pname).unsafeCast() }
    override fun getProgramiv(program: Int, pname: Int, params: FBuffer): Unit = run {
                when (pname) {
                    INFO_LOG_LENGTH -> params.arrayInt[0] = gl.getProgramInfoLog(program.get())?.length?.plus(1) ?: 1
                    else -> params.arrayInt[0] = gl.getProgramParameter(program.get(), pname).unsafeCast()
                }
            }
    override fun getShaderiv(shader: Int, pname: Int, params: FBuffer): Unit = run {
                when (pname) {
                    INFO_LOG_LENGTH -> params.arrayInt[0] = gl.getShaderInfoLog(shader.get())?.length?.plus(1) ?: 1
                    else -> params.arrayInt[0] = gl.getShaderParameter(shader.get(), pname).unsafeCast()
                }
            }
    override fun getShaderInfoLog(shader: Int, bufSize: Int, length: FBuffer, infoLog: FBuffer): Unit = run { val str = gl.getShaderInfoLog(shader.get()) ?: ""; length.arrayInt[0] = str.length; infoLog.putAsciiString(str) }
    override fun getShaderPrecisionFormat(shadertype: Int, precisiontype: Int, range: FBuffer, precision: FBuffer): Unit = run { val info = gl.getShaderPrecisionFormat(shadertype, precisiontype); if (info != null) { range.arrayInt[0] = info.rangeMin; range.arrayInt[1] = info.rangeMax; precision.arrayInt[0] = info.precision } }
    override fun getShaderSource(shader: Int, bufSize: Int, length: FBuffer, source: FBuffer): Unit = run { val str = gl.getShaderSource(shader.get()) ?: ""; length.arrayInt[0] = str.length; source.putAsciiString(str) }
    override fun getString(name: Int): String = gl.getParameter(name).unsafeCast()
    override fun getTexParameterfv(target: Int, pname: Int, params: FBuffer): Unit = run { params.arrayFloat[0] = gl.getTexParameter(target, pname).unsafeCast() }
    override fun getTexParameteriv(target: Int, pname: Int, params: FBuffer): Unit = run { params.arrayInt[0] = gl.getTexParameter(target, pname).unsafeCast() }
    override fun getUniformfv(program: Int, location: Int, params: FBuffer): Unit = run { params.arrayFloat[0] = gl.getUniform(program.get(), location.get()).unsafeCast() }
    override fun getUniformiv(program: Int, location: Int, params: FBuffer): Unit = run { params.arrayInt[0] = gl.getUniform(program.get(), location.get()).unsafeCast() }
    override fun getVertexAttribfv(index: Int, pname: Int, params: FBuffer): Unit = run { params.arrayFloat[0] = gl.getVertexAttrib(index, pname).unsafeCast() }
    override fun getVertexAttribiv(index: Int, pname: Int, params: FBuffer): Unit = run { params.arrayInt[0] = gl.getVertexAttrib(index, pname).unsafeCast() }
    override fun getVertexAttribPointerv(index: Int, pname: Int, pointer: FBuffer): Unit = run { pointer.arrayInt[0] = gl.getVertexAttrib(index, pname).unsafeCast() }
    override fun hint(target: Int, mode: Int): Unit = gl.hint(target, mode)
    override fun isBuffer(buffer: Int): Boolean = gl.isBuffer(buffer.get())
    override fun isEnabled(cap: Int): Boolean = gl.isEnabled(cap)
    override fun isFramebuffer(framebuffer: Int): Boolean = gl.isFramebuffer(framebuffer.get())
    override fun isProgram(program: Int): Boolean = gl.isProgram(program.get())
    override fun isRenderbuffer(renderbuffer: Int): Boolean = gl.isRenderbuffer(renderbuffer.get())
    override fun isShader(shader: Int): Boolean = gl.isShader(shader.get())
    override fun isTexture(texture: Int): Boolean = gl.isTexture(texture.get())
    override fun lineWidth(width: Float): Unit = gl.lineWidth(width)
    override fun linkProgram(program: Int): Unit = gl.linkProgram(program.get())
    override fun pixelStorei(pname: Int, param: Int): Unit = gl.pixelStorei(pname, param)
    override fun polygonOffset(factor: Float, units: Float): Unit = gl.polygonOffset(factor, units)
    override fun readPixels(x: Int, y: Int, width: Int, height: Int, format: Int, type: Int, pixels: FBuffer): Unit = gl.readPixels(x, y, width, height, format, type, pixels.arrayUByte)
    override fun releaseShaderCompiler(): Unit = Unit
    override fun renderbufferStorage(target: Int, internalformat: Int, width: Int, height: Int): Unit = gl.renderbufferStorage(target, internalformat, width, height)
    override fun sampleCoverage(value: Float, invert: Boolean): Unit = gl.sampleCoverage(value, invert)
    override fun scissor(x: Int, y: Int, width: Int, height: Int): Unit = gl.scissor(x, y, width, height)
    override fun shaderBinary(count: Int, shaders: FBuffer, binaryformat: Int, binary: FBuffer, length: Int): Unit = throw KmlGlException("shaderBinary not implemented in Webgl")
    override fun shaderSource(shader: Int, string: String): Unit = run { gl.shaderSource(shader.get(), "#ifdef GL_ES\nprecision mediump float;\n#endif\n$string") }
    override fun stencilFunc(func: Int, ref: Int, mask: Int): Unit = gl.stencilFunc(func, ref, mask)
    override fun stencilFuncSeparate(face: Int, func: Int, ref: Int, mask: Int): Unit = gl.stencilFuncSeparate(face, func, ref, mask)
    override fun stencilMask(mask: Int): Unit = gl.stencilMask(mask)
    override fun stencilMaskSeparate(face: Int, mask: Int): Unit = gl.stencilMaskSeparate(face, mask)
    override fun stencilOp(fail: Int, zfail: Int, zpass: Int): Unit = gl.stencilOp(fail, zfail, zpass)
    override fun stencilOpSeparate(face: Int, sfail: Int, dpfail: Int, dppass: Int): Unit = gl.stencilOpSeparate(face, sfail, dpfail, dppass)
    override fun texImage2D(target: Int, level: Int, internalformat: Int, width: Int, height: Int, border: Int, format: Int, type: Int, pixels: FBuffer?): Unit {
        val vpixels = when (type) {
            FLOAT -> pixels?.f32
            else -> pixels?.arrayUByte
        }
        gl.texImage2D(target, level, internalformat, width, height, border, format, type, vpixels)
    }
    override fun texImage2D(target: Int, level: Int, internalformat: Int, format: Int, type: Int, data: NativeImage): Unit = gl.texImage2D(target, level, internalformat, format, type, (data as HtmlNativeImage).texSource)
    override fun texParameterf(target: Int, pname: Int, param: Float): Unit = gl.texParameterf(target, pname, param)
    override fun texParameterfv(target: Int, pname: Int, params: FBuffer): Unit = gl.texParameterf(target, pname, params.arrayFloat[0])
    override fun texParameteri(target: Int, pname: Int, param: Int): Unit = gl.texParameteri(target, pname, param)
    override fun texParameteriv(target: Int, pname: Int, params: FBuffer): Unit = gl.texParameteri(target, pname, params.arrayInt[0])
    override fun texSubImage2D(target: Int, level: Int, xoffset: Int, yoffset: Int, width: Int, height: Int, format: Int, type: Int, pixels: FBuffer): Unit = gl.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels.arrayUByte)
    override fun uniform1f(location: Int, v0: Float): Unit = gl.uniform1f(location.get(), v0)
    override fun uniform1fv(location: Int, count: Int, value: FBuffer): Unit = gl.uniform1fv(location.get(), value.arrayFloat)
    override fun uniform1i(location: Int, v0: Int): Unit = gl.uniform1i(location.get(), v0)
    override fun uniform1iv(location: Int, count: Int, value: FBuffer): Unit = gl.uniform1iv(location.get(), value.arrayInt)
    override fun uniform2f(location: Int, v0: Float, v1: Float): Unit = gl.uniform2f(location.get(), v0, v1)
    override fun uniform2fv(location: Int, count: Int, value: FBuffer): Unit = gl.uniform2fv(location.get(), value.arrayFloat)
    override fun uniform2i(location: Int, v0: Int, v1: Int): Unit = gl.uniform2i(location.get(), v0, v1)
    override fun uniform2iv(location: Int, count: Int, value: FBuffer): Unit = gl.uniform2iv(location.get(), value.arrayInt)
    override fun uniform3f(location: Int, v0: Float, v1: Float, v2: Float): Unit = gl.uniform3f(location.get(), v0, v1, v2)
    override fun uniform3fv(location: Int, count: Int, value: FBuffer): Unit = gl.uniform3fv(location.get(), value.arrayFloat)
    override fun uniform3i(location: Int, v0: Int, v1: Int, v2: Int): Unit = gl.uniform3i(location.get(), v0, v1, v2)
    override fun uniform3iv(location: Int, count: Int, value: FBuffer): Unit = gl.uniform3iv(location.get(), value.arrayInt)
    override fun uniform4f(location: Int, v0: Float, v1: Float, v2: Float, v3: Float): Unit = gl.uniform4f(location.get(), v0, v1, v2, v3)
    override fun uniform4fv(location: Int, count: Int, value: FBuffer): Unit = gl.uniform4fv(location.get(), value.arrayFloat)
    override fun uniform4i(location: Int, v0: Int, v1: Int, v2: Int, v3: Int): Unit = gl.uniform4i(location.get(), v0, v1, v2, v3)
    override fun uniform4iv(location: Int, count: Int, value: FBuffer): Unit = gl.uniform4iv(location.get(), value.arrayInt)
    override fun uniformMatrix2fv(location: Int, count: Int, transpose: Boolean, value: FBuffer): Unit = gl.uniformMatrix2fv(location.get(), transpose, value.arrayFloat.sliceIfRequired(count * 2 * 2))
    override fun uniformMatrix3fv(location: Int, count: Int, transpose: Boolean, value: FBuffer): Unit = gl.uniformMatrix3fv(location.get(), transpose, value.arrayFloat.sliceIfRequired(count * 3 * 3))
    override fun uniformMatrix4fv(location: Int, count: Int, transpose: Boolean, value: FBuffer): Unit = gl.uniformMatrix4fv(location.get(), transpose, value.arrayFloat.sliceIfRequired(count * 4 * 4))
    override fun useProgram(program: Int): Unit = gl.useProgram(program.get())
    override fun validateProgram(program: Int): Unit = gl.validateProgram(program.get())
    override fun vertexAttrib1f(index: Int, x: Float): Unit = gl.vertexAttrib1f(index, x)
    override fun vertexAttrib1fv(index: Int, v: FBuffer): Unit = gl.vertexAttrib1fv(index, v)
    override fun vertexAttrib2f(index: Int, x: Float, y: Float): Unit = gl.vertexAttrib2f(index, x, y)
    override fun vertexAttrib2fv(index: Int, v: FBuffer): Unit = gl.vertexAttrib2fv(index, v)
    override fun vertexAttrib3f(index: Int, x: Float, y: Float, z: Float): Unit = gl.vertexAttrib3f(index, x, y, z)
    override fun vertexAttrib3fv(index: Int, v: FBuffer): Unit = gl.vertexAttrib3fv(index, v)
    override fun vertexAttrib4f(index: Int, x: Float, y: Float, z: Float, w: Float): Unit = gl.vertexAttrib4f(index, x, y, z, w)
    override fun vertexAttrib4fv(index: Int, v: FBuffer): Unit = gl.vertexAttrib4fv(index, v)
    override fun vertexAttribPointer(index: Int, size: Int, type: Int, normalized: Boolean, stride: Int, pointer: Long): Unit = gl.vertexAttribPointer(index, size, type, normalized, stride, pointer.toInt())
    override fun viewport(x: Int, y: Int, width: Int, height: Int): Unit = gl.viewport(x, y, width, height)

    private fun Float32Buffer.sliceIfRequired(count: Int): Float32Buffer = if (size == count) this else Float32Array(this.buffer, 0, count)

    override val extensions by lazy { (gl.getSupportedExtensions() ?: arrayOf()).toSet() }

    override val isFloatTextureSupported: Boolean by lazy {
        //println("extensions: $extensions")

        gl.getExtension("OES_texture_float_linear") != null // Also request it to support linear filtering if possible!
            || gl.getExtension("OES_texture_float") != null
            || webglVersion >= 2 // Supported by default in WebGL 2
    }

    var _instancedArraysSet: Boolean = false
    var _instancedArrays: dynamic = null
    val instancedArrays: dynamic
        get() {
            if (!_instancedArraysSet) {
                _instancedArraysSet = true
                _instancedArrays = gl.getExtension("ANGLE_instanced_arrays")
            }
            return _instancedArrays
        }

    override val isInstancedSupported: Boolean get() = (webglVersion >= 2) || (instancedArrays != null)

    override fun drawArraysInstanced(mode: Int, first: Int, count: Int, instancecount: Int) {
        if (webglVersion >= 2) {
            gl.asDynamic().drawArraysInstanced(mode, first, count, instancecount)
        } else {
            instancedArrays.drawArraysInstancedANGLE(mode, first, count, instancecount)
        }
    }

    override fun drawElementsInstanced(mode: Int, count: Int, type: Int, indices: Int, instancecount: Int) {
        if (webglVersion >= 2) {
            gl.asDynamic().drawElementsInstanced(mode, count, type, indices, instancecount)
        } else {
            instancedArrays.drawElementsInstancedANGLE(mode, count, type, indices, instancecount)
        }
    }

    override fun vertexAttribDivisor(index: Int, divisor: Int) {
        if (webglVersion >= 2) {
            gl.asDynamic().vertexAttribDivisor(index, divisor)
        } else {
            instancedArrays.vertexAttribDivisorANGLE(index, divisor)
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy