├── .travis.yml ├── src ├── test │ ├── resources │ │ ├── npot.ktx │ │ ├── test.dds │ │ ├── PlyonTexture.tga │ │ ├── array_r8_uint.dds │ │ ├── array_r8_uint.ktx │ │ ├── kueken7_rgb8.jpg │ │ ├── kueken7_srgb8.jpg │ │ ├── kueken7_srgb8.png │ │ ├── kueken8_srgb8.jpg │ │ ├── cube_rgba8_unorm.dds │ │ ├── cube_rgba8_unorm.ktx │ │ ├── kueken7_a8_unorm.dds │ │ ├── kueken7_l8_unorm.dds │ │ ├── kueken7_r8_uint.dds │ │ ├── kueken7_rgb10a2u.dds │ │ ├── kueken7_bgr8_srgb.dds │ │ ├── kueken7_bgr8_unorm.dds │ │ ├── kueken7_bgra8_srgb.dds │ │ ├── kueken7_bgra8_srgb.ktx │ │ ├── kueken7_bgrx8_srgb.dds │ │ ├── kueken7_r16_unorm.dds │ │ ├── kueken7_rgb8_srgb.ktx │ │ ├── kueken7_rgb8_unorm.ktx │ │ ├── kueken7_rgba8_srgb.dds │ │ ├── kueken7_rgba8_srgb.ktx │ │ ├── kueken8_bgr8_unorm.dds │ │ ├── kueken8_rgba8_srgb.dds │ │ ├── kueken8_rgba8_srgb.ktx │ │ ├── kueken7_bgra8_unorm.dds │ │ ├── kueken7_bgra8_unorm.ktx │ │ ├── kueken7_bgrx8_unorm.dds │ │ ├── kueken7_r5g6b5_unorm.dds │ │ ├── kueken7_r5g6b5_unorm.ktx │ │ ├── kueken7_r_ati1n_unorm.dds │ │ ├── kueken7_r_eac_snorm.ktx │ │ ├── kueken7_r_eac_unorm.ktx │ │ ├── kueken7_rg_eac_snorm.ktx │ │ ├── kueken7_rg_eac_unorm.ktx │ │ ├── kueken7_rgb10a2_unorm.dds │ │ ├── kueken7_rgb5a1_unorm.dds │ │ ├── kueken7_rgb5a1_unorm.ktx │ │ ├── kueken7_rgb5a1_unorm_.dds │ │ ├── kueken7_rgb9e5_ufloat.dds │ │ ├── kueken7_rgb9e5_ufloat.ktx │ │ ├── kueken7_rgb_atc_unorm.dds │ │ ├── kueken7_rgb_dxt1_srgb.ktx │ │ ├── kueken7_rgb_etc2_srgb.dds │ │ ├── kueken7_rgb_etc2_srgb.ktx │ │ ├── kueken7_rgba16_sfloat.dds │ │ ├── kueken7_rgba16_sfloat.ktx │ │ ├── kueken7_rgba4_unorm.dds │ │ ├── kueken7_rgba4_unorm.ktx │ │ ├── kueken7_rgba8_unorm.dds │ │ ├── kueken7_rgba8_unorm.ktx │ │ ├── kueken7_rg11b10_ufloat.dds │ │ ├── kueken7_rg11b10_ufloat.ktx │ │ ├── kueken7_rg_ati2n_unorm.dds │ │ ├── kueken7_rgb_dxt1_unorm.ktx │ │ ├── kueken7_rgb_etc1_unorm.dds │ │ ├── kueken7_rgb_etc1_unorm.ktx │ │ ├── kueken7_rgb_etc2_unorm.dds │ │ ├── kueken7_rgba_dxt1_srgb.dds │ │ ├── kueken7_rgba_dxt1_unorm.dds │ │ ├── kueken7_rgba_dxt3_unorm.dds │ │ ├── kueken7_rgba_dxt5_srgb.dds │ │ ├── kueken7_rgba_dxt5_srgb.ktx │ │ ├── kueken7_rgba_dxt5_unorm.dds │ │ ├── kueken7_rgba_dxt5_unorm.ktx │ │ ├── kueken7_rgba_etc2_srgb.ktx │ │ ├── kueken8_rgba_dxt1_unorm.dds │ │ ├── kueken7_rgba_astc4x4_srgb.dds │ │ ├── kueken7_rgba_astc4x4_srgb.ktx │ │ ├── kueken7_rgba_astc8x5_srgb.ktx │ │ ├── kueken7_rgba_astc8x8_unorm.dds │ │ ├── kueken7_rgba_dxt5_unorm1.dds │ │ ├── kueken7_rgba_dxt5_unorm2.dds │ │ ├── kueken7_rgba_etc2_a1_srgb.ktx │ │ ├── kueken7_rgb_pvrtc_2bpp_srgb.ktx │ │ ├── kueken7_rgb_pvrtc_2bpp_unorm.dds │ │ ├── kueken7_rgb_pvrtc_4bpp_srgb.ktx │ │ ├── kueken7_rgb_pvrtc_4bpp_unorm.dds │ │ ├── kueken7_rgba_astc12x12_srgb.ktx │ │ ├── kueken7_rgba_atc_explicit_unorm.dds │ │ ├── kueken7_rgba_pvrtc2_2bpp_srgb.ktx │ │ ├── kueken7_rgba_pvrtc2_2bpp_unorm.ktx │ │ ├── kueken7_rgba_pvrtc2_4bpp_srgb.ktx │ │ ├── kueken7_rgba_pvrtc2_4bpp_unorm.dds │ │ ├── kueken7_rgba_pvrtc2_4bpp_unorm.ktx │ │ ├── kueken7_r_ati1n_unorm_decompressed.dds │ │ ├── kueken7_rg_ati2n_unorm_decompressed.dds │ │ ├── kueken7_rgba_atc_interpolate_unorm.dds │ │ ├── kueken7_rgba_dxt1_unorm_decompressed.dds │ │ ├── kueken7_rgba_dxt3_unorm_decompressed.dds │ │ └── kueken7_rgba_dxt5_unorm_decompressed.dds │ ├── kotlin │ │ └── gli_ │ │ │ ├── util.kt │ │ │ ├── coreLoadImage.kt │ │ │ ├── coreFormat.kt │ │ │ ├── coreLoadGenRect.kt │ │ │ ├── levelData.kt │ │ │ ├── coreLoadGen2dArray.kt │ │ │ ├── coreLoadGen2d.kt │ │ │ ├── coreLoadGen3d.kt │ │ │ ├── coreLoadGenCube.kt │ │ │ ├── coreLoadGenCubeArray.kt │ │ │ ├── coreLoadGen1dArray.kt │ │ │ ├── coreLoadGen1d.kt │ │ │ ├── coreStorage.kt │ │ │ ├── coreLoadKtx.kt │ │ │ ├── core.kt │ │ │ ├── transform.kt │ │ │ ├── coreImage.kt │ │ │ ├── coreAddressing.kt │ │ │ ├── coreLoadDds.kt │ │ │ ├── coreSave.kt │ │ │ ├── testCopySub.kt │ │ │ ├── coreLoad.kt │ │ │ └── make_texture.kt │ └── java │ │ └── gli_ │ │ └── test.java └── main │ ├── resources │ └── logo-mini.png │ └── kotlin │ ├── module-info │ └── gli_ │ ├── makeTexture.kt │ ├── gli.kt │ ├── load.kt │ ├── misc.kt │ ├── target.kt │ ├── save.kt │ ├── clear.kt │ ├── kmg.kt │ ├── tga.kt │ ├── saveImage.kt │ ├── ktx.kt │ ├── Cache.kt │ ├── Texture3d.kt │ ├── saveKmg.kt │ ├── TextureCube.kt │ ├── loadKmg.kt │ ├── TextureCubeArray.kt │ ├── Texture2dArray.kt │ ├── Texture2d.kt │ ├── copy.kt │ ├── Texture1dArray.kt │ ├── loadKtx.kt │ ├── Texture1d.kt │ ├── saveKtx.kt │ ├── ByteBufferBackedInputStream.kt │ ├── saveDds.kt │ ├── Storage.kt │ ├── loadDds.kt │ ├── Image.kt │ └── loadImage.kt ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── .idea ├── vcs.xml ├── kotlinc.xml ├── php.xml ├── misc.xml └── runConfigurations │ ├── gli__clean_build__no_docs_.xml │ └── gli__clean_assemble__no_docs_.xml ├── jitpack.yml ├── settings.gradle.kts ├── LICENSE ├── gradlew.bat ├── .github └── workflows │ └── build.yml ├── .gitignore ├── gradlew └── README.md /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - openjdk11 -------------------------------------------------------------------------------- /src/test/resources/npot.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/npot.ktx -------------------------------------------------------------------------------- /src/test/resources/test.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/test.dds -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/resources/logo-mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/main/resources/logo-mini.png -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-XX:MaxMetaspaceSize=1g 2 | org.gradle.daemon=false 3 | #systemProp.dynamicAlignVerbose=true -------------------------------------------------------------------------------- /src/test/resources/PlyonTexture.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/PlyonTexture.tga -------------------------------------------------------------------------------- /src/test/resources/array_r8_uint.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/array_r8_uint.dds -------------------------------------------------------------------------------- /src/test/resources/array_r8_uint.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/array_r8_uint.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb8.jpg -------------------------------------------------------------------------------- /src/test/resources/kueken7_srgb8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_srgb8.jpg -------------------------------------------------------------------------------- /src/test/resources/kueken7_srgb8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_srgb8.png -------------------------------------------------------------------------------- /src/test/resources/kueken8_srgb8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken8_srgb8.jpg -------------------------------------------------------------------------------- /src/test/resources/cube_rgba8_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/cube_rgba8_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/cube_rgba8_unorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/cube_rgba8_unorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_a8_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_a8_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_l8_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_l8_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_r8_uint.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_r8_uint.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb10a2u.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb10a2u.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_bgr8_srgb.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_bgr8_srgb.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_bgr8_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_bgr8_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_bgra8_srgb.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_bgra8_srgb.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_bgra8_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_bgra8_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_bgrx8_srgb.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_bgrx8_srgb.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_r16_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_r16_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb8_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb8_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb8_unorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb8_unorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba8_srgb.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba8_srgb.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba8_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba8_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken8_bgr8_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken8_bgr8_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken8_rgba8_srgb.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken8_rgba8_srgb.dds -------------------------------------------------------------------------------- /src/test/resources/kueken8_rgba8_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken8_rgba8_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_bgra8_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_bgra8_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_bgra8_unorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_bgra8_unorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_bgrx8_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_bgrx8_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_r5g6b5_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_r5g6b5_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_r5g6b5_unorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_r5g6b5_unorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_r_ati1n_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_r_ati1n_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_r_eac_snorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_r_eac_snorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_r_eac_unorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_r_eac_unorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rg_eac_snorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rg_eac_snorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rg_eac_unorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rg_eac_unorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb10a2_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb10a2_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb5a1_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb5a1_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb5a1_unorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb5a1_unorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb5a1_unorm_.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb5a1_unorm_.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb9e5_ufloat.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb9e5_ufloat.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb9e5_ufloat.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb9e5_ufloat.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb_atc_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb_atc_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb_dxt1_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb_dxt1_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb_etc2_srgb.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb_etc2_srgb.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb_etc2_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb_etc2_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba16_sfloat.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba16_sfloat.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba16_sfloat.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba16_sfloat.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba4_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba4_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba4_unorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba4_unorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba8_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba8_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba8_unorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba8_unorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rg11b10_ufloat.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rg11b10_ufloat.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rg11b10_ufloat.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rg11b10_ufloat.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rg_ati2n_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rg_ati2n_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb_dxt1_unorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb_dxt1_unorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb_etc1_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb_etc1_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb_etc1_unorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb_etc1_unorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb_etc2_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb_etc2_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_dxt1_srgb.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_dxt1_srgb.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_dxt1_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_dxt1_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_dxt3_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_dxt3_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_dxt5_srgb.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_dxt5_srgb.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_dxt5_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_dxt5_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_dxt5_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_dxt5_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_dxt5_unorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_dxt5_unorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_etc2_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_etc2_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken8_rgba_dxt1_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken8_rgba_dxt1_unorm.dds -------------------------------------------------------------------------------- /src/test/kotlin/gli_/util.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import java.net.* 4 | 5 | fun uriOf(str: String): URI = ClassLoader.getSystemResource(str).toURI() -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_astc4x4_srgb.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_astc4x4_srgb.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_astc4x4_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_astc4x4_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_astc8x5_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_astc8x5_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_astc8x8_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_astc8x8_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_dxt5_unorm1.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_dxt5_unorm1.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_dxt5_unorm2.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_dxt5_unorm2.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_etc2_a1_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_etc2_a1_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb_pvrtc_2bpp_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb_pvrtc_2bpp_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb_pvrtc_2bpp_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb_pvrtc_2bpp_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb_pvrtc_4bpp_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb_pvrtc_4bpp_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgb_pvrtc_4bpp_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgb_pvrtc_4bpp_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_astc12x12_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_astc12x12_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_atc_explicit_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_atc_explicit_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_pvrtc2_2bpp_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_pvrtc2_2bpp_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_pvrtc2_2bpp_unorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_pvrtc2_2bpp_unorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_pvrtc2_4bpp_srgb.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_pvrtc2_4bpp_srgb.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_pvrtc2_4bpp_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_pvrtc2_4bpp_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_pvrtc2_4bpp_unorm.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_pvrtc2_4bpp_unorm.ktx -------------------------------------------------------------------------------- /src/test/resources/kueken7_r_ati1n_unorm_decompressed.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_r_ati1n_unorm_decompressed.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rg_ati2n_unorm_decompressed.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rg_ati2n_unorm_decompressed.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_atc_interpolate_unorm.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_atc_interpolate_unorm.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_dxt1_unorm_decompressed.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_dxt1_unorm_decompressed.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_dxt3_unorm_decompressed.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_dxt3_unorm_decompressed.dds -------------------------------------------------------------------------------- /src/test/resources/kueken7_rgba_dxt5_unorm_decompressed.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kotlin-graphics/gli/HEAD/src/test/resources/kueken7_rgba_dxt5_unorm_decompressed.dds -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /jitpack.yml: -------------------------------------------------------------------------------- 1 | jdk: 2 | - openjdk11 3 | 4 | #install: 5 | # - echo "Running a custom install command" 6 | # - ./gradlew clean assemble -x dokkaHtml -x dokkaHtmlJar -x javadoc -x dokkaJavadocJar publishToMavenLocal -------------------------------------------------------------------------------- /src/main/kotlin/module-info: -------------------------------------------------------------------------------- 1 | module kotlin.graphics.gli { 2 | 3 | requires java.desktop; 4 | requires kotlin.stdlib; 5 | 6 | requires org.lwjgl; 7 | 8 | requires kotlin.graphics.glm; 9 | requires kotlin.graphics.kool; 10 | requires kotlin.graphics.unsigned; 11 | 12 | exports gli_; 13 | } -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "gli" 2 | 3 | pluginManagement { 4 | repositories { 5 | gradlePluginPortal() 6 | maven("https://raw.githubusercontent.com/kotlin-graphics/mary/master") 7 | } 8 | } 9 | 10 | gradle.rootProject { 11 | group = "kotlin.graphics" 12 | version = "0.8.3.0-22" 13 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Sep 12 17:04:04 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip 7 | distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 8 | -------------------------------------------------------------------------------- /.idea/php.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 12 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreLoadImage.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import io.kotest.core.spec.style.StringSpec 4 | 5 | class coreLoadImage : StringSpec() { 6 | 7 | init { 8 | 9 | "load" { 10 | 11 | val textureTga = gli.load(uriOf("PlyonTexture.tga")) 12 | // textureTga.format shouldBe params.format 13 | // 14 | // val kmg = params.filename + ".kmg" 15 | // gli.save(textureTga, kmg) 16 | // val textureSavedKMG = gli.load(kmg) 17 | // textureSavedKMG.format shouldBe params.format 18 | // textureSavedKMG shouldBe textureTga 19 | // Files.delete(pathOf(kmg)) 20 | // 21 | // gli.save(textureTga, ktx) 22 | // val textureSavedKTX = gli.load(ktx) 23 | // textureSavedKTX.format shouldBe params.format 24 | // textureSavedKTX shouldBe textureTga 25 | // Files.delete(pathOf(ktx)) 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreFormat.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import io.kotest.matchers.shouldBe 4 | import io.kotest.core.spec.style.StringSpec 5 | 6 | 7 | class coreFormat : StringSpec() { 8 | 9 | init { 10 | 11 | "valid" { 12 | 13 | for (format in Format.FIRST .. Format.LAST) 14 | format.isValid shouldBe true 15 | Format.UNDEFINED.isValid shouldBe false 16 | } 17 | 18 | "component" { 19 | 20 | for (formatIndex in Format.FIRST.i until Format.COUNT) { 21 | val components = Format.values().first { it.i == formatIndex }.componentCount 22 | (components in 1..4) shouldBe true 23 | } 24 | } 25 | 26 | "compressed" { 27 | 28 | Format.R8_SRGB_PACK8.isCompressed shouldBe false 29 | Format.RGB_DXT1_SRGB_BLOCK8.isCompressed shouldBe true 30 | } 31 | 32 | "block" { 33 | Format.RGBA8_UNORM_PACK8.blockSize shouldBe 4 34 | Format.RGB10A2_UNORM_PACK32.blockSize shouldBe 4 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 kotlin-graphics 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.idea/runConfigurations/gli__clean_build__no_docs_.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 17 | 19 | true 20 | true 21 | false 22 | 23 | 24 | -------------------------------------------------------------------------------- /.idea/runConfigurations/gli__clean_assemble__no_docs_.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 17 | 19 | true 20 | true 21 | false 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreLoadGenRect.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.vec3.Vec3i 4 | import io.kotest.matchers.shouldBe 5 | import io.kotest.core.spec.style.StringSpec 6 | import java.nio.file.Files 7 | 8 | class coreLoadGenRect : StringSpec() { 9 | 10 | init { 11 | 12 | "load rect" { 13 | 14 | for (target in Target.RECT..Target.RECT_ARRAY) 15 | for (format in Format.FIRST .. Format.LAST) { 16 | 17 | if (format.isCompressed && target == Target._3D) 18 | continue 19 | 20 | val layers = if (target.isTargetArray) 2 else 1 21 | val faces = if (target.isTargetCube) 6 else 1 22 | val blockExtent = format.blockExtend 23 | 24 | val texture = Texture(target, format, blockExtent * Vec3i(blockExtent.y, blockExtent.x, 1), layers, faces, 2) 25 | texture.clear() 26 | 27 | "gen_rect_test.kmg".let { 28 | gli.save(texture, it) 29 | val textureKMG = gli.load(it) 30 | texture shouldBe textureKMG 31 | Files.delete(pathOf(it)) 32 | } 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/levelData.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import io.kotest.core.spec.style.StringSpec 4 | 5 | /** 6 | * Created by GBarbieri on 21.04.2017. 7 | */ 8 | 9 | class levelData : StringSpec() { 10 | 11 | init { 12 | 13 | // "main" { 14 | // 15 | // val TEXTURE_DIFFUSE = "kueken7_rgba8_srgb.dds" 16 | // 17 | // val texture = Texture2d(gli.loadDds(javaClass.getResource("/$TEXTURE_DIFFUSE").toURI())) 18 | // gl.profile = gl.Profile.GL32 19 | // 20 | // val format = gl.translate(texture.format, texture.swizzles) 21 | // for (level in 0 until texture.levels()) { 22 | // 23 | // println("level: $level, internal format: ${format.internal}") 24 | // println("size: (${texture[level].extent().x}, ${texture[level].extent().y})") 25 | // println("format: (${format.external}, type: ${format.type})") 26 | // println("data: (${texture[level].data()})") 27 | // val r = texture[level].data()[0] 28 | // val g = texture[level].data()[1] 29 | // val b = texture[level].data()[2] 30 | // val a = texture[level].data()[3] 31 | //// val r = texture.data()[0] 32 | //// val g = texture.data()[1] 33 | //// val b = texture.data()[2] 34 | //// val a = texture.data()[3] 35 | // println("pixel 0: ($r, $g, $b, $a)") 36 | // } 37 | // texture.dispose() 38 | // } 39 | } 40 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/makeTexture.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.glm 4 | import glm_.vec1.Vec1i 5 | import glm_.vec2.Vec2i 6 | import glm_.vec3.Vec3i 7 | 8 | interface makeTexture { 9 | 10 | fun makeTexture1d(format: Format, extent: Vec1i, levels: Int = glm.levels(Vec3i(extent.x, 1, 1))) = 11 | Texture(Target._1D, format, Vec3i(extent.x, 1, 1), 1, 1, levels) 12 | 13 | fun makeTexture1dArray(format: Format, extent: Vec1i, layers: Int, levels: Int = glm.levels(Vec3i(extent.x, 1, 1))) = 14 | Texture(Target._1D_ARRAY, format, Vec3i(extent.x, 1, 1), layers, 1, levels) 15 | 16 | fun makeTexture2d(format: Format, extent: Vec2i, levels: Int = glm.levels(Vec3i(extent, 1))) = 17 | Texture(Target._2D, format, Vec3i(extent, 1), 1, 1, levels) 18 | 19 | fun makeTexture2dArray(format: Format, extent: Vec2i, layer: Int, levels: Int = glm.levels(Vec3i(extent, 1))) = 20 | Texture(Target._2D_ARRAY, format, Vec3i(extent, 1), layer, 1, levels) 21 | 22 | fun makeTexture3d(format: Format, extent: Vec3i, levels: Int = glm.levels(extent)) = 23 | Texture(Target._3D, format, extent, 1, 1, levels) 24 | 25 | fun makeTextureCube(format: Format, extent: Vec2i, levels: Int = glm.levels(Vec3i(extent, 1))) = 26 | Texture(Target.CUBE, format, Vec3i(extent, 1), 1, 6, levels) 27 | 28 | fun makeTextureCubeArray(format: Format, extent: Vec2i, layer: Int, levels: Int = glm.levels(Vec3i(extent, 1))) = 29 | Texture(Target.CUBE_ARRAY, format, Vec3i(extent, 1), layer, 6, levels) 30 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreLoadGen2dArray.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.vec3.Vec3i 4 | import io.kotest.matchers.shouldBe 5 | import io.kotest.core.spec.style.StringSpec 6 | import java.nio.file.Files 7 | 8 | class coreLoadGen2dArray : StringSpec() { 9 | 10 | init { 11 | 12 | "load 2d array" { 13 | 14 | for (format in Format.FIRST .. Format.LAST) { 15 | 16 | val target = Target._2D_ARRAY 17 | 18 | val layers = 2 19 | val faces = 1 20 | val blockExtent = format.blockExtend 21 | 22 | val texture = Texture(target, format, blockExtent * Vec3i(blockExtent.y, blockExtent.x, 1), layers, faces, 2) 23 | texture.clear() 24 | 25 | "test2d_array.dds".let { 26 | gli.save(texture, it) 27 | val textureDDS = gli.load(it) 28 | texture shouldBe textureDDS 29 | Files.delete(pathOf(it)) 30 | } 31 | 32 | "test2d_array.ktx".let { 33 | gli.save(texture, it) 34 | val textureKTX = gli.load(it) 35 | texture shouldBe textureKTX 36 | Files.delete(pathOf(it)) 37 | } 38 | 39 | "test2d_array.kmg".let { 40 | gli.save(texture, it) 41 | val textureKMG = gli.load(it) 42 | texture shouldBe textureKMG 43 | Files.delete(pathOf(it)) 44 | } 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreLoadGen2d.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.vec3.Vec3i 4 | import io.kotest.matchers.shouldBe 5 | import io.kotest.core.spec.style.StringSpec 6 | import java.nio.file.Files 7 | 8 | class coreLoadGen2d : StringSpec() { 9 | 10 | init { 11 | 12 | "load 2d" { 13 | 14 | for (format in Format.FIRST .. Format.LAST) { 15 | 16 | val target = Target._2D 17 | 18 | val layers = if (target.isTargetArray) 2 else 1 19 | val faces = if (target.isTargetCube) 6 else 1 20 | val blockExtent = format.blockExtend 21 | 22 | val texture = Texture(target, format, blockExtent * Vec3i(blockExtent.y, blockExtent.x, 1), layers, faces, 2) 23 | texture.clear() 24 | 25 | "test2d.dds".let { 26 | gli.save(texture, it) 27 | val textureDDS = gli.load(it) 28 | texture shouldBe textureDDS 29 | Files.delete(pathOf(it)) 30 | } 31 | 32 | "test2d.ktx".let { 33 | gli.save(texture, it) 34 | val textureKTX = gli.load(it) 35 | texture shouldBe textureKTX 36 | Files.delete(pathOf(it)) 37 | } 38 | 39 | "test2d.kmg".let { 40 | gli.save(texture, it) 41 | val textureKMG = gli.load(it) 42 | texture shouldBe textureKMG 43 | Files.delete(pathOf(it)) 44 | } 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreLoadGen3d.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.vec3.Vec3i 4 | import io.kotest.matchers.shouldBe 5 | import io.kotest.core.spec.style.StringSpec 6 | import java.nio.file.Files 7 | 8 | class coreLoadGen3d : StringSpec() { 9 | 10 | init { 11 | 12 | "load 3d" { 13 | 14 | for (format in Format.FIRST .. Format.LAST) { 15 | 16 | val target = Target._3D 17 | 18 | val layers = if (target.isTargetArray) 2 else 1 19 | val faces = if (target.isTargetCube) 6 else 1 20 | val blockExtent = format.blockExtend 21 | 22 | val texture = Texture(target, format, blockExtent * Vec3i(blockExtent.y, blockExtent.x, 1), layers, faces, 2) 23 | texture.clear() 24 | 25 | "test3d.dds".let { 26 | gli.save(texture, it) 27 | val textureDDS = gli.load(it) 28 | texture shouldBe textureDDS 29 | Files.delete(pathOf(it)) 30 | } 31 | 32 | "test3d.ktx".let { 33 | gli.save(texture, it) 34 | val textureKTX = gli.load(it) 35 | texture shouldBe textureKTX 36 | Files.delete(pathOf(it)) 37 | } 38 | 39 | "test3d.kmg".let { 40 | gli.save(texture, it) 41 | val textureKMG = gli.load(it) 42 | texture shouldBe textureKMG 43 | Files.delete(pathOf(it)) 44 | } 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreLoadGenCube.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.vec3.Vec3i 4 | import io.kotest.matchers.shouldBe 5 | import io.kotest.core.spec.style.StringSpec 6 | import java.nio.file.Files 7 | 8 | class coreLoadGenCube : StringSpec() { 9 | 10 | init { 11 | 12 | "load cube" { 13 | 14 | for (format in Format.FIRST .. Format.LAST) { 15 | 16 | val target = Target.CUBE 17 | 18 | val layers = if (target.isTargetArray) 2 else 1 19 | val faces = if (target.isTargetCube) 6 else 1 20 | val blockExtent = format.blockExtend 21 | 22 | val texture = Texture(target, format, blockExtent * Vec3i(blockExtent.y, blockExtent.x, 1), layers, faces, 2) 23 | texture.clear() 24 | 25 | "test_cube.dds".let { 26 | gli.save(texture, it) 27 | val textureDDS = gli.load(it) 28 | texture shouldBe textureDDS 29 | Files.delete(pathOf(it)) 30 | } 31 | 32 | "test_cube.ktx".let { 33 | gli.save(texture, it) 34 | val textureKTX = gli.load(it) 35 | texture shouldBe textureKTX 36 | Files.delete(pathOf(it)) 37 | } 38 | 39 | "test_cube.kmg".let { 40 | gli.save(texture, it) 41 | val textureKMG = gli.load(it) 42 | texture shouldBe textureKMG 43 | Files.delete(pathOf(it)) 44 | } 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/gli.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.L 4 | import kool.Address 5 | import org.lwjgl.system.MemoryUtil 6 | 7 | 8 | object gli : 9 | 10 | clear, 11 | 12 | copy, 13 | 14 | duplicate, 15 | 16 | load, 17 | loadDds, 18 | loadKmg, 19 | loadKtx, 20 | loadImage, 21 | 22 | makeTexture, 23 | 24 | save, 25 | saveDds, 26 | saveKmg, 27 | saveKtx, 28 | saveImage, 29 | 30 | view { 31 | 32 | @JvmField 33 | val gl = gli_.gl 34 | val dx = gli_.dx 35 | 36 | /** Texture filtring modes */ 37 | enum class Filter { 38 | INVALID, // -1 39 | NONE, 40 | NEAREST, 41 | LINEAR; 42 | 43 | val i = ordinal - 1 44 | 45 | companion object { 46 | val FIRST = NEAREST 47 | val LAST = LINEAR 48 | val COUNT = LAST.i - FIRST.i + 1 49 | } 50 | } 51 | } 52 | 53 | 54 | class Java { 55 | 56 | companion object { 57 | @JvmField 58 | val gli = gli_.gli 59 | } 60 | } 61 | 62 | fun memCopy(src: Long, dst: Long, bytes: Int) = MemoryUtil.memCopy(src, dst, bytes.L) 63 | fun memCopy(src: Address, dst: Address, bytes: Int) = memCopy(src.toLong(), dst.toLong(), bytes) 64 | 65 | 66 | const val GLI_VERSION_MAJOR = 0 67 | const val GLI_VERSION_MINOR = 8 68 | const val GLI_VERSION_PATCH = 3 69 | const val GLI_VERSION_REVISION = 0 70 | const val GLI_VERSION_BUILD = 22 71 | const val GLI_VERSION = GLI_VERSION_MAJOR * 1_000 + GLI_VERSION_MINOR * 100 + GLI_VERSION_PATCH * 10 + GLI_VERSION_REVISION + GLI_VERSION_BUILD / 10f 72 | -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreLoadGenCubeArray.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.vec3.Vec3i 4 | import io.kotest.matchers.shouldBe 5 | import io.kotest.core.spec.style.StringSpec 6 | import java.nio.file.Files 7 | 8 | class coreLoadGenCubeArray : StringSpec() { 9 | 10 | init { 11 | 12 | "load cube array" { 13 | 14 | for (format in Format.FIRST .. Format.LAST) { 15 | 16 | val target = Target.CUBE_ARRAY 17 | 18 | val layers = if (target.isTargetArray) 2 else 1 19 | val faces = if (target.isTargetCube) 6 else 1 20 | val blockExtent = format.blockExtend 21 | 22 | val texture = Texture(target, format, blockExtent * Vec3i(blockExtent.y, blockExtent.x, 1), layers, faces, 2) 23 | texture.clear() 24 | 25 | "test_cube_array.dds".let { 26 | gli.save(texture, it) 27 | val textureDDS = gli.load(it) 28 | texture shouldBe textureDDS 29 | Files.delete(pathOf(it)) 30 | } 31 | 32 | "test_cube_array.ktx".let { 33 | gli.save(texture, it) 34 | val textureKTX = gli.load(it) 35 | texture shouldBe textureKTX 36 | Files.delete(pathOf(it)) 37 | } 38 | 39 | "test_cube_array.kmg".let { 40 | gli.save(texture, it) 41 | val textureKMG = gli.load(it) 42 | texture shouldBe textureKMG 43 | Files.delete(pathOf(it)) 44 | } 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/load.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.or 4 | import glm_.vec3.Vec3i 5 | import kool.* 6 | import java.awt.image.* 7 | import java.awt.image.BufferedImage.* 8 | import java.io.File 9 | import java.net.URI 10 | import java.nio.ByteBuffer 11 | import java.nio.file.Path 12 | import java.nio.file.Paths 13 | import javax.imageio.ImageIO 14 | 15 | /** 16 | * Created by elect on 01/05/17. 17 | */ 18 | 19 | interface load { 20 | 21 | fun load(uri: URI) = load(Paths.get(uri)) 22 | fun load(uri: URI, flipY: Boolean) = load(Paths.get(uri), flipY) 23 | 24 | fun load(filename: String) = load(Paths.get(filename)) 25 | fun load(filename: String, flipY: Boolean) = load(Paths.get(filename), flipY) 26 | 27 | fun load(path: Path, flipY: Boolean = false) = when (val ext = path.extension) { 28 | "dds" -> gli.loadDds(path) 29 | "kmg" -> gli.loadKmg(path) 30 | "ktx" -> gli.loadKtx(path) 31 | "bmp", "gif", "ico", "icns", "iff", "jpeg", "jpg", "pam", "pbm", "pct", "pgm", "pict", "png", "pnm", "ppm", 32 | "targa", "tga", "tif", "tiff", "wbmp" -> gli.loadImage(path.toFile(), flipY) 33 | else -> error("unsupported extension: $ext") 34 | } 35 | 36 | fun load(buffer: ByteBuffer, type: String, flipY: Boolean = false): Texture = when (type) { 37 | "dds" -> gli.loadDds(buffer) 38 | "kmg" -> gli.loadKmg(buffer) 39 | "ktx" -> gli.loadKtx(buffer) 40 | "bmp", "gif", "ico", "icns", "iff", "jpeg", "jpg", "pam", "pbm", "pct", "pgm", "pict", "png", "pnm", "ppm", 41 | "targa", "tga", "tif", "tiff", "wbmp" -> gli.loadImageFromMem(buffer, flipY) 42 | else -> error("Type not supported") 43 | } 44 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/misc.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.vec2.Vec2i 4 | import java.awt.image.BufferedImage 5 | import java.nio.ByteBuffer 6 | import java.nio.file.Path 7 | import java.nio.file.Paths 8 | import java.util.* 9 | 10 | fun pathOf(filename: String, vararg more: String): Path = Paths.get(filename, *more) 11 | //fun URI.toPath(): Path = Paths.get(this) 12 | 13 | val Path.extension get() = toString().substringAfterLast(".").lowercase(Locale.getDefault()) 14 | 15 | fun ByteBuffer.flipY(size: Vec2i) = flipY(size.x, size.y) 16 | 17 | fun ByteBuffer.flipY(width: Int, height: Int) { 18 | for (line in 0 until height / 2) 19 | for (x in 0 until width) { 20 | val up = width * (height - line - 1) + x 21 | val down = width * line + x 22 | val tmp = get(down) 23 | put(down, get(up)) 24 | put(up, tmp) 25 | } 26 | } 27 | 28 | operator fun Array.get(index: Format): dx.Format = get(index.i - Format.FIRST.i) 29 | 30 | fun BufferedImage.flipY() { 31 | var scanline1: Any? = null 32 | var scanline2: Any? = null 33 | for (i in 0 until height / 2) { 34 | scanline1 = raster.getDataElements(0, i, width, 1, scanline1) 35 | scanline2 = raster.getDataElements(0, height - i - 1, width, 1, scanline2) 36 | raster.setDataElements(0, i, width, 1, scanline2) 37 | raster.setDataElements(0, height - i - 1, width, 1, scanline1) 38 | } 39 | } 40 | 41 | //fun main() { 42 | // val file = File("C:\\Users\\elect\\Pictures\\1.png") 43 | // println(file.exists() && file.canRead()) 44 | // val image = ImageIO.read(file) 45 | // image.flipY() 46 | // ImageIO.write(image, "png", File("flipped.png")) 47 | //} -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreLoadGen1dArray.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.vec3.Vec3i 4 | import io.kotest.matchers.shouldBe 5 | import io.kotest.core.spec.style.StringSpec 6 | import java.nio.file.Files 7 | 8 | class coreLoadGen1dArray : StringSpec() { 9 | 10 | init { 11 | 12 | "load 1d array" { 13 | 14 | for (format in Format.FIRST .. Format.LAST) { 15 | 16 | val target = Target._1D_ARRAY 17 | 18 | if ((format.isCompressed && (target.isTarget1d || target == Target._3D)) || target.isTargetRect) 19 | continue 20 | 21 | val layers = if (target.isTargetArray) 2 else 1 22 | val faces = if (target.isTargetCube) 6 else 1 23 | val blockExtent = format.blockExtend 24 | 25 | val texture = Texture(target, format, blockExtent * Vec3i(blockExtent.y, blockExtent.x, 1), layers, faces, 2) 26 | texture.clear() 27 | 28 | "test1d_array.dds".let { 29 | gli.save(texture, it) 30 | val textureDDS = gli.load(it) 31 | texture shouldBe textureDDS 32 | Files.delete(pathOf(it)) 33 | } 34 | 35 | "test1d_array.ktx".let { 36 | gli.save(texture, it) 37 | val textureKTX = gli.load(it) 38 | texture shouldBe textureKTX 39 | Files.delete(pathOf(it)) 40 | } 41 | 42 | "test1d_array.kmg".let { 43 | gli.save(texture, it) 44 | val textureKMG = gli.load(it) 45 | texture shouldBe textureKMG 46 | Files.delete(pathOf(it)) 47 | } 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/target.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | /** 4 | * Created by elect on 02/04/17. 5 | */ 6 | 7 | enum class Target { 8 | INVALID, 9 | _1D, 10 | _1D_ARRAY, 11 | _2D, 12 | _2D_ARRAY, 13 | _3D, 14 | RECT, 15 | RECT_ARRAY, 16 | CUBE, 17 | CUBE_ARRAY; 18 | 19 | val i = ordinal - 1 // invalid -> -1 20 | 21 | val isTarget1d by lazy { this == _1D || this == _1D_ARRAY } 22 | val isTargetArray by lazy { this == _1D_ARRAY || this == _2D_ARRAY || this == CUBE_ARRAY } 23 | val isTargetCube by lazy { this == CUBE || this == CUBE_ARRAY } 24 | val isTargetRect by lazy { this == RECT || this == RECT_ARRAY } 25 | 26 | operator fun rangeTo(that: Target): TargetRange = TargetRange(this, that) 27 | 28 | class TargetRange(override val start: Target, override val endInclusive: Target) : ClosedRange, Iterable { 29 | override fun iterator() = TargetIterator(this) 30 | override fun contains(value: Target) = value.i in start.i..endInclusive.i 31 | } 32 | 33 | class TargetIterator(val targetRange: TargetRange) : Iterator { 34 | var current = targetRange.start 35 | var done = false 36 | override fun next(): Target { 37 | val res = current 38 | if (current == targetRange.endInclusive) 39 | done = true 40 | else 41 | current = Target.values()[current.ordinal + 1] 42 | return res 43 | } 44 | 45 | override fun hasNext() = if (done) false else current <= targetRange.endInclusive 46 | } 47 | 48 | companion object { 49 | val FIRST = _1D 50 | val LAST = CUBE_ARRAY 51 | val COUNT = LAST.i - FIRST.i + 1 52 | infix fun of(int: Int): Target = values().first { it.i == int } 53 | } 54 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreLoadGen1d.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.vec3.Vec3i 4 | import io.kotest.matchers.shouldBe 5 | import io.kotest.core.spec.style.StringSpec 6 | import java.nio.file.Files 7 | 8 | class coreLoadGen1d : StringSpec() { 9 | 10 | init { 11 | 12 | "load 1d" { 13 | 14 | for (format in Format.FIRST .. Format.LAST) { 15 | 16 | val target = Target._1D 17 | 18 | if ((format.isCompressed && (target.isTarget1d || target == Target._3D)) || target.isTargetRect) 19 | continue 20 | 21 | val layers = if (target.isTargetArray) 2 else 1 22 | val faces = if (target.isTargetCube) 6 else 1 23 | val blockExtent = format.blockExtend 24 | 25 | val texture = Texture(target, format, blockExtent * Vec3i(blockExtent.y, blockExtent.x, 1), layers, faces, 2) 26 | texture.clear() 27 | 28 | if(format == Format.L8_UNORM_PACK8) 29 | println() 30 | 31 | "test1d.dds".let { 32 | gli.save(texture, it) 33 | val textureDDS = gli.load(it) 34 | texture shouldBe textureDDS 35 | Files.delete(pathOf(it)) 36 | } 37 | 38 | "test1d.ktx".let { 39 | gli.save(texture, it) 40 | val textureKTX = gli.load(it) 41 | texture shouldBe textureKTX 42 | Files.delete(pathOf(it)) 43 | } 44 | 45 | "test1d.kmg".let { 46 | gli.save(texture, it) 47 | val textureKMG = gli.load(it) 48 | texture shouldBe textureKMG 49 | Files.delete(pathOf(it)) 50 | } 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreStorage.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.vec3.Vec3i 4 | import glm_.vec4.Vec4b 5 | import io.kotest.matchers.shouldBe 6 | import io.kotest.core.spec.style.StringSpec 7 | 8 | /** 9 | * Created by GBarbieri on 03.04.2017. 10 | */ 11 | 12 | class coreStorage : StringSpec() { 13 | 14 | init { 15 | 16 | "storage layer size" { 17 | 18 | val storage = Storage( 19 | format = Format.RGBA8_UNORM_PACK8, 20 | extent = Vec3i(2, 2, 1), 21 | layers = 2, faces = 1, levels = 1) 22 | 23 | for (i in 0..3) 24 | storage.data()[i] = Vec4b(255, 127, 0, 255) 25 | for (i in 0..3) 26 | storage.data()[i + 4] = Vec4b(0, 127, 255, 255) 27 | 28 | with(storage) { 29 | blockSize shouldBe Vec4b.size 30 | levelSize(0) shouldBe Vec4b.size * 2 * 2 31 | faceSize(0, levels - 1) == Vec4b.size * 2 * 2 32 | layerSize(0, faces - 1, 0, levels - 1) shouldBe Vec4b.size * 2 * 2 33 | size() shouldBe Vec4b.size * 2 * 2 * 2 34 | } 35 | } 36 | 37 | "storage face size" { 38 | 39 | val storage = Storage( 40 | format = Format.RGBA8_UNORM_PACK8, 41 | extent = Vec3i(2, 2, 1), 42 | layers = 1, faces = 6, levels = 1) 43 | 44 | with(storage) { 45 | 46 | blockSize shouldBe Vec4b.size 47 | 48 | levelSize(0) shouldBe Vec4b.size * 2 * 2 49 | 50 | faceSize(0, levels - 1) shouldBe Vec4b.size * 2 * 2 51 | 52 | layerSize(0, faces - 1, 0, levels - 1) shouldBe Vec4b.size * 2 * 2 * 6 53 | 54 | size() shouldBe Vec4b.size * 2 * 2 * 6 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/save.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import java.net.URI 4 | import java.nio.file.Path 5 | import java.nio.file.Paths 6 | 7 | interface save { 8 | 9 | /** Save a texture storage_linear to file. 10 | * @param texture Source texture to save 11 | * @param path Path for where to save the file. It must include the filaname and filename extension. 12 | * The function use the filename extension included in the path to figure out the file container to use. 13 | * @return Returns false if the function fails to save the file. */ 14 | fun save(texture: Texture, path: Path): Boolean = when (val ext = path.extension) { 15 | "dds" -> gli.saveDds(texture, path) 16 | "kmg" -> gli.saveKmg(texture, path) 17 | "ktx" -> gli.saveKtx(texture, path) 18 | "bmp", "gif", "ico", "icns", "iff", "jpeg", "jpg", "pam", "pbm", "pct", "pgm", "pict", "png", "pnm", "ppm", 19 | "targa", "tga", "tif", "tiff", "wbmp" -> gli.saveImage(texture, path) 20 | else -> error("unsupported extension: $ext") 21 | } 22 | 23 | /** Save a texture storage_linear to file. 24 | * @param texture Source texture to save 25 | * @param filename: String for where to save the file. It must include the filaname and filename extension. 26 | * The function use the filename extension included in the path to figure out the file container to use. 27 | * @return Returns false if the function fails to save the file. */ 28 | fun save(texture: Texture, filename: String): Boolean = save(texture, Paths.get(filename)) 29 | 30 | /** Save a texture storage_linear to file. 31 | * @param texture Source texture to save 32 | * @param uri: Uri for where to save the file. It must include the filaname and filename extension. 33 | * The function use the filename extension included in the path to figure out the file container to use. 34 | * @return Returns false if the function fails to save the file. */ 35 | fun save(texture: Texture, uri: URI): Boolean = save(texture, Paths.get(uri)) 36 | } -------------------------------------------------------------------------------- /src/test/java/gli_/test.java: -------------------------------------------------------------------------------- 1 | package gli_; 2 | 3 | import glm_.vec3.Vec3i; 4 | import org.lwjgl.opengl.GL12C; 5 | import org.lwjgl.opengl.GL33C; 6 | 7 | import java.nio.IntBuffer; 8 | 9 | import static gli_.Java.gli; 10 | import static kool.BuildersKt.IntBuffer; 11 | import static org.lwjgl.opengl.GL11.*; 12 | import static org.lwjgl.opengl.GL13.glCompressedTexSubImage2D; 13 | import static org.lwjgl.opengl.GL42.glTexStorage2D; 14 | 15 | public class test { 16 | 17 | public static void main(String[] args) { 18 | 19 | 20 | } 21 | 22 | public static int createTexture(String filename) { 23 | 24 | Texture texture = gli.load(filename); 25 | if (texture.empty()) 26 | return 0; 27 | 28 | gli_.gli.gl.setProfile(gl.Profile.GL33); 29 | gl.Format format = gli_.gli.gl.translate(texture.getFormat(), texture.getSwizzles()); 30 | gl.Target target = gli_.gli.gl.translate(texture.getTarget()); 31 | assert (texture.getFormat().isCompressed() && target == gl.Target._2D); 32 | 33 | IntBuffer textureName = IntBuffer(1); 34 | glGenTextures(textureName); 35 | glBindTexture(target.getI(), textureName.get(0)); 36 | glTexParameteri(target.getI(), GL12C.GL_TEXTURE_BASE_LEVEL, 0); 37 | glTexParameteri(target.getI(), GL12C.GL_TEXTURE_MAX_LEVEL, texture.levels() - 1); 38 | IntBuffer swizzles = IntBuffer(4); 39 | texture.getSwizzles().to(swizzles); 40 | glTexParameteriv(target.getI(), GL33C.GL_TEXTURE_SWIZZLE_RGBA, swizzles); 41 | Vec3i extent = texture.extent(0); 42 | glTexStorage2D(target.getI(), texture.levels(), format.getInternal().getI(), extent.getX(), extent.getY()); 43 | for (int level = 0; level < texture.levels(); level++) { 44 | extent = texture.extent(level); 45 | glCompressedTexSubImage2D( 46 | target.getI(), level, 0, 0, extent.getX(), extent.getY(), 47 | format.getInternal().getI(), texture.data(0, 0, level)); 48 | } 49 | return textureName.get(0); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreLoadKtx.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import io.kotest.matchers.shouldBe 4 | import io.kotest.core.spec.style.StringSpec 5 | import java.nio.file.Files 6 | 7 | class coreLoadKtx : StringSpec() { 8 | 9 | init { 10 | 11 | "load ktx" { 12 | 13 | val filenames = listOf( 14 | "kueken7_rgba4_unorm.ktx", 15 | "kueken7_r5g6b5_unorm.ktx", 16 | "kueken7_rgb5a1_unorm.ktx", 17 | "kueken7_rgb8_unorm.ktx", 18 | "kueken7_rgba_dxt5_srgb.ktx", 19 | "kueken7_rgb_dxt1_srgb.ktx", 20 | "kueken7_rgba8_srgb.ktx", 21 | "kueken7_rgb8_srgb.ktx", 22 | "kueken7_rg11b10_ufloat.ktx", 23 | "kueken7_rgb9e5_ufloat.ktx", 24 | "kueken7_rgba_astc4x4_srgb.ktx", 25 | "kueken7_rgba_astc8x5_srgb.ktx", 26 | "kueken7_rgba_astc12x12_srgb.ktx", 27 | "kueken7_rgb_etc1_unorm.ktx", 28 | "kueken7_rgb_etc2_srgb.ktx", 29 | "kueken7_rgba_etc2_srgb.ktx", 30 | "kueken7_rgba_etc2_a1_srgb.ktx", 31 | "kueken7_r_eac_snorm.ktx", 32 | "kueken7_r_eac_unorm.ktx", 33 | "kueken7_rg_eac_snorm.ktx", 34 | "kueken7_rg_eac_unorm.ktx", 35 | "kueken7_rgb_pvrtc_2bpp_srgb.ktx", 36 | "kueken7_rgb_pvrtc_4bpp_srgb.ktx", 37 | // "kueken7_rgba_pvrtc2_2bpp_unorm.ktx", 38 | // "kueken7_rgba_pvrtc2_2bpp_srgb.ktx", 39 | "kueken7_rgba_pvrtc2_4bpp_unorm.ktx", 40 | "kueken7_rgba_pvrtc2_4bpp_srgb.ktx") 41 | 42 | filenames.forEach { 43 | 44 | val textureA = gli.loadKtx(uriOf(it)) 45 | gli.saveKtx(textureA, it) 46 | val textureB = gli.loadKtx(it) 47 | Files.delete(pathOf(it)) 48 | 49 | textureA shouldBe textureB 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/clear.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | interface clear { 4 | 5 | /** Clear a complete texture */ 6 | fun clear(texture: Texture) = texture.clear() 7 | 8 | /** Clear a complete texture */ 9 | fun clear(texture: Texture, blockData: Any) = texture clear blockData 10 | 11 | /** Clear a specific image of a texture */ 12 | fun clear(texture: Texture, layer: Int, face: Int, level: Int, blockData: Any) = texture.clear(layer, face, level, blockData) 13 | 14 | /** Clear an entire level of a texture */ 15 | fun clearLevel(texture: Texture, baseLevel: Int, levelCount: Int, blockData: Any) { 16 | for (layerIndex in 0 until texture.layers()) 17 | for (faceIndex in 0 until texture.faces()) 18 | for (levelIndex in 0 until levelCount) 19 | texture.clear(layerIndex, faceIndex, baseLevel + levelIndex, blockData) 20 | } 21 | 22 | /** Clear multiple levels of a texture */ 23 | fun clearLevel(texture: Texture, baseLevel: Int, blockData: Any) = clearLevel(texture, baseLevel, 1, blockData) 24 | 25 | /** Clear an entire face of a texture */ 26 | fun clearFace(texture: Texture, baseFace: Int, faceCount: Int, blockData: Any) { 27 | for (layerIndex in 0 until texture.layers()) 28 | for (faceIndex in 0 until faceCount) 29 | for (levelIndex in 0 until texture.levels()) 30 | texture.clear(layerIndex, baseFace + faceIndex, levelIndex, blockData) 31 | } 32 | 33 | /** Clear multiple faces of a texture */ 34 | fun clearFace(texture: Texture, baseFace: Int, blockData: Any) = clearFace(texture, baseFace, 1, blockData) 35 | 36 | /** Clear an entire layer of a texture */ 37 | fun clearLayer(texture: Texture, baseLayer: Int, layerCount: Int, blockData: Any) { 38 | for (layerIndex in 0 until layerCount) 39 | for (faceIndex in 0 until texture.faces()) 40 | for (levelIndex in 0 until texture.levels()) 41 | texture.clear(layerIndex + baseLayer, faceIndex, levelIndex, blockData) 42 | } 43 | 44 | /** Clear multiple layers of a texture */ 45 | fun clearLayer(texture: Texture, baseLayer: Int, blockData: Any) = clearLayer(texture, baseLayer, 1, blockData) 46 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/kmg.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.BYTES 4 | import glm_.b 5 | import kool.BYTES 6 | import java.nio.ByteBuffer 7 | 8 | 9 | object kmg { 10 | 11 | val FOURCC_KMG100 = byteArrayOf(0xAB.b, 0x4B.b, 0x49.b, 0x4D.b, 0x20.b, 0x31.b, 0x31.b, 0xBB.b, 0x0D.b, 0x0A.b, 0x1A.b, 0x0A) 12 | 13 | class Header10 { 14 | 15 | var endianness = 0 16 | var format = 0 17 | var target = 0 18 | var swizzleRed = 0 19 | var swizzleGreen = 0 20 | var swizzleBlue = 0 21 | var swizzleAlpha = 0 22 | var pixelWidth = 0 23 | var pixelHeight = 0 24 | var pixelDepth = 0 25 | var layers = 0 26 | var levels = 0 27 | var faces = 0 28 | var generateMipmaps = 0 29 | var baseLevel = 0 30 | var maxLevel = 0 31 | 32 | companion object { 33 | val size = 16 * Int.BYTES 34 | } 35 | 36 | constructor() 37 | 38 | constructor(buffer: ByteBuffer) { 39 | 40 | endianness = buffer.int 41 | format = buffer.int 42 | target = buffer.int 43 | swizzleRed = buffer.int 44 | swizzleGreen = buffer.int 45 | swizzleBlue = buffer.int 46 | swizzleAlpha = buffer.int 47 | pixelWidth = buffer.int 48 | pixelHeight = buffer.int 49 | pixelDepth = buffer.int 50 | layers = buffer.int 51 | levels = buffer.int 52 | faces = buffer.int 53 | generateMipmaps = buffer.int 54 | baseLevel = buffer.int 55 | maxLevel = buffer.int 56 | } 57 | 58 | fun to(data: ByteBuffer) = data 59 | .putInt(endianness) 60 | .putInt(format) 61 | .putInt(target) 62 | .putInt(swizzleRed) 63 | .putInt(swizzleGreen) 64 | .putInt(swizzleBlue) 65 | .putInt(swizzleAlpha) 66 | .putInt(pixelWidth) 67 | .putInt(pixelHeight) 68 | .putInt(pixelDepth) 69 | .putInt(layers) 70 | .putInt(levels) 71 | .putInt(faces) 72 | .putInt(generateMipmaps) 73 | .putInt(baseLevel) 74 | .putInt(maxLevel) 75 | } 76 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/tga.kt: -------------------------------------------------------------------------------- 1 | /* This library is free software; you can redistribute it and/or 2 | modify it under the terms of the GNU Lesser General Public 3 | License as published by the Free Software Foundation; either 4 | version 2.1 of the License, or (at your option) any later version. 5 | 6 | This library is distributed in the hope that it will be useful, 7 | but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9 | Lesser General Public License for more details. 10 | 11 | You should have received a copy of the GNU Lesser General Public 12 | License along with this library; if not, write to the Free Software 13 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 14 | 15 | Copyright (c) 2003 Reality Interactive, Inc. 16 | */ 17 | 18 | package gli_ 19 | 20 | /** 21 | *

Various header and such constants for the TGA image format.

22 | * 23 | * @author Rob Grzywinski rgrzywinski@realityinteractive.com 24 | * @version $Id: TGAConstants.java,v 1.1 2005/04/12 11:23:53 ornedan Exp $ 25 | * @since 1.0 26 | */ 27 | enum class TgaImageType(val i: Int) { 28 | /** An image type indicating no image data. */ 29 | NO_IMAGE(0), 30 | /** An image type indicating an uncompressed color mapped (indexed) image. */ 31 | COLOR_MAP(1), 32 | /** An image type indicating an uncompressed true-color image. */ 33 | TRUE_COLOR(2), 34 | /** An image type indicating a black and white (monochrome) image. */ 35 | MONO(3), 36 | /** An image type indicating an RLE (run-length encoded) color-mapped (indexed) image. */ 37 | RLE_COLOR_MAP(9), 38 | /** An image type indicating an RLE (run-length encoded) true-color image. */ 39 | RLE_TRUE_COLOR(10), 40 | /** An image type indicating an RLE (run-length encoded) black and white (monochrome) image. */ 41 | RLE_MONO(11) 42 | } 43 | 44 | enum class TgaImageDescriptorBit(val i: Int) { 45 | /** The bit of the image descriptor field (5.5) indicating that the first pixel should be at the left or the right. */ 46 | LEFT_RIGHT_BIT(0x10), 47 | /** The bit of the image descriptor field (5.5) indicating that the first pixel should be at the bottom or the top. */ 48 | BOTTOM_TOP_BIT(0x20) 49 | } -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /src/main/kotlin/gli_/saveImage.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import java.awt.image.BufferedImage 4 | import java.awt.image.DataBufferByte 5 | import java.nio.file.Path 6 | import javax.imageio.ImageIO 7 | 8 | interface saveImage { 9 | 10 | fun saveImage(texture: Texture, path: Path): Boolean { 11 | 12 | if (texture.empty()) return false 13 | 14 | val (w, h, _) = texture.extent(0) 15 | val format = texture.format 16 | val compCount = format.formatInfo.component 17 | 18 | val image = when (format) { 19 | Format.RGB8_UNORM_PACK8 -> BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR).apply { 20 | val src = texture.data() 21 | val dst = (raster.dataBuffer as DataBufferByte).data 22 | for (i in dst.indices step 3) { 23 | dst[i + 0] = src[i + 2] 24 | dst[i + 1] = src[i + 1] 25 | dst[i + 2] = src[i + 0] 26 | } 27 | } 28 | Format.RGBA8_UNORM_PACK8 -> BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR).apply { 29 | val src = texture.data() 30 | val dst = (raster.dataBuffer as DataBufferByte).data 31 | for (i in dst.indices step 4) { 32 | dst[i + 0] = src[i + 3] 33 | dst[i + 1] = src[i + 2] 34 | dst[i + 2] = src[i + 1] 35 | dst[i + 3] = src[i + 0] 36 | } 37 | } 38 | else -> error("unsupported format") 39 | } 40 | 41 | val ext = path.fileName.toString().substringAfterLast('.') 42 | val file = path.toFile() 43 | file.createNewFile() 44 | return ImageIO.write(image, ext, file) 45 | } 46 | 47 | // /** 48 | // * @param quality Jpg quality from 1 to 100 49 | // */ 50 | // fun saveJpg(texture: Texture, path: Path, quality: Int = 80) : Boolean { 51 | // return saveUsingStbi(texture, path) { file, width, height, comp, data, _ -> 52 | // STBImageWrite.stbi_write_jpg(file, width, height, comp, data, quality) 53 | // } 54 | // } 55 | // 56 | // fun saveBmp(texture: Texture, path: Path): Boolean { 57 | // return saveUsingStbi(texture, path) { file, width, height, comp, data, _ -> 58 | // STBImageWrite.stbi_write_bmp(file, width, height, comp, data) 59 | // } 60 | // } 61 | // 62 | // fun saveTga(texture: Texture, path: Path) : Boolean { 63 | // return saveUsingStbi(texture, path) { file, width, height, comp, data, _ -> 64 | // STBImageWrite.stbi_write_tga(file, width, height, comp, data) 65 | // } 66 | // } 67 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/core.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.b 4 | import glm_.glm 5 | import glm_.vec2.Vec2i 6 | import glm_.vec4.Vec4b 7 | import io.kotest.core.spec.style.StringSpec 8 | import io.kotest.matchers.shouldBe 9 | import kool.* 10 | import java.nio.ByteOrder 11 | 12 | class core : StringSpec() { 13 | 14 | init { 15 | 16 | "create texture storage" { 17 | 18 | val texture = Texture2d(Format.RGBA8_UINT_PACK8, Vec2i(256)) 19 | texture.clear(Vec4b(255, 127, 0, 255)) 20 | val levels = texture.levels() 21 | 22 | assert(levels > 1) 23 | 24 | assert(texture.notEmpty()) 25 | 26 | val texelA = texture[0].data()[0] 27 | val texelB = texture[0].data()[1] 28 | val texelC = texture[0].data()[2] 29 | val texelD = texture[0].data()[3] 30 | 31 | val texel = Vec4b(255, 127, 0, 255) 32 | assert(texelA == texel) 33 | assert(texelB == texel) 34 | assert(texelC == texel) 35 | assert(texelD == texel) 36 | } 37 | 38 | "reset memset zero" { } // TODO 39 | "reset loop zero" { } // TODO 40 | 41 | "floorMultiple" { 42 | 43 | val a = glm.floorMultiple(3, 4) 44 | val b = glm.floorMultiple(6, 4) 45 | val c = glm.floorMultiple(8, 4) 46 | val d = glm.floorMultiple(9, 4) 47 | 48 | a shouldBe 0 49 | b shouldBe 4 50 | c shouldBe 8 51 | d shouldBe 8 52 | } 53 | 54 | "flipY" { 55 | run { 56 | val buffer = java.nio.ByteBuffer.allocate(16) 57 | for (i in 0..15) 58 | buffer[i] = i.b 59 | val expected = byteArrayOf( 60 | 12, 13, 14, 15, 61 | 8, 9, 10, 11, 62 | 4, 5, 6, 7, 63 | 0, 1, 2, 3) 64 | 65 | buffer.flipY(Vec2i(4)) 66 | for (i in 0..15) 67 | buffer[i] shouldBe expected[i] 68 | } 69 | run { 70 | val buffer = java.nio.ByteBuffer.allocate(20) 71 | for (i in 0..19) 72 | buffer[i] = i.b 73 | val expected = byteArrayOf( 74 | 16, 17, 18, 19, 75 | 12, 13, 14, 15, 76 | 8, 9, 10, 11, 77 | 4, 5, 6, 7, 78 | 0, 1, 2, 3) 79 | 80 | buffer.flipY(Vec2i(4, 5)) 81 | for (i in 0..19) 82 | buffer[i] shouldBe expected[i] 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/transform.kt: -------------------------------------------------------------------------------- 1 | //package gli_ 2 | // 3 | //import glm_.vec1.Vec1i 4 | //import glm_.vec4.Vec4ub 5 | //import io.kotest.core.spec.style.StringSpec 6 | // 7 | //class transform : StringSpec() { 8 | // 9 | // init { 10 | // 11 | // transformTexture1d() 12 | // transform_array::test < gli::texture1d_array > () 13 | // transform::test < gli::texture2d > () 14 | // transform_array::test < gli::texture2d_array > () 15 | // transform::test < gli::texture3d > () 16 | // transform::test < gli::texture_cube > () 17 | // transform_array::test < gli::texture_cube_array > () 18 | // } 19 | // 20 | // fun average(a: Vec4ub, b: Vec4ub) = Vec4ub((a + b) / 2) 21 | // 22 | // fun transformTexture1d() { 23 | // 24 | // val textureA=Texture1d (Format.RGBA8_UNORM_PACK8, Vec1i(4)) 25 | // textureA clear Vec4ub(255, 127, 0, 255) 26 | // val textureB =Texture1d(Format.RGBA8_UNORM_PACK8, Vec1i(4)) 27 | // textureB clear Vec4ub(255, 127, 64, 192) 28 | // val textureO=Texture1d (Format.RGBA8_UNORM_PACK8, Vec1i(4)) 29 | // 30 | // gli::transform < gli::u8vec4 > (textureO, TextureA, TextureB, average) 31 | // 32 | // gli::u8vec4 const * const data = textureO.template data < gli ::u8vec4 > () 33 | // for (gli:: texture1d::size_type TexelIndex = 0, TexelCount = TextureO.template size(); TexelIndex < TexelCount; ++TexelIndex) 34 | // { 35 | // *(data + TexelIndex) == gli::u8vec4(255, 127, 32, 223) ? 0 : 1 36 | // GLI_ASSERT(!Error) 37 | // } 38 | // } 39 | // 40 | // namespace transform_array 41 | // { 42 | // template < typename texture_type > 43 | // int test () 44 | // { 45 | // int Error = 0 46 | // 47 | // texture_type TextureA (gli::FORMAT_RGBA8_UNORM_PACK8, typename texture_type::extent_type(4), 2) 48 | // TextureA.clear(gli::u8vec4(255, 127, 0, 255)) 49 | // texture_type TextureB (gli::FORMAT_RGBA8_UNORM_PACK8, typename texture_type::extent_type(4), 2) 50 | // TextureB.clear(gli::u8vec4(255, 127, 64, 192)) 51 | // texture_type TextureO (gli::FORMAT_RGBA8_UNORM_PACK8, typename texture_type::extent_type(4), 2) 52 | // 53 | // gli::transform < gli::u8vec4 > (TextureO, TextureA, TextureB, average) 54 | // 55 | // gli::u8vec4 const * const data = TextureO.template data < gli ::u8vec4 > () 56 | // for (typename texture_type ::size_type TexelIndex = 0, TexelCount = TextureO.template size(); TexelIndex < TexelCount; ++TexelIndex) 57 | // { 58 | // *(data + TexelIndex) == gli::u8vec4(255, 127, 32, 223) ? 0 : 1 59 | // GLI_ASSERT(!Error) 60 | // } 61 | // 62 | // return Error 63 | // } 64 | // } 65 | //} -------------------------------------------------------------------------------- /src/main/kotlin/gli_/ktx.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.BYTES 4 | import glm_.b 5 | import kool.BYTES 6 | import java.nio.ByteBuffer 7 | 8 | object ktx { 9 | 10 | val FOURCC_KTX10 = byteArrayOf(0xAB.b, 0x4B.b, 0x54.b, 0x58.b, 0x20.b, 0x31.b, 0x31.b, 0xBB.b, 0x0D.b, 0x0A.b, 0x1A.b, 0x0A.b) 11 | val FOURCC_KTX20 = byteArrayOf(0xAB.b, 0x4B.b, 0x54.b, 0x58.b, 0x20.b, 0x32.b, 0x30.b, 0xBB.b, 0x0D.b, 0x0A.b, 0x1A.b, 0x0A.b) 12 | 13 | class Header10 { 14 | 15 | var endianness = 0 16 | var glType = 0 17 | var glTypeSize = 0 18 | var glFormat = 0 19 | var glInternalFormat = 0 20 | var glBaseInternalFormat = 0 21 | var pixelWidth = 0 22 | var pixelHeight = 0 23 | var pixelDepth = 0 24 | var numberOfArrayElements = 0 25 | var numberOfFaces = 0 26 | var numberOfMipmapLevels = 0 27 | var bytesOfKeyValueData = 0 28 | 29 | constructor() 30 | 31 | constructor(data: ByteBuffer) { 32 | 33 | endianness = data.int 34 | glType = data.int 35 | glTypeSize = data.int 36 | glFormat = data.int 37 | glInternalFormat = data.int 38 | glBaseInternalFormat = data.int 39 | pixelWidth = data.int 40 | pixelHeight = data.int 41 | pixelDepth = data.int 42 | numberOfArrayElements = data.int 43 | numberOfFaces = data.int 44 | numberOfMipmapLevels = data.int 45 | bytesOfKeyValueData = data.int 46 | } 47 | 48 | fun to(buffer: ByteBuffer) = buffer 49 | .putInt(endianness) 50 | .putInt(glType) 51 | .putInt(glTypeSize) 52 | .putInt(glFormat) 53 | .putInt(glInternalFormat) 54 | .putInt(glBaseInternalFormat) 55 | .putInt(pixelWidth) 56 | .putInt(pixelHeight) 57 | .putInt(pixelDepth) 58 | .putInt(numberOfArrayElements) 59 | .putInt(numberOfFaces) 60 | .putInt(numberOfMipmapLevels) 61 | .putInt(bytesOfKeyValueData) 62 | 63 | val target 64 | get () = when { 65 | numberOfFaces > 1 -> when { 66 | numberOfArrayElements > 0 -> Target.CUBE_ARRAY 67 | else -> Target.CUBE 68 | } 69 | numberOfArrayElements > 0 -> when { 70 | pixelHeight == 0 -> Target._1D_ARRAY 71 | else -> Target._2D_ARRAY 72 | } 73 | pixelHeight == 0 -> Target._1D 74 | pixelDepth > 0 -> Target._3D 75 | else -> Target._2D 76 | } 77 | 78 | companion object { 79 | val size = 13 * Int.BYTES 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/Cache.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.glm 4 | import glm_.vec3.Vec3i 5 | import kool.adr 6 | 7 | /** Pre compute at texture instance creation some information for faster access to texels */ 8 | class Cache { 9 | 10 | val faces: Int 11 | val levels: Int 12 | 13 | private val baseAddresses : LongArray 14 | private val imageExtent = Array(16) { Vec3i() } 15 | private val imageMemorySize = IntArray(16) 16 | 17 | private val globalMemorySize: Int 18 | 19 | constructor( 20 | storage: Storage, 21 | format: Format, 22 | baseLayer: Int, layers: Int, 23 | baseFace: Int, maxFace: Int, 24 | baseLevel: Int, maxLevel: Int 25 | ) { 26 | faces = maxFace - baseFace + 1 27 | levels = maxLevel - baseLevel + 1 28 | 29 | baseAddresses = LongArray(layers * faces * levels) 30 | 31 | assert(glm.levels(storage.extent(0)) < imageMemorySize.size) 32 | 33 | for (layer in 0 until layers) 34 | 35 | for (face in 0 until faces) 36 | 37 | for (level in 0 until levels) { 38 | 39 | val index = indexCache(layer, face, level) 40 | val offset = storage.baseOffset(baseLayer + layer, baseFace + face, baseLevel + level) 41 | baseAddresses[index] = storage.data().adr.toLong() + offset 42 | } 43 | 44 | for (level in 0 until levels) { 45 | 46 | val srcExtent = storage.extent(baseLevel + level) 47 | val dstExtent = srcExtent * format.blockExtend / storage.blockExtent 48 | 49 | imageExtent[level] = glm.max(dstExtent, 1) 50 | imageMemorySize[level] = storage.levelSize(baseLevel + level) 51 | } 52 | 53 | globalMemorySize = storage.layerSize(baseFace, maxFace, baseLevel, maxLevel) * layers 54 | } 55 | 56 | /** JVM constructor for C++ by value */ 57 | constructor(cache: Cache) { 58 | faces = cache.faces 59 | levels = cache.levels 60 | baseAddresses = cache.baseAddresses.clone() 61 | repeat(imageExtent.size) { 62 | imageExtent[it] = cache.imageExtent[it] 63 | imageMemorySize[it] = cache.imageMemorySize[it] 64 | } 65 | globalMemorySize = cache.globalMemorySize 66 | } 67 | 68 | private fun indexCache(layer: Int, face: Int, level: Int) = ((layer * faces) + face) * levels + level 69 | 70 | /** Base addresses of each images of a texture. */ 71 | fun baseAddress(layer: Int, face: Int, level: Int) = baseAddresses[indexCache(layer, face, level)] 72 | 73 | /** In texels */ 74 | fun extent(level: Int) = imageExtent[level] 75 | 76 | /** In bytes */ 77 | fun memorySize(level: Int) = imageMemorySize[level] 78 | 79 | /** In bytes */ 80 | val memorySize get() = globalMemorySize 81 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/Texture3d.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.glm 4 | import glm_.vec3.Vec3i 5 | import kotlin.reflect.KClass 6 | 7 | /** 8 | * Created by GBarbieri on 04.04.2017. 9 | */ 10 | 11 | /** 3d texture */ 12 | class Texture3d : Texture { 13 | 14 | /** Create an empty texture 3D. */ 15 | constructor() : super() 16 | 17 | /** Create a texture3d and allocate a new storage_linear. */ 18 | constructor(format: Format, extent: Vec3i, levels: Int, swizzles: Swizzles = Swizzles()) : 19 | super(Target._3D, format, extent, 1, 1, levels, swizzles) 20 | 21 | /** Create a texture3d and allocate a new storage_linear with a complete mipmap chain. */ 22 | constructor(format: Format, extent: Vec3i, swizzles: Swizzles = Swizzles()) : 23 | super(Target._3D, format, extent, 1, 1, glm.levels(extent), swizzles) 24 | 25 | /** Create a texture3d view with an existing storage_linear. */ 26 | constructor(texture: Texture) : super(texture, Target._3D, texture.format) 27 | 28 | /** Create a texture3d view with an existing storage_linear. */ 29 | constructor(texture: Texture, format: Format, 30 | baseLayer: Int, maxLayer: Int, 31 | baseFace: Int, maxFace: Int, 32 | baseLevel: Int, maxLevel: Int, 33 | swizzles: Swizzles = Swizzles()) : 34 | super(texture, Target._3D, format, baseLayer, maxLayer, baseFace, maxFace, baseLevel, maxLevel, swizzles) 35 | 36 | /** Create a texture3d view, reference a subset of an existing texture3d instance. */ 37 | constructor(texture: Texture, baseLevel: Int, maxLevel: Int) : 38 | super(texture, Target._3D, texture.format, 39 | texture.baseLayer, texture.maxLayer, 40 | texture.baseFace, texture.maxFace, 41 | texture.baseLevel + baseLevel, texture.baseLevel + maxLevel) 42 | 43 | /** for duplicate */ 44 | constructor(format: Format, extent: Vec3i, layers: Int, faces: Int, levels: Int, swizzles: Swizzles = Swizzles()) : 45 | super(Target._3D, format, extent, layers, faces, levels, swizzles) 46 | 47 | /** Create a view of the image identified by Level in the mipmap chain of the texture. */ 48 | operator fun get(level: Int): Image { 49 | assert(level < levels()) 50 | return Image(storage!!, format, baseLayer, baseFace, baseLevel + level) 51 | } 52 | 53 | internal inline fun load(texelCoord: Vec3i, level: Int): T = super.load(texelCoord, 0, 0, level) 54 | fun load(kClass: KClass<*>, texelCoord: Vec3i, level: Int): T = super.load(kClass, texelCoord, 0, 0, level) 55 | 56 | internal inline fun store(texelCoord: Vec3i, level: Int, texel: T) = super.store(texelCoord, 0, 0, level, texel) 57 | fun store(kClass: KClass<*>, texelCoord: Vec3i, level: Int, texel: T) = super.store(kClass, texelCoord, 0, 0, level, texel) 58 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/saveKmg.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import kool.* 4 | import java.nio.channels.FileChannel 5 | import java.nio.file.Path 6 | import java.nio.file.StandardOpenOption 7 | 8 | interface saveKmg { 9 | 10 | /** Save a texture storage_linear to a KMG (Khronos Image) file. 11 | * @param texture Source texture to save 12 | * @param path Path for where to save the file. It must include the filaname and filename extension. 13 | * This function ignores the filename extension in the path and save to KMG anyway but keep the requested 14 | * filename extension. 15 | * @return Returns false if the function fails to save the file. */ 16 | fun saveKmg(texture: Texture, path: Path): Boolean { 17 | 18 | if (texture.empty()) return false 19 | 20 | val data = Buffer(kmg.FOURCC_KMG100.size + kmg.Header10.size + texture.size) 21 | 22 | kmg.FOURCC_KMG100.forEach { data.put(it) } 23 | 24 | val swizzle = texture.swizzles 25 | 26 | kmg.Header10().apply { 27 | endianness = 0x04030201 28 | format = texture.format.i 29 | target = texture.target.i 30 | swizzleRed = swizzle[0].i 31 | swizzleGreen = swizzle[1].i 32 | swizzleBlue = swizzle[2].i 33 | swizzleAlpha = swizzle[3].i 34 | pixelWidth = texture.extent().x 35 | pixelHeight = texture.extent().y 36 | pixelDepth = texture.extent().z 37 | layers = texture.layers() 38 | levels = texture.levels() 39 | faces = texture.faces() 40 | generateMipmaps = gli.Filter.NONE.i 41 | baseLevel = texture.baseLevel 42 | maxLevel = texture.maxLevel 43 | 44 | to(data) 45 | } 46 | 47 | for (layer in 0 until texture.layers()) 48 | for (level in 0 until texture.levels()) { 49 | 50 | val faceSize = texture.size(level) 51 | for (face in 0 until texture.faces()) { 52 | 53 | val src = texture.data(layer, face, level) 54 | memCopy(src.adr, data.adr, faceSize) 55 | 56 | data.pos += faceSize 57 | assert(data.pos <= data.cap) 58 | } 59 | } 60 | 61 | FileChannel.open(path, StandardOpenOption.CREATE, StandardOpenOption.WRITE).use { 62 | data.pos = 0 63 | while (data.hasRemaining()) it.write(data) 64 | } 65 | 66 | return true 67 | } 68 | 69 | /** Save a texture storage_linear to a KMG (Khronos Image) file. 70 | * @param texture Source texture to save 71 | * @param filename String for where to save the file. It must include the filaname and filename extension. 72 | * This function ignores the filename extension in the path and save to KMG anyway but keep the requested 73 | * filename extension. 74 | * @return Returns false if the function fails to save the file. */ 75 | fun saveKmg(texture: Texture, filename: String) = saveKmg(texture, pathOf(filename)) 76 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreImage.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.vec3.Vec3i 4 | import glm_.vec4.Vec4b 5 | import glm_.vec4.Vec4ub 6 | import io.kotest.matchers.shouldBe 7 | import io.kotest.core.spec.style.StringSpec 8 | 9 | /** 10 | * Created by elect on 08/04/17. 11 | */ 12 | 13 | class coreImage : StringSpec() { 14 | 15 | init { 16 | 17 | "image ctor" { 18 | 19 | val imageA = Image(Format.RGBA8_UINT_PACK8, Vec3i(4, 4, 1)) 20 | val imageB = Image(Format.RGBA8_UINT_PACK8, Vec3i(4, 4, 1)) 21 | val imageC = imageA 22 | val imageD = Image(imageA, Format.RGBA8_UINT_PACK8) 23 | val imageE = Image(imageD, Format.RGBA8_UINT_PACK8) 24 | 25 | imageA shouldBe imageB 26 | imageC shouldBe imageB 27 | imageA shouldBe imageE 28 | } 29 | 30 | "image data" { 31 | 32 | val imageA = Image() 33 | imageA.empty() shouldBe true 34 | 35 | val imageB = Image(Format.RGBA8_UNORM_PACK8, Vec3i(1)) 36 | imageB.size shouldBe Vec4b.size 37 | 38 | Vec4b(255, 127, 0, 255) to imageB.data() 39 | imageB.notEmpty() shouldBe true 40 | } 41 | 42 | "image query" { 43 | 44 | val image = Image(Format.RGBA8_UINT_PACK8, Vec3i(1)) 45 | 46 | image.size shouldBe Vec4b.size 47 | image.notEmpty() shouldBe true 48 | image.extent() shouldBe Vec3i(1) 49 | } 50 | 51 | "fetch" { 52 | 53 | val image = Image(Format.RGBA8_UINT_PACK8, Vec3i(4, 2, 1)) 54 | image.data()[0] = Vec4ub(255, 0, 0, 255) 55 | image.data()[1] = Vec4ub(255, 128, 0, 255) 56 | image.data()[2] = Vec4ub(255, 255, 0, 255) 57 | image.data()[3] = Vec4ub(128, 255, 0, 255) 58 | image.data()[4] = Vec4ub(0, 255, 0, 255) 59 | image.data()[5] = Vec4ub(0, 255, 255, 255) 60 | image.data()[6] = Vec4ub(0, 0, 255, 255) 61 | image.data()[7] = Vec4ub(255, 0, 255, 255) 62 | 63 | val data0 = image.load(Vec3i(0, 0, 0)) 64 | val data1 = image.load(Vec3i(1, 0, 0)) 65 | val data2 = image.load(Vec3i(2, 0, 0)) 66 | val data3 = image.load(Vec3i(3, 0, 0)) 67 | val data4 = image.load(Vec3i(0, 1, 0)) 68 | val data5 = image.load(Vec3i(1, 1, 0)) 69 | val data6 = image.load(Vec3i(2, 1, 0)) 70 | val data7 = image.load(Vec3i(3, 1, 0)) 71 | 72 | data0 shouldBe Vec4ub(255, 0, 0, 255) 73 | data1 shouldBe Vec4ub(255, 128, 0, 255) 74 | data2 shouldBe Vec4ub(255, 255, 0, 255) 75 | data3 shouldBe Vec4ub(128, 255, 0, 255) 76 | data4 shouldBe Vec4ub(0, 255, 0, 255) 77 | data5 shouldBe Vec4ub(0, 255, 255, 255) 78 | data6 shouldBe Vec4ub(0, 0, 255, 255) 79 | data7 shouldBe Vec4ub(255, 0, 255, 255) 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/TextureCube.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.glm 4 | import glm_.vec2.Vec2i 5 | import glm_.vec3.Vec3i 6 | import kotlin.reflect.KClass 7 | 8 | /** 9 | * Created by GBarbieri on 04.04.2017. 10 | */ 11 | 12 | /** Cube map texture */ 13 | class TextureCube : Texture { 14 | 15 | /** Create an empty texture cube. */ 16 | constructor() : super() 17 | 18 | /** Create a textureCube and allocate a new storage_linear. */ 19 | constructor(format: Format, extent: Vec2i, levels: Int, swizzles: Swizzles = Swizzles()) : 20 | super(Target.CUBE, format, Vec3i(extent, 1), 1, 6, levels, swizzles) 21 | 22 | /** Create a textureCube and allocate a new storage_linear with a complete mipmap chain. */ 23 | constructor(format: Format, extent: Vec2i, swizzles: Swizzles = Swizzles()) : 24 | super(Target.CUBE, format, Vec3i(extent, 1), 1, 6, glm.levels(extent), swizzles) 25 | 26 | /** Create a textureCube view with an existing storage_linear. */ 27 | constructor(texture: Texture) : super(texture, Target.CUBE, texture.format) 28 | 29 | /** Create a textureCube view with an existing storage_linear. */ 30 | constructor(texture: Texture, format: Format, 31 | baseLayer: Int, maxLayer: Int, 32 | baseFace: Int, maxFace: Int, 33 | baseLevel: Int, maxLevel: Int, 34 | swizzles: Swizzles = Swizzles()) : 35 | super(texture, Target.CUBE, format, baseLayer, maxLayer, baseFace, maxFace, baseLevel, maxLevel, swizzles) 36 | 37 | /** Create a textureCube view, reference a subset of an existing textureCube instance. */ 38 | constructor(texture: Texture, 39 | baseFace: Int, maxFace: Int, 40 | baseLevel: Int, maxLevel: Int) : 41 | super(texture, Target.CUBE, texture.format, 42 | texture.baseLayer, texture.maxLayer, 43 | texture.baseFace + baseFace, texture.baseFace + maxFace, 44 | texture.baseLevel + baseLevel, texture.baseLevel + maxLevel) 45 | 46 | /** Create a view of the texture identified by Face in the texture cube. */ 47 | operator fun get(face: Int): Texture2d { 48 | assert(face < faces()) 49 | 50 | return Texture2d( 51 | this, format, 52 | baseLayer, maxLayer, 53 | baseFace + face, baseFace + face, 54 | baseLevel, maxLevel) 55 | } 56 | 57 | fun extent_(level: Int = 0) = Vec2i(super.extent(level)) 58 | 59 | internal inline fun load(texelCoord: Vec2i, face: Int, level: Int): T = super.load(Vec3i(texelCoord, 0), 0, face, level) 60 | fun load(kClass: KClass<*>, texelCoord: Vec2i, face: Int, level: Int): T = super.load(kClass, Vec3i(texelCoord, 0), 0, face, level) 61 | 62 | internal inline fun store(texelCoord: Vec2i, face: Int, level: Int, texel: T) = super.store(Vec3i(texelCoord, 0), 0, face, level, texel) 63 | fun store(kClass: KClass<*>, texelCoord: Vec2i, face: Int, level: Int, texel: T) = super.store(kClass, Vec3i(texelCoord, 0), 0, face, level, texel) 64 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/loadKmg.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.i 4 | import glm_.vec3.Vec3i 5 | import kool.* 6 | import java.net.URI 7 | import java.nio.ByteBuffer 8 | import java.nio.ByteOrder 9 | import java.nio.channels.FileChannel 10 | import java.nio.file.Path 11 | import java.nio.file.Paths 12 | import java.nio.file.StandardOpenOption 13 | 14 | interface loadKmg { 15 | 16 | /** Loads a texture storage_linear from KMG (Khronos Image) file. Returns an empty storage_linear in case of failure. 17 | * @param filename String of the file to open including filaname and filename extension */ 18 | fun loadKmg(filename: String) = loadKmg(Paths.get(filename)) 19 | 20 | fun loadKmg(uri: URI) = loadKmg(Paths.get(uri)) 21 | 22 | /** Loads a texture storage_linear from KMG (Khronos Image) file. Returns an empty storage_linear in case of failure. 23 | * @param path Path of the file to open including filaname and filename extension */ 24 | fun loadKmg(path: Path): Texture { 25 | 26 | val buffer = FileChannel.open(path, StandardOpenOption.READ).use { channel -> 27 | Buffer(channel.size().i).also { 28 | while (channel.read(it) > 0); 29 | it.pos = 0 30 | it.order(ByteOrder.nativeOrder()) 31 | } 32 | } 33 | 34 | return loadKmg(buffer) 35 | } 36 | 37 | /** Loads a texture storage_linear from KMG (Khronos Image) file. Returns an empty storage_linear in case of failure. 38 | * @param data buffer of the texture container data to read */ 39 | fun loadKmg(data: ByteBuffer): Texture { 40 | 41 | assert(data.rem >= kmg.Header10.size) 42 | 43 | // KMG100 44 | run { 45 | if (kmg.FOURCC_KMG100.all { it == data.get() }) // CONSUMED 46 | return loadKmg100(data) 47 | } 48 | 49 | return Texture() 50 | } 51 | 52 | private fun loadKmg100(data: ByteBuffer): Texture { 53 | 54 | val header = kmg.Header10(data) 55 | 56 | val texture = Texture( 57 | target = Target.of(header.target), 58 | format = Format.of(header.format), 59 | extent = Vec3i(header.pixelWidth, header.pixelHeight, header.pixelDepth), 60 | layers = header.layers, 61 | faces = header.faces, 62 | levels = header.levels, 63 | swizzles = Swizzles(header.swizzleRed, header.swizzleGreen, header.swizzleBlue, header.swizzleAlpha)) 64 | 65 | for (layer in 0 until texture.layers()) 66 | for (level in 0 until texture.levels()) { 67 | 68 | val faceSize = texture.size(level) 69 | for (face in 0 until texture.faces()) { 70 | 71 | val dst = texture.data(layer, face, level) 72 | memCopy(data.adr, dst.adr, faceSize) 73 | 74 | data.pos += faceSize 75 | assert(data.pos <= data.cap) 76 | } 77 | } 78 | 79 | return Texture( 80 | texture, texture.target, texture.format, 81 | texture.baseLayer, texture.maxLayer, 82 | texture.baseFace, texture.maxFace, 83 | header.baseLevel, header.maxLevel, 84 | texture.swizzles) 85 | } 86 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/TextureCubeArray.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.glm 4 | import glm_.vec2.Vec2i 5 | import glm_.vec3.Vec3i 6 | import kotlin.reflect.KClass 7 | 8 | /** 9 | * Created by GBarbieri on 04.04.2017. 10 | */ 11 | 12 | /** cube array texture */ 13 | class TextureCubeArray : Texture { 14 | 15 | /** Create an empty texture cube array */ 16 | constructor() : super() 17 | 18 | /** Create a texture cube array and allocate a new storage_linear */ 19 | constructor(format: Format, extent: Vec2i, layers: Int, levels: Int, swizzles: Swizzles = Swizzles()) : 20 | super(Target.CUBE_ARRAY, format, Vec3i(extent, 1), layers, 6, levels, swizzles) 21 | 22 | /** Create a texture2d_array and allocate a new storage_linear with a complete mipmap chain */ 23 | constructor(format: Format, extent: Vec2i, layers: Int, swizzles: Swizzles = Swizzles()) : 24 | super(Target.CUBE_ARRAY, format, Vec3i(extent, 1), layers, 6, glm.levels(extent), swizzles) 25 | 26 | /** Create a texture2d_array view with an existing storage_linear */ 27 | constructor(texture: Texture) : super(texture, Target.CUBE_ARRAY, texture.format) 28 | 29 | /** Create a texture2d_array view with an existing storage_linear */ 30 | constructor(texture: Texture, format: Format, 31 | baseLayer: Int, maxLayer: Int, 32 | baseFace: Int, maxFace: Int, 33 | baseLevel: Int, maxLevel: Int, 34 | swizzles: Swizzles = Swizzles()) : 35 | super(texture, Target.CUBE_ARRAY, format, baseLayer, maxLayer, baseFace, maxFace, baseLevel, maxLevel, swizzles) 36 | 37 | /** Create a texture view, reference a subset of an exiting storage_linear */ 38 | constructor(texture: Texture, 39 | baseLayer: Int, maxLayer: Int, 40 | baseFace: Int, maxFace: Int, 41 | baseLevel: Int, maxLevel: Int) : 42 | super(texture, Target.CUBE_ARRAY, texture.format, 43 | texture.baseLayer + baseLayer, texture.baseLayer + maxLayer, 44 | texture.baseFace + baseFace, texture.baseFace + maxFace, 45 | texture.baseLevel + baseLevel, texture.baseLevel + maxLevel) 46 | 47 | /** Create a view of the texture identified by Layer in the texture array */ 48 | operator fun get(layer: Int): TextureCube { 49 | 50 | assert(layer < layers()) 51 | 52 | return TextureCube( 53 | this, format, 54 | baseLayer + layer, baseLayer + layer, 55 | baseFace, maxFace, 56 | baseLevel, maxLevel) 57 | } 58 | 59 | fun extent_(level: Int = 0) = Vec2i(super.extent(level)) 60 | 61 | internal inline fun load(texelCoord: Vec2i, layer: Int, face: Int, level: Int): T = super.load(Vec3i(texelCoord, 0), layer, face, level) 62 | fun load(kClass: KClass<*>, texelCoord: Vec2i, layer: Int, face: Int, level: Int): T = super.load(kClass, Vec3i(texelCoord, 0), layer, face, level) 63 | 64 | internal inline fun store(texelCoord: Vec2i, layer: Int, face: Int, level: Int, texel: T) = super.store(Vec3i(texelCoord,0), layer, face, level, texel) 65 | fun store(kClass: KClass<*>, texelCoord: Vec2i, layer: Int, face: Int, level: Int, texel: T) = super.store(kClass, Vec3i(texelCoord,0), layer, face, level, texel) 66 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/Texture2dArray.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.glm 4 | import glm_.vec2.Vec2i 5 | import glm_.vec3.Vec3i 6 | import kotlin.reflect.KClass 7 | 8 | /** 9 | * Created by GBarbieri on 04.04.2017. 10 | */ 11 | 12 | /** 2d array texture */ 13 | class Texture2dArray : Texture { 14 | 15 | /** Create an empty texture 2D array */ 16 | constructor() : super() 17 | 18 | /** Create a texture2d_array and allocate a new storage_linear */ 19 | constructor(format: Format, extent: Vec2i, layers: Int, levels: Int, swizzles: Swizzles = Swizzles()) : 20 | super(Target._2D_ARRAY, format, Vec3i(extent, 1), layers, 1, levels, swizzles) 21 | 22 | /** Create a texture2d_array and allocate a new storage_linear with a complete mipmap chain */ 23 | constructor(format: Format, extent: Vec2i, layers: Int, swizzles: Swizzles = Swizzles()) : this(format, Vec3i(extent, 1), layers, swizzles) 24 | 25 | constructor(format: Format, extent: Vec3i, layers: Int, swizzles: Swizzles = Swizzles()) : 26 | super(Target._2D_ARRAY, format, extent, layers, 1, glm.levels(extent), swizzles) 27 | 28 | /** Create a texture2d_array view with an existing storage_linear */ 29 | constructor(texture: Texture) : super(texture, Target._2D_ARRAY, texture.format) 30 | 31 | /** Create a texture2d_array view with an existing storage_linear */ 32 | constructor(texture: Texture, format: Format, 33 | baseLayer: Int, maxLayer: Int, 34 | baseFace: Int, maxFace: Int, 35 | baseLevel: Int, maxLevel: Int, 36 | swizzles: Swizzles = Swizzles()) : 37 | super(texture, Target._2D_ARRAY, format, baseLayer, maxLayer, baseFace, maxFace, baseLevel, maxLevel, swizzles) 38 | 39 | /** Create a texture view, reference a subset of an exiting storage_linear */ 40 | constructor(texture: Texture, 41 | baseLayer: Int, maxLayer: Int, 42 | baseLevel: Int, maxLevel: Int) : 43 | super(texture, Target._2D_ARRAY, texture.format, 44 | texture.baseLayer + baseLayer, texture.baseLayer + maxLayer, 45 | texture.baseFace, texture.maxFace, 46 | texture.baseLevel + baseLevel, texture.baseLevel + maxLevel) 47 | 48 | /** Create a view of the texture identified by Layer in the texture array */ 49 | operator fun get(layer: Int): Texture2d { 50 | 51 | assert(layer < layers()) 52 | 53 | return Texture2d(this, format, 54 | baseLayer + layer, baseLayer + layer, 55 | baseFace, maxFace, 56 | baseLevel, maxLevel) 57 | } 58 | 59 | fun extent_(level: Int = 0) = Vec2i(super.extent(level)) 60 | 61 | internal inline fun load(texelCoord: Vec2i, layer: Int, level: Int): T = super.load(Vec3i(texelCoord.x, texelCoord.y, 0), layer, 0, level) 62 | fun load(kClass: KClass<*>, texelCoord: Vec2i, layer: Int, level: Int): T = super.load(kClass, Vec3i(texelCoord.x, texelCoord.y, 0), layer, 0, level) 63 | 64 | internal inline fun store(texelCoord: Vec2i, layer: Int, level: Int, texel: T) = super.store(Vec3i(texelCoord.x, texelCoord.y, 0), layer, 0, level, texel) 65 | fun store(kClass: KClass<*>, texelCoord: Vec2i, layer: Int, level: Int, texel: T) = super.store(kClass, Vec3i(texelCoord.x, texelCoord.y, 0), layer, 0, level, texel) 66 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/Texture2d.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.glm 4 | import glm_.vec2.Vec2i 5 | import glm_.vec3.Vec3i 6 | import kotlin.reflect.KClass 7 | 8 | /** 9 | * Created by GBarbieri on 03.04.2017. 10 | */ 11 | 12 | /** 2d texture */ 13 | class Texture2d : Texture { 14 | 15 | /** Create an empty texture 2D. */ 16 | constructor() : super() 17 | 18 | /** Create a texture2d and allocate a new storage_linear. */ 19 | constructor(format: Format, extent: Vec2i, levels: Int, swizzles: Swizzles = Swizzles()) : 20 | super(Target._2D, format, Vec3i(extent, 1), 1, 1, levels, swizzles) 21 | 22 | /** vec3i extend */ 23 | constructor(format: Format, extent: Vec3i, levels: Int, swizzles: Swizzles = Swizzles()) : 24 | super(Target._2D, format, extent, 1, 1, levels, swizzles) 25 | 26 | /** Create a texture2d and allocate a new storage_linear with a complete mipmap chain. */ 27 | constructor(format: Format, extent: Vec2i, swizzles: Swizzles = Swizzles()) : 28 | this(format, Vec3i(extent, 1), swizzles) 29 | 30 | constructor(format: Format, extent: Vec3i, swizzles: Swizzles = Swizzles()) : 31 | super(Target._2D, format, extent, 1, 1, glm.levels(extent), swizzles) 32 | 33 | /** Create a texture2d view with an existing storage_linear. */ 34 | constructor(texture: Texture) : super(texture, Target._2D, texture.format) 35 | 36 | /** Create a texture2d view with an existing storage_linear. */ 37 | constructor(texture: Texture, format: Format, 38 | baseLayer: Int, maxLayer: Int, 39 | baseFace: Int, maxFace: Int, 40 | baseLevel: Int, maxLevel: Int, 41 | swizzles: Swizzles = Swizzles()) : 42 | super(texture, Target._2D, format, baseLayer, maxLayer, baseFace, maxFace, baseLevel, maxLevel, swizzles) 43 | 44 | /** Create a texture2d view, reference a subset of an existing texture2d instance. */ 45 | constructor(texture: Texture, baseLevel: Int, maxLevel: Int) : 46 | super(texture, Target._2D, texture.format, 47 | texture.baseLayer, texture.maxLayer, 48 | texture.baseFace, texture.maxFace, 49 | texture.baseLevel + baseLevel, texture.baseLevel + maxLevel) 50 | 51 | /** for duplicate */ 52 | constructor(format: Format, extent: Vec3i, layers: Int, faces: Int, levels: Int, swizzles: Swizzles = Swizzles()) : 53 | super(Target._2D, format, extent, layers, faces, levels, swizzles) 54 | 55 | /** Create a view of the image identified by Level in the mipmap chain of the texture. */ 56 | operator fun get(level: Int): Image { 57 | assert(level < levels()) 58 | return Image(storage!!, format, baseLayer, baseFace, baseLevel + level) 59 | } 60 | 61 | fun extent_(level: Int = 0) = Vec2i(super.extent(level)) 62 | 63 | internal inline fun load(texelCoord: Vec2i, level: Int): T = super.load(Vec3i(texelCoord, 0), 0, 0, level) 64 | fun load(kclass: KClass<*>, texelCoord: Vec2i, level: Int): T = super.load(kclass, Vec3i(texelCoord, 0), 0, 0, level) 65 | internal inline fun store(texelCoord: Vec2i, level: Int, texel: T) = super.store(Vec3i(texelCoord, 0), 0, 0, level, texel) 66 | fun store(kclass: KClass<*>, texelCoord: Vec2i, level: Int, texel: T) = super.store(kclass, Vec3i(texelCoord, 0), 0, 0, level, texel) 67 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/copy.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | interface copy { 4 | 5 | /** Copy a specific image of a texture */ 6 | fun copy( 7 | textureSrc: Texture, layerSrc: Int, faceSrc: Int, levelSrc: Int, 8 | textureDst: Texture, layerDst: Int, faceDst: Int, levelDst: Int 9 | ) = 10 | textureDst.copy(textureSrc, layerSrc, faceSrc, levelSrc, layerDst, faceDst, levelDst) 11 | 12 | /** Copy a texture */ 13 | fun copy( 14 | textureSrc: Texture, 15 | textureDst: Texture 16 | ) = 17 | copyLayer(textureSrc, 0, textureDst, 0, textureDst.layers()) 18 | 19 | /** Copy multiple levels of a texture */ 20 | fun copyLevel( 21 | textureSrc: Texture, baseLevelSrc: Int, 22 | textureDst: Texture, baseLevelDst: Int, 23 | levelCount: Int 24 | ) { 25 | for (layerIndex in 0 until textureSrc.layers()) 26 | for (faceIndex in 0 until textureSrc.faces()) 27 | for (levelIndex in 0 until levelCount) 28 | textureDst.copy( 29 | textureSrc, 30 | layerIndex, faceIndex, baseLevelSrc + levelIndex, 31 | layerIndex, faceIndex, baseLevelDst + levelIndex) 32 | } 33 | 34 | /** Copy an entire level of a texture */ 35 | fun copyLevel( 36 | textureSrc: Texture, baseLevelSrc: Int, 37 | textureDst: Texture, baseLevelDst: Int 38 | ) = 39 | copyLevel(textureSrc, baseLevelSrc, textureDst, baseLevelDst, 1) 40 | 41 | /** Copy multiple faces of a texture */ 42 | fun copyFace( 43 | textureSrc: Texture, baseFaceSrc: Int, 44 | textureDst: Texture, baseFaceDst: Int, 45 | faceCount: Int 46 | ) { 47 | for (layerIndex in 0 until textureSrc.layers()) 48 | for (faceIndex in 0 until faceCount) 49 | for (levelIndex in 0 until textureSrc.levels()) 50 | textureDst.copy( 51 | textureSrc, 52 | layerIndex, baseFaceSrc + faceIndex, levelIndex, 53 | layerIndex, baseFaceDst + faceIndex, levelIndex) 54 | } 55 | 56 | /** Copy an entire face of a texture */ 57 | fun copyFace( 58 | textureSrc: Texture, baseFaceSrc: Int, 59 | textureDst: Texture, baseFaceDst: Int 60 | ) = 61 | copyFace(textureSrc, baseFaceSrc, textureDst, baseFaceDst, 1) 62 | 63 | /** Copy multiple layers of a texture */ 64 | fun copyLayer( 65 | textureSrc: Texture, baseLayerSrc: Int, 66 | textureDst: Texture, baseLayerDst: Int, 67 | layerCount: Int 68 | ) { 69 | for (layerIndex in 0 until layerCount) 70 | for (faceIndex in 0 until textureSrc.faces()) 71 | for (levelIndex in 0 until textureSrc.levels()) 72 | textureDst.copy( 73 | textureSrc, 74 | baseLayerSrc + layerIndex, faceIndex, levelIndex, 75 | baseLayerDst + layerIndex, faceIndex, levelIndex) 76 | } 77 | 78 | /** Copy an entire layer of a texture */ 79 | fun copyLayer( 80 | textureSrc: Texture, baseLayerSrc: Int, 81 | textureDst: Texture, baseLayerDst: Int 82 | ) = 83 | copyLayer(textureSrc, baseLayerSrc, textureDst, baseLayerDst, 1) 84 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/Texture1dArray.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.glm 4 | import glm_.vec1.Vec1i 5 | import glm_.vec3.Vec3i 6 | import kotlin.reflect.KClass 7 | 8 | /** 9 | * Created by GBarbieri on 04.04.2017. 10 | */ 11 | 12 | /** 1d array texture */ 13 | class Texture1dArray : Texture { 14 | 15 | /** Create an empty texture 1D array */ 16 | constructor() : super() 17 | 18 | /** Create a texture1d_array and allocate a new storage_linear */ 19 | constructor( 20 | format: Format, 21 | extent: Vec1i, 22 | layers: Int, 23 | levels: Int, 24 | swizzles: Swizzles = Swizzles() 25 | ) : 26 | super(Target._1D_ARRAY, format, Vec3i(extent.x, 1, 1), layers, 1, levels, swizzles) 27 | 28 | /** Create a texture1d_array and allocate a new storage_linear with a complete mipmap chain */ 29 | constructor( 30 | format: Format, 31 | extent: Vec1i, 32 | layers: Int, 33 | swizzles: Swizzles = Swizzles() 34 | ) : 35 | super(Target._1D_ARRAY, format, Vec3i(extent.x, 1, 1), layers, 1, glm.levels(extent), swizzles) 36 | 37 | /** Create a texture1d_array view with an existing storage_linear */ 38 | constructor( 39 | texture: Texture 40 | ) : 41 | super(texture, Target._1D_ARRAY, texture.format) 42 | 43 | /** Create a texture1d_array view with an existing storage_linear */ 44 | constructor( 45 | texture: Texture, 46 | format: Format, 47 | baseLayer: Int, maxLayer: Int, 48 | baseFace: Int, maxFace: Int, 49 | baseLevel: Int, maxLevel: Int, 50 | swizzles: Swizzles = Swizzles() 51 | ) : 52 | super(texture, Target._1D_ARRAY, format, baseLayer, maxLayer, baseFace, maxFace, baseLevel, maxLevel, swizzles) 53 | 54 | /** Create a texture view, reference a subset of an exiting storage_linear */ 55 | constructor(texture: Texture, 56 | baseLayer: Int, maxLayer: Int, 57 | baseLevel: Int, maxLevel: Int 58 | ) : 59 | super(texture, Target._1D_ARRAY, texture.format, 60 | texture.baseLayer + baseLayer, texture.baseLayer + maxLayer, 61 | texture.baseFace, texture.maxFace, 62 | texture.baseLevel + baseLevel, texture.baseLevel + maxLevel) 63 | 64 | /** Create a view of the texture identified by Layer in the texture array */ 65 | operator fun get(layer: Int): Texture1d { 66 | 67 | assert(notEmpty() && layer < layers()) 68 | 69 | return Texture1d( 70 | this, format, 71 | baseLayer + layer, baseLayer + layer, 72 | baseFace, maxFace, 73 | baseLevel, maxLevel) 74 | } 75 | 76 | fun extent_(level: Int = 0) = Vec1i(super.extent(level)) 77 | 78 | internal inline fun load(texelCoord: Vec1i, layer: Int, level: Int): T = super.load(Vec3i(texelCoord.x, 0, 0), layer, 0, level) 79 | 80 | fun load(kClass: KClass<*>, texelCoord: Vec1i, layer: Int, level: Int): T = super.load(kClass, Vec3i(texelCoord.x, 0, 0), layer, 0, level) 81 | 82 | internal inline fun store(texelCoord: Vec1i, layer: Int, level: Int, texel: T) = super.store(Vec3i(texelCoord.x, 0, 0), layer, 0, level, texel) 83 | fun store(kClass: KClass<*>, texelCoord: Vec1i, layer: Int, level: Int, texel: T) = super.store(kClass, Vec3i(texelCoord.x, 0, 0), layer, 0, level, texel) 84 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/loadKtx.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.BYTES 4 | import glm_.glm 5 | import glm_.i 6 | import glm_.vec3.Vec3i 7 | import kool.* 8 | import java.net.URI 9 | import java.nio.ByteBuffer 10 | import java.nio.ByteOrder 11 | import java.nio.channels.FileChannel 12 | import java.nio.file.Path 13 | import java.nio.file.Paths 14 | import java.nio.file.StandardOpenOption 15 | 16 | interface loadKtx { 17 | 18 | /** Loads a texture storage_linear from KTX memory. Returns an empty storage_linear in case of failure. 19 | * @param filename String of the file to open including filaname and filename extension */ 20 | fun loadKtx(filename: String) = loadKtx(Paths.get(filename)) 21 | 22 | fun loadKtx(uri: URI) = loadKtx(Paths.get(uri)) 23 | 24 | /** Loads a texture storage_linear from KTX file. Returns an empty storage_linear in case of failure. 25 | * @param path Path of the file to open including filaname and filename extension */ 26 | fun loadKtx(path: Path): Texture { 27 | 28 | val buffer = FileChannel.open(path, StandardOpenOption.READ).use { channel -> 29 | Buffer(channel.size().i).also { 30 | while (channel.read(it) > 0); 31 | it.pos = 0 32 | it.order(ByteOrder.nativeOrder()) 33 | } 34 | } 35 | 36 | return loadKtx(buffer) 37 | } 38 | 39 | /** Loads a texture storage_linear from KTX memory. Returns an empty storage_linear in case of failure. 40 | * @param data buffer of the texture container data to read */ 41 | fun loadKtx(data: ByteBuffer): Texture { 42 | 43 | assert(data.rem >= ktx.Header10.size) 44 | 45 | // KTX10 46 | run { 47 | if (ktx.FOURCC_KTX10.all { it == data.get() }) 48 | return loadKtx10(data) 49 | } 50 | 51 | return Texture() 52 | } 53 | 54 | private fun loadKtx10(data: ByteBuffer): Texture { 55 | 56 | val header = ktx.Header10(data) 57 | 58 | // Skip key value data 59 | data.pos += header.bytesOfKeyValueData 60 | 61 | gl.profile = gl.Profile.KTX 62 | val format = gl.find( 63 | gl.InternalFormat.of(header.glInternalFormat), 64 | gl.ExternalFormat.of(header.glFormat), 65 | gl.TypeFormat.of(header.glType)) 66 | assert(format.isValid) 67 | 68 | val blockSize = format.blockSize 69 | 70 | val texture = Texture( 71 | target = header.target, 72 | format = format, 73 | extent = Vec3i( 74 | x = header.pixelWidth, 75 | y = glm.max(header.pixelHeight, 1), 76 | z = glm.max(header.pixelDepth, 1)), 77 | layers = glm.max(header.numberOfArrayElements, 1), 78 | faces = glm.max(header.numberOfFaces, 1), 79 | levels = glm.max(header.numberOfMipmapLevels, 1)) 80 | 81 | for (level in 0 until texture.levels()) { 82 | 83 | data.pos += Int.BYTES 84 | 85 | for (layer in 0 until texture.layers()) 86 | for (face in 0 until texture.faces()) { 87 | 88 | val faceSize = texture.size(level) 89 | val dst = texture.data(layer, face, level) 90 | memCopy(data.adr, dst.adr, faceSize) 91 | data.pos += glm.max(blockSize, glm.ceilMultiple(faceSize, 4)) 92 | } 93 | } 94 | return texture 95 | } 96 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/Texture1d.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.glm 4 | import glm_.vec1.Vec1i 5 | import glm_.vec3.Vec3i 6 | import kotlin.reflect.KClass 7 | 8 | /** 9 | * Created by GBarbieri on 04.04.2017. 10 | */ 11 | 12 | /** 1d texture */ 13 | class Texture1d : Texture { 14 | 15 | /** Create an empty texture 1D */ 16 | constructor() : super() 17 | 18 | /** Create a texture1d and allocate a new storage_linear */ 19 | constructor( 20 | format: Format, 21 | extent: Vec1i, 22 | levels: Int, 23 | swizzles: Swizzles = Swizzles() 24 | ) : 25 | super(Target._1D, format, Vec3i(extent.x, 1, 1), 1, 1, levels, swizzles) 26 | 27 | /** vec3i extend */ 28 | constructor( 29 | format: Format, 30 | extent: Vec3i, 31 | levels: Int, 32 | swizzles: Swizzles = Swizzles() 33 | ) : 34 | super(Target._1D, format, extent, 1, 1, levels, swizzles) 35 | 36 | /** Create a texture1d and allocate a new storage_linear */ 37 | constructor( 38 | format: Format, 39 | extent: Vec1i, 40 | swizzles: Swizzles = Swizzles() 41 | ) : 42 | super(Target._1D, format, Vec3i(extent.x, 1, 1), 1, 1, glm.levels(extent), swizzles) 43 | 44 | /** Create a texture1d view with an existing storage_linear */ 45 | constructor( 46 | texture: Texture 47 | ) : 48 | super(texture, Target._1D, texture.format) 49 | 50 | /** Create a texture1d view with an existing storage_linear */ 51 | constructor( 52 | texture: Texture, 53 | format: Format, 54 | baseLayer: Int, maxLayer: Int, 55 | baseFace: Int, maxFace: Int, 56 | baseLevel: Int, maxLevel: Int, 57 | swizzles: Swizzles = Swizzles() 58 | ) : 59 | super(texture, Target._1D, format, baseLayer, maxLayer, baseFace, maxFace, baseLevel, maxLevel, swizzles) 60 | 61 | /** Create a texture1d view, reference a subset of an existing texture1d instance */ 62 | constructor( 63 | texture: Texture, 64 | baseLevel: Int, maxLevel: Int 65 | ) : 66 | super(texture, Target._1D, texture.format, 67 | texture.baseLayer, texture.maxLayer, 68 | texture.baseFace, texture.maxFace, 69 | texture.baseLevel + baseLevel, texture.baseLevel + maxLevel) 70 | 71 | /** for duplicate */ 72 | constructor(format: Format, extent: Vec3i, layers: Int, faces: Int, levels: Int, swizzles: Swizzles = Swizzles()) : 73 | super(Target._1D, format, extent, layers, faces, levels, swizzles) 74 | 75 | /** Create a view of the image identified by Level in the mipmap chain of the texture. */ 76 | operator fun get(level: Int): Image { 77 | assert(level < levels()) 78 | return Image(storage!!, format, baseLayer, baseFace, baseLevel + level) 79 | } 80 | 81 | fun extent_(level: Int = 0) = Vec1i(super.extent(level)) 82 | 83 | internal inline fun load(texelCoord: Vec1i, level: Int): T = super.load(Vec3i(texelCoord.x, 0, 0), 0, 0, level) 84 | fun load(kClass: KClass<*>, texelCoord: Vec1i, level: Int): T = super.load(kClass, Vec3i(texelCoord.x, 0, 0), 0, 0, level) 85 | internal inline fun store(texelCoord: Vec1i, level: Int, texel: T) = super.store(T::class, Vec3i(texelCoord.x, 0, 0), 0, 0, level, texel) 86 | fun store(kClass: KClass<*>, texelCoord: Vec1i, level: Int, texel: T) = super.store(kClass, Vec3i(texelCoord.x, 0, 0), 0, 0, level, texel) 87 | } -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: [ push ] 4 | 5 | jobs: 6 | 7 | linux: 8 | name: 'Linux' 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v3 13 | - uses: gradle/wrapper-validation-action@v1 14 | - name: Set up JDK 1.8 15 | uses: actions/setup-java@v3 16 | with: 17 | distribution: temurin 18 | java-version: 8 19 | - name: Grant execute permission for gradlew 20 | run: chmod +x gradlew 21 | # - name: Build with Gradle 22 | # run: ./gradlew build -x dokkaHtml -x dokkaHtmlJar 23 | - uses: burrunan/gradle-cache-action@v1 24 | name: Build 25 | with: 26 | arguments: assemble #-x dokkaHtml -x dokkaHtmlJar -x javadoc -x dokkaJavadocJar 27 | # - name: Cleanup Gradle Cache 28 | # # Remove some files from the Gradle cache, so they aren't cached by GitHub Actions. 29 | # # Restoring these files from a GitHub Actions cache might cause problems for future builds. 30 | # run: | 31 | # rm -f ~/.gradle/caches/modules-2/modules-2.lock 32 | # rm -f ~/.gradle/caches/modules-2/gc.properties 33 | # - name: Show Working directory content 34 | # run: ls 35 | # - uses: actions/checkout@master 36 | # with: 37 | # repository: kotlin-graphics/mary 38 | # path: ./mary 39 | - name: Show ../.. directory content 40 | run: ls ../.. 41 | # - name: move mary up 42 | # run: mv ./mary ../.. 43 | # - name: Show Working directory content 44 | # run: ls 45 | # - name: Show ../.. directory content 46 | # run: ls ../.. 47 | 48 | windows: 49 | name: 'Windows' 50 | runs-on: windows-latest 51 | 52 | steps: 53 | - uses: actions/checkout@v3 54 | - uses: gradle/wrapper-validation-action@v1 55 | - name: Set up JDK 1.8 56 | uses: actions/setup-java@v3 57 | with: 58 | distribution: temurin 59 | java-version: 8 60 | # - name: Build with Gradle 61 | # run: .\gradlew.bat build -x dokkaHtml -x dokkaHtmlJar 62 | - uses: burrunan/gradle-cache-action@v1 63 | name: Build 64 | with: 65 | arguments: assemble #-x dokkaHtml -x dokkaHtmlJar -x javadoc -x dokkaJavadocJar 66 | # - name: Cleanup Gradle Cache 67 | # # Remove some files from the Gradle cache, so they aren't cached by GitHub Actions. 68 | # # Restoring these files from a GitHub Actions cache might cause problems for future builds. 69 | # run: | 70 | # rm -f ~/.gradle/caches/modules-2/modules-2.lock 71 | # rm -f ~/.gradle/caches/modules-2/gc.properties 72 | 73 | mac: 74 | name: 'Mac OS' 75 | runs-on: macos-latest 76 | 77 | steps: 78 | - uses: actions/checkout@v3 79 | - uses: gradle/wrapper-validation-action@v1 80 | - name: Set up JDK 1.8 81 | uses: actions/setup-java@v3 82 | with: 83 | distribution: temurin 84 | java-version: 8 85 | - name: Grant execute permission for gradlew 86 | run: chmod +x gradlew 87 | # - name: Build with Gradle 88 | # run: ./gradlew build -x dokkaHtml -x dokkaHtmlJar 89 | - uses: burrunan/gradle-cache-action@v1 90 | name: Build 91 | with: 92 | arguments: assemble #-x dokkaHtml -x dokkaHtmlJar -x javadoc -x dokkaJavadocJar 93 | # - name: Cleanup Gradle Cache 94 | # # Remove some files from the Gradle cache, so they aren't cached by GitHub Actions. 95 | # # Restoring these files from a GitHub Actions cache might cause problems for future builds. 96 | # run: | 97 | # rm -f ~/.gradle/caches/modules-2/modules-2.lock 98 | # rm -f ~/.gradle/caches/modules-2/gc.properties 99 | -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreAddressing.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.vec3.Vec3i 4 | import io.kotest.matchers.shouldBe 5 | import io.kotest.core.spec.style.StringSpec 6 | 7 | class coreAddressing : StringSpec() { 8 | 9 | init { 10 | 11 | "layers" { 12 | 13 | class Test(val dimensions: Vec3i, val format: Format, val baseOffset: Int, val size: Int) 14 | 15 | val tests = arrayOf( 16 | Test(Vec3i(4, 4, 1), Format.RGBA8_UINT_PACK8, 64, 128), 17 | Test(Vec3i(4, 4, 1), Format.RGB16_SFLOAT_PACK16, 96, 192), 18 | Test(Vec3i(4, 4, 1), Format.RGBA32_SFLOAT_PACK32, 256, 512), 19 | Test(Vec3i(4, 4, 1), Format.RGBA_DXT1_UNORM_BLOCK8, 8, 16), 20 | Test(Vec3i(8, 8, 1), Format.RGBA_DXT1_UNORM_BLOCK8, 32, 64), 21 | Test(Vec3i(4, 4, 1), Format.R_ATI1N_SNORM_BLOCK8, 8, 16)) 22 | 23 | for (test in tests) { 24 | 25 | val storage = Storage( 26 | format = test.format, 27 | extent = test.dimensions, 28 | layers = 2, 29 | faces = 1, 30 | levels = 1) 31 | 32 | val baseOffset = storage.baseOffset(1, 0, 0) 33 | val size = storage.size() 34 | 35 | baseOffset shouldBe test.baseOffset 36 | size shouldBe test.size 37 | } 38 | } 39 | 40 | "faces" { 41 | 42 | class Test(val format: Format, val level: Int, val baseOffset: Int, val size: Int) 43 | 44 | val tests = arrayOf( 45 | Test(Format.RGBA8_UINT_PACK8, 0, 0, 340), 46 | Test(Format.RGBA8_UINT_PACK8, 1, 256, 340), 47 | Test(Format.R8_UINT_PACK8, 1, 64, 85), 48 | Test(Format.RGBA8_UINT_PACK8, 3, 336, 340), 49 | Test(Format.RGBA32_SFLOAT_PACK32, 0, 0, 1360), 50 | Test(Format.RGBA32_SFLOAT_PACK32, 1, 1024, 1360), 51 | Test(Format.RGB_DXT1_UNORM_BLOCK8, 0, 0, 56), 52 | Test(Format.RGB_DXT1_UNORM_BLOCK8, 1, 32, 56), 53 | Test(Format.RGBA_DXT5_UNORM_BLOCK16, 1, 64, 112)) 54 | 55 | for (test in tests) { 56 | 57 | val storage = Storage( 58 | format = test.format, 59 | extent = Vec3i(8, 8, 1), 60 | layers = 1, 61 | faces = 1, 62 | levels = 4) 63 | 64 | val baseOffset = storage.baseOffset(0, 0, test.level) 65 | val size = storage.size() 66 | 67 | baseOffset shouldBe test.baseOffset 68 | size shouldBe test.size 69 | } 70 | } 71 | 72 | "levels" { 73 | 74 | class Test(val format: Format, val level: Int, val baseOffset: Int, val size: Int) 75 | 76 | val tests = arrayOf( 77 | Test(Format.RGBA8_UINT_PACK8, 0, 0, 340), 78 | Test(Format.RGBA8_UINT_PACK8, 1, 256, 340), 79 | Test(Format.RGBA8_UINT_PACK8, 3, 336, 340), 80 | Test(Format.RGBA32_SFLOAT_PACK32, 0, 0, 1360), 81 | Test(Format.RGBA32_SFLOAT_PACK32, 1, 1024, 1360), 82 | Test(Format.RGB_DXT1_UNORM_BLOCK8, 0, 0, 56), 83 | Test(Format.RGBA_DXT1_UNORM_BLOCK8, 1, 32, 56)) 84 | 85 | for (test in tests) { 86 | 87 | val storage = Storage( 88 | format = test.format, 89 | extent = Vec3i(8, 8, 1), 90 | layers = 1, 91 | faces = 1, 92 | levels = 4) 93 | 94 | val baseOffset = storage.baseOffset(0, 0, test.level) 95 | val size = storage.size() 96 | 97 | baseOffset shouldBe test.baseOffset 98 | size shouldBe test.size 99 | } 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreLoadDds.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import io.kotest.matchers.shouldBe 4 | import io.kotest.core.spec.style.StringSpec 5 | import java.nio.file.Files 6 | 7 | /** 8 | * Created by GBarbieri on 05.04.2017. 9 | */ 10 | 11 | class coreLoadDds : StringSpec() { 12 | 13 | init { 14 | 15 | "load dds" { 16 | 17 | class Params(val filename: String, val format: Format) 18 | 19 | fun load(params: Params) { 20 | 21 | val textureA = gli.loadDds(uriOf(params.filename)) 22 | textureA.format shouldBe params.format 23 | 24 | gli.saveDds(textureA, params.filename) 25 | val textureB = gli.loadDds(uriOf(params.filename)) 26 | textureB.format shouldBe params.format 27 | Files.delete(pathOf(params.filename)) 28 | 29 | textureA shouldBe textureB 30 | } 31 | 32 | val params = listOf( 33 | Params("kueken7_bgrx8_unorm.dds", Format.BGR8_UNORM_PACK32), 34 | Params("kueken7_rgba_dxt5_unorm1.dds", Format.RGBA_DXT5_UNORM_BLOCK16), 35 | Params("kueken7_rgba_dxt5_unorm2.dds", Format.RGBA_DXT5_UNORM_BLOCK16), 36 | Params("array_r8_uint.dds", Format.R8_UINT_PACK8), 37 | Params("kueken7_rgba_astc4x4_srgb.dds", Format.RGBA_ASTC_4X4_SRGB_BLOCK16), 38 | Params("kueken7_bgra8_srgb.dds", Format.BGRA8_SRGB_PACK8), 39 | Params("kueken7_r16_unorm.dds", Format.R16_UINT_PACK16), 40 | Params("kueken7_r8_sint.dds", Format.R8_SINT_PACK8), 41 | Params("kueken7_r8_uint.dds", Format.R8_UINT_PACK8), 42 | Params("kueken7_rgba4_unorm.dds", Format.BGRA4_UNORM_PACK16), 43 | Params("kueken7_r5g6b5_unorm.dds", Format.B5G6R5_UNORM_PACK16), 44 | Params("kueken7_rgb5a1_unorm.dds", Format.BGR5A1_UNORM_PACK16), 45 | Params("kueken7_rgba_dxt1_unorm.dds", Format.RGBA_DXT1_UNORM_BLOCK8), 46 | Params("kueken7_rgba_dxt1_srgb.dds", Format.RGBA_DXT1_SRGB_BLOCK8), 47 | Params("kueken8_rgba_dxt1_unorm.dds", Format.RGBA_DXT1_UNORM_BLOCK8), 48 | Params("kueken7_rgba_dxt5_unorm.dds", Format.RGBA_DXT5_UNORM_BLOCK16), 49 | Params("kueken7_rgba_dxt5_srgb.dds", Format.RGBA_DXT5_SRGB_BLOCK16), 50 | Params("kueken7_rgb_etc1_unorm.dds", Format.RGB_ETC_UNORM_BLOCK8), 51 | Params("kueken7_rgb_atc_unorm.dds", Format.RGB_ATC_UNORM_BLOCK8), 52 | Params("kueken7_rgba_atc_explicit_unorm.dds", Format.RGBA_ATCA_UNORM_BLOCK16), 53 | Params("kueken7_rgba_atc_interpolate_unorm.dds", Format.RGBA_ATCI_UNORM_BLOCK16), 54 | Params("kueken7_rgb_pvrtc_2bpp_unorm.dds", Format.RGB_PVRTC1_16X8_UNORM_BLOCK32), 55 | Params("kueken7_rgb_pvrtc_4bpp_unorm.dds", Format.RGB_PVRTC1_8X8_UNORM_BLOCK32), 56 | Params("kueken7_r_ati1n_unorm.dds", Format.R_ATI1N_UNORM_BLOCK8), 57 | Params("kueken7_rg_ati2n_unorm.dds", Format.RG_ATI2N_UNORM_BLOCK16), 58 | Params("kueken7_bgr8_unorm.dds", Format.BGR8_UNORM_PACK8), 59 | Params("kueken7_rgba8_srgb.dds", Format.RGBA8_SRGB_PACK8), 60 | Params("kueken7_bgra8_unorm.dds", Format.BGRA8_UNORM_PACK8), 61 | Params("kueken7_a8_unorm.dds", Format.A8_UNORM_PACK8), 62 | Params("kueken7_l8_unorm.dds", Format.L8_UNORM_PACK8), 63 | Params("kueken7_rgb10a2_unorm.dds", Format.RGB10A2_UNORM_PACK32), 64 | Params("kueken7_rgb10a2u.dds", Format.RGB10A2_UINT_PACK32), 65 | Params("kueken7_rgba8_snorm.dds", Format.RGBA8_SNORM_PACK8), 66 | Params("kueken7_rgba16_sfloat.dds", Format.RGBA16_SFLOAT_PACK16), 67 | Params("kueken7_rg11b10_ufloat.dds", Format.RG11B10_UFLOAT_PACK32), 68 | Params("kueken7_rgb9e5_ufloat.dds", Format.RGB9E5_UFLOAT_PACK32) 69 | ) 70 | 71 | params.forEach { load(it) } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/java,gradle,intellij,kotlin 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=java,gradle,intellij,kotlin 3 | 4 | ### Intellij ### 5 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 6 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 7 | 8 | # User-specific stuff 9 | .idea/**/workspace.xml 10 | .idea/**/tasks.xml 11 | .idea/**/usage.statistics.xml 12 | .idea/**/dictionaries 13 | .idea/**/shelf 14 | 15 | # Generated files 16 | .idea/**/contentModel.xml 17 | 18 | # Sensitive or high-churn files 19 | .idea/**/dataSources/ 20 | .idea/**/dataSources.ids 21 | .idea/**/dataSources.local.xml 22 | .idea/**/sqlDataSources.xml 23 | .idea/**/dynamic.xml 24 | .idea/**/uiDesigner.xml 25 | .idea/**/dbnavigator.xml 26 | 27 | # Gradle 28 | .idea/**/gradle.xml 29 | .idea/**/libraries 30 | 31 | # Gradle and Maven with auto-import 32 | # When using Gradle or Maven with auto-import, you should exclude module files, 33 | # since they will be recreated, and may cause churn. Uncomment if using 34 | # auto-import. 35 | .idea/artifacts 36 | .idea/compiler.xml 37 | .idea/jarRepositories.xml 38 | .idea/modules.xml 39 | .idea/*.iml 40 | .idea/modules 41 | *.iml 42 | *.ipr 43 | 44 | # CMake 45 | cmake-build-*/ 46 | 47 | # Mongo Explorer plugin 48 | .idea/**/mongoSettings.xml 49 | 50 | # File-based project format 51 | *.iws 52 | 53 | # IntelliJ 54 | out/ 55 | 56 | # mpeltonen/sbt-idea plugin 57 | .idea_modules/ 58 | 59 | # JIRA plugin 60 | atlassian-ide-plugin.xml 61 | 62 | # Cursive Clojure plugin 63 | .idea/replstate.xml 64 | 65 | # Crashlytics plugin (for Android Studio and IntelliJ) 66 | com_crashlytics_export_strings.xml 67 | crashlytics.properties 68 | crashlytics-build.properties 69 | fabric.properties 70 | 71 | # Editor-based Rest Client 72 | .idea/httpRequests 73 | 74 | # Android studio 3.1+ serialized cache file 75 | .idea/caches/build_file_checksums.ser 76 | 77 | ### Intellij Patch ### 78 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 79 | 80 | # *.iml 81 | # modules.xml 82 | # .idea/misc.xml 83 | # *.ipr 84 | 85 | # Sonarlint plugin 86 | # https://plugins.jetbrains.com/plugin/7973-sonarlint 87 | .idea/**/sonarlint/ 88 | 89 | # SonarQube Plugin 90 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin 91 | .idea/**/sonarIssues.xml 92 | 93 | # Markdown Navigator plugin 94 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced 95 | .idea/**/markdown-navigator.xml 96 | .idea/**/markdown-navigator-enh.xml 97 | .idea/**/markdown-navigator/ 98 | 99 | # Cache file creation bug 100 | # See https://youtrack.jetbrains.com/issue/JBR-2257 101 | .idea/$CACHE_FILE$ 102 | 103 | # CodeStream plugin 104 | # https://plugins.jetbrains.com/plugin/12206-codestream 105 | .idea/codestream.xml 106 | 107 | ### Java ### 108 | # Compiled class file 109 | *.class 110 | 111 | # Log file 112 | *.log 113 | 114 | # BlueJ files 115 | *.ctxt 116 | 117 | # Mobile Tools for Java (J2ME) 118 | .mtj.tmp/ 119 | 120 | # Package Files # 121 | *.jar 122 | *.war 123 | *.nar 124 | *.ear 125 | *.zip 126 | *.tar.gz 127 | *.rar 128 | 129 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 130 | hs_err_pid* 131 | 132 | ### Kotlin ### 133 | # Compiled class file 134 | 135 | # Log file 136 | 137 | # BlueJ files 138 | 139 | # Mobile Tools for Java (J2ME) 140 | 141 | # Package Files # 142 | 143 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 144 | 145 | ### Gradle ### 146 | .gradle 147 | build/ 148 | 149 | # Ignore Gradle GUI config 150 | gradle-app.setting 151 | 152 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 153 | !gradle-wrapper.jar 154 | 155 | # Cache of project 156 | .gradletasknamecache 157 | 158 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 159 | # gradle/wrapper/gradle-wrapper.properties 160 | 161 | ### Gradle Patch ### 162 | **/build/ 163 | 164 | # End of https://www.toptal.com/developers/gitignore/api/java,gradle,intellij,kotlin -------------------------------------------------------------------------------- /src/main/kotlin/gli_/saveKtx.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.BYTES 4 | import glm_.glm 5 | import kool.* 6 | import java.nio.channels.FileChannel 7 | import java.nio.file.Path 8 | import java.nio.file.StandardOpenOption 9 | 10 | interface saveKtx { 11 | 12 | /** Save a texture storage_linear to a KTX file. 13 | * @param texture Source texture to save 14 | * @param path Path for where to save the file. It must include the filaname and filename extension. 15 | * This function ignores the filename extension in the path and save to KTX anyway but keep the requested 16 | * filename extension. 17 | * @return Returns false if the function fails to save the file. */ 18 | fun saveKtx(texture: Texture, path: Path): Boolean { 19 | 20 | if (texture.empty()) return false 21 | 22 | gl.profile = gl.Profile.KTX 23 | val format = gl.translate(texture.format, texture.swizzles) 24 | val target = texture.target 25 | 26 | val desc = texture.format.formatInfo 27 | 28 | val data = Buffer(computeKtxStorageSize(texture)) 29 | 30 | ktx.FOURCC_KTX10.forEach{ data.put(it) } 31 | 32 | ktx.Header10().apply { 33 | 34 | endianness = 0x04030201 35 | glType = format.type.i 36 | glTypeSize = if (format.type == gl.TypeFormat.NONE) 1 else desc.blockSize 37 | glFormat = format.external.i 38 | glInternalFormat = format.internal.i 39 | glBaseInternalFormat = format.external.i 40 | pixelWidth = texture.extent().x 41 | pixelHeight = if (!target.isTarget1d) texture.extent().y else 0 42 | pixelDepth = if (target == Target._3D) texture.extent().z else 0 43 | numberOfArrayElements = if (target.isTargetArray) texture.layers() else 0 44 | numberOfFaces = if (target.isTargetCube) texture.faces() else 1 45 | numberOfMipmapLevels = texture.levels() 46 | bytesOfKeyValueData = 0 47 | 48 | to(data) 49 | } 50 | 51 | for (level in 0 until texture.levels()) { 52 | 53 | var imageSize = data.pos 54 | data.pos += Int.BYTES 55 | 56 | for (layer in 0 until texture.layers()) 57 | for (face in 0 until texture.faces()) { 58 | 59 | val faceSize = texture.size(level) 60 | 61 | memCopy(texture.data(layer, face, level).adr, data.adr, faceSize) 62 | 63 | val paddedSize = glm.ceilMultiple(faceSize, 4) 64 | 65 | imageSize += paddedSize 66 | data.pos += paddedSize 67 | 68 | assert(data.pos <= data.cap) 69 | } 70 | 71 | imageSize = glm.ceilMultiple(imageSize, 4) 72 | } 73 | 74 | FileChannel.open(path, StandardOpenOption.CREATE, StandardOpenOption.WRITE).use { 75 | data.pos = 0 76 | while (data.hasRemaining()) it.write(data) 77 | } 78 | 79 | data.free() 80 | 81 | return true 82 | } 83 | 84 | /** Save a texture storage_linear to a KTX file. 85 | * @param texture Source texture to save 86 | * @param filename String for where to save the file. It must include the filaname and filename extension. 87 | * This function ignores the filename extension in the path and save to KTX anyway but keep the requested 88 | * filename extension. 89 | * @return Returns false if the function fails to save the file. */ 90 | fun saveKtx(texture: Texture, filename: String) = saveKtx(texture, pathOf(filename)) 91 | 92 | fun computeKtxStorageSize(texture: Texture): Int { 93 | 94 | val blockSize = texture.format.blockSize 95 | var totalSize = ktx.FOURCC_KTX10.size + ktx.Header10.size 96 | 97 | for (level in 0 until texture.levels()) { 98 | 99 | totalSize += Int.BYTES 100 | 101 | for (layer in 0 until texture.layers()) 102 | for (face in 0 until texture.faces()) { 103 | 104 | val faceSize = texture.size(level) 105 | val paddedSize = glm.max(blockSize, glm.ceilMultiple(faceSize, 4)) 106 | 107 | totalSize += paddedSize 108 | } 109 | } 110 | return totalSize 111 | } 112 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreSave.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.vec1.Vec1b 4 | import glm_.vec2.Vec2b 5 | import glm_.vec2.Vec2i 6 | import glm_.vec3.Vec3b 7 | import glm_.vec4.Vec4b 8 | import io.kotest.matchers.shouldBe 9 | import io.kotest.core.spec.style.StringSpec 10 | import java.nio.file.Files 11 | 12 | class coreSave : StringSpec() { 13 | 14 | init { 15 | 16 | "l8 unorm" { 17 | 18 | val texture = Texture2d(Format.L8_UNORM_PACK8, Vec2i(4)) 19 | texture clear Vec1b(127) 20 | 21 | val dds = "orange_l8_unorm.dds" 22 | gli.save(texture, dds) 23 | val textureL8unormDDS = gli.load(dds) 24 | Files.delete(pathOf(dds)) 25 | 26 | val ktx = "orange_l8_unorm.ktx" 27 | gli.save(texture, ktx) 28 | val textureL8unormKTX = gli.load(ktx) 29 | Files.delete(pathOf(ktx)) 30 | 31 | texture shouldBe textureL8unormDDS 32 | texture shouldBe textureL8unormKTX 33 | textureL8unormDDS shouldBe textureL8unormKTX 34 | } 35 | 36 | "la8 unorm" { 37 | 38 | val texture = Texture2d(Format.LA8_UNORM_PACK8, Vec2i(4)) 39 | texture clear Vec2b(255, 127) 40 | 41 | val dds = "orange_la8_unorm.dds" 42 | gli.save(texture, dds) 43 | val textureLA8unormDDS = gli.load(dds) 44 | Files.delete(pathOf(dds)) 45 | 46 | val ktx = "orange_la8_unorm.ktx" 47 | gli.save(texture, ktx) 48 | val textureLA8unormKTX = gli.load(ktx) 49 | Files.delete(pathOf(ktx)) 50 | 51 | texture shouldBe textureLA8unormDDS 52 | texture shouldBe textureLA8unormKTX 53 | textureLA8unormDDS shouldBe textureLA8unormKTX 54 | } 55 | 56 | "rgba8 unorm" { 57 | 58 | val texture = Texture2d(Format.RGBA8_UNORM_PACK8, Vec2i(4)) 59 | texture clear Vec4b(255, 127, 0, 255) 60 | 61 | val dds = "orange_rgba8_unorm.dds" 62 | gli.save(texture, dds) 63 | val textureRGBA8unormDDS = gli.load(dds) 64 | Files.delete(pathOf(dds)) 65 | 66 | val ktx = "orange_rgba8_unorm.ktx" 67 | gli.save(texture, ktx) 68 | val textureRGBA8unormKTX = gli.load(ktx) 69 | Files.delete(pathOf(ktx)) 70 | 71 | texture shouldBe textureRGBA8unormDDS 72 | texture shouldBe textureRGBA8unormKTX 73 | textureRGBA8unormDDS shouldBe textureRGBA8unormKTX 74 | } 75 | 76 | "using ImageIO" { 77 | // without alpha 78 | run { 79 | val texture = Texture2d(Format.RGB8_UNORM_PACK8, Vec2i(4)) // no alpha, jpeg cant handle that 80 | texture clear Vec3b(255, 127, 255) 81 | 82 | // ico and bmp cant handle not 4 component images 83 | // icns and wbmp always fail 84 | val extensions = listOf(/*"bmp",*/ "gif", /*"ico",*/ /*"icns",*/ "iff", "jpeg", "jpg", 85 | "pam", "pbm", "pct", "pgm", "pict", "png", "pnm", "ppm", "targa", "tga", "tif", "tiff"/*, "wbmp"*/) 86 | 87 | for (ext in extensions) { 88 | val filename = "temp.$ext" 89 | gli.save(texture, filename) shouldBe true 90 | 91 | gli.load(filename) 92 | 93 | Files.delete(pathOf(filename)) 94 | } 95 | } 96 | // with alpha 97 | run { 98 | val texture = Texture2d(Format.RGBA8_UNORM_PACK8, Vec2i(4)) 99 | texture clear Vec4b(255, 127, 255, 255) 100 | 101 | // jpeg cant handle transparency, 102 | // icns, targa and wbmp always fail 103 | val extensions = listOf("bmp", "gif", "ico", /*"icns",*/ "iff", /*"jpeg", "jpg",*/ 104 | "pam", /*"pbm",*/ "pct", /*"pgm",*/ "pict", "png", /*"pnm", "ppm", "targa", "tga",*/ "tif", "tiff"/*, "wbmp"*/) 105 | 106 | for (ext in extensions) { 107 | val filename = "temp.$ext" 108 | gli.save(texture, filename) shouldBe true 109 | 110 | gli.load(filename) 111 | 112 | Files.delete(pathOf(filename)) 113 | } 114 | } 115 | } 116 | } 117 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/ByteBufferBackedInputStream.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import java.io.* 4 | import java.nio.* 5 | 6 | class ByteBufferBackedInputStream(val buf: ByteBuffer) : InputStream() { 7 | 8 | /** 9 | * Reads the next byte of data from the input stream. The value byte is 10 | * returned as an int in the range 0 to 11 | * 255. If no byte is available because the end of the stream 12 | * has been reached, the value -1 is returned. This method 13 | * blocks until input data is available, the end of the stream is detected, 14 | * or an exception is thrown. 15 | * 16 | *

A subclass must provide an implementation of this method. 17 | * 18 | * @return the next byte of data, or -1 if the end of the 19 | * stream is reached. 20 | * @exception IOException if an I/O error occurs. 21 | */ 22 | override fun read(): Int { 23 | return if (!buf.hasRemaining()) { 24 | -1 25 | } else buf.get().toInt() and 0xFF 26 | } 27 | 28 | /** 29 | * Reads up to len bytes of data from the input stream into 30 | * an array of bytes. An attempt is made to read as many as 31 | * len bytes, but a smaller number may be read. 32 | * The number of bytes actually read is returned as an integer. 33 | * 34 | *

This method blocks until input data is available, end of file is 35 | * detected, or an exception is thrown. 36 | * 37 | *

If len is zero, then no bytes are read and 38 | * 0 is returned; otherwise, there is an attempt to read at 39 | * least one byte. If no byte is available because the stream is at end of 40 | * file, the value -1 is returned; otherwise, at least one 41 | * byte is read and stored into b. 42 | * 43 | *

The first byte read is stored into element b[off], the 44 | * next one into b[off+1], and so on. The number of bytes read 45 | * is, at most, equal to len. Let k be the number of 46 | * bytes actually read; these bytes will be stored in elements 47 | * b[off] through b[off+k-1], 48 | * leaving elements b[off+k] through 49 | * b[off+len-1] unaffected. 50 | * 51 | *

In every case, elements b[0] through 52 | * b[off] and elements b[off+len] through 53 | * b[b.length-1] are unaffected. 54 | * 55 | *

The read(b, off, len) method 56 | * for class InputStream simply calls the method 57 | * read() repeatedly. If the first such call results in an 58 | * IOException, that exception is returned from the call to 59 | * the read(b, off, len) method. If 60 | * any subsequent call to read() results in a 61 | * IOException, the exception is caught and treated as if it 62 | * were end of file; the bytes read up to that point are stored into 63 | * b and the number of bytes read before the exception 64 | * occurred is returned. The default implementation of this method blocks 65 | * until the requested amount of input data len has been read, 66 | * end of file is detected, or an exception is thrown. Subclasses are encouraged 67 | * to provide a more efficient implementation of this method. 68 | * 69 | * @param off the start offset in array b 70 | * at which the data is written. 71 | * @param len the maximum number of bytes to read. 72 | * @return the total number of bytes read into the buffer, or 73 | * -1 if there is no more data because the end of 74 | * the stream has been reached. 75 | * @exception IOException If the first byte cannot be read for any reason 76 | * other than end of file, or if the input stream has been closed, or if 77 | * some other I/O error occurs. 78 | * @exception NullPointerException If b is null. 79 | * @exception IndexOutOfBoundsException If off is negative, 80 | * len is negative, or len is greater than 81 | * b.length - off 82 | * @see java.io.InputStream#read() 83 | */ 84 | override fun read(bytes: ByteArray, off: Int, len: Int): Int { 85 | @Suppress("NAME_SHADOWING") 86 | var len = len 87 | if (!buf.hasRemaining()) { 88 | return -1 89 | } 90 | 91 | len = Math.min(len, buf.remaining()) 92 | buf.get(bytes, off, len) 93 | return len 94 | } 95 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/testCopySub.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.b 4 | import glm_.vec2.Vec2i 5 | import glm_.vec3.Vec3 6 | import glm_.vec3.Vec3i 7 | import glm_.vec4.Vec4ub 8 | import io.kotest.matchers.shouldBe 9 | import io.kotest.matchers.shouldNotBe 10 | import io.kotest.core.spec.style.StringSpec 11 | 12 | class testCopySub : StringSpec() { 13 | 14 | init { 15 | 16 | "sub copy" { 17 | 18 | val source = Texture2d(Format.R8_UNORM_PACK8, Vec2i(4), 1) 19 | source clear 0.b 20 | source.store(Vec2i(1, 1), 0, 1.b) 21 | source.store(Vec2i(2, 1), 0, 2.b) 22 | source.store(Vec2i(2, 2), 0, 3.b) 23 | source.store(Vec2i(1, 2), 0, 4.b) 24 | 25 | val destination = Texture2d(source.format, source.extent_(), source.levels()) 26 | destination clear 255.b 27 | 28 | destination.copy(source, 0, 0, 0, Vec3i(1, 1, 0), 0, 0, 0, 29 | Vec3i(1, 1, 0), Vec3i(2, 2, 1)) 30 | for (indexY in 1..2) 31 | for (indexX in 1..2) 32 | source.load(Vec2i(indexX, indexY), 0) shouldBe destination.load(Vec2i(indexX, indexY), 0) 33 | } 34 | 35 | "sub copy2" { 36 | 37 | val source = Texture2d(Format.R8_UNORM_PACK8, Vec2i(5, 4), 1) 38 | source clear 0.b 39 | source.store(Vec2i(1, 1), 0, 1.b) 40 | source.store(Vec2i(2, 1), 0, 2.b) 41 | source.store(Vec2i(2, 2), 0, 3.b) 42 | source.store(Vec2i(1, 2), 0, 4.b) 43 | 44 | val destination = Texture2d(source.format, source.extent_(), source.levels()) 45 | destination clear 255.b 46 | 47 | destination.copy(source, 0, 0, 0, Vec3i(1, 1, 0), 0, 0, 0, 48 | Vec3i(1, 1, 0), Vec3i(2, 2, 1)) 49 | for (indexY in 0 until source.extent().y) 50 | for (indexX in 0 until source.extent().x) { 51 | val texelCoord = Vec2i(indexX, indexY) 52 | val texelSrc = source.load(texelCoord, 0) 53 | val texelDst = destination.load(texelCoord, 0) 54 | (texelSrc == texelDst || (texelSrc == 0.b && texelDst == 255.b)) shouldBe true 55 | } 56 | } 57 | 58 | "sub copy rgb32f" { 59 | 60 | val source = Texture2d(Format.RGB32_SFLOAT_PACK32, Vec2i(4, 2), 1) 61 | for (texelIndex in 0 until source.size()) 62 | source.data()[texelIndex] = Vec3(texelIndex + 1) 63 | 64 | val destination = Texture2d(source.format, source.extent_(), source.levels()) 65 | destination clear Vec3(255) 66 | 67 | destination.copy(source, 0, 0, 0, Vec3i(1, 1, 0), 0, 0, 0, 68 | Vec3i(1, 1, 0), Vec3i(2, 1, 1)) 69 | for (indexY in 0 until source.extent().y) 70 | for (indexX in 0 until source.extent().x) { 71 | val texelCoord = Vec2i(indexX, indexY) 72 | val texelSrc = source.load(texelCoord, 0) 73 | val texelDst = destination.load(texelCoord, 0) 74 | (texelSrc == texelDst || (/*texelSrc == gli::u8vec4(0) &&*/ texelDst == Vec3(255))) shouldBe true 75 | } 76 | } 77 | 78 | "sub copy rgba8" { 79 | 80 | val source = Texture2d(Format.RGBA8_UNORM_PACK8, Vec2i(4, 2), 1) 81 | for (texelIndex in 0 until source.size()) 82 | source.data()[texelIndex] = Vec4ub(texelIndex + 1) 83 | 84 | val destination = Texture2d(source.format, source.extent_(), source.levels()) 85 | destination clear Vec4ub(255) 86 | 87 | destination.copy(source, 0, 0, 0, Vec3i(1, 1, 0), 0, 0, 0, 88 | Vec3i(1, 1, 0), Vec3i(2, 1, 1)) 89 | for (indexY in 0 until source.extent().y) 90 | for (indexX in 0 until source.extent().x) { 91 | val texelCoord = Vec2i(indexX, indexY) 92 | val texelSrc = source.load(texelCoord, 0) 93 | val texelDst = destination.load(texelCoord, 0) 94 | (texelSrc == texelDst || (/*texelSrc == gli::u8vec4(0) &&*/ texelDst == Vec4ub(255))) shouldBe true 95 | } 96 | } 97 | 98 | "sub clear rgba8" { 99 | 100 | val clear = Texture2d(Format.RGBA8_UNORM_PACK8, Vec2i(4, 2), 1) 101 | clear clear Vec4ub(0) 102 | 103 | val source = Texture2d(Format.RGBA8_UNORM_PACK8, Vec2i(4, 2), 1) 104 | source clear Vec4ub(0) 105 | source.clear(0, 0, 0, Vec3i(1, 1, 0), Vec3i(2, 1, 1), Vec4ub(255)) 106 | 107 | source shouldNotBe clear 108 | 109 | val destination = Texture2d(source.format, source.extent_(), source.levels()) 110 | destination clear Vec4ub(0) 111 | destination.copy(source, 0, 0, 0, Vec3i(1, 1, 0), 0, 0, 0, 112 | Vec3i(1, 1, 0), Vec3i(2, 1, 1)) 113 | 114 | destination shouldNotBe clear 115 | 116 | source shouldBe destination 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/coreLoad.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import io.kotest.matchers.shouldBe 4 | import io.kotest.core.spec.style.StringSpec 5 | import org.lwjgl.BufferUtils 6 | import java.io.FileInputStream 7 | import java.nio.ByteBuffer 8 | import java.nio.file.Files 9 | import java.nio.file.Paths 10 | 11 | 12 | class coreLoad : StringSpec() { 13 | 14 | init { 15 | 16 | "load" { 17 | 18 | class Params(val filename: String, val format: Format) 19 | 20 | fun loadFileKtx(params: Params) { 21 | 22 | val ktx = params.filename + ".ktx" 23 | val textureKTX = gli.load(uriOf(ktx)) 24 | textureKTX.format shouldBe params.format 25 | 26 | val dds = params.filename + ".dds" 27 | gli.save(textureKTX, dds) 28 | val textureSavedDDS = gli.load(dds) 29 | textureSavedDDS.format shouldBe params.format 30 | textureSavedDDS shouldBe textureKTX 31 | Files.delete(pathOf(dds)) 32 | 33 | gli.save(textureKTX, ktx) 34 | val textureSavedKTX = gli.load(ktx) 35 | textureSavedKTX.format shouldBe params.format 36 | textureSavedDDS shouldBe textureSavedKTX 37 | Files.delete(pathOf(ktx)) 38 | } 39 | 40 | fun loadFileKmg(params: Params) { 41 | 42 | val ktx = params.filename + ".ktx" 43 | val textureKTX = gli.load(uriOf(ktx)) 44 | textureKTX.format shouldBe params.format 45 | 46 | val kmg = params.filename + ".kmg" 47 | gli.save(textureKTX, kmg) 48 | val textureSavedKMG = gli.load(kmg) 49 | textureSavedKMG.format shouldBe params.format 50 | textureSavedKMG shouldBe textureKTX 51 | Files.delete(pathOf(kmg)) 52 | 53 | gli.save(textureKTX, ktx) 54 | val textureSavedKTX = gli.load(ktx) 55 | textureSavedKTX.format shouldBe params.format 56 | textureSavedKTX shouldBe textureKTX 57 | Files.delete(pathOf(ktx)) 58 | } 59 | 60 | fun loaFileDds(params: Params) { 61 | 62 | val dds = params.filename + ".dds" 63 | val textureDDS = gli.load(uriOf(dds)) 64 | textureDDS.format == params.format 65 | 66 | val kmg = params.filename + ".kmg" 67 | gli.save(textureDDS, kmg) 68 | val textureSavedKMG = gli.load(kmg) 69 | Files.delete(pathOf(kmg)) 70 | 71 | textureSavedKMG.format shouldBe params.format 72 | textureSavedKMG shouldBe textureDDS 73 | 74 | gli.save(textureDDS, dds) 75 | val textureSavedDDS = gli.load(dds) 76 | Files.delete(pathOf(dds)) 77 | 78 | textureSavedDDS.format shouldBe params.format 79 | textureSavedDDS shouldBe textureDDS 80 | } 81 | 82 | val params = listOf( 83 | Params("array_r8_uint", Format.R8_UINT_PACK8), 84 | Params("kueken7_rgba8_unorm", Format.RGBA8_UNORM_PACK8), 85 | Params("kueken7_rgba8_srgb", Format.RGBA8_SRGB_PACK8), 86 | Params("kueken7_bgra8_unorm", Format.BGRA8_UNORM_PACK8), 87 | Params("kueken7_bgra8_srgb", Format.BGRA8_SRGB_PACK8), 88 | Params("kueken7_r5g6b5_unorm", Format.B5G6R5_UNORM_PACK16), 89 | Params("kueken7_rgba4_unorm", Format.BGRA4_UNORM_PACK16), 90 | Params("kueken7_rgb5a1_unorm", Format.BGR5A1_UNORM_PACK16), 91 | Params("kueken8_rgba8_srgb", Format.RGBA8_SRGB_PACK8), 92 | Params("kueken7_rgba_dxt5_unorm", Format.RGBA_DXT5_UNORM_BLOCK16)) 93 | 94 | params.forEach { 95 | loadFileKtx(it) 96 | loadFileKmg(it) 97 | loaFileDds(it) 98 | } 99 | } 100 | 101 | "loadPng" { 102 | val filename = "kueken7_srgb8.png" 103 | 104 | gli.load(uriOf(filename)) 105 | } 106 | 107 | "loadTga" { 108 | val filename = "PlyonTexture.tga" 109 | 110 | gli.load(uriOf(filename)) 111 | } 112 | 113 | "loadJpg" { 114 | val files = listOf("kueken7_rgb8.jpg", "kueken7_srgb8.jpg", "kueken8_srgb8.jpg") 115 | for(file in files) { 116 | gli.load(uriOf(file)) 117 | } 118 | } 119 | 120 | "loadFromMemory" { 121 | val files = listOf("kueken7_srgb8.png", 122 | "kueken7_rgb8.jpg", 123 | "kueken7_srgb8.jpg", 124 | "kueken8_srgb8.jpg") 125 | 126 | for(file in files) { 127 | 128 | println("loading $file from mem") 129 | 130 | val uri = uriOf(file) 131 | val path = Paths.get(uri).toAbsolutePath().toString() 132 | 133 | val bytes = FileInputStream(path).use { it.readBytes() } 134 | val buffer = ByteBuffer.wrap(bytes) 135 | 136 | gli.load(buffer, file.substringAfterLast('.')) 137 | } 138 | } 139 | } 140 | } -------------------------------------------------------------------------------- /src/test/kotlin/gli_/make_texture.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.vec1.Vec1i 4 | import glm_.vec2.Vec2i 5 | import glm_.vec3.Vec3i 6 | import glm_.vec4.Vec4ub 7 | import io.kotest.matchers.shouldBe 8 | import io.kotest.core.spec.style.StringSpec 9 | 10 | class make_texture : StringSpec() { 11 | 12 | init { 13 | 14 | "is make_texture equivalent to ctor" { 15 | 16 | run { 17 | val textureA = gli.makeTexture1d(Format.RGBA8_UNORM_PACK8, Vec1i(4), 2) 18 | textureA clear Vec4ub(255, 127, 0, 255) 19 | 20 | val textureB = Texture1d(Format.RGBA8_UNORM_PACK8, Vec1i(4), 2) 21 | textureB clear Vec4ub(255, 127, 0, 255) 22 | 23 | val extentC = Vec3i(4, 1, 1) 24 | val textureC = Texture(Target._1D, Format.RGBA8_UNORM_PACK8, extentC, 1, 1, 2) 25 | textureC clear Vec4ub(255, 127, 0, 255) 26 | 27 | textureA shouldBe textureB 28 | textureA shouldBe textureC 29 | textureB shouldBe textureC 30 | } 31 | 32 | run { 33 | val textureA = gli.makeTexture1dArray(Format.RGBA8_UNORM_PACK8, Vec1i(4), 3, 2) 34 | textureA clear Vec4ub(255, 127, 0, 255) 35 | 36 | val textureB = Texture1dArray(Format.RGBA8_UNORM_PACK8, Vec1i(4), 3, 2) 37 | textureB clear Vec4ub(255, 127, 0, 255) 38 | 39 | val extentC = Vec3i(4, 1, 1) 40 | val textureC = Texture(Target._1D_ARRAY, Format.RGBA8_UNORM_PACK8, extentC, 3, 1, 2) 41 | textureC clear Vec4ub(255, 127, 0, 255) 42 | 43 | textureA shouldBe textureB 44 | textureA shouldBe textureC 45 | textureB shouldBe textureC 46 | } 47 | 48 | run { 49 | val textureA = gli.makeTexture2d(Format.RGBA8_UNORM_PACK8, Vec2i(4), 2) 50 | textureA clear Vec4ub(255, 127, 0, 255) 51 | 52 | val textureB = Texture2d(Format.RGBA8_UNORM_PACK8, Vec2i(4), 2) 53 | textureB clear Vec4ub(255, 127, 0, 255) 54 | 55 | val extentC = Vec3i(4, 4, 1) 56 | val textureC = Texture(Target._2D, Format.RGBA8_UNORM_PACK8, extentC, 1, 1, 2) 57 | textureC clear Vec4ub(255, 127, 0, 255) 58 | 59 | textureA shouldBe textureB 60 | textureA shouldBe textureC 61 | textureB shouldBe textureC 62 | } 63 | 64 | run { 65 | val textureA = gli.makeTexture2dArray(Format.RGBA8_UNORM_PACK8, Vec2i(4), 3, 2) 66 | textureA clear Vec4ub(255, 127, 0, 255) 67 | 68 | val textureB = Texture2dArray(Format.RGBA8_UNORM_PACK8, Vec2i(4), 3, 2) 69 | textureB clear Vec4ub(255, 127, 0, 255) 70 | 71 | val extentC = Vec3i(4, 4, 1) 72 | val textureC = Texture(Target._2D_ARRAY, Format.RGBA8_UNORM_PACK8, extentC, 3, 1, 2) 73 | textureC clear Vec4ub(255, 127, 0, 255) 74 | 75 | textureA shouldBe textureB 76 | textureA shouldBe textureC 77 | textureB shouldBe textureC 78 | } 79 | 80 | run { 81 | val textureA = gli.makeTexture3d(Format.RGBA8_UNORM_PACK8, Vec3i(4), 2) 82 | textureA clear Vec4ub(255, 127, 0, 255) 83 | 84 | val textureB = Texture3d(Format.RGBA8_UNORM_PACK8, Vec3i(4), 2) 85 | textureB clear Vec4ub(255, 127, 0, 255) 86 | 87 | val extentC = Vec3i(4) 88 | val textureC = Texture(Target._3D, Format.RGBA8_UNORM_PACK8, extentC, 1, 1, 2) 89 | textureC clear Vec4ub(255, 127, 0, 255) 90 | 91 | textureA shouldBe textureB 92 | textureA shouldBe textureC 93 | textureB shouldBe textureC 94 | } 95 | 96 | run { 97 | val textureA = gli.makeTextureCube(Format.RGBA8_UNORM_PACK8, Vec2i(4), 2) 98 | textureA clear Vec4ub(255, 127, 0, 255) 99 | 100 | val textureB = TextureCube(Format.RGBA8_UNORM_PACK8, Vec2i(4), 2) 101 | textureB clear Vec4ub(255, 127, 0, 255) 102 | 103 | val extentC = Vec3i(4, 4, 1) 104 | val textureC = Texture(Target.CUBE, Format.RGBA8_UNORM_PACK8, extentC, 1, 6, 2) 105 | textureC clear Vec4ub(255, 127, 0, 255) 106 | 107 | textureA shouldBe textureB 108 | textureA shouldBe textureC 109 | textureB shouldBe textureC 110 | } 111 | 112 | run { 113 | val textureA = gli.makeTextureCubeArray(Format.RGBA8_UNORM_PACK8, Vec2i(4), 3, 2) 114 | textureA clear Vec4ub(255, 127, 0, 255) 115 | 116 | val textureB = TextureCubeArray(Format.RGBA8_UNORM_PACK8, Vec2i(4), 3, 2) 117 | textureB clear Vec4ub(255, 127, 0, 255) 118 | 119 | val extentC = Vec3i(4, 4, 1) 120 | val textureC = Texture(Target.CUBE_ARRAY, Format.RGBA8_UNORM_PACK8, extentC, 3, 6, 2) 121 | textureC clear Vec4ub(255, 127, 0, 255) 122 | 123 | textureA shouldBe textureB 124 | textureA shouldBe textureC 125 | textureB shouldBe textureC 126 | } 127 | } 128 | } 129 | } -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save ( ) { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![gli](/src/main/resources/logo-mini.png) 2 | 3 | [![Build Status](https://github.com/kotlin-graphics/gli/workflows/build/badge.svg)](https://github.com/kotlin-graphics/gli/actions?workflow=build) 4 | [![license](https://img.shields.io/badge/License-MIT-orange.svg)](https://github.com/kotlin-graphics/gli/blob/master/LICENSE) 5 | [![Release](https://jitpack.io/v/kotlin-graphics/gli.svg)](https://jitpack.io/#kotlin-graphics/gli) 6 | ![Size](https://github-size-badge.herokuapp.com/kotlin-graphics/gli.svg) 7 | [![Github All Releases](https://img.shields.io/github/downloads/kotlin-graphics/gli/total.svg)]() 8 | [![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin) 9 | 10 | This is the Kotlin port of the original [OpenGL Image](http://gli.g-truc.net/) (*GLI*), written by [g-truc](https://github.com/Groovounet) ([repository](https://github.com/g-truc/gli)), a header only C++ image library for graphics software. 11 | 12 | *GLI* provides classes and functions to load image files, facilitate graphics APIs texture creation, compare textures, access texture texels, sample textures, convert textures, generate mipmaps, etc. 13 | 14 | This library works perfectly with *[OpenGL](https://www.opengl.org)* or *[Vulkan](https://www.khronos.org/vulkan)* but it also ensures interoperability with other third party libraries and SDK. 15 | It is a good candidate for software rendering (raytracing / rasterization), image processing, image based software testing or any development context that requires a simple and convenient image library. 16 | 17 | Don't hesitate to contribute to the project by submitting [issues](https://github.com/kotlin-graphics/gli/issues) or [pull requests](https://github.com/kotlin-graphics/gli/pulls) for bugs and features. Any feedback is welcome at [elect86@gmail.com](mailto://elect86@gmail.com). 18 | 19 | Kotlin: 20 | ```kotlin 21 | import gli_.gli 22 | 23 | fun createTexture(filename: String): Int { 24 | 25 | val texture = gli.load(filename) 26 | if(texture.empty()) 27 | return 0 28 | 29 | gli.gl.profile = gl.Profile.GL33 30 | val format = gli.gl.translate(texture.format, texture.swizzles) 31 | val target = gli.gl.translate(texture.target) 32 | assert(texture.format.isCompressed && target == gl.Target._2D) 33 | 34 | val textureName = intBufferBig(1) 35 | glGenTextures(textureName) 36 | glBindTexture(target.i, textureName[0]) 37 | glTexParameteri(target.i, GL_TEXTURE_BASE_LEVEL, 0) 38 | glTexParameteri(target.i, GL_TEXTURE_MAX_LEVEL, texture.levels() - 1) 39 | val swizzles = intBufferBig(4) 40 | format.swizzles to swizzles 41 | glTexParameteriv(target.i, GL_TEXTURE_SWIZZLE_RGBA, swizzles) 42 | var extent = texture.extent() 43 | glTexStorage2D(target.i, texture.levels(), format.internal.i, extent.x, extent.y) 44 | for(level in 0 until texture.levels()) { 45 | extent = texture.extent(level) 46 | glCompressedTexSubImage2D( 47 | target.i, level, 0, 0, extent.x, extent.y, 48 | format.internal.i, texture.data(0, 0, level)) 49 | } 50 | val texName = textureName[0] 51 | textureName.free() 52 | return texName 53 | } 54 | ``` 55 | 56 | Kotlin with [gl-next](https://github.com/kotlin-graphics/gln): 57 | ```kotlin 58 | fun createTexture(filename: String): Int { 59 | 60 | val texture = gli.load(filename) 61 | if(texture.empty()) 62 | return 0 63 | 64 | gli.gl.profile = gl.Profile.GL33 65 | val (target, format) = gli.gl.translate(texture) 66 | assert(texture.format.isCompressed && target == gl.Target._2D) 67 | 68 | return initTexture2d { 69 | levels = 0 until texture.levels() 70 | swizzles = format.swizzles 71 | storage(texture.levels(), format.internal, texture.extent()) 72 | levels.forEach { 73 | compressedSubImage(it, texture.extent(it), format.internal, texture.data(0, 0, it)) 74 | } 75 | } 76 | } 77 | ``` 78 | 79 | Java: 80 | ```java 81 | public static int createTexture(String filename) { 82 | 83 | Texture texture = gli.load(filename); 84 | if (texture.empty()) 85 | return 0; 86 | 87 | gli_.gli.gl.setProfile(gl.Profile.GL33); 88 | gl.Format format = gli_.gli.gl.translate(texture.getFormat(), texture.getSwizzles()); 89 | gl.Target target = gli_.gli.gl.translate(texture.getTarget()); 90 | assert (texture.getFormat().isCompressed() && target == gl.Target._2D); 91 | 92 | IntBuffer textureName = intBufferBig(1); 93 | glGenTextures(textureName); 94 | glBindTexture(target.getI(), textureName.get(0)); 95 | glTexParameteri(target.getI(), GL12.GL_TEXTURE_BASE_LEVEL, 0); 96 | glTexParameteri(target.getI(), GL12.GL_TEXTURE_MAX_LEVEL, texture.levels() - 1); 97 | IntBuffer swizzles = intBufferBig(4); 98 | texture.getSwizzles().to(swizzles); 99 | glTexParameteriv(target.getI(), GL33.GL_TEXTURE_SWIZZLE_RGBA, swizzles); 100 | Vec3i extent = texture.extent(0); 101 | glTexStorage2D(target.getI(), texture.levels(), format.getInternal().getI(), extent.x, extent.y); 102 | for (int level = 0; level < texture.levels(); level++) { 103 | extent = texture.extent(level); 104 | glCompressedTexSubImage2D( 105 | target.getI(), level, 0, 0, extent.x, extent.y, 106 | format.getInternal().getI(), texture.data(0, 0, level)); 107 | } 108 | int texName = textureName.get(0); 109 | MemoryUtil.memFree(textureName); 110 | return texName 111 | } 112 | ``` 113 | 114 | ### Supported Image Formats 115 | 116 | * [KTX](https://www.khronos.org/opengles/sdk/tools/KTX/) 117 | * [DDS](https://msdn.microsoft.com/en-us/library/windows/desktop/bb943990%28v=vs.85%29.aspx) 118 | * KMG 119 | * jpg 120 | * png 121 | * gif 122 | * bmp 123 | * tga 124 | 125 | 126 | ### How to retrieve it: 127 | 128 | ```kotlin 129 | repositories { 130 | maven("https://raw.githubusercontent.com/kotlin-graphics/mary/master") 131 | // or with magik plugin 132 | //github("kotlin-graphics/mary") 133 | } 134 | dependencies { 135 | implementation("kotlin.graphics:gli:0.8.3.0-20") 136 | } 137 | ``` 138 | 139 | You can find more info by [mary](https://github.com/kotlin-graphics/mary) -------------------------------------------------------------------------------- /src/main/kotlin/gli_/saveDds.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import gli_.detail.has 4 | import gli_.detail.or 5 | import gli_.dx.has 6 | import glm_.L 7 | import glm_.b 8 | import kool.* 9 | import java.nio.channels.FileChannel 10 | import java.nio.file.Path 11 | import java.nio.file.Paths 12 | import java.nio.file.StandardOpenOption 13 | 14 | interface saveDds { 15 | 16 | private fun getFourcc(requireDX10Header: Boolean, format: Format, dxFormat: dx.Format) = when { 17 | requireDX10Header -> when { 18 | format.formatInfo.flags has detail.Cap.DDS_GLI_EXT_BIT -> dx.D3dfmt.GLI1 19 | else -> dx.D3dfmt.DX10 20 | } 21 | else -> if (dxFormat.ddPixelFormat has dx.Ddpf.FOURCC) dxFormat.d3DFormat else dx.D3dfmt.UNKNOWN 22 | } 23 | 24 | 25 | fun getDimension(target: Target): Int { 26 | val table = arrayOf( 27 | detail.D3d10resourceDimension.TEXTURE1D, //TARGET_1D, 28 | detail.D3d10resourceDimension.TEXTURE1D, //TARGET_1D_ARRAY, 29 | detail.D3d10resourceDimension.TEXTURE2D, //TARGET_2D, 30 | detail.D3d10resourceDimension.TEXTURE2D, //TARGET_2D_ARRAY, 31 | detail.D3d10resourceDimension.TEXTURE3D, //TARGET_3D, 32 | detail.D3d10resourceDimension.TEXTURE2D, //TARGET_RECT, 33 | detail.D3d10resourceDimension.TEXTURE2D, //TARGET_RECT_ARRAY, 34 | detail.D3d10resourceDimension.TEXTURE2D, //TARGET_CUBE, 35 | detail.D3d10resourceDimension.TEXTURE2D //TARGET_CUBE_ARRAY 36 | ) 37 | assert(table.size == Target.COUNT) { "Table needs to be updated" } 38 | return table[target.i].i 39 | } 40 | 41 | /** Save a texture storage_linear to a DDS file. 42 | * @param texture Source texture to save 43 | * @param filename string for where to save the file. It must include the filaname and filename extension. 44 | * This function ignores the filename extension in the path and save to DDS anyway but keep the requested filename extension. 45 | * @return returns false if the function fails to save the file. */ 46 | fun saveDds(texture: Texture, filename: String): Boolean { 47 | 48 | if (texture.empty()) return false // TODO check combinations 49 | 50 | return saveDds(texture, Paths.get(filename)) 51 | } 52 | 53 | /** Save a texture storage_linear to a DDS file. 54 | * 55 | * @param texture Source texture to save 56 | * @param path path for where to save the file. It must include the filaname and filename extension. 57 | * This function ignores the filename extension in the path and save to DDS anyway but keep the requested filename extension. 58 | * @return Returns false if the function fails to save the file. */ 59 | fun saveDds(texture: Texture, path: Path): Boolean { 60 | 61 | if (texture.empty()) return false 62 | 63 | val dxFormat = dx.translate(texture.format) 64 | 65 | val requireDX10Header = dxFormat.d3DFormat == dx.D3dfmt.GLI1 || dxFormat.d3DFormat == dx.D3dfmt.DX10 || 66 | texture.target.isTargetArray || texture.target.isTarget1d 67 | 68 | var length = texture.size + detail.FOURCC_DDS.size + detail.DdsHeader.SIZE 69 | if (requireDX10Header) length += detail.DdsHeader10.SIZE 70 | val data = Buffer(length) 71 | 72 | detail.FOURCC_DDS.forEach { data.put(it.b) } 73 | 74 | val header = detail.DdsHeader() 75 | 76 | val desc = texture.format.formatInfo 77 | 78 | var caps = detail.DdsFlag.CAPS or detail.DdsFlag.WIDTH or detail.DdsFlag.PIXELFORMAT or detail.DdsFlag.MIPMAPCOUNT 79 | if (!texture.target.isTarget1d) 80 | caps = caps or detail.DdsFlag.HEIGHT 81 | if (texture.target == Target._3D) 82 | caps = caps or detail.DdsFlag.DEPTH 83 | //caps |= Storage.levels() > 1 ? detail::DDSD_MIPMAPCOUNT : 0; 84 | caps = caps or if (desc.flags has detail.Cap.COMPRESSED_BIT) detail.DdsFlag.LINEARSIZE else detail.DdsFlag.PITCH 85 | 86 | with(header) { 87 | size = detail.DdsHeader.SIZE 88 | flags = caps 89 | width = texture.extent().x 90 | height = texture.extent().y 91 | pitch = if (desc.flags has detail.Cap.COMPRESSED_BIT) texture.size / texture.faces() else 32 92 | depth = if (texture.extent().z > 1) texture.extent().z else 0 93 | mipMapLevels = texture.levels() 94 | with(format) { 95 | size = detail.DdsPixelFormat.SIZE 96 | flags = if (requireDX10Header) dx.Ddpf.FOURCC.i else dxFormat.ddPixelFormat.i 97 | fourCC = getFourcc(requireDX10Header, texture.format, dxFormat).i 98 | bpp = texture.format.bitsPerPixel 99 | mask = dxFormat.mask 100 | } 101 | //header.surfaceFlags = detail::DDSCAPS_TEXTURE | (Storage.levels() > 1 ? detail::DDSCAPS_MIPMAP : 0); 102 | surfaceFlags = detail.DdsSurfaceFlag.TEXTURE or detail.DdsSurfaceFlag.MIPMAP 103 | cubemapFlags = 0 104 | 105 | // Cubemap 106 | if (texture.faces() > 1) { 107 | assert(texture.faces() == 6) 108 | cubemapFlags = cubemapFlags or detail.DdsCubemapFlag.CUBEMAP_ALLFACES or detail.DdsCubemapFlag.CUBEMAP 109 | } 110 | 111 | // Texture3D 112 | if (texture.extent().z > 1) 113 | cubemapFlags = cubemapFlags or detail.DdsCubemapFlag.VOLUME 114 | 115 | to(data) 116 | } 117 | 118 | if (requireDX10Header) detail.DdsHeader10().apply { 119 | arraySize = texture.layers() 120 | resourceDimension = getDimension(texture.target) 121 | miscFlag = 0 //Storage.levels() > 0 ? detail::D3D10_RESOURCE_MISC_GENERATE_MIPS : 0; 122 | format = dxFormat.dxgiFormat.i 123 | alphaFlags = detail.DdsAlphaMode.UNKNOWN.i 124 | 125 | to(data) 126 | } 127 | 128 | val src = texture.data() 129 | val dst = data 130 | memCopy(src.adr, dst.adr, src.cap) 131 | 132 | FileChannel.open(path, StandardOpenOption.CREATE, StandardOpenOption.WRITE).use { 133 | data.pos = 0 134 | while (data.hasRemaining()) 135 | it.write(data) 136 | // it.truncate(data.rem.L) 137 | } 138 | 139 | return true 140 | } 141 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/Storage.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import kool.adr 4 | import kool.free 5 | import glm_.glm 6 | import glm_.vec1.Vec1i 7 | import glm_.vec2.Vec2i 8 | import glm_.vec3.Vec3i 9 | import kool.rem 10 | import org.lwjgl.system.MemoryUtil 11 | import java.nio.ByteBuffer 12 | 13 | /** 14 | * Created by GBarbieri on 03.04.2017. 15 | */ 16 | 17 | class Storage { 18 | 19 | var layers = 0 20 | private set 21 | var faces = 0 22 | private set 23 | var levels = 0 24 | private set 25 | var blockSize = 0 26 | private set 27 | 28 | private var blockCount = Vec3i(0) 29 | 30 | var blockExtent = Vec3i(0) 31 | private set 32 | 33 | private var extent = Vec3i(0) 34 | 35 | private var data: ByteBuffer? = null 36 | 37 | constructor() 38 | constructor(storage: Storage) { 39 | layers = storage.layers 40 | faces = storage.faces 41 | levels = storage.levels 42 | blockSize = storage.blockSize 43 | blockCount = Vec3i(storage.blockCount) 44 | blockExtent = Vec3i(storage.blockExtent) 45 | extent = Vec3i(storage.extent) 46 | data = MemoryUtil.memByteBuffer(storage.data!!.adr.toLong(), storage.data!!.remaining()) 47 | } 48 | 49 | constructor(format: Format, extent: Vec3i, layers: Int, faces: Int, levels: Int) { 50 | this.layers = layers 51 | this.faces = faces 52 | this.levels = levels 53 | this.blockSize = format.blockSize 54 | this.blockCount = glm.max(extent / format.blockExtend, 1) 55 | this.blockExtent = format.blockExtend 56 | this.extent = extent 57 | 58 | assert(layers >= 0 && faces >= 0 && levels >= 0) 59 | assert(glm.all(glm.greaterThan(extent, Vec3i(0)))) 60 | 61 | data = MemoryUtil.memCalloc(layerSize(0, faces - 1, 0, levels - 1) * layers) 62 | } 63 | 64 | fun empty() = data == null 65 | fun notEmpty() = data != null 66 | 67 | fun blockCount(level: Int): Vec3i { 68 | assert(level in 0 until levels) 69 | return glm.ceilMultiple(extent(level), blockExtent) / blockExtent 70 | } 71 | 72 | fun extent(level: Int): Vec3i { 73 | assert(level in 0 until levels) 74 | return glm.max(extent shr level, 1) 75 | } 76 | 77 | fun size() = data!!.rem 78 | 79 | fun data() = data!! 80 | 81 | inline fun data() = getReinterpreter(T::class).apply { data = data() } 82 | 83 | /** Compute the relative memory offset to access the data for a specific layer, face and level */ 84 | fun baseOffset(layer: Int, face: Int, level: Int): Int { 85 | 86 | assert(notEmpty()) 87 | assert(layer in 0 until layers && face in 0 until faces && level in 0 until levels) 88 | 89 | val layerSize = layerSize(0, faces - 1, 0, levels - 1) 90 | val faceSize = faceSize(0, levels - 1) 91 | 92 | return layerSize * layer + faceSize * face + (0 until level).sumOf { levelSize(it) } 93 | } 94 | 95 | fun imageOffset(coord: Int, extend: Int): Int { 96 | assert(coord <= extend) 97 | return coord 98 | } 99 | 100 | fun imageOffset(coord: Vec1i, extend: Vec1i): Int { 101 | assert(glm.all(glm.lessThan(coord, extend))) 102 | return coord.x 103 | } 104 | 105 | fun imageOffset(coord: Vec2i, extend: Vec2i): Int { 106 | assert(glm.all(glm.lessThan(coord, extend))) 107 | return coord.x + coord.y * extend.x 108 | } 109 | 110 | fun imageOffset(coord: Vec3i, extent: Vec3i): Int { 111 | assert(glm.all(glm.lessThan(coord, extent))) 112 | return coord.x + coord.y * extent.x + coord.z * extent.x * extent.y 113 | } 114 | 115 | /** Copy a subset of a specific image of a texture */ 116 | fun copy(storageSrc: Storage, 117 | layerSrc: Int, faceSrc: Int, levelSrc: Int, blockIndexSrc: Vec3i, 118 | layerDst: Int, faceDst: Int, levelDst: Int, blockIndexDst: Vec3i, 119 | blockCount: Vec3i) { 120 | 121 | val baseOffsetSrc = storageSrc.baseOffset(layerSrc, faceSrc, levelSrc) 122 | val baseOffsetDst = baseOffset(layerDst, faceDst, levelDst) 123 | val imageSrc = storageSrc.data!!.adr.toLong() + baseOffsetSrc 124 | val imageDst = data!!.adr.toLong() + baseOffsetDst 125 | 126 | for (blockIndexZ in 0 until blockCount.z) 127 | for (blockIndexY in 0 until blockCount.y) { 128 | 129 | val blockIndex = Vec3i(0, blockIndexY, blockIndexZ) 130 | val offsetSrc = storageSrc.imageOffset(blockIndexSrc + blockIndex, storageSrc.extent(levelSrc)) * storageSrc.blockSize 131 | val offsetDst = imageOffset(blockIndexDst + blockIndex, extent(levelDst)) * blockSize 132 | val dataSrc = imageSrc + offsetSrc 133 | val dataDst = imageDst + offsetDst 134 | memCopy(dataSrc, dataDst, blockSize * blockCount.x) 135 | } 136 | } 137 | 138 | fun levelSize(level: Int): Int { 139 | assert(level in 0 until levels) 140 | return blockSize * glm.compMul(blockCount(level)) 141 | } 142 | 143 | fun faceSize(baseLevel: Int, maxLevel: Int): Int { 144 | 145 | assert(maxLevel in 0 until levels) 146 | assert(baseLevel in 0 until levels) 147 | assert(baseLevel <= maxLevel) 148 | // The size of a face is the sum of the size of each level. 149 | return (baseLevel..maxLevel).sumOf { levelSize(it) } 150 | } 151 | 152 | fun layerSize(baseFace: Int, maxFace: Int, baseLevel: Int, maxLevel: Int): Int { 153 | 154 | assert(maxFace in 0 until faces) 155 | assert(baseFace in 0 until faces) 156 | assert(maxLevel in 0 until levels) 157 | assert(baseLevel in 0 until levels) 158 | // The size of a layer is the sum of the size of each face. All the faces have the same size. 159 | return faceSize(baseLevel, maxLevel) * (maxFace - baseFace + 1) 160 | } 161 | 162 | fun dispose() = data?.free() 163 | 164 | override fun equals(other: Any?): Boolean { 165 | return if (other !is Storage) false 166 | else layers == other.layers && 167 | faces == other.faces && 168 | levels == other.levels && 169 | blockSize == other.blockSize && 170 | blockCount == other.blockCount && 171 | blockExtent == other.blockExtent && 172 | extent == other.extent && 173 | data == other.data 174 | } 175 | 176 | override fun hashCode(): Int { 177 | var result = layers 178 | result = 31 * result + faces 179 | result = 31 * result + levels 180 | result = 31 * result + blockSize 181 | result = 31 * result + blockCount.hashCode() 182 | result = 31 * result + blockExtent.hashCode() 183 | result = 31 * result + extent.hashCode() 184 | result = 31 * result + (data?.hashCode() ?: 0) 185 | return result 186 | } 187 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/loadDds.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import gli_.detail.has 4 | import gli_.dx.has 5 | import gli_.dx.or 6 | import glm_.b 7 | import glm_.glm 8 | import glm_.has 9 | import glm_.i 10 | import glm_.vec3.Vec3i 11 | import kool.* 12 | import java.io.File 13 | import java.net.URI 14 | import java.nio.ByteBuffer 15 | import java.nio.ByteOrder 16 | import java.nio.channels.FileChannel 17 | import java.nio.file.Path 18 | import java.nio.file.Paths 19 | import java.nio.file.StandardOpenOption 20 | 21 | /** 22 | * Created by GBarbieri on 05.04.2017. 23 | */ 24 | 25 | interface loadDds { 26 | 27 | /** Loads a texture storage_linear from DDS memory. Returns an empty storage_linear in case of failure. 28 | * @param filename String of the file to open including filaname and filename extension */ 29 | fun loadDds(filename: String) = loadDds(Paths.get(filename)) 30 | 31 | fun loadDds(uri: URI) = loadDds(Paths.get(uri)) 32 | 33 | /** Loads a texture storage_linear from DDS memory. Returns an empty storage_linear in case of failure. 34 | * @param uri Uri of the file to open including filaname and filename extension */ 35 | fun loadDds(path: Path): Texture { 36 | 37 | val buffer = FileChannel.open(path, StandardOpenOption.READ).use { channel -> 38 | Buffer(channel.size().i).also { 39 | while (channel.read(it) > 0); 40 | it.pos = 0 41 | it.order(ByteOrder.nativeOrder()) 42 | } 43 | } 44 | 45 | return loadDds(buffer) 46 | } 47 | 48 | /** Loads a texture storage_linear from DDS file. Returns an empty storage_linear in case of failure. */ 49 | fun loadDds(data: ByteBuffer): Texture { 50 | 51 | assert(data.cap >= detail.FOURCC_DDS.size) 52 | 53 | if (!detail.FOURCC_DDS.all { data.get() == it.b }) 54 | return Texture() 55 | 56 | assert(data.remaining() >= detail.DdsHeader.SIZE) 57 | 58 | val header = detail.DdsHeader(data) 59 | 60 | val header10 = with(header.format) { 61 | if (flags has dx.Ddpf.FOURCC && (fourCC == dx.D3dfmt.DX10.i || fourCC == dx.D3dfmt.GLI1.i)) 62 | detail.DdsHeader10(data) 63 | else 64 | detail.DdsHeader10() 65 | } 66 | 67 | fun has(format: Format) = glm.all(glm.equal(header.format.mask, dx.translate(format).mask)) 68 | 69 | val format = with(header.format) { 70 | if ((flags has (dx.Ddpf.RGB or dx.Ddpf.ALPHAPIXELS or dx.Ddpf.ALPHA or dx.Ddpf.YUV or dx.Ddpf.LUMINANCE)) && bpp != 0) 71 | when (bpp) { 72 | 8 -> when { 73 | has(Format.RG4_UNORM_PACK8) -> Format.RG4_UNORM_PACK8 74 | has(Format.RG4_UNORM_PACK8) -> Format.RG4_UNORM_PACK8 75 | has(Format.L8_UNORM_PACK8) -> Format.L8_UNORM_PACK8 76 | has(Format.A8_UNORM_PACK8) -> Format.A8_UNORM_PACK8 77 | has(Format.R8_UNORM_PACK8) -> Format.R8_UNORM_PACK8 78 | has(Format.RG3B2_UNORM_PACK8) -> Format.RG3B2_UNORM_PACK8 79 | else -> throw Error() 80 | } 81 | 16 -> when { 82 | has(Format.RGBA4_UNORM_PACK16) -> Format.RGBA4_UNORM_PACK16 83 | has(Format.BGRA4_UNORM_PACK16) -> Format.BGRA4_UNORM_PACK16 84 | has(Format.R5G6B5_UNORM_PACK16) -> Format.R5G6B5_UNORM_PACK16 85 | has(Format.B5G6R5_UNORM_PACK16) -> Format.B5G6R5_UNORM_PACK16 86 | has(Format.RGB5A1_UNORM_PACK16) -> Format.RGB5A1_UNORM_PACK16 87 | has(Format.BGR5A1_UNORM_PACK16) -> Format.BGR5A1_UNORM_PACK16 88 | has(Format.LA8_UNORM_PACK8) -> Format.LA8_UNORM_PACK8 89 | has(Format.RG8_UNORM_PACK8) -> Format.RG8_UNORM_PACK8 90 | has(Format.L16_UNORM_PACK16) -> Format.L16_UNORM_PACK16 91 | has(Format.A16_UNORM_PACK16) -> Format.A16_UNORM_PACK16 92 | has(Format.R16_UNORM_PACK16) -> Format.R16_UNORM_PACK16 93 | else -> throw Error() 94 | } 95 | 24 -> when { 96 | has(Format.RGB8_UNORM_PACK8) -> Format.RGB8_UNORM_PACK8 97 | has(Format.BGR8_UNORM_PACK8) -> Format.BGR8_UNORM_PACK8 98 | else -> throw Error() 99 | } 100 | 32 -> when { 101 | has(Format.BGR8_UNORM_PACK32) -> Format.BGR8_UNORM_PACK32 102 | has(Format.BGRA8_UNORM_PACK8) -> Format.BGRA8_UNORM_PACK8 103 | has(Format.RGBA8_UNORM_PACK8) -> Format.RGBA8_UNORM_PACK8 104 | has(Format.RGB10A2_UNORM_PACK32) -> Format.RGB10A2_UNORM_PACK32 105 | has(Format.LA16_UNORM_PACK16) -> Format.LA16_UNORM_PACK16 106 | has(Format.RG16_UNORM_PACK16) -> Format.RG16_UNORM_PACK16 107 | has(Format.R32_SFLOAT_PACK32) -> Format.R32_SFLOAT_PACK32 108 | else -> throw Error() 109 | } 110 | else -> throw Error() 111 | } 112 | else if ((flags has dx.Ddpf.FOURCC.i) && (fourCC != dx.D3dfmt.DX10.i) && (fourCC != dx.D3dfmt.GLI1.i)) 113 | dx.find(detail.remapFourCC(fourCC)) 114 | else if (fourCC == dx.D3dfmt.DX10.i || fourCC == dx.D3dfmt.GLI1.i) 115 | dx.find(dx.D3dfmt.of(fourCC), dx.DxgiFormat(header10.format)) 116 | else throw Error() 117 | } 118 | 119 | val mipMapCount = if (header.flags has detail.DdsFlag.MIPMAPCOUNT.i) header.mipMapLevels else 1 120 | val faceCount = when { 121 | header.cubemapFlags has detail.DdsCubemapFlag.CUBEMAP.i -> 122 | glm.bitCount(header.cubemapFlags and detail.DdsCubemapFlag.CUBEMAP_ALLFACES.i) 123 | header10.miscFlag has detail.D3d10resourceMiscFlag.TEXTURECUBE -> 6 124 | else -> 1 125 | } 126 | 127 | val depthCount = when { 128 | header.cubemapFlags has detail.DdsCubemapFlag.VOLUME.i -> header.depth 129 | else -> 1 130 | } 131 | 132 | val texture = Texture(getTarget(header, header10), format, Vec3i(header.width, header.height, depthCount), 133 | glm.max(header10.arraySize, 1), faceCount, mipMapCount) 134 | 135 | assert(data.cap == data.pos + texture.size) 136 | 137 | memCopy(data.adr, texture.data().adr, texture.size) 138 | 139 | return texture 140 | } 141 | 142 | fun getTarget(header: detail.DdsHeader, header10: detail.DdsHeader10) = when { 143 | 144 | header.cubemapFlags has detail.DdsCubemapFlag.CUBEMAP || header10.miscFlag has detail.D3d10resourceMiscFlag.TEXTURECUBE -> 145 | if (header10.arraySize > 1) Target.CUBE_ARRAY 146 | else Target.CUBE 147 | 148 | header10.arraySize > 1 -> 149 | if (header.flags has detail.DdsFlag.HEIGHT) Target._2D_ARRAY 150 | else Target._1D_ARRAY 151 | 152 | header10.resourceDimension == detail.D3d10resourceDimension.TEXTURE1D.i -> Target._1D 153 | 154 | header10.resourceDimension == detail.D3d10resourceDimension.TEXTURE3D.i || (header.flags has detail.DdsFlag.DEPTH.i) 155 | || (header.cubemapFlags has detail.DdsCubemapFlag.VOLUME.i) -> Target._3D 156 | 157 | else -> Target._2D 158 | } 159 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/Image.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import kool.adr 4 | import kool.cap 5 | import kool.free 6 | import glm_.glm 7 | import kool.set 8 | import glm_.vec3.Vec3i 9 | import org.lwjgl.system.MemoryUtil 10 | import org.lwjgl.system.MemoryUtil.memByteBuffer 11 | import java.nio.ByteBuffer 12 | import kotlin.reflect.KClass 13 | 14 | /** 15 | * Created by elect on 08/04/17. 16 | */ 17 | 18 | /** Image, representation for a single texture level */ 19 | class Image { 20 | 21 | private var storage: Storage? = null 22 | 23 | var format = Format.UNDEFINED 24 | private set 25 | 26 | var baseLevel = 0 27 | private set 28 | 29 | var size = 0 30 | private set 31 | 32 | private var data: ByteBuffer? = null 33 | 34 | /** Create an empty image instance */ 35 | constructor() 36 | 37 | /** Create an image object and allocate an image storoge for it. */ 38 | constructor(format: Format, extent: Vec3i) { 39 | storage = Storage(format, extent, 1, 1, 1) 40 | this.format = format 41 | baseLevel = 0 42 | data = memByteBuffer(storage!!.data().adr.toLong(), storage!!.data().remaining()) 43 | size = computeSize(0) 44 | } 45 | 46 | /** Create an image object by sharing an existing image storage_linear from another image instance. 47 | * This image object is effectively an image view where format can be reinterpreted with a different 48 | * compatible image format. 49 | * For formats to be compatible, the block size of source and destination must match. */ 50 | constructor(image: Image, format: Format) { 51 | storage = Storage(image.storage!!) 52 | this.format = format 53 | baseLevel = image.baseLevel 54 | data = memByteBuffer(image.data!!.adr.toLong(), image.data!!.remaining()) 55 | size = image.size 56 | assert(format.blockSize == image.format.blockSize) 57 | } 58 | 59 | /** Create an image object by sharing an existing image storage_linear from another image instance. 60 | * This image object is effectively an image view where the layer, the face and the level allows identifying 61 | * a specific subset of the image storage_linear source. 62 | * This image object is effectively a image view where the format can be reinterpreted 63 | * with a different compatible image format. */ 64 | constructor(storage: Storage, format: Format, baseLayer: Int, baseFace: Int, baseLevel: Int) { 65 | this.storage = Storage(storage) 66 | this.format = format 67 | this.baseLevel = baseLevel 68 | data = computeData(baseLayer, baseFace, baseLevel) 69 | size = computeSize(baseLevel) 70 | } 71 | 72 | fun computeData(baseLayer: Int, baseFace: Int, baseLevel: Int): ByteBuffer { 73 | val baseOffset = storage!!.baseOffset(baseLayer, baseFace, baseLevel) 74 | return memByteBuffer(storage!!.data().adr.toLong() + baseOffset, storage!!.data().remaining() - baseOffset) 75 | } 76 | 77 | fun computeSize(level: Int): Int { 78 | assert(notEmpty()) 79 | return storage!!.levelSize(level) 80 | } 81 | 82 | /** Return whether the image instance is empty, no storage_linear or description have been assigned to the instance. */ 83 | fun empty() = storage?.empty() ?: true 84 | 85 | fun notEmpty() = !empty() 86 | 87 | /** Return the dimensions of an image instance: width, height and depth. */ 88 | fun extent(): Vec3i { 89 | 90 | assert(notEmpty()) 91 | 92 | val srcExtent = storage!!.extent(baseLevel) 93 | val dstExtent = srcExtent * format.blockExtend / storage!!.blockExtent 94 | 95 | return glm.max(dstExtent, 1) 96 | } 97 | 98 | /** Return the memory size of an image instance storage_linear in bytes. */ 99 | // fun size(): Int { 100 | // assert(notEmpty()) 101 | // return size 102 | // } 103 | 104 | /** Return the number of blocks contained in an image instance storage_linear. 105 | * genType size must match the block size corresponding to the image format. */ 106 | inline fun size() = size(T::class) 107 | 108 | fun size(kClass: KClass<*>): Int { 109 | val blockSize = getSize(kClass) 110 | assert(blockSize <= storage!!.blockSize) 111 | return size / blockSize 112 | } 113 | 114 | /** Return a pointer to the beginning of the image instance data. */ 115 | fun data(): ByteBuffer? { 116 | assert(notEmpty()) 117 | return data 118 | } 119 | 120 | inline fun data(): reinterpreter = data(T::class) 121 | fun data(kClass: KClass<*>) = getReinterpreter(kClass).apply { data = data()!! } 122 | 123 | /** Clear the entire image storage_linear with zeros */ 124 | fun clear() { 125 | assert(notEmpty()) 126 | repeat(storage!!.data().cap) { storage!!.data()[it] = 0 } 127 | } 128 | 129 | /** Clear the entire image storage_linear with Texel which type must match the image storage_linear format block size 130 | * If the type of genType doesn't match the type of the image format, no conversion is performed and the data will 131 | * be reinterpreted as if is was of the image format. */ 132 | infix fun clear(texel: T) { 133 | assert(notEmpty() && format.blockSize == getSize(texel::class)) 134 | for (i in 0 until size(texel::class)) 135 | data(texel::class)[i] = texel 136 | } 137 | 138 | /** Load the texel located at TexelCoord coordinates. 139 | * It's an error to call this function if the format is compressed. 140 | * It's an error if TexelCoord values aren't between [0, dimensions]. */ 141 | inline fun load(texelCoord: Vec3i): T { 142 | assert(notEmpty() && !format.isCompressed) 143 | assert(blockSize() == getSize(T::class)) 144 | // GLI_ASSERT(glm::all(glm::lessThan(TexelCoord, this->extent()))); TODO 145 | return getReinterpreter(T::class).apply { data = data()!! }[textelLinearAddressing(extent(), texelCoord)] 146 | } 147 | 148 | fun blockSize() = storage!!.blockSize 149 | // 150 | // /// Store the texel located at TexelCoord coordinates. 151 | // /// It's an error to call this function if the format is compressed. 152 | // /// It's an error if TexelCoord values aren't between [0, dimensions]. 153 | // template 154 | // void store(extent_type const & TexelCoord, genType const & Data); 155 | 156 | override fun equals(other: Any?) = when { 157 | other !is Image -> false 158 | extent() != other.extent() -> false 159 | size != other.size -> false 160 | else -> memCmp(other.data!!) 161 | } 162 | 163 | private fun memCmp(b: ByteBuffer): Boolean { 164 | for (i in 0 until size) 165 | if (data()!!.get(i) != b[i]) 166 | return false 167 | return true 168 | } 169 | 170 | companion object { 171 | fun textelLinearAddressing(extent: Vec3i, texelCoord: Vec3i): Int { 172 | assert(glm.all(glm.lessThan(texelCoord, extent))) 173 | return texelCoord.x + extent.x * (texelCoord.y + extent.y * texelCoord.z) 174 | } 175 | } 176 | 177 | override fun hashCode(): Int { 178 | var result = storage?.hashCode() ?: 0 179 | result = 31 * result + format.hashCode() 180 | result = 31 * result + baseLevel 181 | result = 31 * result + size 182 | result = 31 * result + (data?.hashCode() ?: 0) 183 | return result 184 | } 185 | 186 | fun dispose() = data?.free() 187 | } -------------------------------------------------------------------------------- /src/main/kotlin/gli_/loadImage.kt: -------------------------------------------------------------------------------- 1 | package gli_ 2 | 3 | import glm_.b 4 | import glm_.or 5 | import glm_.vec3.Vec3i 6 | import kool.* 7 | import java.awt.image.* 8 | import java.awt.image.BufferedImage.* 9 | import java.io.File 10 | import java.net.URI 11 | import java.nio.ByteBuffer 12 | import java.nio.file.Path 13 | import java.nio.file.Paths 14 | import javax.imageio.ImageIO 15 | 16 | interface loadImage { 17 | 18 | fun loadImage(file: File, flipY: Boolean): Texture { 19 | 20 | if (!file.exists()) throw NoSuchFileException(file) 21 | 22 | val image = ImageIO.read(file) 23 | return loadImage(image, flipY) 24 | } 25 | 26 | fun loadImageFromMem(buffer: ByteBuffer, flipY: Boolean): Texture { 27 | val input = ByteBufferBackedInputStream(buffer) 28 | val image = ImageIO.read(input) 29 | return loadImage(image, flipY) 30 | } 31 | 32 | fun loadImage(image: BufferedImage, flipY: Boolean = false): Texture { 33 | val extent = Vec3i(image.width, image.height, 1) 34 | if (flipY) 35 | image.flipY() 36 | return when (image.type) { 37 | TYPE_INT_RGB -> Texture(Target._2D, Format.RGB8_UNORM_PACK8, extent, 1, 1, 1).apply { 38 | val dst = data() 39 | var i = 0 40 | (image.raster.dataBuffer as DataBufferInt).data.forEach { 41 | dst[i++] = (it ushr 16).b 42 | dst[i++] = (it ushr 8).b 43 | dst[i++] = it.b 44 | } 45 | } 46 | TYPE_INT_ARGB -> Texture(Target._2D, Format.RGBA8_UNORM_PACK8, extent, 1, 1, 1).apply { 47 | // push alpha at the end 48 | val dst = data() 49 | var i = 0 50 | (image.raster.dataBuffer as DataBufferInt).data.forEach { 51 | dst[i++] = (it ushr 16).b 52 | dst[i++] = (it ushr 8).b 53 | dst[i++] = it.b 54 | dst[i++] = (it ushr 24).b 55 | } 56 | } 57 | TYPE_INT_ARGB_PRE -> Texture(Target._2D, Format.RGBA8_UNORM_PACK8, extent, 1, 1, 1).apply { 58 | // push alpha at the end and demultiply 59 | val dst = data() 60 | var i = 0 61 | (image.raster.dataBuffer as DataBufferInt).data.forEach { 62 | val a = it ushr 24 63 | dst[i++] = ((it ushr 16) / a).b 64 | dst[i++] = ((it ushr 8) / a).b 65 | dst[i++] = (it / a).b 66 | dst[i++] = a.b 67 | } 68 | } 69 | TYPE_INT_BGR -> Texture(Target._2D, Format.RGB8_UNORM_PACK8, extent, 1, 1, 1).apply { 70 | // switch blue and red 71 | val dst = data() 72 | var i = 0 73 | (image.raster.dataBuffer as DataBufferInt).data.forEach { 74 | dst[i++] = it.b 75 | dst[i++] = (it ushr 8).b 76 | dst[i++] = (it ushr 16).b 77 | } 78 | } 79 | TYPE_3BYTE_BGR -> Texture(Target._2D, Format.RGB8_UNORM_PACK8, extent, 1, 1, 1).apply { 80 | // switch blue and red 81 | val dst = data() 82 | val src = (image.raster.dataBuffer as DataBufferByte).data 83 | for (i in src.indices step 3) { 84 | dst[i] = src[i + 2] 85 | dst[i + 1] = src[i + 1] 86 | dst[i + 2] = src[i] 87 | } 88 | } 89 | TYPE_4BYTE_ABGR -> Texture(Target._2D, Format.RGBA8_UNORM_PACK8, extent, 1, 1, 1).apply { 90 | // invert 91 | val dst = data() 92 | val src = (image.raster.dataBuffer as DataBufferByte).data 93 | for (i in src.indices step 4) { 94 | dst[i] = src[i + 3] 95 | dst[i + 1] = src[i + 2] 96 | dst[i + 2] = src[i + 1] 97 | dst[i + 3] = src[i] 98 | } 99 | } 100 | TYPE_4BYTE_ABGR_PRE -> Texture(Target._2D, Format.RGBA8_UNORM_PACK8, extent, 1, 1, 1).apply { 101 | // invert and demultiply 102 | val dst = data() 103 | val src = (image.raster.dataBuffer as DataBufferByte).data 104 | for (i in src.indices step 4) { 105 | val a = src[i] 106 | dst[i] = (src[i + 3] / a).b 107 | dst[i + 1] = (src[i + 2] / a).b 108 | dst[i + 2] = (src[i + 1] / a).b 109 | dst[i + 3] = a 110 | } 111 | } 112 | TYPE_USHORT_565_RGB -> Texture(Target._2D, Format.R5G6B5_UNORM_PACK16, extent, 1, 1, 1).apply { 113 | // 1 to 1 114 | val dst = data() 115 | var i = 0 116 | (image.raster.dataBuffer as DataBufferUShort).data.forEach { 117 | dst.putShort(i++ * Short.BYTES, it) 118 | } 119 | } 120 | TYPE_USHORT_555_RGB -> Texture(Target._2D, Format.A1RGB5_UNORM_PACK16, extent, 1, 1, 1).apply { 121 | // ~ 1 to 1 122 | val dst = data() 123 | var i = 0 124 | (image.raster.dataBuffer as DataBufferUShort).data.forEach { 125 | val a1rgb5 = it or 0b1000_0000_0000 // hardcode alpha to 1, opaque 126 | dst.putShort(i++ * Short.BYTES, a1rgb5) 127 | } 128 | } 129 | TYPE_BYTE_GRAY -> Texture(Target._2D, Format.R8_UNORM_PACK8, extent, 1, 1, 1).apply { 130 | // 1 to 1 131 | val dst = data() 132 | var i = 0 133 | val dataBuffer = image.raster.dataBuffer as DataBufferByte 134 | dataBuffer.data.forEach { dst[i++] = it } 135 | } 136 | TYPE_USHORT_GRAY -> Texture(Target._2D, Format.R16_UNORM_PACK16, extent, 1, 1, 1).apply { 137 | // 1 to 1 138 | val dst = data() 139 | var i = 0 140 | val dataBuffer = image.raster.dataBuffer as DataBufferUShort 141 | dataBuffer.data.forEach { dst.putShort(i++ * Short.BYTES, it) } 142 | } 143 | TYPE_BYTE_BINARY, TYPE_BYTE_INDEXED -> { 144 | val c = image.colorModel as IndexColorModel 145 | val colors = IntArray(c.mapSize) 146 | c.getRGBs(colors) 147 | val dataBuffer = image.raster.dataBuffer as DataBufferByte 148 | val src = dataBuffer.data 149 | when { 150 | c.hasAlpha() -> Texture(Target._2D, Format.RGBA8_UNORM_PACK8, extent, 1, 1, 1).apply { 151 | val dst = data() 152 | for (i in src.indices step 4) { 153 | dst[i + 0] = src[i + 1] // r 154 | dst[i + 1] = src[i + 2] // g 155 | dst[i + 2] = src[i + 3] // b 156 | dst[i + 3] = src[i + 0] // a 157 | } 158 | } 159 | else -> Texture(Target._2D, Format.RGB8_UNORM_PACK8, extent, 1, 1, 1).apply { 160 | val dst = data() 161 | var j = 0 162 | for (i in src.indices step 4) { 163 | dst[j++] = src[i + 1] // r 164 | dst[j++] = src[i + 2] // g 165 | dst[j++] = src[i + 3] // b 166 | } 167 | } 168 | } 169 | } 170 | else -> error("not yet supported") 171 | } 172 | } 173 | } --------------------------------------------------------------------------------