├── .gitignore ├── docs ├── custom.md ├── context.md ├── renderables.md ├── index.md ├── gltf.md ├── billboards.md ├── meshes.md ├── projection.md ├── light.md ├── env.md └── filters.md ├── readme ├── web.jpg ├── desktop.jpg ├── mobile.jpg ├── collage1.jpg └── korender32.png ├── quickstart ├── README.md ├── composeApp │ └── src │ │ ├── androidMain │ │ ├── res │ │ │ ├── values │ │ │ │ └── strings.xml │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ └── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── MainActivity.kt │ │ └── AndroidManifest.xml │ │ ├── webMain │ │ ├── resources │ │ │ ├── styles.css │ │ │ └── index.html │ │ └── kotlin │ │ │ └── main.kt │ │ ├── commonMain │ │ ├── composeResources │ │ │ └── files │ │ │ │ └── icon.png │ │ └── kotlin │ │ │ └── App.kt │ │ └── desktopMain │ │ └── kotlin │ │ └── main.kt ├── gradle │ ├── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ └── libs.versions.toml ├── gradle.properties ├── build.gradle.kts ├── .gitignore └── settings.gradle.kts ├── korender-framework ├── korender │ └── src │ │ ├── commonMain │ │ ├── kotlin │ │ │ ├── Shadows.kt │ │ │ ├── impl │ │ │ │ ├── gl │ │ │ │ │ ├── GLBuffer.kt │ │ │ │ │ ├── GLProgram.kt │ │ │ │ │ ├── GLShader.kt │ │ │ │ │ ├── GLTexture.kt │ │ │ │ │ ├── GLFrameBuffer.kt │ │ │ │ │ ├── GLVertexArray.kt │ │ │ │ │ └── GLUniformLocation.kt │ │ │ │ ├── buffer │ │ │ │ │ ├── NativeBuffer.kt │ │ │ │ │ └── NativeFloatBuffer.kt │ │ │ │ ├── glgpu │ │ │ │ │ └── GLBindableTexture.kt │ │ │ │ ├── camera │ │ │ │ │ ├── Camera.kt │ │ │ │ │ └── DefaultCamera.kt │ │ │ │ ├── prefab │ │ │ │ │ └── InternalPrefab.kt │ │ │ │ ├── engine │ │ │ │ │ ├── Retention.kt │ │ │ │ │ ├── shadow │ │ │ │ │ │ └── ShadowAlgorithms.kt │ │ │ │ │ ├── CaptureContext.kt │ │ │ │ │ ├── TouchBox.kt │ │ │ │ │ ├── FrameInfoManager.kt │ │ │ │ │ └── ReusableFrameBufferHolder.kt │ │ │ │ ├── material │ │ │ │ │ └── Uniforms.kt │ │ │ │ ├── projection │ │ │ │ │ └── Projection.kt │ │ │ │ ├── context │ │ │ │ │ ├── DefaultShadowContext.kt │ │ │ │ │ ├── DefaultDeferredShadingContext.kt │ │ │ │ │ ├── DefaultPipeMeshContext.kt │ │ │ │ │ └── DefaultInstancedContext.kt │ │ │ │ ├── gltf │ │ │ │ │ └── ByteArrayReader.kt │ │ │ │ ├── image │ │ │ │ │ └── Tga.kt │ │ │ │ ├── Resources.kt │ │ │ │ └── font │ │ │ │ │ └── Fonts.kt │ │ │ ├── Materials.kt │ │ │ ├── math │ │ │ │ ├── FloatMath.kt │ │ │ │ ├── ColorRGBA.kt │ │ │ │ ├── ColorRGB.kt │ │ │ │ ├── Vec2.kt │ │ │ │ ├── BoundingBox.kt │ │ │ │ └── Mat3.kt │ │ │ ├── context │ │ │ │ ├── PipeMeshContext.kt │ │ │ │ ├── InstancedContext.kt │ │ │ │ ├── ShadowContext.kt │ │ │ │ └── DeferredShadingContext.kt │ │ │ ├── Matrices.kt │ │ │ ├── Textures.kt │ │ │ ├── Platform.kt │ │ │ ├── Korender.kt │ │ │ ├── Touch.kt │ │ │ ├── Images.kt │ │ │ └── gltf │ │ │ │ └── GltfUpdate.kt │ │ └── composeResources │ │ │ └── files │ │ │ ├── shader │ │ │ ├── plugin │ │ │ │ ├── normal.pipe.frag │ │ │ │ ├── output.normal.frag │ │ │ │ ├── emission.factor.frag │ │ │ │ ├── vnormal.skinning.vert │ │ │ │ ├── depth.log.frag │ │ │ │ ├── albedo.radiant.frag │ │ │ │ ├── emission.texture.frag │ │ │ │ ├── occlusion.texture.frag │ │ │ │ ├── normal.radiant.frag │ │ │ │ ├── metallic_roughness.texture.frag │ │ │ │ ├── specular_glossiness.texture.frag │ │ │ │ ├── sky.texture.frag │ │ │ │ ├── sky.cube.frag │ │ │ │ ├── depth.pipe.frag │ │ │ │ ├── depth.radiant.frag │ │ │ │ ├── output.radiant.frag │ │ │ │ ├── specular_glossiness.factor.frag │ │ │ │ ├── vprojection.fixedyrange.vert │ │ │ │ ├── normal.texture.frag │ │ │ │ ├── terrain.texture.frag │ │ │ │ ├── normal.terrain.frag │ │ │ │ ├── position.pipe.frag │ │ │ │ ├── texturing.triplanar.frag │ │ │ │ ├── vprojection.ortho.vert │ │ │ │ ├── vprojection.frustum.vert │ │ │ │ ├── vprojection.log.vert │ │ │ │ ├── sky.fastcloud.frag │ │ │ │ ├── position.radiant.frag │ │ │ │ ├── sky.starry.frag │ │ │ │ └── vposition.skinning.vert │ │ │ ├── lib │ │ │ │ ├── noise.glsl │ │ │ │ ├── header.glsl │ │ │ │ ├── noisebias.glsl │ │ │ │ ├── skyibl.glsl │ │ │ │ ├── space.glsl │ │ │ │ ├── octa.glsl │ │ │ │ ├── sky.glsl │ │ │ │ ├── normalmap.glsl │ │ │ │ ├── blur.glsl │ │ │ │ ├── ubo.glsl │ │ │ │ ├── sg.glsl │ │ │ │ └── light.glsl │ │ │ ├── screen.vert │ │ │ ├── sky │ │ │ │ ├── sky.vert │ │ │ │ └── sky.frag │ │ │ ├── gui │ │ │ │ ├── image.frag │ │ │ │ ├── font.frag │ │ │ │ ├── image.vert │ │ │ │ └── font.vert │ │ │ ├── effect │ │ │ │ ├── identity.frag │ │ │ │ ├── env-debug.frag │ │ │ │ ├── fxaa.frag │ │ │ │ ├── blurh.frag │ │ │ │ ├── blurv.frag │ │ │ │ ├── adjust.frag │ │ │ │ ├── fire.frag │ │ │ │ ├── fog.frag │ │ │ │ ├── bloom.frag │ │ │ │ ├── smoke.frag │ │ │ │ ├── shadow-debug.frag │ │ │ │ ├── fireball.frag │ │ │ │ └── kawase.frag │ │ │ ├── deferred │ │ │ │ ├── composition-bloom.glsl │ │ │ │ ├── decalblend.frag │ │ │ │ ├── composition.frag │ │ │ │ ├── decal.vert │ │ │ │ └── composition-ssr.glsl │ │ │ ├── base.vert │ │ │ ├── caster.frag │ │ │ ├── pipe.vert │ │ │ └── billboard.vert │ │ │ ├── fbm.png │ │ │ ├── noise.png │ │ │ ├── font │ │ │ └── anta.ttf │ │ │ └── gui │ │ │ ├── slider.empty.png │ │ │ ├── slider.left.png │ │ │ ├── slider.right.png │ │ │ ├── joystick.inner.png │ │ │ ├── joystick.outer.png │ │ │ ├── slider.handle.png │ │ │ ├── checkbox.checked.png │ │ │ ├── progressbar.empty.png │ │ │ ├── checkbox.unchecked.png │ │ │ └── progressbar.filled.png │ │ ├── androidMain │ │ └── kotlin │ │ │ └── impl │ │ │ ├── gl │ │ │ ├── GLBuffer.kt │ │ │ ├── GLProgram.kt │ │ │ ├── GLShader.kt │ │ │ ├── GLTexture.kt │ │ │ ├── GLUniformLocation.kt │ │ │ ├── GLFrameBuffer.kt │ │ │ └── GLVertexArray.kt │ │ │ └── buffer │ │ │ ├── NativeBuffer.kt │ │ │ └── NativeFloatBuffer.kt │ │ ├── webMain │ │ └── kotlin │ │ │ └── impl │ │ │ ├── gl │ │ │ ├── GLShader.kt │ │ │ ├── GLTexture.kt │ │ │ ├── GLFrameBuffer.kt │ │ │ ├── GLVertexArray.kt │ │ │ ├── GLUniformLocation.kt │ │ │ ├── GLBuffer.kt │ │ │ └── GLProgram.kt │ │ │ └── buffer │ │ │ ├── NativeBuffer.kt │ │ │ └── NativeFloatBuffer.kt │ │ └── desktopMain │ │ └── kotlin │ │ ├── impl │ │ ├── gl │ │ │ ├── GLBuffer.kt │ │ │ ├── GLProgram.kt │ │ │ ├── GLShader.kt │ │ │ ├── GLTexture.kt │ │ │ ├── GLFrameBuffer.kt │ │ │ ├── GLUniformLocation.kt │ │ │ └── GLVertexArray.desktop.kt │ │ └── buffer │ │ │ ├── NativeBuffer.kt │ │ │ └── NativeFloatBuffer.kt │ │ └── KeyMapping.kt ├── examples │ ├── korender32.ico │ ├── korender32.png │ └── src │ │ ├── webMain │ │ ├── resources │ │ │ ├── manifest.json │ │ │ ├── styles.css │ │ │ └── index.html │ │ └── kotlin │ │ │ └── main.kt │ │ ├── androidMain │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ └── ic_launcher_background.xml │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_background.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_monochrome.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_background.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_monochrome.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_background.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_monochrome.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_background.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_monochrome.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_background.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_monochrome.png │ │ │ └── mipmap-anydpi-v26 │ │ │ │ └── ic_launcher.xml │ │ ├── kotlin │ │ │ └── MainActivity.kt │ │ └── AndroidManifest.xml │ │ ├── commonMain │ │ ├── composeResources │ │ │ ├── drawable │ │ │ │ ├── menu.png │ │ │ │ └── korender32.png │ │ │ └── files │ │ │ │ ├── cube │ │ │ │ ├── sea │ │ │ │ │ ├── nx.jpg │ │ │ │ │ ├── ny.jpg │ │ │ │ │ ├── nz.jpg │ │ │ │ │ ├── px.jpg │ │ │ │ │ ├── py.jpg │ │ │ │ │ └── pz.jpg │ │ │ │ └── room │ │ │ │ │ ├── nx.jpg │ │ │ │ │ ├── ny.jpg │ │ │ │ │ ├── nz.jpg │ │ │ │ │ ├── px.jpg │ │ │ │ │ ├── py.jpg │ │ │ │ │ └── pz.jpg │ │ │ │ ├── infcity │ │ │ │ ├── dw.jpg │ │ │ │ ├── lw.jpg │ │ │ │ ├── moon.png │ │ │ │ ├── road.jpg │ │ │ │ ├── roof.jpg │ │ │ │ ├── tree.glb │ │ │ │ ├── swat-woman.glb │ │ │ │ ├── moon.secsky.plugin.frag │ │ │ │ └── window.emission.plugin.frag │ │ │ │ ├── model │ │ │ │ └── head.jpg │ │ │ │ ├── font │ │ │ │ └── orbitron.ttf │ │ │ │ ├── gltf │ │ │ │ └── ai │ │ │ │ │ └── swat.glb │ │ │ │ ├── texture │ │ │ │ ├── brick.jpg │ │ │ │ ├── decal.png │ │ │ │ ├── grass.jpg │ │ │ │ ├── splat.png │ │ │ │ ├── korender32.png │ │ │ │ ├── asphalt-albedo.jpg │ │ │ │ └── asphalt-normal.jpg │ │ │ │ ├── island │ │ │ │ ├── models │ │ │ │ │ └── plane.glb │ │ │ │ ├── terrain │ │ │ │ │ ├── runway.jpg │ │ │ │ │ └── shader │ │ │ │ │ │ └── height.glsl │ │ │ │ ├── tree │ │ │ │ │ └── shader │ │ │ │ │ │ └── island.foliage.discard.frag │ │ │ │ └── building │ │ │ │ │ └── shader │ │ │ │ │ └── island.window.albedo.frag │ │ │ │ ├── terrain │ │ │ │ ├── terrain-albedo.jpg │ │ │ │ └── terrain-height.png │ │ │ │ └── procterrain │ │ │ │ ├── height.glsl │ │ │ │ └── albedo.glsl │ │ └── kotlin │ │ │ ├── infcity │ │ │ ├── Tools.kt │ │ │ ├── Triangulation.kt │ │ │ └── CityStrategy.kt │ │ │ ├── BlurExample.kt │ │ │ ├── FxaaExample.kt │ │ │ ├── island │ │ │ ├── Loader.kt │ │ │ ├── BinaryReader.kt │ │ │ ├── city │ │ │ │ └── CityStrategy.kt │ │ │ └── Terrain.kt │ │ │ ├── ObjFileExample.kt │ │ │ ├── PipeExample.kt │ │ │ ├── MultipleViewportsExample.kt │ │ │ ├── TransparencyExample.kt │ │ │ ├── SkyExample.kt │ │ │ ├── GltfCrowdExample.kt │ │ │ └── MetallicRoughnessExample.kt │ │ └── desktopMain │ │ └── kotlin │ │ └── main.kt ├── baker │ ├── src │ │ ├── commonMain │ │ │ ├── composeResources │ │ │ │ └── files │ │ │ │ │ └── ltree │ │ │ │ │ ├── albedo.volume.frag │ │ │ │ │ ├── oak.png │ │ │ │ │ ├── leaf.png │ │ │ │ │ ├── spruce.png │ │ │ │ │ └── normal.volume.frag │ │ │ └── kotlin │ │ │ │ ├── ltree │ │ │ │ ├── generator │ │ │ │ │ ├── TreeGenerator.kt │ │ │ │ │ ├── LTree.kt │ │ │ │ │ └── SpruceTreeGenerator.kt │ │ │ │ ├── Util.kt │ │ │ │ └── clusterizer │ │ │ │ │ ├── Clusterizer.kt │ │ │ │ │ └── KMeans.kt │ │ │ │ ├── island │ │ │ │ └── pixelmap │ │ │ │ │ ├── Float2PixelMap.kt │ │ │ │ │ ├── ChannelMap.kt │ │ │ │ │ ├── FloatPixelMap.kt │ │ │ │ │ └── PixelMap.kt │ │ │ │ └── tree │ │ │ │ ├── ImageTool.kt │ │ │ │ └── Metaball.kt │ │ └── desktopMain │ │ │ └── kotlin │ │ │ └── main.kt │ └── build.gradle.kts ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── build.gradle.kts ├── gradle.properties ├── settings.gradle.kts └── .gitignore ├── mkdocs.yml └── .github └── workflows ├── deploy-mkdocs.yml └── deploy-wasm.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea 3 | build -------------------------------------------------------------------------------- /docs/custom.md: -------------------------------------------------------------------------------- 1 | # Custom shaders 2 | -------------------------------------------------------------------------------- /readme/web.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/readme/web.jpg -------------------------------------------------------------------------------- /readme/desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/readme/desktop.jpg -------------------------------------------------------------------------------- /readme/mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/readme/mobile.jpg -------------------------------------------------------------------------------- /readme/collage1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/readme/collage1.jpg -------------------------------------------------------------------------------- /readme/korender32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/readme/korender32.png -------------------------------------------------------------------------------- /quickstart/README.md: -------------------------------------------------------------------------------- 1 | This is a Kotlin Multiplatform project with Korender 3D engine targeting Android, Desktop. 2 | 3 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/Shadows.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender 2 | 3 | interface ShadowAlgorithmDeclaration -------------------------------------------------------------------------------- /korender-framework/examples/korender32.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/korender32.ico -------------------------------------------------------------------------------- /korender-framework/examples/korender32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/korender32.png -------------------------------------------------------------------------------- /korender-framework/examples/src/webMain/resources/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "display": "fullscreen", 3 | "orientation": "landscape" 4 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/gl/GLBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | expect class GLBuffer -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/gl/GLProgram.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | expect class GLProgram -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/gl/GLShader.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | expect class GLShader -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/gl/GLTexture.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | expect class GLTexture -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/composeResources/files/ltree/albedo.volume.frag: -------------------------------------------------------------------------------- 1 | vec4 pluginAlbedo() { 2 | return volumeAlbedo; 3 | } -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | QuickStart 3 | -------------------------------------------------------------------------------- /quickstart/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/quickstart/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/gl/GLFrameBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | expect class GLFrameBuffer -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/gl/GLVertexArray.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | expect class GLVertexArray -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/normal.pipe.frag: -------------------------------------------------------------------------------- 1 | vec3 pluginNormal() { 2 | return pipeNormal; 3 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/gl/GLUniformLocation.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | expect class GLUniformLocation -------------------------------------------------------------------------------- /korender-framework/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /korender-framework/korender/src/androidMain/kotlin/impl/gl/GLBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | actual class GLBuffer(internal val buffer: Int) -------------------------------------------------------------------------------- /korender-framework/korender/src/androidMain/kotlin/impl/gl/GLProgram.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | actual class GLProgram(internal val program: Int) -------------------------------------------------------------------------------- /korender-framework/korender/src/androidMain/kotlin/impl/gl/GLShader.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | actual class GLShader(internal val glHandle: Int) -------------------------------------------------------------------------------- /korender-framework/korender/src/androidMain/kotlin/impl/gl/GLTexture.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | actual class GLTexture(internal val texture: Int) -------------------------------------------------------------------------------- /korender-framework/korender/src/androidMain/kotlin/impl/gl/GLUniformLocation.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | actual class GLUniformLocation(val glHandle: Int) -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/output.normal.frag: -------------------------------------------------------------------------------- 1 | vec4 pluginOutput() { 2 | return vec4((normal + 1.) * 0.5, 1.0); 3 | } -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/kotlin/ltree/generator/TreeGenerator.kt: -------------------------------------------------------------------------------- 1 | package ltree.generator 2 | 3 | interface TreeGenerator { 4 | fun generateTree(): LTree 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/androidMain/kotlin/impl/gl/GLFrameBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | actual class GLFrameBuffer(internal val frameBuffer: Int) -------------------------------------------------------------------------------- /quickstart/composeApp/src/webMain/resources/styles.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | width: 100%; 3 | height: 100%; 4 | margin: 0; 5 | padding: 0; 6 | overflow: hidden; 7 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/webMain/resources/styles.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | width: 100%; 3 | height: 100%; 4 | margin: 0; 5 | padding: 0; 6 | overflow: hidden; 7 | } -------------------------------------------------------------------------------- /quickstart/composeApp/src/commonMain/composeResources/files/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/quickstart/composeApp/src/commonMain/composeResources/files/icon.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Korender Demo 4 | -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/quickstart/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/quickstart/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/quickstart/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/quickstart/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/fbm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/korender/src/commonMain/composeResources/files/fbm.png -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/quickstart/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/composeResources/files/ltree/oak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/baker/src/commonMain/composeResources/files/ltree/oak.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/korender/src/commonMain/composeResources/files/noise.png -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/emission.factor.frag: -------------------------------------------------------------------------------- 1 | #uniform vec3 emissionFactor; 2 | 3 | vec3 pluginEmission() { 4 | return emissionFactor; 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/vnormal.skinning.vert: -------------------------------------------------------------------------------- 1 | vec3 pluginVNormal() { 2 | return mat3(transpose(inverse(model * skinningMatrix))) * normal; 3 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/Materials.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender 2 | 3 | interface MaterialModifier 4 | 5 | interface PostShadingEffect 6 | 7 | interface PostProcessingEffect -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/quickstart/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/quickstart/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/quickstart/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/composeResources/files/ltree/leaf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/baker/src/commonMain/composeResources/files/ltree/leaf.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/drawable/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/drawable/menu.png -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/math/FloatMath.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.math 2 | 3 | object FloatMath { 4 | val PI = kotlin.math.PI.toFloat() 5 | val PIdiv2 = PI * 0.5f 6 | } -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/quickstart/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/quickstart/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/composeResources/files/ltree/spruce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/baker/src/commonMain/composeResources/files/ltree/spruce.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ffffff 4 | -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/cube/sea/nx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/cube/sea/nx.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/cube/sea/ny.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/cube/sea/ny.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/cube/sea/nz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/cube/sea/nz.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/cube/sea/px.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/cube/sea/px.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/cube/sea/py.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/cube/sea/py.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/cube/sea/pz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/cube/sea/pz.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/infcity/dw.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/infcity/dw.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/infcity/lw.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/infcity/lw.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/model/head.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/model/head.jpg -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/font/anta.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/korender/src/commonMain/composeResources/files/font/anta.ttf -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/depth.log.frag: -------------------------------------------------------------------------------- 1 | #import "$vprojection" 2 | 3 | float pluginDepth() { 4 | return log2(vdepth) / log2(projectionFar + 1.0); 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/webMain/kotlin/impl/gl/GLShader.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | import org.khronos.webgl.WebGLShader 4 | 5 | actual class GLShader(internal val shader: WebGLShader) -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/drawable/korender32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/drawable/korender32.png -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/cube/room/nx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/cube/room/nx.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/cube/room/ny.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/cube/room/ny.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/cube/room/nz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/cube/room/nz.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/cube/room/px.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/cube/room/px.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/cube/room/py.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/cube/room/py.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/cube/room/pz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/cube/room/pz.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/font/orbitron.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/font/orbitron.ttf -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/gltf/ai/swat.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/gltf/ai/swat.glb -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/infcity/moon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/infcity/moon.png -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/infcity/road.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/infcity/road.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/infcity/roof.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/infcity/roof.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/infcity/tree.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/infcity/tree.glb -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/texture/brick.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/texture/brick.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/texture/decal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/texture/decal.png -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/texture/grass.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/texture/grass.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/texture/splat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/texture/splat.png -------------------------------------------------------------------------------- /korender-framework/korender/src/webMain/kotlin/impl/gl/GLTexture.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | import org.khronos.webgl.WebGLTexture 4 | 5 | actual class GLTexture(internal val texture: WebGLTexture) -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-hdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-hdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-hdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-hdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-mdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-mdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-mdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-mdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/gui/slider.empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/korender/src/commonMain/composeResources/files/gui/slider.empty.png -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/gui/slider.left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/korender/src/commonMain/composeResources/files/gui/slider.left.png -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/gui/slider.right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/korender/src/commonMain/composeResources/files/gui/slider.right.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-xhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-xhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-xhdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-xhdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-xxhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-xxhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-xxhdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-xxhdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/infcity/swat-woman.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/infcity/swat-woman.glb -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/texture/korender32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/texture/korender32.png -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/gui/joystick.inner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/korender/src/commonMain/composeResources/files/gui/joystick.inner.png -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/gui/joystick.outer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/korender/src/commonMain/composeResources/files/gui/joystick.outer.png -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/gui/slider.handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/korender/src/commonMain/composeResources/files/gui/slider.handle.png -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/albedo.radiant.frag: -------------------------------------------------------------------------------- 1 | uniform samplerCube colorCubeTexture; 2 | 3 | vec4 pluginAlbedo() { 4 | return texture(colorCubeTexture, radiantDir); 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/emission.texture.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D emissionTexture; 2 | 3 | vec3 pluginEmission() { 4 | return texture(emissionTexture, vtex).rgb; 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/occlusion.texture.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D occlusionTexture; 2 | 3 | float pluginOcclusion() { 4 | return texture(occlusionTexture, vtex).r; 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/desktopMain/kotlin/impl/gl/GLBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | actual class GLBuffer(internal val glHandle: Int) { 4 | override fun toString() = glHandle.toString() 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/desktopMain/kotlin/impl/gl/GLProgram.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | actual class GLProgram(internal val glHandle: Int) { 4 | override fun toString() = glHandle.toString() 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/desktopMain/kotlin/impl/gl/GLShader.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | actual class GLShader(internal val glHandle: Int) { 4 | override fun toString() = glHandle.toString() 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/desktopMain/kotlin/impl/gl/GLTexture.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | actual class GLTexture(internal val glHandle: Int) { 4 | override fun toString() = glHandle.toString() 5 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/island/models/plane.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/island/models/plane.glb -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/island/terrain/runway.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/island/terrain/runway.jpg -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/gui/checkbox.checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/korender/src/commonMain/composeResources/files/gui/checkbox.checked.png -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/gui/progressbar.empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/korender/src/commonMain/composeResources/files/gui/progressbar.empty.png -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/terrain/terrain-albedo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/terrain/terrain-albedo.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/terrain/terrain-height.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/terrain/terrain-height.png -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/texture/asphalt-albedo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/texture/asphalt-albedo.jpg -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/texture/asphalt-normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/examples/src/commonMain/composeResources/files/texture/asphalt-normal.jpg -------------------------------------------------------------------------------- /korender-framework/korender/src/androidMain/kotlin/impl/gl/GLVertexArray.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | actual class GLVertexArray(internal val glHandle: Int) { 4 | override fun toString() = glHandle.toString() 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/gui/checkbox.unchecked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/korender/src/commonMain/composeResources/files/gui/checkbox.unchecked.png -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/gui/progressbar.filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zakgof/korender/HEAD/korender-framework/korender/src/commonMain/composeResources/files/gui/progressbar.filled.png -------------------------------------------------------------------------------- /korender-framework/korender/src/desktopMain/kotlin/impl/gl/GLFrameBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | actual class GLFrameBuffer(internal val glHandle: Int) { 4 | override fun toString() = glHandle.toString() 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/desktopMain/kotlin/impl/gl/GLUniformLocation.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | actual class GLUniformLocation(val glHandle: Int) { 4 | override fun toString() = glHandle.toString() 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/webMain/kotlin/impl/gl/GLFrameBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | import org.khronos.webgl.WebGLFramebuffer 4 | 5 | actual class GLFrameBuffer(internal val frameBuffer: WebGLFramebuffer?) -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/normal.radiant.frag: -------------------------------------------------------------------------------- 1 | uniform samplerCube normalCubeTexture; 2 | 3 | vec3 pluginNormal() { 4 | return texture(normalCubeTexture, radiantDir).rgb * 2. - 1.; 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/webMain/kotlin/impl/gl/GLVertexArray.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | import com.zakgof.korender.WebGLVertexArray 4 | 5 | actual class GLVertexArray(internal val vertexArray: WebGLVertexArray) -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/infcity/Tools.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples.infcity 2 | 3 | import kotlin.random.Random 4 | 5 | fun Int.chance(block: () -> Unit) { 6 | if (Random.nextInt(100) < this) block() 7 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/lib/noise.glsl: -------------------------------------------------------------------------------- 1 | mat2 msw = mat2(1.6, 1.2, -1.2, 1.6); 2 | 3 | uniform sampler2D fbmTexture; 4 | 5 | float fbm(vec2 uv) { 6 | return texture(fbmTexture, uv).r; 7 | } 8 | -------------------------------------------------------------------------------- /korender-framework/korender/src/desktopMain/kotlin/impl/gl/GLVertexArray.desktop.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | actual class GLVertexArray(internal val glHandle: Int) { 4 | override fun toString() = glHandle.toString() 5 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/island/tree/shader/island.foliage.discard.frag: -------------------------------------------------------------------------------- 1 | bool pluginDiscard() { 2 | float d = 1.0 - abs(dot(normalize(vpos - cameraPos), normal)); 3 | return albedo.a < max(0.12, d); 4 | } -------------------------------------------------------------------------------- /quickstart/gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.code.style=official 2 | 3 | #Gradle 4 | org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M" 5 | 6 | #Android 7 | android.nonTransitiveRClass=true 8 | android.useAndroidX=true -------------------------------------------------------------------------------- /korender-framework/korender/src/webMain/kotlin/impl/gl/GLUniformLocation.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | import org.khronos.webgl.WebGLUniformLocation 4 | 5 | actual class GLUniformLocation(val uniformLocation: WebGLUniformLocation) 6 | 7 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/metallic_roughness.texture.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D metallicRoughnessTexture; 2 | 3 | vec2 pluginMetallicRoughness() { 4 | return texture(metallicRoughnessTexture, vtex).bg; 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/specular_glossiness.texture.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D specularGlossinessTexture; 2 | 3 | vec4 pluginSpecularGlossiness() { 4 | return texture(specularGlossinessTexture, vtex); 5 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/sky.texture.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D skyTexture; 2 | 3 | vec3 sky(vec3 look, float bias) { 4 | vec2 uv = skydiskfrom(look, 2.5); 5 | return texture(skyTexture, uv, bias).rgb; 6 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/sky.cube.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/noisebias.glsl" 2 | 3 | uniform samplerCube cubeTexture; 4 | 5 | vec3 sky(vec3 look, float bias) { 6 | return texture(cubeTexture, look, bias).rgb; 7 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/webMain/kotlin/impl/gl/GLBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | import org.khronos.webgl.WebGLBuffer 4 | 5 | actual class GLBuffer(internal val buffer: WebGLBuffer) { 6 | override fun toString() = buffer.toString() 7 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/depth.pipe.frag: -------------------------------------------------------------------------------- 1 | #import "$vprojection" 2 | 3 | float pluginDepth() { 4 | vec4 vclip = pluginVProjection((view * vec4(position, 1.0)).xyz); 5 | return 0.5 * vclip.z / vclip.w + 0.5; 6 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/depth.radiant.frag: -------------------------------------------------------------------------------- 1 | #import "$vprojection" 2 | 3 | float pluginDepth() { 4 | vec4 vclip = pluginVProjection((view * vec4(position, 1.0)).xyz); 5 | return 0.5 * vclip.z / vclip.w + 0.5; 6 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/output.radiant.frag: -------------------------------------------------------------------------------- 1 | #uniform float radiantMax; 2 | 3 | vec4 pluginOutput() { 4 | float radiant = length(cameraPos - vpos) / radiantMax; 5 | return vec4(radiant, radiant, radiant, 1.0); 6 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/webMain/kotlin/impl/gl/GLProgram.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gl 2 | 3 | import org.khronos.webgl.WebGLProgram 4 | 5 | actual class GLProgram(internal val program: WebGLProgram) { 6 | override fun toString() = program.toString() 7 | } -------------------------------------------------------------------------------- /quickstart/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.androidApplication) apply false 3 | alias(libs.plugins.jetbrainsCompose) apply false 4 | alias(libs.plugins.compose.compiler) apply false 5 | alias(libs.plugins.kotlinMultiplatform) apply false 6 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/specular_glossiness.factor.frag: -------------------------------------------------------------------------------- 1 | #uniform vec3 specularFactor; 2 | #uniform float glossinessFactor; 3 | 4 | vec4 pluginSpecularGlossiness() { 5 | return vec4(specularFactor, glossinessFactor); 6 | } -------------------------------------------------------------------------------- /quickstart/composeApp/src/webMain/kotlin/main.kt: -------------------------------------------------------------------------------- 1 | import androidx.compose.ui.ExperimentalComposeUiApi 2 | import androidx.compose.ui.window.ComposeViewport 3 | 4 | @OptIn(ExperimentalComposeUiApi::class) 5 | fun main() { 6 | ComposeViewport { 7 | App() 8 | } 9 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/screen.vert: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | 3 | layout(location = 2) in vec2 tex; 4 | out vec2 vtex; 5 | 6 | void main() { 7 | vtex = tex; 8 | gl_Position = vec4((tex * 2.0) - 1.0, -1.0, 1.0); 9 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/buffer/NativeBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.buffer 2 | 3 | expect interface NativeBuffer { 4 | fun rewind(): NativeBuffer 5 | fun size(): Int 6 | fun position(): Int 7 | fun position(offset: Int) 8 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/glgpu/GLBindableTexture.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.glgpu 2 | 3 | import com.zakgof.korender.impl.gl.GLTexture 4 | 5 | internal interface GLBindableTexture { 6 | val glHandle: GLTexture 7 | fun bind(unit: Int) 8 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/lib/header.glsl: -------------------------------------------------------------------------------- 1 | #ifdef OPENGL 2 | #version 330 3 | #else 4 | #version 300 es 5 | precision highp float; 6 | precision highp int; 7 | precision highp sampler2D; 8 | precision highp sampler2DShadow; 9 | #endif 10 | -------------------------------------------------------------------------------- /quickstart/composeApp/src/desktopMain/kotlin/main.kt: -------------------------------------------------------------------------------- 1 | import androidx.compose.ui.window.Window 2 | import androidx.compose.ui.window.application 3 | 4 | fun main() = application { 5 | Window( 6 | onCloseRequest = ::exitApplication, 7 | title = "QuickStart", 8 | ) { 9 | App() 10 | } 11 | } -------------------------------------------------------------------------------- /quickstart/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/sky/sky.vert: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | 4 | layout(location = 2) in vec2 tex; 5 | 6 | out vec2 vtex; 7 | 8 | void main() { 9 | vtex = tex; 10 | gl_Position = vec4((tex * 2.0) - 1.0, 1.0, 1.0); 11 | } -------------------------------------------------------------------------------- /korender-framework/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/camera/Camera.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.camera 2 | 3 | import com.zakgof.korender.CameraDeclaration 4 | import com.zakgof.korender.math.Mat4 5 | import com.zakgof.korender.math.Vec3 6 | 7 | internal interface Camera: CameraDeclaration { 8 | val mat4: Mat4 9 | } 10 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/lib/noisebias.glsl: -------------------------------------------------------------------------------- 1 | mat2 msw = mat2(1.6, 1.2, -1.2, 1.6); 2 | 3 | uniform sampler2D fbmTexture; 4 | 5 | float fbm(vec2 uv) { 6 | return texture(fbmTexture, uv).r; 7 | } 8 | 9 | float fbm2(vec2 uv, float bias) { 10 | return texture(fbmTexture, uv, bias).r; 11 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/gui/image.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | 3 | in vec2 vtex; 4 | 5 | out vec4 fragColor; 6 | 7 | uniform sampler2D imageTexture; 8 | 9 | void main() { 10 | vec4 texel = texture(imageTexture, vtex); 11 | fragColor = vec4(texel.rgb * texel.a, texel.a); 12 | } -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/infcity/Triangulation.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples.infcity 2 | 3 | import com.zakgof.korender.math.Vec2 4 | import com.zakgof.korender.math.Vec3 5 | 6 | interface Triangulation { 7 | val points: List 8 | val normals: List 9 | val texs: List 10 | val indexes: List 11 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/effect/identity.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | 3 | in vec2 vtex; 4 | 5 | uniform sampler2D colorInputTexture; 6 | uniform sampler2D depthInputTexture; 7 | 8 | void main() { 9 | gl_FragColor = texture(colorInputTexture, vtex); 10 | gl_FragDepth = texture(depthInputTexture, vtex).r; 11 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/prefab/InternalPrefab.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.prefab 2 | 3 | import com.zakgof.korender.MaterialModifier 4 | import com.zakgof.korender.Prefab 5 | import com.zakgof.korender.context.FrameContext 6 | 7 | interface InternalPrefab : Prefab { 8 | fun render(fc: FrameContext, vararg materialModifiers: MaterialModifier) 9 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/androidMain/kotlin/impl/buffer/NativeBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.buffer 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | actual interface NativeBuffer { 6 | val byteBuffer: ByteBuffer 7 | actual fun rewind(): NativeBuffer 8 | actual fun size(): Int 9 | actual fun position(): Int 10 | actual fun position(offset: Int) 11 | } 12 | -------------------------------------------------------------------------------- /korender-framework/korender/src/desktopMain/kotlin/impl/buffer/NativeBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.buffer 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | actual interface NativeBuffer { 6 | val byteBuffer: ByteBuffer 7 | actual fun rewind(): NativeBuffer 8 | actual fun size(): Int 9 | actual fun position(): Int 10 | actual fun position(offset: Int) 11 | } 12 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/gui/font.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | 3 | in vec2 vtex; 4 | #uniform vec4 color; 5 | uniform sampler2D fontTexture; 6 | 7 | #uniforms 8 | 9 | out vec4 fragColor; 10 | 11 | void main() { 12 | vec4 texel = texture(fontTexture, vtex) * color; 13 | fragColor = vec4(texel.rgb * texel.a, texel.a); 14 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/webMain/kotlin/impl/buffer/NativeBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.buffer 2 | 3 | import org.khronos.webgl.ArrayBufferView 4 | 5 | actual interface NativeBuffer { 6 | val array: ArrayBufferView 7 | actual fun rewind(): NativeBuffer 8 | actual fun size(): Int 9 | actual fun position(): Int 10 | actual fun position(offset: Int) 11 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/lib/skyibl.glsl: -------------------------------------------------------------------------------- 1 | vec3 skyibl(vec3 N, vec3 V, float roughness, vec3 diffFactor, vec3 specFactor) { 2 | vec3 R = reflect(-V, N); 3 | float maxBias = 8.; // TODO ! Get from da sky 4 | vec3 envDiffuse = sky(N, maxBias) * diffFactor; 5 | vec3 envSpec = sky(R, roughness * maxBias) * specFactor; 6 | return envDiffuse + envSpec; 7 | } -------------------------------------------------------------------------------- /quickstart/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .kotlin 3 | .gradle 4 | **/build/ 5 | xcuserdata 6 | !src/**/build/ 7 | local.properties 8 | .idea 9 | .DS_Store 10 | captures 11 | .externalNativeBuild 12 | .cxx 13 | *.xcodeproj/* 14 | !*.xcodeproj/project.pbxproj 15 | !*.xcodeproj/xcshareddata/ 16 | !*.xcodeproj/project.xcworkspace/ 17 | !*.xcworkspace/contents.xcworkspacedata 18 | **/xcshareddata/WorkspaceSettings.xcsettings 19 | -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /korender-framework/examples/src/webMain/kotlin/main.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof 2 | 3 | import androidx.compose.ui.ExperimentalComposeUiApi 4 | import androidx.compose.ui.window.ComposeViewport 5 | import com.zakgof.korender.examples.AppExample 6 | import kotlinx.browser.document 7 | 8 | @OptIn(ExperimentalComposeUiApi::class) 9 | fun main() { 10 | ComposeViewport(document.body!!) { 11 | AppExample() 12 | } 13 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/context/PipeMeshContext.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.context 2 | 3 | import com.zakgof.korender.math.Vec3 4 | 5 | interface PipeMeshContext { 6 | fun sequence(block: PipeMeshSequenceContext.() -> Unit) 7 | fun cycle(block: PipeMeshSequenceContext.() -> Unit) 8 | } 9 | 10 | interface PipeMeshSequenceContext { 11 | fun node(position: Vec3, radius: Float) 12 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/lib/space.glsl: -------------------------------------------------------------------------------- 1 | #import "$vprojection" 2 | 3 | vec3 screenToWorldSpace(vec2 vtex, float depth) { 4 | vec4 viewPosition = screenToViewSpace(vtex, depth); 5 | return (inverse(view) * viewPosition).xyz; 6 | } 7 | 8 | vec3 screenToLook(vec2 vtex) { 9 | vec3 worldPos = screenToWorldSpace(vtex, 0.5); 10 | return normalize(worldPos - cameraPos); 11 | } 12 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/Matrices.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender 2 | 3 | import com.zakgof.korender.math.Vec3 4 | 5 | interface ProjectionDeclaration { 6 | val width: Float 7 | val height: Float 8 | val near: Float 9 | val far: Float 10 | } 11 | 12 | interface ProjectionMode 13 | 14 | interface CameraDeclaration { 15 | val position: Vec3 16 | val direction: Vec3 17 | val up: Vec3 18 | } -------------------------------------------------------------------------------- /quickstart/composeApp/src/webMain/resources/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Korender Quick Start 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/gui/image.vert: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | 4 | layout(location = 2) in vec2 tex; 5 | out vec2 vtex; 6 | 7 | #uniform vec2 pos; 8 | #uniform vec2 size; 9 | #uniforms 10 | 11 | void main() { 12 | vtex = vec2(tex.x, 1.0 - tex.y); 13 | vec2 quad = pos + tex * size; 14 | gl_Position = vec4((quad * 2.0) - 1.0, -1.0, 1.0); 15 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/vprojection.fixedyrange.vert: -------------------------------------------------------------------------------- 1 | #uniform float fixedYMin; 2 | #uniform float fixedYMax; 3 | 4 | vec4 pluginVProjection(vec3 viewPos) { 5 | return vec4( 6 | viewPos.x * 2. / projectionWidth, 7 | viewPos.y * 2. / projectionHeight, 8 | vpos.y * 2.0 / (fixedYMin - fixedYMax) - (fixedYMin + fixedYMax) / (fixedYMin - fixedYMax), 9 | 1.0 10 | ); 11 | } -------------------------------------------------------------------------------- /korender-framework/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.kotlinMultiplatform) apply false 3 | alias(libs.plugins.androidKotlinMultiplatformLibrary) apply false 4 | alias(libs.plugins.androidApplication) apply false 5 | alias(libs.plugins.jetbrainsCompose) apply false 6 | alias(libs.plugins.composeCompiler) apply false 7 | alias(libs.plugins.kotlinSerialization) apply false 8 | alias(libs.plugins.vanniktech.mavenPublish) apply false 9 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/buffer/NativeFloatBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.buffer 2 | 3 | expect class NativeFloatBuffer(size: Int) : NativeBuffer { 4 | fun put(v: Float) 5 | override fun rewind(): NativeFloatBuffer 6 | override fun size(): Int 7 | override fun position(): Int 8 | override fun position(offset: Int) 9 | } 10 | 11 | fun NativeFloatBuffer.put(v: FloatArray) { 12 | v.forEach { put(it) } 13 | } -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/kotlin/com/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example 2 | 3 | import App 4 | import android.os.Bundle 5 | import androidx.activity.ComponentActivity 6 | import androidx.activity.compose.setContent 7 | 8 | class MainActivity : ComponentActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | setContent { 12 | App() 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /korender-framework/baker/src/desktopMain/kotlin/main.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.baker 2 | 3 | import androidx.compose.ui.window.Window 4 | import androidx.compose.ui.window.application 5 | import ltree.LTreeBaker 6 | 7 | fun main() = application { 8 | Window( 9 | onCloseRequest = ::exitApplication, 10 | title = "Korender Baker" 11 | ) { 12 | LTreeBaker() 13 | // BillboardTreeBaker() 14 | // RadiantTreeBaker() 15 | } 16 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/webMain/resources/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Korender Demo 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/deferred/composition-bloom.glsl: -------------------------------------------------------------------------------- 1 | uniform sampler2D bloomTexture; 2 | uniform sampler2D bloomDepth; 3 | #uniform float bloomAmount; 4 | 5 | void compositionBloom() { 6 | vec4 bloomSample = texture(bloomTexture, vtex); 7 | float bDepth = texture(bloomDepth, vtex).r; 8 | float depthRatio = 1.0 - smoothstep(depth - 0.1, depth + 0.1, bDepth); 9 | color += bloomSample.rgb * depthRatio * bloomAmount; 10 | } 11 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/gui/font.vert: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | 3 | layout(location = 2) in vec2 tex; 4 | layout(location = 11) in vec4 insttexrect; 5 | layout(location = 12) in vec4 instscreenrect; 6 | 7 | out vec2 vtex; 8 | 9 | void main() { 10 | vtex = insttexrect.xy + tex * insttexrect.zw; 11 | vec2 screen = instscreenrect.xy + tex * instscreenrect.zw; 12 | gl_Position = vec4((screen * 2.0) - 1.0, -1.0, 1.0); 13 | } -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/kotlin/island/pixelmap/Float2PixelMap.kt: -------------------------------------------------------------------------------- 1 | package island.pixelmap 2 | 3 | import java.awt.image.BufferedImage 4 | 5 | class Float2PixelMap(side: Int) : FloatPixelMap(side) { 6 | 7 | override val imageType = BufferedImage.TYPE_3BYTE_BGR 8 | 9 | override val pixelChannels = 3 10 | 11 | override fun fillPixel(value: Float, pixel: IntArray) { 12 | val h = (value * 65535).toInt() 13 | pixel[0] = h and 255 14 | pixel[1] = h shr 8 15 | } 16 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/infcity/moon.secsky.plugin.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D moonTexture; 2 | 3 | vec3 pluginSecsky(vec3 look, vec3 color) { 4 | 5 | vec2 uve = skydiskfromlook(look, 1.5); 6 | 7 | vec2 tex = (uve - vec2(0.48, 0.85)) * 24.0; 8 | 9 | if (tex.x > 0.0 && tex.x < 1.0 && tex.y > 0.0 && tex.y < 1.0) { 10 | vec4 moon = texture(moonTexture, tex); 11 | color = moon.rgb * moon.a + color * (1.0 - moon.a); 12 | } 13 | return color; 14 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/kotlin/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender 2 | 3 | import android.os.Bundle 4 | import androidx.activity.ComponentActivity 5 | import androidx.activity.compose.setContent 6 | import com.zakgof.korender.examples.AppExample 7 | 8 | class MainActivity : ComponentActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | setContent { 12 | AppExample() 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /korender-framework/gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.code.style=official 2 | 3 | #Gradle 4 | org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M" 5 | 6 | 7 | #Android 8 | android.nonTransitiveRClass=true 9 | android.useAndroidX=true 10 | 11 | #MPP 12 | kotlin.mpp.androidSourceSetLayoutVersion=2 13 | 14 | #Development 15 | development=true 16 | 17 | org.jetbrains.compose.experimental.jscanvas.enabled=true 18 | 19 | #Korender 20 | korenderVersion = 0.7.0 21 | korenderVersionSuffix = -SNAPSHOT -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/effect/env-debug.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/sky.glsl" 3 | 4 | in vec2 vtex; 5 | 6 | uniform samplerCube envTexture0; 7 | 8 | #uniforms 9 | 10 | out vec4 fragColor; 11 | 12 | void main() { 13 | 14 | vec3 look = screenToLook(vtex); 15 | 16 | vec3 color = texture(envTexture0, look).rgb; 17 | // float d = pow(max(dot(look, vec3(0., 0., -1.)), 0.), 200.); 18 | 19 | fragColor = vec4(color, 1.); 20 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/infcity/window.emission.plugin.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D windowTexture; 2 | uniform sampler2D noiseTexture; 3 | 4 | vec3 pluginEmission() { 5 | 6 | float delta = fract(vpos.x); 7 | vec2 uv = delta < 0.001 || delta > 0.999 ? vpos.zy : vpos.xy; 8 | 9 | float noise = textureLod(noiseTexture, 0.01 * floor(uv) + vec2(time * 0.0002), 0.0).r; 10 | vec3 emission = textureLod(windowTexture, vtex, 0.0).rgb; 11 | 12 | return emission * step(0.52, noise); 13 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/effect/fxaa.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | 4 | in vec2 vtex; 5 | 6 | uniform sampler2D colorInputTexture; 7 | uniform sampler2D depthInputTexture; 8 | 9 | out vec4 fragColor; 10 | 11 | #import "!shader/lib/fxaa.glsl" 12 | 13 | void main() { 14 | vec3 color = fxaa(colorInputTexture, vtex, screenWidth, screenHeight); 15 | fragColor = vec4(color, 1.0); 16 | gl_FragDepth = texture(depthInputTexture, vtex).r; 17 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/procterrain/height.glsl: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/noise.glsl" 2 | 3 | vec3 pluginTerrainCenter() { 4 | return vec3(0., -14., 0.); 5 | } 6 | 7 | int pluginTerrainTextureSize() { 8 | return 1024; 9 | } 10 | 11 | float pluginTerrainHeight(vec2 uv) { 12 | return -1500.0 13 | + 100.0 * fbm(uv * 0.6) 14 | + 400.0 * fbm(uv * 0.2) 15 | + 281.0 * sin(uv.x * 2.3) 16 | + 1000.0 * sin(uv.x * 0.3) 17 | + 281.0 * cos(uv.y * 2.3) 18 | + 1000.0 * cos(uv.y * 0.3); 19 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/engine/Retention.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.engine 2 | 3 | import com.zakgof.korender.RetentionPolicy 4 | 5 | internal object ImmediatelyFreeRetentionPolicy: RetentionPolicy 6 | 7 | internal object KeepForeverRetentionPolicy: RetentionPolicy 8 | 9 | internal class UntilGenerationRetentionPolicy(val generation: Int) : RetentionPolicy 10 | 11 | internal class TimeRetentionPolicy(val seconds: Float) : RetentionPolicy 12 | 13 | internal interface Retentionable { 14 | val retentionPolicy: RetentionPolicy 15 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/normal.texture.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D normalTexture; 2 | 3 | vec3 pluginNormal() { 4 | vec3 tangentNormal = texture(normalTexture, vtex).rgb * 2.0 - 1.0; 5 | 6 | vec3 Q1 = dFdx(vpos); 7 | vec3 Q2 = dFdy(vpos); 8 | vec2 st1 = dFdx(vtex); 9 | vec2 st2 = dFdy(vtex); 10 | 11 | vec3 N = normalize(vnormal); 12 | vec3 T = normalize(Q1 * st2.t - Q2 * st1.t); 13 | vec3 B = cross(N, T); 14 | 15 | mat3 TBN = mat3(T, B, N); 16 | return normalize(TBN * tangentNormal); 17 | } -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/kotlin/ltree/generator/LTree.kt: -------------------------------------------------------------------------------- 1 | package ltree.generator 2 | 3 | import com.zakgof.korender.math.Vec3 4 | 5 | class LTree( 6 | val branches: List, 7 | val leaves: List, 8 | ) { 9 | 10 | interface Branch { 11 | val head: Vec3 12 | val tail: Vec3 13 | var raidusAtHead: Float 14 | var raidusAtTail: Float 15 | } 16 | 17 | class Leaf( 18 | val mount: Vec3, 19 | val blade: Vec3, 20 | val normal: Vec3, 21 | val width: Float 22 | ) 23 | 24 | } 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/engine/shadow/ShadowAlgorithms.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.engine.shadow 2 | 3 | import com.zakgof.korender.ShadowAlgorithmDeclaration 4 | 5 | internal class InternalVsmShadow(val blurRadius: Float?) : ShadowAlgorithmDeclaration 6 | 7 | internal class InternalHardShadow : ShadowAlgorithmDeclaration 8 | 9 | internal class InternalSoftwarePcfShadow(val samples: Int, val blurRadius: Float, val bias: Float) : ShadowAlgorithmDeclaration 10 | 11 | internal class InternalHardwarePcfShadow(val bias: Float) : ShadowAlgorithmDeclaration 12 | 13 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/effect/blurh.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | #import "!shader/lib/blur.glsl" 4 | 5 | in vec2 vtex; 6 | 7 | #uniform float radius; 8 | 9 | #uniforms 10 | 11 | uniform sampler2D colorInputTexture; 12 | uniform sampler2D depthInputTexture; 13 | 14 | out vec4 fragColor; 15 | 16 | void main() { 17 | fragColor = vec4(blur(colorInputTexture, vtex, radius, vec2(1., 0.), screenWidth), 1.); 18 | gl_FragDepth = minDepthBlur(depthInputTexture, vtex, radius, vec2(1., 0.), screenWidth); 19 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/effect/blurv.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | #import "!shader/lib/blur.glsl" 4 | 5 | in vec2 vtex; 6 | 7 | #uniform float radius; 8 | 9 | #uniforms 10 | 11 | uniform sampler2D colorInputTexture; 12 | uniform sampler2D depthInputTexture; 13 | 14 | out vec4 fragColor; 15 | 16 | void main() { 17 | fragColor = vec4(blur(colorInputTexture, vtex, radius, vec2(0., 1.), screenHeight), 1.); 18 | gl_FragDepth = minDepthBlur(depthInputTexture, vtex, radius, vec2(0., 1.), screenHeight); 19 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/Textures.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender 2 | 3 | interface TextureDeclaration 4 | 5 | interface Texture3DDeclaration 6 | 7 | interface CubeTextureDeclaration 8 | 9 | enum class TextureFilter { 10 | Nearest, 11 | Linear, 12 | MipMap 13 | } 14 | 15 | enum class TextureWrap { 16 | MirroredRepeat, 17 | ClampToEdge, 18 | Repeat 19 | } 20 | 21 | enum class CubeTextureSide { 22 | NX, NY, NZ, PX, PY, PZ 23 | } 24 | 25 | typealias CubeTextureResources = Map 26 | 27 | typealias CubeTextureImages = Map -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/island/building/shader/island.window.albedo.frag: -------------------------------------------------------------------------------- 1 | vec4 pluginAlbedo() { 2 | 3 | vec2 f = fract(vtex); 4 | 5 | vec2 d = 4.0 * fwidth(vtex) * fwidth(vtex); 6 | 7 | float wndratio = 8 | smoothstep(0.2 - d.x, 0.2 + d.x, f.x) * 9 | smoothstep(0.8 + d.x, 0.8 - d.x, f.x) * 10 | smoothstep(0.2 - d.y, 0.2 + d.y, f.y) * 11 | smoothstep(0.8 + d.y, 0.8 - d.y, f.y); 12 | 13 | if (vpos.y < 130.0) 14 | wndratio = 0.; 15 | 16 | return mix(texture(baseColorTexture, vtex), vec4(0.0, 0.0, 0.0, 1.0), wndratio); 17 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/terrain.texture.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D heightTexture; 2 | #uniform float heightScale; 3 | #uniform float outsideHeight; 4 | #uniform vec3 terrainCenter; 5 | 6 | vec3 pluginTerrainCenter() { 7 | return terrainCenter; 8 | } 9 | 10 | int pluginTerrainTextureSize() { 11 | return textureSize(heightTexture, 0).x; 12 | } 13 | 14 | float pluginTerrainHeight(vec2 uv) { 15 | if (uv.x < 0. || uv.x > 1. || uv.y < 0. || uv.y > 1.) 16 | return outsideHeight; 17 | return heightScale * texture(heightTexture, uv).r + terrainCenter.y; 18 | } -------------------------------------------------------------------------------- /korender-framework/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "korender-root" 2 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") 3 | 4 | pluginManagement { 5 | repositories { 6 | maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") 7 | google() 8 | gradlePluginPortal() 9 | mavenCentral() 10 | } 11 | } 12 | 13 | dependencyResolutionManagement { 14 | repositories { 15 | google() 16 | mavenCentral() 17 | maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") 18 | } 19 | } 20 | 21 | include(":korender") 22 | include(":examples") 23 | include(":baker") -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/material/Uniforms.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.material 2 | 3 | import com.zakgof.korender.PostShadingEffect 4 | import com.zakgof.korender.RetentionPolicy 5 | import com.zakgof.korender.impl.engine.InternalPassDeclaration 6 | import com.zakgof.korender.impl.engine.Retentionable 7 | 8 | internal class InternalPostShadingEffect( 9 | val effectPasses: List, 10 | val keepTextures: Set, 11 | val compositionMaterialModifier: InternalMaterialModifier, 12 | override val retentionPolicy: RetentionPolicy 13 | ) : PostShadingEffect, Retentionable 14 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/projection/Projection.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.projection 2 | 3 | import com.zakgof.korender.ProjectionDeclaration 4 | import com.zakgof.korender.ProjectionMode 5 | 6 | internal class Projection ( 7 | override val width: Float, 8 | override val height: Float, 9 | override val near: Float, 10 | override val far: Float, 11 | val mode: ProjectionMode 12 | ) : ProjectionDeclaration 13 | 14 | internal object FrustumProjectionMode: ProjectionMode 15 | 16 | internal object OrthoProjectionMode: ProjectionMode 17 | 18 | internal class LogProjectionMode(c: Float): ProjectionMode -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/island/terrain/shader/height.glsl: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/noise.glsl" 2 | 3 | uniform sampler2D heightTexture; 4 | 5 | vec3 pluginTerrainCenter() { 6 | return vec3(0.); 7 | } 8 | 9 | int pluginTerrainTextureSize() { 10 | return 512; 11 | } 12 | 13 | float pluginTerrainHeight(vec2 uv) { 14 | 15 | if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) 16 | return - 256.0 * 16.0 * 0.1; 17 | 18 | vec4 samp = texture(heightTexture, uv); 19 | 20 | float base = (samp.g * 255.0 + samp.r) * 16.0 - 256.0 * 16.0 * 0.1; 21 | 22 | 23 | return base + 0.3 * fbm(uv * 256.0); 24 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/lib/octa.glsl: -------------------------------------------------------------------------------- 1 | vec2 encodeOcta(vec3 n) { 2 | n /= (abs(n.x) + abs(n.y) + abs(n.z)); 3 | vec2 e = n.xy; 4 | if (n.z < 0.0) 5 | e = (1.0 - abs(e.yx)) * vec2( 6 | e.x >= 0.0 ? 1.0 : -1.0, 7 | e.y >= 0.0 ? 1.0 : -1.0); 8 | return e * 0.5 + 0.5; // map [-1,1] → [0,1] 9 | } 10 | 11 | vec3 decodeOcta(vec2 e) 12 | { 13 | e = e * 2.0 - 1.0; // [0,1] -> [-1,1] 14 | vec3 n = vec3(e.x, e.y, 1.0 - abs(e.x) - abs(e.y)); 15 | float t = clamp(-n.z, 0.0, 1.0); 16 | n.x += (n.x >= 0.0 ? -t : t); 17 | n.y += (n.y >= 0.0 ? -t : t); 18 | return normalize(n); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/normal.terrain.frag: -------------------------------------------------------------------------------- 1 | #ifdef PLUGIN_TERRAIN 2 | #import "$terrain" 3 | #endif 4 | 5 | vec3 pluginNormal() { 6 | 7 | float nstep = 1.0 / float(pluginTerrainTextureSize()); 8 | 9 | float hL = pluginTerrainHeight(vtex + vec2(-nstep, 0.)); 10 | float hR = pluginTerrainHeight(vtex + vec2(nstep, 0.)); 11 | float hD = pluginTerrainHeight(vtex + vec2(0, -nstep)); 12 | float hU = pluginTerrainHeight(vtex + vec2(0, nstep)); 13 | 14 | vec3 dx = normalize(vec3(2.0, hR - hL, 0.0)); 15 | vec3 dz = normalize(vec3(0.0, hU - hD, 2.0)); 16 | 17 | return normalize(cross(dz, dx)); 18 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/position.pipe.frag: -------------------------------------------------------------------------------- 1 | vec3 pipeNormal; 2 | in vec3 vleft; 3 | in vec2 vscale; 4 | 5 | vec3 pluginPosition() { 6 | float cos = (vtex.x - 0.5) * 2.0; 7 | float width = mix(vscale.x, vscale.y, vtex.y); 8 | vec3 flatPos = vpos + vleft * cos + vnormal * vtex.y; 9 | 10 | vec3 toEye = normalize(cameraPos - vpos); 11 | vec3 back = normalize(cross(vnormal, vleft)); 12 | pipeNormal = normalize((vleft * cos + back * sqrt(1.0 - cos * cos)) * length(vnormal) + 13 | normalize(vnormal) * (vscale.y - vscale.x)); 14 | 15 | return vpos - back * width * (1.0 - dot(pipeNormal, toEye)); 16 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/Platform.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender 2 | 3 | import com.zakgof.korender.context.KorenderContext 4 | import com.zakgof.korender.impl.font.FontDef 5 | import com.zakgof.korender.impl.image.InternalImage 6 | import kotlinx.coroutines.Deferred 7 | 8 | internal expect object Platform { 9 | 10 | val target: KorenderContext.TargetPlatform 11 | 12 | internal fun createImage(width: Int, height: Int, format: PixelFormat): InternalImage 13 | 14 | internal fun loadImage(bytes: ByteArray, type: String): Deferred 15 | 16 | internal fun loadFont(bytes: ByteArray): Deferred 17 | 18 | fun nanoTime(): Long 19 | 20 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/lib/sky.glsl: -------------------------------------------------------------------------------- 1 | vec3 lookfromskydisk(vec2 vtex, float distortion) { 2 | vec2 uv = vtex - vec2(0.5); 3 | float angle = 3.1415926 * length(uv); 4 | float dsin = distortion * sin(angle); 5 | return normalize(vec3(uv.x * dsin, length(uv) * cos(angle), uv.y * dsin)); 6 | } 7 | 8 | vec2 skydiskfromlook(vec3 look, float distortion) { 9 | float l = length(look.xz); 10 | float theta = atan(l, look.y * distortion); 11 | return vec2(0.5) + vec2(look.xz) * (theta / (3.1415926 * l)); 12 | } 13 | 14 | vec2 skydisk(vec2 vtex, float distortion) { 15 | vec3 look = screenToLook(vtex); 16 | return skydiskfromlook(look, distortion); 17 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/engine/CaptureContext.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.engine 2 | 3 | import com.zakgof.korender.impl.camera.Camera 4 | import com.zakgof.korender.impl.projection.Projection 5 | import com.zakgof.korender.math.Vec3 6 | 7 | internal class EnvCaptureContext( 8 | val resolution: Int, 9 | val position: Vec3, 10 | val near: Float, 11 | val far: Float, 12 | val insideOut: Boolean, 13 | val sceneDeclaration: SceneDeclaration 14 | ) 15 | 16 | internal class FrameCaptureContext( 17 | val width: Int, 18 | val height: Int, 19 | val camera: Camera, 20 | val projection: Projection, 21 | val sceneDeclaration: SceneDeclaration 22 | ) -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/engine/TouchBox.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.engine 2 | 3 | import com.zakgof.korender.TouchEvent 4 | import com.zakgof.korender.TouchHandler 5 | 6 | internal class TouchBox( 7 | private val x: Int, 8 | private val y: Int, 9 | private val w: Int, 10 | private val h: Int, 11 | val id: Any?, 12 | private val handler: TouchHandler 13 | ) { 14 | fun touch(touchEvent: TouchEvent, forced: Boolean): Boolean { 15 | if (forced || touchEvent.x > x && touchEvent.x < x + w && touchEvent.y > y && touchEvent.y < y + h) { 16 | handler(touchEvent) 17 | return true 18 | } 19 | return false 20 | } 21 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/context/DefaultShadowContext.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.context 2 | 3 | import com.zakgof.korender.ShadowAlgorithmDeclaration 4 | import com.zakgof.korender.context.ShadowContext 5 | import com.zakgof.korender.impl.engine.CascadeDeclaration 6 | import com.zakgof.korender.impl.engine.ShadowDeclaration 7 | 8 | internal class DefaultShadowContext(private val shadowDeclaration: ShadowDeclaration) : ShadowContext { 9 | override fun Cascade(mapSize: Int, near: Float, far: Float, fixedYRange: Pair?, algorithm: ShadowAlgorithmDeclaration) { 10 | shadowDeclaration.cascades += CascadeDeclaration(mapSize, near, far, fixedYRange, algorithm) 11 | } 12 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/context/InstancedContext.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.context 2 | 3 | import com.zakgof.korender.math.Transform 4 | import com.zakgof.korender.math.Vec2 5 | import com.zakgof.korender.math.Vec3 6 | 7 | interface InstancingDeclaration 8 | 9 | interface GltfInstancingDeclaration 10 | 11 | interface BillboardInstancingDeclaration 12 | 13 | interface InstancedBillboardsContext { 14 | fun Instance(pos: Vec3, scale: Vec2 = Vec2(1f, 1f), rotation: Float = 0f) 15 | } 16 | 17 | interface InstancedRenderablesContext { 18 | fun Instance(transform: Transform) 19 | } 20 | 21 | interface InstancedGltfContext { 22 | fun Instance(transform: Transform, time: Float? = null, animation: Int? = null) 23 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/context/ShadowContext.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.context 2 | 3 | import com.zakgof.korender.ShadowAlgorithmDeclaration 4 | 5 | interface ShadowContext { 6 | /** 7 | * Defines a shadow mapping cascade. 8 | * 9 | * @param mapSize shadow texture size 10 | * @param near distance from camera to this cascade's near plane 11 | * @param near distance from camera to this cascade's far plane 12 | * @param fixedYRange optional Y range for occluders for optimization 13 | * @param algorithm shadow mapping algorithm declaration 14 | */ 15 | fun Cascade(mapSize: Int, near: Float, far: Float, fixedYRange: Pair? = null, algorithm: ShadowAlgorithmDeclaration) 16 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/Korender.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender 2 | 3 | import androidx.compose.runtime.Composable 4 | import com.zakgof.korender.context.KorenderContext 5 | 6 | @Composable 7 | expect fun Korender( 8 | appResourceLoader: ResourceLoader = { throw KorenderException("No application resource provided") }, 9 | block: KorenderContext.() -> Unit 10 | ) 11 | 12 | typealias ResourceLoader = suspend (String) -> ByteArray 13 | 14 | class KorenderException(message: String) : RuntimeException(message) 15 | 16 | class FrameInfo( 17 | val frame: Long, 18 | val time: Float, 19 | val dt: Float, 20 | val avgFps: Float, 21 | val pending: Int 22 | ) 23 | 24 | interface Prefab 25 | 26 | interface RetentionPolicy -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/composeResources/files/procterrain/albedo.glsl: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/noise.glsl" 2 | 3 | vec4 pluginAlbedo() { 4 | 5 | vec3 snow = vec3(0.9, 0.9, 0.9); 6 | vec3 rock = vec3(0.5, 0.4, 0.4); 7 | vec3 grass = vec3(0.2, 0.6, 0.3); 8 | 9 | 10 | float snowW = smoothstep(200.0, 201.0, vpos.y + 300.0 * fbm(vtex)); 11 | float rockW = smoothstep(-0.85, -0.84, -vnormal.y); 12 | float grassW = fbm(vtex * 4.0); 13 | 14 | vec3 color = (snow * snowW + 15 | rock * rockW + 16 | grass * grassW) / (snowW + rockW + grassW); 17 | 18 | 19 | float c = 0.25 + 20 | fbm(vtex * 64.0) * 0.5 + 21 | fbm(vtex * 128.0) * 0.25; 22 | 23 | return vec4(color + c, 1.0); 24 | 25 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/Touch.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender 2 | 3 | class TouchEvent(val type: Type, val button: Button, val x: Float, val y: Float) { 4 | 5 | enum class Type { 6 | UP, 7 | DOWN, 8 | MOVE 9 | } 10 | 11 | enum class Button { 12 | NONE, 13 | LEFT, 14 | RIGHT 15 | } 16 | } 17 | 18 | class KeyEvent(val type: Type, val key: String) { 19 | enum class Type { 20 | UP, 21 | DOWN 22 | } 23 | } 24 | 25 | typealias TouchHandler = (TouchEvent) -> Unit 26 | typealias KeyHandler = (KeyEvent) -> Unit 27 | 28 | fun onClick(touchEvent: TouchEvent, clickHandler: () -> Unit) { 29 | if (touchEvent.type == TouchEvent.Type.DOWN) { 30 | clickHandler() 31 | } 32 | } -------------------------------------------------------------------------------- /docs/context.md: -------------------------------------------------------------------------------- 1 | ### Korender and Frame contexts 2 | 3 | To insert Korender rendering viewport into your Compose Multiplatform UI, call the `Korender` function from the parent `@Composable` function: 4 | 5 | ````kotlin 6 | @Composable 7 | fun App() { 8 | Column { 9 | Text("Korender Viewport below !!!") 10 | Korender { 11 | 12 | } 13 | } 14 | } 15 | ```` 16 | 17 | Add initialization code into `Korender` context, per-frame code and renderable objects into `Frame` context: 18 | 19 | ````kotlin 20 | Korender { 21 | // Code here will run once on Korender viewport initialization 22 | Frame { 23 | // Code here will run on every frame 24 | // Place your renderable declaration functions here 25 | } 26 | } 27 | ```` -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/texturing.triplanar.frag: -------------------------------------------------------------------------------- 1 | #uniform float triplanarScale; 2 | 3 | vec4 triplanar(sampler2D tex, vec3 pos, vec3 normal) { 4 | 5 | vec3 blend_weights = abs(normal.xyz); 6 | blend_weights = max(blend_weights, 0.0); 7 | blend_weights /= (blend_weights.x + blend_weights.y + blend_weights.z); 8 | vec4 blended_color; 9 | 10 | vec4 col1 = texture(tex, pos.yz); 11 | vec4 col2 = texture(tex, pos.zx); 12 | vec4 col3 = texture(tex, pos.xy); 13 | 14 | return col1.xyzw * blend_weights.xxxx + 15 | col2.xyzw * blend_weights.yyyy + 16 | col3.xyzw * blend_weights.zzzz; 17 | } 18 | 19 | vec4 pluginTexturing() { 20 | return triplanar(baseColorTexture, vpos * triplanarScale, vnormal); 21 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/lib/normalmap.glsl: -------------------------------------------------------------------------------- 1 | #ifdef NORMAL_MAP 2 | 3 | vec3 getNormalFromMap(vec3 vnormal, vec2 vtex, vec3 vpos) { 4 | 5 | #ifdef TRIPLANAR 6 | vec3 tangentNormal = triplanarNormal(vpos * triplanarScale, vnormal).rgb; 7 | #else 8 | vec3 tangentNormal = texture(normalTexture, vtex).rgb; 9 | #endif 10 | 11 | tangentNormal = tangentNormal * 2.0 - 1.0; // Convert from [0,1] to [-1,1] 12 | 13 | vec3 Q1 = dFdx(vpos); 14 | vec3 Q2 = dFdy(vpos); 15 | vec2 st1 = dFdx(vtex); 16 | vec2 st2 = dFdy(vtex); 17 | 18 | vec3 N = normalize(vnormal); 19 | vec3 T = normalize(Q1 * st2.t - Q2 * st1.t); 20 | vec3 B = cross(N, T); 21 | 22 | mat3 TBN = mat3(T, B, N); 23 | return normalize(TBN * tangentNormal); 24 | } 25 | 26 | #endif -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/effect/adjust.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | 3 | in vec2 vtex; 4 | 5 | #uniform float brightness; // -1..1, 0 is unity 6 | #uniform float contrast; // 0..2, 1 is unity 7 | #uniform float saturation; // 0..inf, 1 is unity 8 | 9 | #uniforms 10 | 11 | uniform sampler2D colorInputTexture; 12 | uniform sampler2D depthInputTexture; 13 | out vec4 fragColor; 14 | 15 | void main() { 16 | vec4 color = texture(colorInputTexture, vtex); 17 | color.rgb += brightness; 18 | color.rgb = ((color.rgb - 0.5) * contrast) + 0.5; 19 | float lumi = dot(color.rgb, vec3(0.299, 0.587, 0.114)); 20 | color.rgb = mix(vec3(lumi), color.rgb, saturation); 21 | fragColor = color; 22 | gl_FragDepth = texture(depthInputTexture, vtex).r; 23 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/webMain/kotlin/impl/buffer/NativeFloatBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.buffer 2 | 3 | import org.khronos.webgl.Float32Array 4 | import org.khronos.webgl.set 5 | 6 | actual class NativeFloatBuffer(override val array: Float32Array) : NativeBuffer { 7 | 8 | actual constructor(size: Int) : this(Float32Array(size)) 9 | 10 | private var position = 0 11 | 12 | actual fun put(v: Float) { 13 | array[position++] = v 14 | } 15 | 16 | actual override fun rewind(): NativeFloatBuffer { 17 | position = 0 18 | return this 19 | } 20 | 21 | actual override fun size(): Int = array.length 22 | 23 | actual override fun position() = position 24 | 25 | actual override fun position(offset: Int) { 26 | position = offset; 27 | } 28 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/sky/sky.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | 4 | in vec2 vtex; 5 | 6 | #uniforms 7 | 8 | out vec4 fragColor; 9 | 10 | #import "!shader/lib/space.glsl" 11 | #import "!shader/lib/sky.glsl" 12 | #import "$sky" 13 | 14 | #ifdef PLUGIN_SECSKY 15 | #import "$secsky" 16 | #endif 17 | 18 | void main() { 19 | 20 | vec3 look = screenToLook(vtex); 21 | vec3 color = sky(look, 0.); 22 | 23 | #ifdef PLUGIN_SECSKY 24 | color = pluginSecsky(look, color); 25 | #endif 26 | 27 | fragColor = vec4(color, 1.); 28 | 29 | vec4 v = vec4(0.0, 0.0, -2.0 , 1.0); 30 | 31 | vec3 w = (inverse(view) * v).xyz; 32 | 33 | // 34 | // if (look.z < -0.9) 35 | // fragColor = vec4(1.0, 0.0, 0.0, 0.999); 36 | } -------------------------------------------------------------------------------- /docs/renderables.md: -------------------------------------------------------------------------------- 1 | ## Renderables basics 2 | 3 | To render objects, add their `Renderable` declarations into the `Frame` context 4 | 5 | ```kotlin 6 | Frame { 7 | Renderable( 8 | base(color = ColorRGBA.Red, metallicFactor = 0f, roughnessFactor = 0.2f), 9 | mesh = sphere(), 10 | transform = translate(-2f, -1f, -5f), 11 | transparent = false 12 | ) 13 | ``` 14 | 15 | A `Renderable` declaration has the following parameters: 16 | 17 | - `materialModifiers` - define the surface material properties of a renderable 18 | - `mesh` - defines the geometry of the object. Internally, a mesh is an indexed list of vertices forming triangles 19 | - `transform` - model space transformation of the object, such as scaling, rotation, or positioning 20 | - `transparent` - flag specifying if the object has any transparency -------------------------------------------------------------------------------- /korender-framework/.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /.fleet 3 | .gradle 4 | .kotlin 5 | build 6 | local.properties 7 | /examples/src/commonMain/composeResources/files/island/building/buildings.bin 8 | /examples/src/commonMain/composeResources/files/island/terrain/color.png 9 | /examples/src/commonMain/composeResources/files/island/terrain/height.png 10 | /examples/src/commonMain/composeResources/files/island/terrain/sdf.png 11 | /examples/src/commonMain/composeResources/files/island/terrain/mountain.png 12 | /examples/src/commonMain/composeResources/files/island/terrain/runway.bin 13 | /examples/src/commonMain/composeResources/files/island/tree/trees.bin 14 | /examples/src/commonMain/composeResources/files/island/tree/cards.bin 15 | /examples/src/commonMain/composeResources/files/island/tree/branches.bin 16 | /examples/src/commonMain/composeResources/files/island/tree/atlas.png -------------------------------------------------------------------------------- /quickstart/gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | agp = "8.13.2" 3 | android-compileSdk = "36" 4 | android-minSdk = "29" 5 | android-targetSdk = "36" 6 | androidx-activityCompose = "1.12.2" 7 | compose-plugin = "1.9.3" 8 | kotlin = "2.3.0" 9 | korender = "0.6.1" 10 | 11 | [libraries] 12 | androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" } 13 | korender = { module = "com.github.zakgof:korender", version.ref = "korender" } 14 | 15 | [plugins] 16 | androidApplication = { id = "com.android.application", version.ref = "agp" } 17 | jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" } 18 | compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } 19 | kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Korender 2 | 3 | **Korender** is a Kotlin Multiplatform 3D graphics rendering engine based on OpenGL / OpenGL ES / WebGL. 4 | 5 | Latest version: **0.6.1** 6 | Github: [https://github.com/zakgof/korender](https://github.com/zakgof/korender) 7 | License: [Apache-2.0](https://github.com/zakgof/korender?tab=Apache-2.0-1-ov-file#) 8 | Web demo: [https://zakgof.github.io/projects/korender/wasm](https://zakgof.github.io/projects/korender/wasm) 9 | 10 | #### Supported platforms 11 | | Platform | 3D API | 12 | |-------------------------|-------------| 13 | | Desktop (Windows/Linux) | OpenGL 3.3 | 14 | | Android | OpenGL ES 3 | 15 | | Web | WebGL 2 | 16 | 17 | There is a partial support for MacOS, however note that OpenGL is officially deprecated starting MacOS 10.14 Mojave. 18 | 19 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Korender Wiki 2 | theme: 3 | name: readthedocs 4 | nav: 5 | - Home: index.md 6 | - User Guide: 7 | - Contexts: context.md 8 | - Asset management: assets.md 9 | - Renderables: renderables.md 10 | - Materials: materials.md 11 | - Meshes: meshes.md 12 | - Projection and camera: projection.md 13 | - Lights and shadows: light.md 14 | - Sky rendering: sky.md 15 | - Environment mapping: env.md 16 | - Post-process filters: filters.md 17 | - Effects: effects.md 18 | - GTLF support: gltf.md 19 | - Terrain: terrain.md 20 | - GUI: gui.md 21 | - Billboards: billboards.md 22 | - Instancing: instancing.md 23 | 24 | - Deferred renderer: deferred.md 25 | - Offscreen rendering: offscreen.md 26 | - Extending Korender: 27 | - Plugins: plugins.md 28 | #- Custom shaders: custom.md 29 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/Images.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender 2 | 3 | import com.zakgof.korender.math.ColorRGBA 4 | 5 | enum class PixelFormat(val bytes: Int) { 6 | RGB(3), 7 | RGBA(4), 8 | Gray(1), 9 | Gray16(2); 10 | } 11 | 12 | interface Image { 13 | 14 | val width: Int 15 | val height: Int 16 | val format: PixelFormat 17 | 18 | fun pixel(x: Int, y: Int): ColorRGBA 19 | 20 | fun setPixel(x: Int, y: Int, color: ColorRGBA) 21 | 22 | fun toTga(): ByteArray 23 | 24 | fun toRaw(): ByteArray 25 | } 26 | 27 | interface Image3D { 28 | 29 | val width: Int 30 | val height: Int 31 | val depth: Int 32 | val format: PixelFormat 33 | 34 | fun pixel(x: Int, y: Int, z: Int): ColorRGBA 35 | 36 | fun setPixel(x: Int, y: Int, z: Int, color: ColorRGBA) 37 | 38 | fun toRaw(): ByteArray 39 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/desktopMain/kotlin/main.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender 2 | 3 | import androidx.compose.material.MaterialTheme 4 | import androidx.compose.material.Scaffold 5 | import androidx.compose.material.darkColors 6 | import androidx.compose.ui.window.Window 7 | import androidx.compose.ui.window.application 8 | import com.zakgof.app.resources.Res 9 | import com.zakgof.app.resources.korender32 10 | import com.zakgof.korender.examples.AppExample 11 | import org.jetbrains.compose.resources.painterResource 12 | 13 | fun main() = application { 14 | Window( 15 | icon = painterResource(Res.drawable.korender32), 16 | onCloseRequest = ::exitApplication, 17 | title = "Korender Demo" 18 | ) { 19 | MaterialTheme(colors = darkColors()) { 20 | Scaffold { 21 | AppExample() 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/kotlin/ltree/Util.kt: -------------------------------------------------------------------------------- 1 | package ltree 2 | 3 | import com.zakgof.korender.math.FloatMath.PI 4 | import com.zakgof.korender.math.Vec3 5 | import com.zakgof.korender.math.x 6 | import com.zakgof.korender.math.y 7 | import kotlin.math.abs 8 | import kotlin.math.cos 9 | import kotlin.math.sin 10 | import kotlin.random.Random 11 | 12 | fun Vec3.randomOrtho(r: Random): Vec3 { 13 | val reference = if (abs(this.x) < 0.99) 1.x else 1.y 14 | val ortho1 = (this % reference).normalize() 15 | val ortho2 = (this % ortho1).normalize() 16 | val angle = r.nextFloat() * 2f * PI 17 | return ortho1 * cos(angle) + ortho2 * sin(angle) 18 | } 19 | 20 | fun Vec3.randomOrtho() = randomOrtho(Random) 21 | 22 | fun Random.floatIn(f1: Float, f2: Float) = f1 + this.nextFloat() * (f2 - f1) 23 | 24 | fun jitter() : Float { 25 | return Random.nextFloat() * 0.2f + 0.9f 26 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/effect/fire.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | #import "!shader/lib/noise.glsl" 4 | 5 | // Inspired by Xavier Benech https://www.shadertoy.com/view/XsXSWS 6 | 7 | in vec3 vpos; 8 | in vec3 vnormal; 9 | in vec2 vtex; 10 | 11 | #uniform float strength; 12 | 13 | #uniforms 14 | 15 | out vec4 fragColor; 16 | 17 | void main() { 18 | vec2 uv = vtex; 19 | vec2 q = vec2((uv.x - 0.5) * 0.4, 1.0 - (uv.y * 2. - 0.50)); 20 | float n = fbm(0.1 * (strength * q - vec2(0, 3. * time))) * 1.4 - 0.4; 21 | float c = 1. - 7. * pow(max(0., length(q * vec2(1.8 + q.y * 1.5, .75)) - n * max(0., q.y + .25)), 1.2); 22 | c *= (n + 0.6); 23 | if (c < 0.001) 24 | discard; 25 | 26 | vec3 color = vec3(2.0*c, 0.5*c+c*c-0.4, 3.0*c-2.5); 27 | fragColor = vec4(color * c, c); 28 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/effect/fog.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | 4 | in vec2 vtex; 5 | 6 | uniform sampler2D colorInputTexture; 7 | uniform sampler2D depthInputTexture; 8 | 9 | #uniform vec3 fogColor; 10 | #uniform float density; 11 | 12 | #uniforms 13 | 14 | out vec4 fragColor; 15 | 16 | #import "!shader/lib/space.glsl" 17 | #import "!shader/lib/sky.glsl" 18 | 19 | void main() { 20 | 21 | vec3 color = texture(colorInputTexture, vtex).rgb; 22 | float depth = texture(depthInputTexture, vtex).r; 23 | 24 | vec3 world = screenToWorldSpace(vtex, depth); 25 | float distance = length(world - cameraPos); 26 | 27 | float fogFactor = exp( -density * distance); 28 | 29 | color = mix(fogColor.rgb, color, fogFactor); 30 | 31 | fragColor = vec4(color, 1.0); 32 | gl_FragDepth = depth; 33 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/vprojection.ortho.vert: -------------------------------------------------------------------------------- 1 | vec4 pluginVProjection(vec3 viewPos) { 2 | return vec4( 3 | viewPos.x * 2. / projectionWidth, 4 | viewPos.y * 2. / projectionHeight, 5 | - 2.0 * viewPos.z / (projectionFar - projectionNear) - (projectionFar + projectionNear) / (projectionFar - projectionNear), 6 | 1.0 7 | ); 8 | } 9 | 10 | vec4 screenToViewSpace(vec2 vtex, float depth) { 11 | vec3 ndc = vec3(vtex * 2.0 - 1.0, depth * 2.0 - 1.0); 12 | float zview = - 2.0 * projectionNear * projectionFar / ((projectionFar + projectionNear) - ndc.z * (projectionFar - projectionNear)); 13 | return vec4( 14 | ndc.x * projectionWidth * 0.5, 15 | ndc.y * projectionHeight * 0.5, 16 | - 0.5 * ndc.z * (projectionFar - projectionNear) - (projectionFar + projectionNear), 17 | 1.0 18 | ); 19 | } -------------------------------------------------------------------------------- /.github/workflows/deploy-mkdocs.yml: -------------------------------------------------------------------------------- 1 | name: Deploy MkDocs to GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | 7 | jobs: 8 | build-and-deploy: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Checkout Repository 13 | uses: actions/checkout@v4 14 | 15 | - name: Set up Python 16 | uses: actions/setup-python@v5 17 | with: 18 | python-version: '3.11' 19 | 20 | - name: Install dependencies 21 | run: | 22 | pip install mkdocs mkdocs-material 23 | 24 | - name: Build MkDocs site 25 | run: mkdocs build 26 | 27 | - name: Deploy to GitHub Pages 28 | uses: peaceiris/actions-gh-pages@v4 29 | with: 30 | publish_dir: ./site 31 | destination_dir: projects/korender/wiki 32 | external_repository: zakgof/zakgof.github.io 33 | personal_token: ${{ secrets.DEPLOY_TOKEN }} 34 | publish_branch: main 35 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/deferred/decalblend.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | 3 | in vec2 vtex; 4 | 5 | uniform sampler2D albedoGeometryTexture; 6 | uniform sampler2D normalGeometryTexture; 7 | 8 | uniform sampler2D decalAlbedo; 9 | uniform sampler2D decalNormal; 10 | 11 | layout(location = 0) out vec4 albedoChannel; 12 | layout(location = 1) out vec4 normalChannel; 13 | 14 | void main() { 15 | 16 | vec4 da = texture(decalAlbedo, vtex); 17 | vec4 dn = texture(decalNormal, vtex); 18 | 19 | vec4 origAlbedoSample = texture(albedoGeometryTexture, vtex); 20 | vec4 origNormalSample = texture(normalGeometryTexture, vtex); 21 | 22 | albedoChannel.rgb = mix(origAlbedoSample.rgb, da.rgb, da.a); 23 | albedoChannel.a = origAlbedoSample.a; 24 | 25 | normalChannel.rgb = mix(origNormalSample.rgb, dn.rgb, dn.a); 26 | normalChannel.a = origNormalSample.a; 27 | } -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/kotlin/island/pixelmap/ChannelMap.kt: -------------------------------------------------------------------------------- 1 | package island.pixelmap 2 | 3 | import java.awt.image.BufferedImage 4 | 5 | class ChannelMap(side: Int) : PixelMap(side) { 6 | override val imageType = BufferedImage.TYPE_4BYTE_ABGR 7 | override val pixelChannels = 4 8 | 9 | override fun fillPixel(value: FloatArray, pixel: IntArray) { 10 | pixel[0] = (value[0] * 255).toInt().coerceIn(0, 255) 11 | pixel[1] = (value[1] * 255).toInt().coerceIn(0, 255) 12 | pixel[2] = (value[2] * 255).toInt().coerceIn(0, 255) 13 | pixel[3] = (value[3] * 255).toInt().coerceIn(0, 255) 14 | } 15 | } 16 | 17 | fun channel(channel: Int, weight: Float) = 18 | FloatArray(8).apply { this[channel] = weight } 19 | 20 | fun channels(ch1: Int, ch2: Int, weight: Float) = 21 | FloatArray(8).apply { 22 | this[ch1] = 1f - weight 23 | this[ch2] = weight 24 | } 25 | 26 | 27 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/vprojection.frustum.vert: -------------------------------------------------------------------------------- 1 | vec4 pluginVProjection(vec3 viewPos) { 2 | return vec4( 3 | viewPos.x * 2. * projectionNear / projectionWidth, 4 | viewPos.y * 2. * projectionNear / projectionHeight, 5 | -viewPos.z * (projectionFar + projectionNear) / (projectionFar - projectionNear) - 2. * projectionFar * projectionNear / (projectionFar - projectionNear), 6 | -viewPos.z 7 | ); 8 | } 9 | 10 | vec4 screenToViewSpace(vec2 vtex, float depth) { 11 | vec3 ndc = vec3(vtex * 2.0 - 1.0, depth * 2.0 - 1.0); 12 | float zview = - 2.0 * projectionNear * projectionFar / ((projectionFar + projectionNear) - ndc.z * (projectionFar - projectionNear)); 13 | return vec4( 14 | - ndc.x * zview * projectionWidth * 0.5 / projectionNear, 15 | - ndc.y * zview * projectionHeight * 0.5 / projectionNear, 16 | zview, 17 | 1.0 18 | ); 19 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/math/ColorRGBA.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.math 2 | 3 | data class ColorRGBA(val r: Float, val g: Float, val b: Float, val a: Float) { 4 | 5 | constructor(rgba: Long) : this( 6 | rgba.shr(24).and(0xFF).toFloat() / 255f, 7 | rgba.shr(16).and(0xFF).toFloat() / 255f, 8 | rgba.shr(8).and(0xFF).toFloat() / 255f, 9 | rgba.and(0xFF).toFloat() / 255f 10 | ) 11 | 12 | fun toRGB() = ColorRGB(r, g, b) 13 | 14 | companion object { 15 | val Transparent = ColorRGBA(0f, 0f, 0f, 0f) 16 | fun white(intensity: Float) = ColorRGBA(intensity, intensity, intensity, 1.0f) 17 | val Black = white(0f) 18 | val White = white(1f) 19 | val Blue = ColorRGBA(0f, 0f, 1f, 1f) 20 | val Green = ColorRGBA(0f, 1f, 0f, 1f) 21 | val Red = ColorRGBA(1f, 0f, 0f, 1f) 22 | } 23 | 24 | override fun toString(): String = "Color $r,$g,$b/$a" 25 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/lib/blur.glsl: -------------------------------------------------------------------------------- 1 | vec3 blur(sampler2D tex, vec2 vtex, float radius, vec2 dir, float screen) { 2 | 3 | vec3 color = texture(tex, vtex).rgb; 4 | float w = 1.; 5 | vec2 step = dir / screen; 6 | 7 | for (float i = 1.0; i <= radius; i++) { 8 | float dim = exp(- i * i / (radius * radius)); 9 | w += dim * 2.0; 10 | color += texture(tex, vtex + step * i).rgb * dim; 11 | color += texture(tex, vtex - step * i).rgb * dim; 12 | } 13 | return color / w; 14 | } 15 | 16 | float minDepthBlur(sampler2D tex, vec2 vtex, float radius, vec2 dir, float screen) { 17 | 18 | float depth = texture(tex, vtex).r; 19 | vec2 step = dir / screen; 20 | 21 | for (float i = 1.0; i <= radius; i++) { 22 | depth = min(depth, texture(tex, vtex + step * i).r); 23 | depth = min(depth, texture(tex, vtex - step * i).r); 24 | } 25 | return depth; 26 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/effect/bloom.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | 3 | in vec2 vtex; 4 | 5 | #uniforms 6 | 7 | #uniform float threshold; 8 | 9 | uniform sampler2D colorInputTexture; 10 | uniform sampler2D depthInputTexture; 11 | uniform sampler2D emissionGeometryTexture; 12 | 13 | out vec4 fragColor; 14 | 15 | float lumi(vec3 color) { 16 | return max(color.r, max(color.g, color.b)); 17 | } 18 | 19 | void main() { 20 | vec3 color = texture(colorInputTexture, vtex).rgb; 21 | vec3 emission = texture(emissionGeometryTexture, vtex).rgb; 22 | 23 | float colorSoft = smoothstep(threshold - 0.1, threshold, lumi(color)); // TODO knee 24 | float emissionSoft = lumi(emission); 25 | 26 | float soft = max(colorSoft, emissionSoft); 27 | 28 | vec3 result = color * soft; 29 | 30 | fragColor = vec4(result, 1.0); 31 | gl_FragDepth = (soft < 0.1) ? 1.0 : texture(depthInputTexture, vtex).r; 32 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/androidMain/kotlin/impl/buffer/NativeFloatBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.buffer 2 | 3 | import java.nio.ByteBuffer 4 | import java.nio.ByteOrder 5 | import java.nio.FloatBuffer 6 | 7 | actual class NativeFloatBuffer(override val byteBuffer: ByteBuffer) : NativeBuffer { 8 | 9 | private val floatBuffer: FloatBuffer = byteBuffer.asFloatBuffer() 10 | 11 | actual constructor(size: Int) : 12 | this(ByteBuffer.allocateDirect(size * 4).order(ByteOrder.LITTLE_ENDIAN)) 13 | 14 | actual fun put(v: Float) { 15 | floatBuffer.put(v) 16 | } 17 | 18 | actual override fun size() = floatBuffer.limit() 19 | 20 | actual override fun position() = floatBuffer.position() 21 | 22 | actual override fun position(offset: Int) { 23 | floatBuffer.position(offset) 24 | } 25 | 26 | actual override fun rewind(): NativeFloatBuffer { 27 | floatBuffer.rewind() 28 | return this 29 | } 30 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/deferred/composition.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | #import "!shader/lib/blur.glsl" 4 | 5 | in vec2 vtex; 6 | 7 | uniform sampler2D colorTexture; 8 | uniform sampler2D depthTexture; 9 | uniform sampler2D albedoGeometryTexture; 10 | uniform sampler2D normalGeometryTexture; 11 | 12 | out vec4 fragColor; 13 | float depth; 14 | vec3 color; 15 | 16 | #uniforms 17 | 18 | #ifdef SSR 19 | #import "!shader/deferred/composition-ssr.glsl" 20 | #endif 21 | 22 | #ifdef BLOOM 23 | #import "!shader/deferred/composition-bloom.glsl" 24 | #endif 25 | 26 | void main() { 27 | 28 | depth = texture(depthTexture, vtex).r; 29 | color = texture(colorTexture, vtex).rgb; 30 | 31 | #ifdef SSR 32 | compositionSsr(); 33 | #endif 34 | 35 | #ifdef BLOOM 36 | compositionBloom(); 37 | #endif 38 | 39 | fragColor = vec4(color, 1.); 40 | gl_FragDepth = depth; 41 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/effect/smoke.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | #import "!shader/lib/noise.glsl" 4 | 5 | in vec3 vpos; 6 | in vec2 vsize; 7 | in vec2 vtex; 8 | 9 | #uniform float density; 10 | #uniform float seed; 11 | 12 | #uniforms 13 | 14 | out vec4 fragColor; 15 | 16 | #import "$vprojection" 17 | 18 | void main() { 19 | float r = length(2. * (vtex - 0.5)); 20 | float a = density * clamp(1. - r * r, 0., 1.); 21 | float n = (fbm(seed + vtex * 0.1 + time * 0.005) * 0.7 + 22 | fbm(seed * 2. + vtex * 0.2 - time * 0.005) * 0.7 - 0.66) * a; 23 | n = clamp(n, 0., 1.); 24 | fragColor = vec4(0.05, 0.05, 0.05, 1.0) * n; 25 | 26 | float zoffset = sqrt(vtex.x - vtex.x * vtex.x) * vsize.x * 2.f; 27 | vec4 vclip = pluginVProjection((view * vec4(vpos, 1.) + vec4(0., 0., zoffset, 0.)).xyz); 28 | gl_FragDepth = 0.5 * vclip.z / vclip.w + 0.5; 29 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/desktopMain/kotlin/impl/buffer/NativeFloatBuffer.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.buffer 2 | 3 | import java.nio.ByteBuffer 4 | import java.nio.ByteOrder 5 | import java.nio.FloatBuffer 6 | 7 | actual class NativeFloatBuffer(override val byteBuffer: ByteBuffer) : NativeBuffer { 8 | 9 | private val floatBuffer: FloatBuffer = byteBuffer.asFloatBuffer() 10 | 11 | actual constructor(size: Int) : 12 | this(ByteBuffer.allocateDirect(size * 4).order(ByteOrder.LITTLE_ENDIAN)) 13 | 14 | actual fun put(v: Float) { 15 | floatBuffer.put(v) 16 | } 17 | 18 | actual override fun size() = floatBuffer.limit() 19 | 20 | actual override fun position() = floatBuffer.position() 21 | 22 | actual override fun position(offset: Int) { 23 | floatBuffer.position(offset) 24 | } 25 | 26 | actual override fun rewind(): NativeFloatBuffer { 27 | floatBuffer.rewind() 28 | return this 29 | } 30 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/deferred/decal.vert: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | 4 | layout(location = 0) in vec3 pos; 5 | 6 | #ifdef INSTANCING 7 | layout(location = 11) in vec4 instanceModel0; 8 | layout(location = 12) in vec4 instanceModel1; 9 | layout(location = 13) in vec4 instanceModel2; 10 | layout(location = 14) in vec4 instanceModel3; 11 | #endif 12 | 13 | out vec3 vpos; 14 | 15 | #ifdef INSTANCING 16 | out mat4 model; 17 | #endif 18 | 19 | #ifndef INSTANCING 20 | #uniform mat4 model; 21 | #endif 22 | 23 | #uniforms 24 | 25 | #import "$vprojection" 26 | 27 | void main() { 28 | 29 | #ifdef INSTANCING 30 | model = mat4(instanceModel0, instanceModel1, instanceModel2, instanceModel3); 31 | #endif 32 | 33 | vec4 worldPos = model * vec4(pos, 1.0); 34 | 35 | vec3 viewPos = (view * worldPos).xyz; 36 | gl_Position = pluginVProjection(viewPos); 37 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/gltf/GltfUpdate.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.gltf 2 | 3 | import com.zakgof.korender.CameraDeclaration 4 | import com.zakgof.korender.ProjectionDeclaration 5 | import com.zakgof.korender.math.Transform 6 | 7 | interface GltfUpdate { 8 | 9 | val animations: List 10 | val cameras: List 11 | val instances: List 12 | 13 | interface Animation { 14 | val name: String? 15 | } 16 | 17 | interface Camera { 18 | val name: String? 19 | val camera: CameraDeclaration 20 | val projection: ProjectionDeclaration 21 | } 22 | 23 | interface Instance { 24 | val rootNode: Node 25 | } 26 | 27 | interface Node { 28 | val transform: Transform 29 | val mesh: Mesh? 30 | val children: List 31 | } 32 | 33 | interface Mesh { 34 | val name: String? 35 | val primitives: List 36 | } 37 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/gltf/ByteArrayReader.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.gltf 2 | 3 | import com.zakgof.korender.KorenderException 4 | 5 | internal class ByteArrayReader(private val data: ByteArray) { 6 | 7 | private var position = 0 8 | 9 | fun readUInt32(): Int { 10 | val result = ((data[position].toInt() and 0xFF) or 11 | ((data[position + 1].toInt() and 0xFF) shl 8) or 12 | ((data[position + 2].toInt() and 0xFF) shl 16) or 13 | ((data[position + 3].toInt() and 0xFF) shl 24)) 14 | position += 4 15 | return result 16 | } 17 | 18 | fun readBytes(length: Int): ByteArray { 19 | if (position + length > data.size) throw KorenderException("Not enough data to read") 20 | val result = data.copyOfRange(position, position + length) 21 | position += length 22 | return result 23 | } 24 | 25 | fun hasRemaining(): Boolean = position < data.size 26 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/lib/ubo.glsl: -------------------------------------------------------------------------------- 1 | layout(std140) uniform Frame { 2 | 3 | vec3 cameraPos; 4 | vec3 cameraDir; 5 | 6 | mat4 view; 7 | float projectionWidth; 8 | float projectionHeight; 9 | float projectionNear; 10 | float projectionFar; 11 | 12 | float screenWidth; 13 | float screenHeight; 14 | float time; 15 | 16 | vec3 ambientColor; 17 | int numDirectionalLights; 18 | vec3 directionalLightDir[32]; 19 | vec3 directionalLightColor[32]; 20 | int directionalLightShadowTextureIndex[32]; 21 | int directionalLightShadowTextureCount[32]; 22 | 23 | int numPointLights; 24 | vec3 pointLightPos[32]; 25 | vec3 pointLightColor[32]; 26 | vec3 pointLightAttenuation[32]; 27 | 28 | int numShadows; 29 | mat4 bsps[5]; 30 | vec4 cascade[5]; 31 | float yMin[5]; 32 | float yMax[5]; 33 | int shadowMode[5]; 34 | float f1[5]; 35 | float f2[5]; 36 | int i1[5]; 37 | 38 | }; -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/math/ColorRGB.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.math 2 | 3 | data class ColorRGB(val r: Float, val g: Float, val b: Float) { 4 | 5 | constructor(rgb: Long) : this( 6 | rgb.shr(16).and(0xFF).toFloat() / 255f, 7 | rgb.shr(8).and(0xFF).toFloat() / 255f, 8 | rgb.and(0xFF).toFloat() / 255f 9 | ) 10 | 11 | operator fun times(ratio: Float) = ColorRGB(r * ratio, g * ratio, b * ratio) 12 | 13 | operator fun plus(other: ColorRGB) = ColorRGB(r + other.r, g + other.g, b + other.g) 14 | 15 | fun toRGBA(a: Float) = ColorRGBA(r, g, b, a) 16 | 17 | companion object { 18 | fun white(intensity: Float) = ColorRGB(intensity, intensity, intensity) 19 | val Black = white(0f) 20 | val White = white(1f) 21 | val Blue = ColorRGB(0f, 0f, 1f) 22 | val Green = ColorRGB(0f, 1f, 0f) 23 | val Red = ColorRGB(1f, 0f, 0f) 24 | } 25 | 26 | override fun toString(): String = "Color $r,$g,$b" 27 | } -------------------------------------------------------------------------------- /docs/gltf.md: -------------------------------------------------------------------------------- 1 | # GLTF 2 | 3 | Korender supports loading and rendering GLTF/GLB files, including meshes, animations, and textured materials. 4 | To use one, simply call `Gltf` within a Frame context: 5 | 6 | ````kotlin 7 | Frame { 8 | Gltf(resource = "model.glb") 9 | ```` 10 | 11 | It's possibly to select an animation index from the GLTF file (useful when a GLTF embeds multiple animations) and override time used for animating: 12 | 13 | ````kotlin 14 | Frame { 15 | Gltf(resource = "model.glb", time = ..., animation = ...) 16 | ```` 17 | 18 | Additionally, instancing is available when a number of model instances needs to be rendered: 19 | 20 | ````kotlin 21 | Frame { 22 | Gltf( 23 | resource = "model.glb", 24 | instancing = gltfInstancing("crowd", 10, true) { 25 | repeat(10) { i -> 26 | Instance( 27 | transform = ... // i-th instance dynamic position 28 | ) 29 | } 30 | } 31 | ) 32 | 33 | ```` 34 | 35 | 36 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/vprojection.log.vert: -------------------------------------------------------------------------------- 1 | #ifdef VERTEX_SHADER 2 | out float vdepth; 3 | #else 4 | in float vdepth; 5 | #endif 6 | 7 | vec4 pluginVProjection(vec3 viewPos) { 8 | 9 | #ifdef VERTEX_SHADER 10 | vdepth = 1.0 - viewPos.z; 11 | #endif 12 | 13 | return vec4( 14 | viewPos.x * 2. * projectionNear / projectionWidth, 15 | viewPos.y * 2. * projectionNear / projectionHeight, 16 | - viewPos.z * (2.0 * log2(max(1e-6, 1.0 - viewPos.z)) / log2(projectionFar + 1.0) - 1.0), 17 | - viewPos.z 18 | ); 19 | } 20 | 21 | vec4 screenToViewSpace(vec2 vtex, float depth) { 22 | vec3 ndc = vec3(vtex * 2.0 - 1.0, depth * 2.0 - 1.0); 23 | float zview = 1.0 - pow(projectionFar + 1.0, depth); 24 | return vec4( 25 | - ndc.x * zview * projectionWidth * 0.5 / projectionNear, 26 | - ndc.y * zview * projectionHeight * 0.5 / projectionNear, 27 | zview, 28 | 1.0 29 | ); 30 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/BlurExample.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples 2 | 3 | import androidx.compose.runtime.Composable 4 | import com.zakgof.app.resources.Res 5 | import com.zakgof.korender.Korender 6 | import com.zakgof.korender.math.ColorRGB.Companion.White 7 | import com.zakgof.korender.math.ColorRGBA 8 | import kotlin.math.sin 9 | 10 | @Composable 11 | fun BlurExample() = Korender(appResourceLoader = { Res.readBytes(it) }) { 12 | Frame { 13 | AmbientLight(White) 14 | Renderable( 15 | base(colorTexture = texture("texture/asphalt-albedo.jpg")), 16 | mesh = sphere(3f) 17 | ) 18 | val radius = 5.0f + 5.0f * sin(frameInfo.time) 19 | PostProcess(blur(radius)) 20 | Gui { 21 | Column { 22 | Filler() 23 | Text(id = "fps", text = "BLUR ${radius.toInt()} | FPS ${frameInfo.avgFps.toInt()}", height = 40, color = ColorRGBA(0x66FF55A0)) 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/sky.fastcloud.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/noisebias.glsl" 2 | 3 | #uniform float thickness; 4 | #uniform float density; 5 | #uniform float scale; 6 | #uniform float rippleamount; 7 | #uniform float ripplescale; 8 | #uniform vec3 zenithcolor; 9 | #uniform vec3 horizoncolor; 10 | #uniform float cloudlight; 11 | #uniform float clouddark; 12 | 13 | vec3 sky(vec3 look, float bias) { 14 | 15 | vec2 uv = skydiskfromlook(look, 4.5) + time * 0.001; 16 | 17 | float f = thickness * ((fbm2(uv * scale, bias) - 0.5) + 18 | rippleamount * (fbm2(uv * scale * ripplescale, bias) - 0.5)) + 19 | density - 3.; 20 | 21 | vec3 blue = mix(zenithcolor, horizoncolor, pow(1. - look.y, 6.)); // TODO light direction 22 | 23 | float g = clamp(fbm2(uv * 0.6 - time * 0.003, bias) + 0.4, 0., 1.); 24 | float cloud = mix(cloudlight, clouddark, clamp(f * g * 0.3, 0., 1.)); 25 | 26 | return mix(blue, vec3(cloud), clamp(f, 0., 1.)); 27 | } -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/kotlin/tree/ImageTool.kt: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | import com.zakgof.korender.Image 4 | import java.awt.image.BufferedImage 5 | import java.awt.image.BufferedImage.TYPE_INT_ARGB 6 | import java.io.File 7 | import javax.imageio.ImageIO 8 | 9 | fun saveImage(img: Image, format: String, path: String) { 10 | val bytes = img.toRaw() 11 | val bi = BufferedImage(img.width, img.height, TYPE_INT_ARGB) 12 | val raster = bi.raster 13 | val pixel = IntArray(4) 14 | for (x in 0 until img.width) { 15 | for (y in 0 until img.height) { 16 | pixel[0] = bytes[(x + y * img.width) * 4 + 0].toUByte().toInt() 17 | pixel[1] = bytes[(x + y * img.width) * 4 + 1].toUByte().toInt() 18 | pixel[2] = bytes[(x + y * img.width) * 4 + 2].toUByte().toInt() 19 | pixel[3] = bytes[(x + y * img.width) * 4 + 3].toUByte().toInt() 20 | raster.setPixel(x, img.height - 1 - y, pixel) 21 | } 22 | } 23 | ImageIO.write(bi, format, File(path)) 24 | } -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/composeResources/files/ltree/normal.volume.frag: -------------------------------------------------------------------------------- 1 | uniform sampler3D volumeAlbedoTexture; 2 | uniform sampler3D volumeNormalTexture; 3 | 4 | vec4 volumeAlbedo = vec4(0.); 5 | 6 | vec3 pluginNormal() { 7 | 8 | vec3 start = vec3(vtex, 0.0); 9 | vec3 dir = vec3(0.0, 0.0, 1.0); 10 | 11 | vec3 volumeNormal = vec3(0.); 12 | 13 | const int STEPS = 16; 14 | float stepSize = 1.0 / float(STEPS); 15 | 16 | float maxAlpha = 0.0; 17 | 18 | for (int i = 0; i < STEPS; i++) { 19 | float t = float(i) * stepSize; 20 | vec3 pos = start + dir * t; 21 | vec4 smpl = texture(volumeAlbedoTexture, pos); 22 | 23 | volumeAlbedo.rgb += (1.0 - volumeAlbedo.a) * smpl.rgb * smpl.a; 24 | volumeAlbedo.a += (1.0 - volumeAlbedo.a) * smpl.a; 25 | 26 | vec4 nrml = texture(volumeNormalTexture, pos); 27 | volumeNormal += (nrml.xyz * 2.0 - vec3(1.0)) * smpl.a; 28 | 29 | if (volumeAlbedo.a > 0.95) break; 30 | } 31 | return normalize(volumeNormal); 32 | } -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/kotlin/ltree/clusterizer/Clusterizer.kt: -------------------------------------------------------------------------------- 1 | package ltree.clusterizer 2 | 3 | import com.zakgof.korender.math.FloatMath.PI 4 | import com.zakgof.korender.math.Vec3 5 | import ltree.generator.LTree 6 | import kotlin.math.cos 7 | import kotlin.math.sin 8 | 9 | class ClusteredTree( 10 | val clusters: List 11 | ) { 12 | class Cluster( 13 | val plane: Plane, 14 | val lTree: LTree 15 | ) 16 | } 17 | 18 | fun clusterizeTree(lTree: LTree): ClusteredTree { 19 | 20 | val clustersCount = 16 21 | 22 | val initialPlanes = (0 until clustersCount).map { 23 | val s = sin(it * 2.0f * PI / clustersCount) 24 | val c = cos(it * 2.0f * PI / clustersCount) 25 | val normal = Vec3(s, 0f, c) 26 | Plane(normal * 2.0f, normal) 27 | } 28 | 29 | val kMeans = kMeans(lTree.leaves, initialPlanes) 30 | 31 | val clusters = kMeans.map { 32 | ClusteredTree.Cluster(it.key, LTree(listOf(), it.value)) 33 | } 34 | return ClusteredTree(clusters) 35 | 36 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/effect/shadow-debug.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | 4 | in vec2 vtex; 5 | 6 | uniform sampler2D colorInputTexture; 7 | uniform sampler2D shadowTextures[12]; 8 | 9 | out vec4 fragColor; 10 | 11 | float min = 0.25; 12 | 13 | vec4 box(vec4 color, int index, sampler2D sampler) { 14 | vec2 uv = (vtex - vec2(min * index, 0.0)) / min; 15 | if (numShadows > index && uv.x > 0.0 && uv.x < 1.0 && uv.y > 0.0 && uv.y < 1.0) { 16 | if (uv.x < 0.01 || uv.x > 0.99 || uv.y < 0.01 || uv.y > 0.99) 17 | return vec4(0.7, 0.7, 0.7, 1.0); 18 | return texture(sampler, uv); 19 | } 20 | return color; 21 | } 22 | 23 | 24 | void main() { 25 | vec4 color = texture(colorInputTexture, vtex); 26 | color = box(color, 0, shadowTextures[0]); 27 | color = box(color, 1, shadowTextures[1]); 28 | color = box(color, 2, shadowTextures[2]); 29 | color = box(color, 3, shadowTextures[3]); 30 | fragColor = color; 31 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/engine/FrameInfoManager.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.engine 2 | 3 | import com.zakgof.korender.FrameInfo 4 | import com.zakgof.korender.Platform 5 | 6 | internal class FrameInfoManager() { 7 | 8 | val startNanos: Long = Platform.nanoTime() 9 | 10 | private var frameNumber = 0L 11 | private var prevFrameNano: Long = Platform.nanoTime() 12 | private val frames = ArrayDeque() 13 | fun frame(pending: Int): FrameInfo { 14 | val now = Platform.nanoTime() 15 | val frameTime = now - prevFrameNano 16 | frames.add(frameTime) 17 | val frameInfo = 18 | FrameInfo(frameNumber, (now - startNanos) * 1e-9f, frameTime * 1e-9f, calcAverageFps(), pending) 19 | prevFrameNano = now 20 | frameNumber++ 21 | return frameInfo 22 | } 23 | 24 | private fun calcAverageFps(): Float { 25 | while (frames.size > 128) { 26 | frames.removeAt(0) 27 | } 28 | return 1e9f / frames.average().toFloat() 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/FxaaExample.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples 2 | 3 | import androidx.compose.runtime.Composable 4 | import com.zakgof.app.resources.Res 5 | import com.zakgof.korender.Korender 6 | import com.zakgof.korender.math.ColorRGB.Companion.White 7 | import com.zakgof.korender.math.ColorRGBA.Companion.Green 8 | import com.zakgof.korender.math.ColorRGBA.Companion.Red 9 | import org.jetbrains.compose.resources.ExperimentalResourceApi 10 | 11 | @Composable 12 | fun FxaaExample() = Korender(appResourceLoader = { Res.readBytes(it) }) { 13 | Frame { 14 | AmbientLight(White) 15 | Renderable( 16 | base(color = Green), 17 | mesh = sphere(4f), 18 | ) 19 | val doFxaa = (frameInfo.time.toInt() % 6 < 3) 20 | Gui { 21 | val text = if (doFxaa) "FXAA ON" else "FXAA OFF" 22 | Text(text = text, fontResource = "font/orbitron.ttf", height = 50, color = Red, id = "fxaa") 23 | } 24 | 25 | if (doFxaa) { 26 | PostProcess(fxaa()) 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/engine/ReusableFrameBufferHolder.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.engine 2 | 3 | import com.zakgof.korender.RetentionPolicy 4 | import com.zakgof.korender.impl.glgpu.GlGpuTexture 5 | 6 | internal class ReusableFrameBufferHolder { 7 | 8 | private val locks = mutableMapOf() 9 | 10 | fun request(target: FrameTarget, currentRetentionPolicy: RetentionPolicy): FrameBufferDeclaration { 11 | var index = 0 12 | while(true) { 13 | val fbName = "reusable-${target.width}x${target.height}-$index" 14 | if (!locks.values.contains(fbName)) { 15 | locks[target.colorOutput] = fbName 16 | locks[target.depthOutput] = fbName 17 | return FrameBufferDeclaration(fbName, target.width, target.height, listOf(GlGpuTexture.Preset.RGBAMipmap), true, TransientProperty(currentRetentionPolicy)) 18 | } 19 | index++ 20 | } 21 | } 22 | 23 | fun unlock(textureName: String) { 24 | locks.remove(textureName) 25 | } 26 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/effect/fireball.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | #import "!shader/lib/noise.glsl" 4 | 5 | in vec3 vpos; 6 | in vec2 vsize; 7 | in vec3 vnormal; 8 | in vec2 vtex; 9 | 10 | #uniform float power; 11 | 12 | #uniforms 13 | 14 | out vec4 fragColor; 15 | 16 | #import "$vprojection" 17 | 18 | void main() { 19 | vec2 uv = vtex; 20 | 21 | float r = length(2.0 * (uv - 0.5)); 22 | float a = (1.0 - r * r) * (1.0 - power); 23 | float ripple1 = fbm(uv * 0.25 + time * 0.04) * 3.5; 24 | float ripple2 = fbm(uv * 0.25 - time * 0.04) * 3.5; 25 | float n = (ripple1 + ripple2 - 2.0) * a; 26 | 27 | if (n < 0.2) 28 | discard; 29 | 30 | vec3 color = vec3(2.0*n, 0.5*n+n*n-0.4, 3.0*n-2.5); 31 | 32 | fragColor = vec4(color * n, n - 0.2); 33 | 34 | float zoffset = sqrt(vtex.x - vtex.x*vtex.x) * vsize.x * 1.5f + ripple1; 35 | vec4 vclip = pluginVProjection((view * vec4(vpos, 1.0) + vec4(0., 0., zoffset, 0.)).xyz); 36 | gl_FragDepth = 0.5 * vclip.z / vclip.w + 0.5; 37 | } -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /docs/billboards.md: -------------------------------------------------------------------------------- 1 | # Billboards 2 | 3 | A _billboard_ or _impostor_ is a flat 2D object (usually a textured quad) that always faces the camera, no matter where the camera moves. It's a common trick used to represent complex visuals with simple geometry. 4 | 5 | To render a billboard, add the `Billboard` functional declaration to your `Frame` context. Additionally, apply the `billboard` material to fine-tune: 6 | 7 | ````kotlin 8 | Billboard ( 9 | base(colorTexture = texture("textures/sprite.png")), 10 | billboard( 11 | position = Vec3(3f, 5f, 7f), 12 | scale = Vec2(2f, 2f), 13 | rotation = 0.3f 14 | ), 15 | transparent = true 16 | ) 17 | ```` 18 | 19 | `billboard` materials supports the following parameters: 20 | 21 | | Uniform name | Type | Default value | Description | 22 | |--------------|-------|---------------|-----------------------| 23 | | position | Vec3 | (0, 0, 0) | World position of billboard's center | 24 | | scale | Vec2 | (1, 1) | Billboard's size (horizontal/vertical) | 25 | | rotation | Float | 0.0f | Rotation (in radians) | 26 | -------------------------------------------------------------------------------- /docs/meshes.md: -------------------------------------------------------------------------------- 1 | ## Meshes 2 | 3 | There are predefined helper functions for common shapes: 4 | 5 | - `quad(1.0f, 2.0f)` - quad in *xy* plane with half-side 1.0 along *x* and 2.0 along *y* axis 6 | - `cube(0.5f)` - cube with half-side 0.5 7 | - `sphere(1.0f)` - sphere with radius 1.0 8 | - `disk(1.0f)` - disk with radius 1.0 9 | - `coneTop(1.0f, 2.0f)` - conical surface with height 1.0 and radius 1.0 10 | - `cylinderSide(1.0f, 2.0f)` - cylindrical surface with height 1.0 and radius 1.0 11 | - `obj("models/file.obj")` - loads a mesh from a Wavefront .obj file `models/file.obj` 12 | 13 | It's also possible to generate custom meshes via the `customMesh` helper function: 14 | 15 | ````kotlin 16 | customMesh("road", 4, 6) { 17 | pos(-0.5f, 0f, 0f).normal(1.y).tex(0f, 0f) 18 | pos(-0.5f, 0f, 32f).normal(1.y).tex(0f, 32f) 19 | pos(0.5f, 0f, 32f).normal(1.y).tex(1f, 32f) 20 | pos(0.5f, 0f, 0f).normal(1.y).tex(1f, 0f) 21 | index(0, 1, 2, 0, 2, 3) 22 | } 23 | ```` 24 | 25 | Note that if `dynamic` attribute is set to `true`, the initializer block of the mesh if called every frame and mesh data is updated in GPU dynamically. 26 | 27 | -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/island/Loader.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples.island 2 | 3 | import com.zakgof.korender.context.KorenderContext 4 | import loadRunway 5 | 6 | class Loader(kc: KorenderContext) { 7 | 8 | 9 | val heightMapLoading = kc.loadImage("island/terrain/height.png") 10 | val heightFunc = Height(heightMapLoading) 11 | val runwaySeedLoading = kc.load("files/island/terrain/runway.bin") { loadRunway(it) } 12 | val deferredBuildings = kc.load("files/island/building/buildings.bin") { loadBuildings(it) } 13 | val deferredBranches = kc.load("files/island/tree/branches.bin") { loadBranches(it) } 14 | val deferredCards = kc.load("files/island/tree/cards.bin") { loadCards(it) } 15 | val deferredTreeSeeds = kc.load("files/island/tree/trees.bin") { loadTreeSeeds(heightFunc, it) } 16 | 17 | val deferreds = listOf(heightMapLoading, runwaySeedLoading, deferredBuildings, deferredBranches, deferredCards, deferredTreeSeeds) 18 | 19 | 20 | fun loaded() = deferreds.all { it.isCompleted } 21 | fun percent() = deferreds.count { it.isCompleted } * 100 / deferreds.size 22 | } -------------------------------------------------------------------------------- /quickstart/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "QuickStart" 2 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") 3 | 4 | pluginManagement { 5 | repositories { 6 | google { 7 | mavenContent { 8 | includeGroupAndSubgroups("androidx") 9 | includeGroupAndSubgroups("com.android") 10 | includeGroupAndSubgroups("com.google") 11 | } 12 | } 13 | mavenCentral() 14 | gradlePluginPortal() 15 | } 16 | } 17 | 18 | dependencyResolutionManagement { 19 | repositories { 20 | mavenLocal() 21 | maven { 22 | url = uri("https://central.sonatype.com/repository/maven-snapshots/") 23 | mavenContent { 24 | snapshotsOnly() 25 | } 26 | } 27 | google { 28 | mavenContent { 29 | includeGroupAndSubgroups("androidx") 30 | includeGroupAndSubgroups("com.android") 31 | includeGroupAndSubgroups("com.google") 32 | } 33 | } 34 | mavenCentral() 35 | } 36 | } 37 | 38 | include(":composeApp") -------------------------------------------------------------------------------- /docs/projection.md: -------------------------------------------------------------------------------- 1 | ### Projection 2 | Korender supports perspective (frustum) and orthographic projections. 3 | Set the `projection` property of Korender context to set the projection transform. The below example takes into account the viewport aspect ratio: 4 | 5 | ````kotlin 6 | Frame { 7 | projection = projection(4f * width / height, 4f, 4f, 10000f, ortho()) 8 | ```` 9 | Default projection is `projection(width = 5f * width / height, height = 5f, near = 10f, far = 1000f, frustum())` 10 | 11 | Additionally, Korender supports logarithmic depth buffer - a depth buffer technique that stores the logarithm of the depth value instead of the linear depth. It is especially useful in rendering large-scale scenes (e.g., planetary terrain, open-world games) where depth precision becomes problematic. 12 | ````kotlin 13 | Frame { 14 | projection = projection(4f * width / height, 4f, 4f, 10000f, log()) 15 | ```` 16 | 17 | ### Camera 18 | Set the `camera` property of the Korender context to set the camera: 19 | 20 | ````kotlin 21 | Frame { 22 | camera = camera(Vec3(-2.0f, 5f, 30f), -1.z, 1.y) 23 | ```` 24 | Default camera is `camera(20.z, -1.z, 1.y)` -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/position.radiant.frag: -------------------------------------------------------------------------------- 1 | uniform samplerCube radiantTexture; 2 | uniform samplerCube radiantNormalTexture; 3 | 4 | in vec2 vsize; 5 | in vec3 vcenter; 6 | 7 | vec3 radiantDir; 8 | 9 | vec3 pluginPosition() { 10 | 11 | float radius = vsize.x * 0.5; 12 | vec3 look = normalize(vpos - cameraPos); 13 | 14 | vec3 p = cameraPos; 15 | 16 | float diff; 17 | vec3 n; 18 | 19 | for (int i=0; i<4; i++) { 20 | vec3 ctop = p - vcenter; 21 | float cl = length(ctop); 22 | radiantDir = ctop/cl; 23 | 24 | float radiant = radius * texture(radiantTexture, radiantDir).r; 25 | n = texture(radiantNormalTexture, radiantDir).rgb * 2. - 1.; 26 | 27 | diff = cl - radiant; 28 | float lambda = - diff * dot (n, radiantDir) / dot(n, look); 29 | // if (i > 0) { 30 | // lambda = clamp(lambda, -0.05 * radius/float(i), 1.5 * radius /float(i)); 31 | // } 32 | 33 | p = p + look * lambda; 34 | } 35 | if (diff > 0.01 * radius) { 36 | discard; 37 | } 38 | return p; 39 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/island/BinaryReader.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples.island 2 | 3 | import com.zakgof.korender.math.Vec2 4 | import com.zakgof.korender.math.Vec3 5 | 6 | fun loadBinary(bytes: ByteArray, block: BinaryLoaderContext.() -> T): T { 7 | val context = BinaryLoaderContext(bytes) 8 | return block.invoke(context) 9 | } 10 | 11 | class BinaryLoaderContext(val bytes: ByteArray) { 12 | 13 | private var offset = 0 14 | 15 | fun getInt(): Int { 16 | val bits = (bytes[offset + 3].toInt() and 0xFF shl 24) or 17 | (bytes[offset + 2].toInt() and 0xFF shl 16) or 18 | (bytes[offset + 1].toInt() and 0xFF shl 8) or 19 | (bytes[offset].toInt() and 0xFF) 20 | offset += 4 21 | return bits 22 | } 23 | 24 | fun getFloat() = Float.fromBits(getInt()) 25 | 26 | fun getVec3(): Vec3 { 27 | val x = getFloat() 28 | val y = getFloat() 29 | val z = getFloat() 30 | return Vec3(x, y, z) 31 | } 32 | 33 | fun getVec2(): Vec2 { 34 | val x = getFloat() 35 | val y = getFloat() 36 | return Vec2(x, y) 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /quickstart/composeApp/src/commonMain/kotlin/App.kt: -------------------------------------------------------------------------------- 1 | import androidx.compose.runtime.Composable 2 | import com.zakgof.korender.Korender 3 | import com.zakgof.korender.math.ColorRGBA 4 | import com.zakgof.korender.math.Transform.Companion.translate 5 | import com.zakgof.korender.math.Vec3 6 | import com.zakgof.korender.math.y 7 | import com.example.Res 8 | import kotlin.math.sin 9 | 10 | @Composable 11 | fun App() = Korender(appResourceLoader = { Res.readBytes(it) }) { 12 | Frame { 13 | DirectionalLight(Vec3(1f, -1f, -1f)) 14 | Renderable( 15 | base( 16 | color = ColorRGBA(0.2f, 1.0f, 0.5f + 0.5f * sin(frameInfo.time), 1.0f), 17 | metallicFactor = 0.4f 18 | ), 19 | mesh = sphere(2.0f), 20 | transform = translate(sin(frameInfo.time).y) 21 | ) 22 | Gui { 23 | Column { 24 | Filler() 25 | Row { 26 | Image(id = "icon", imageResource = "icon.png", width = 30, height = 30) 27 | Text(id = "fps", height = 40, text = "FPS: " + frameInfo.avgFps.toInt()) 28 | } 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/context/DefaultDeferredShadingContext.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.context 2 | 3 | import com.zakgof.korender.MaterialModifier 4 | import com.zakgof.korender.PostShadingEffect 5 | import com.zakgof.korender.context.DeferredShadingContext 6 | import com.zakgof.korender.impl.engine.DeferredShadingDeclaration 7 | import com.zakgof.korender.impl.engine.InternalDecalDeclaration 8 | import com.zakgof.korender.math.Vec3 9 | 10 | internal class DefaultDeferredShadingContext(private var deferredShadingDeclaration: DeferredShadingDeclaration) : DeferredShadingContext { 11 | 12 | override fun Shading(vararg shadingModifiers: MaterialModifier) { 13 | deferredShadingDeclaration.shadingModifiers += shadingModifiers 14 | } 15 | 16 | override fun PostShading(vararg effects: PostShadingEffect) { 17 | deferredShadingDeclaration.postShadingEffects += effects 18 | } 19 | 20 | override fun Decal(vararg materialModifiers: MaterialModifier, position: Vec3, look: Vec3, up: Vec3, size: Float) { 21 | deferredShadingDeclaration.decals += InternalDecalDeclaration(position, look, up, size, materialModifiers.asList()) 22 | } 23 | 24 | 25 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/context/DeferredShadingContext.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.context 2 | 3 | import com.zakgof.korender.MaterialModifier 4 | import com.zakgof.korender.PostShadingEffect 5 | import com.zakgof.korender.math.Vec3 6 | 7 | interface DeferredShadingContext { 8 | 9 | /** 10 | * Defines modifiers for the shading step. 11 | * 12 | * @param shadingModifiers shading material modifiers 13 | */ 14 | fun Shading(vararg shadingModifiers: MaterialModifier) 15 | 16 | /** 17 | * Defines post shading effect modifiers. 18 | * 19 | * @param effects post shading effect material modifiers 20 | */ 21 | fun PostShading(vararg effects: PostShadingEffect) 22 | 23 | /** 24 | * Creates a decal. 25 | * 26 | * @param materialModifiers material modifiers 27 | * @param position decal application position 28 | * @param look decal application direction 29 | * @param up up direction for decal application (corresponds to y axis of decal texture) 30 | * @param size decal quad size, in world space units 31 | */ 32 | fun Decal(vararg materialModifiers: MaterialModifier, position: Vec3, look: Vec3, up: Vec3, size: Float) 33 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/lib/sg.glsl: -------------------------------------------------------------------------------- 1 | 2 | vec3 doSpecularGlosiness(vec3 N, vec3 V, vec3 L, vec3 albedo, vec3 lightColor) { 3 | 4 | #ifdef SPECULAR_GLOSSINESS_MAP 5 | vec4 sgtexel = textureRegOrTriplanar(specularGlossinessTexture, vtex, vpos, N); 6 | vec3 specular = sgtexel.rgb * specularFactor.rgb; 7 | float glossiness = sgtexel.a * glossinessFactor; 8 | #else 9 | vec3 specular = specularFactor.rgb; 10 | float glossiness = glossinessFactor; 11 | #endif 12 | 13 | vec3 H = normalize(V + L); 14 | 15 | float NdotV = max(dot(N, V), 0.0); 16 | float NdotL = max(dot(N, L), 0.0); 17 | float NdotH = max(dot(N, H), 0.0); 18 | float VdotH = max(dot(V, H), 0.0); 19 | 20 | vec3 c_diff = albedo.rgb * (1. - max(max(specular.r, specular.g), specular.b)); 21 | vec3 F0 = specular; 22 | float roughness = 1. - glossiness; 23 | 24 | vec3 F = F0 + (1. - F0) * pow(1. - VdotH, 5.); 25 | vec3 f_diffuse = (1. - F) * (1. / PI) * c_diff; 26 | 27 | float D = distributionGGX(NdotH, roughness); 28 | float G = geometrySmith(NdotV, NdotL, roughness); 29 | vec3 f_specular = F * D * G / max(4.0 * NdotV * NdotL, 0.000001); 30 | 31 | return (f_diffuse + f_specular) * NdotL * lightColor; 32 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/camera/DefaultCamera.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.camera 2 | 3 | import com.zakgof.korender.math.Mat4 4 | import com.zakgof.korender.math.Vec3 5 | 6 | internal class DefaultCamera( 7 | override val position: Vec3, 8 | override val direction: Vec3, 9 | override val up: Vec3, 10 | ) : Camera { 11 | 12 | override val mat4: Mat4 = buildMatrix(position, direction, up) 13 | 14 | companion object { 15 | private fun buildMatrix(pos: Vec3, dir: Vec3, up: Vec3): Mat4 { 16 | val right = dir % up 17 | return Mat4( 18 | right.x, right.y, right.z, -pos * right, 19 | up.x, up.y, up.z, -pos * up, 20 | -dir.x, -dir.y, -dir.z, pos * dir, 21 | 0f, 0f, 0f, 1f 22 | ) 23 | } 24 | } 25 | 26 | constructor(m: Mat4) : this( 27 | direction = Vec3(-m.m20, -m.m21, -m.m22), 28 | up = Vec3(m.m10, m.m11, m.m12), 29 | position = -Vec3( 30 | m.m00 * (-m.m03) + m.m10 * (-m.m13) + (-m.m20) * (m.m23), 31 | m.m01 * (-m.m03) + m.m11 * (-m.m13) + (-m.m21) * (m.m23), 32 | m.m02 * (-m.m03) + m.m12 * (-m.m13) + (-m.m22) * (m.m23) 33 | ) 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /.github/workflows/deploy-wasm.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - release 7 | 8 | jobs: 9 | build-and-deploy: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout Repository 14 | uses: actions/checkout@v3 15 | 16 | - name: Set up JDK 17 17 | uses: actions/setup-java@v3 18 | with: 19 | distribution: 'temurin' 20 | java-version: '17' 21 | 22 | - name: Cache Gradle Packages 23 | uses: actions/cache@v3 24 | with: 25 | path: ~/.gradle/caches 26 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} 27 | restore-keys: | 28 | ${{ runner.os }}-gradle- 29 | 30 | - name: Build Wasm 31 | working-directory: ./korender-framework 32 | run: ./gradlew examples:wasmJsBrowserDistribution 33 | 34 | - name: Deploy to GitHub Pages 35 | uses: peaceiris/actions-gh-pages@v4 36 | with: 37 | publish_dir: ./korender-framework/examples/build/dist/wasmJs/productionExecutable 38 | destination_dir: projects/korender/wasm 39 | external_repository: zakgof/zakgof.github.io 40 | personal_token: ${{ secrets.DEPLOY_TOKEN }} 41 | publish_branch: main 42 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/math/Vec2.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.math 2 | 3 | import kotlin.math.sqrt 4 | import kotlin.random.Random 5 | 6 | class Vec2(val x: Float, val y: Float) { 7 | 8 | companion object { 9 | val ZERO = Vec2(0f, 0f) 10 | val X = Vec2(1f, 0f) 11 | val Y = Vec2(0f, 1f) 12 | 13 | fun random(seed: Int): Vec2 { 14 | val r = Random(seed) 15 | return Vec2( 16 | r.nextFloat() - 0.5f, 17 | r.nextFloat() - 0.5f, 18 | ).normalize() 19 | } 20 | 21 | fun random() = Vec2( 22 | Random.nextFloat() - 0.5f, 23 | Random.nextFloat() - 0.5f, 24 | ).normalize() 25 | } 26 | 27 | operator fun unaryMinus(): Vec2 = Vec2(-x, -y) 28 | operator fun times(s: Vec2) = x * s.x + y * s.y 29 | operator fun times(a: Float) = Vec2(a * x, a * y) 30 | fun multpercomp(s: Vec2) = Vec2(x * s.x, y * s.y) 31 | operator fun plus(s: Vec2) = Vec2(x + s.x, y + s.y) 32 | operator fun minus(s: Vec2) = Vec2(x - s.x, y - s.y) 33 | fun lengthSquared() = x * x + y * y 34 | fun length() = sqrt(lengthSquared()) 35 | fun normalize(): Vec2 = this * (1f / length()) 36 | 37 | override fun toString(): String = "($x, $y)" 38 | } 39 | 40 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/deferred/composition-ssr.glsl: -------------------------------------------------------------------------------- 1 | uniform sampler2D ssrTexture; 2 | 3 | #import "!shader/lib/space.glsl" 4 | #import "!shader/lib/pbr.glsl" 5 | 6 | #ifdef SSR_ENV 7 | uniform samplerCube envTexture; 8 | #endif 9 | 10 | void compositionSsr() { 11 | 12 | vec4 ssrSample = texture(ssrTexture, vtex); 13 | color += ssrSample.rgb * ssrSample.a; 14 | 15 | #ifdef SSR_ENV 16 | vec3 vpos = screenToWorldSpace(vtex, depth); 17 | vec4 albedoTexel = texture(albedoGeometryTexture, vtex); 18 | vec4 normalTexel = texture(normalGeometryTexture, vtex); 19 | vec3 albedo = albedoTexel.rgb; 20 | float metallic = albedoTexel.a; 21 | float roughness = normalTexel.a; 22 | vec3 V = normalize(cameraPos - vpos); 23 | vec3 N = normalize(normalTexel.rgb * 2.0 - 1.0); 24 | vec3 R = reflect(-V, N); 25 | vec3 F0 = mix(vec3(0.04), albedo, metallic); 26 | float maxBias = 8.; // TODO ! Get from da sky 27 | vec3 envDiffuse = texture(envTexture, N, maxBias).rgb * albedo * (1.0 - metallic); 28 | vec3 envSpec = texture(envTexture, R, roughness * maxBias).rgb * fresnelSchlick(max(dot(V, N), 0.), F0); 29 | 30 | if (length(normalTexel.rgb) > 0.1) 31 | color += envDiffuse + envSpec * (1.0 - ssrSample.a); 32 | #endif 33 | } 34 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/lib/light.glsl: -------------------------------------------------------------------------------- 1 | vec3 dirLight(int l, vec3 N, vec3 V, vec3 albedo, float metallic, float roughness, float occlusion) { 2 | float shadowRatio = 0.; 3 | int shadowCount = directionalLightShadowTextureCount[l]; 4 | for (int c=0; c>() 10 | val cycles = mutableListOf>() 11 | 12 | override fun sequence(block: PipeMeshSequenceContext.() -> Unit) { 13 | val pipeMeshSequenceContext = DefaultPipeMeshSequenceContext() 14 | block.invoke(pipeMeshSequenceContext) 15 | sequences += pipeMeshSequenceContext.nodes 16 | } 17 | 18 | override fun cycle(block: PipeMeshSequenceContext.() -> Unit) { 19 | val pipeMeshSequenceContext = DefaultPipeMeshSequenceContext() 20 | block.invoke(pipeMeshSequenceContext) 21 | cycles += pipeMeshSequenceContext.nodes 22 | } 23 | } 24 | 25 | internal class DefaultPipeMeshSequenceContext : PipeMeshSequenceContext { 26 | 27 | val nodes = mutableListOf() 28 | 29 | override fun node(position: Vec3, radius: Float) { 30 | nodes += PipeNode(position, radius) 31 | } 32 | } 33 | 34 | internal class PipeNode(val position: Vec3, val radius: Float) -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/infcity/CityStrategy.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples.infcity 2 | 3 | import kotlin.random.Random 4 | 5 | fun generateBuilding(): CityGenerator { 6 | 7 | val generator = CityGenerator() 8 | 9 | val h = 30 + Random.nextInt(20) 10 | val base = h / 6 + Random.nextInt(3) 11 | val main = 2 * h / 4 + Random.nextInt(3) 12 | val loft = h - Random.nextInt(3, 6) 13 | 14 | generator.building(0, 0, 16, 16, h) { 15 | when (level) { 16 | 0 -> 40.chance { symcorner(Random.nextInt(1, 3), Random.nextInt(1, 3)) } 17 | base -> 30.chance { square(Random.nextInt(1, 3), Random.nextInt(1, 3)) } 18 | base -> 30.chance { symcorner(Random.nextInt(1, 3), Random.nextInt(1, 3)) } 19 | base + 1 -> 40.chance { symcorner(1, 1) } 20 | base + 3 -> 20.chance { 21 | symcorner( 22 | Random.nextInt(1, 3), 23 | Random.nextInt(1, 3) 24 | ) 25 | } 26 | main -> square(Random.nextInt(1, 3), Random.nextInt(1, 3)) 27 | main + 1 -> 40.chance { symcorner(1, 1) } 28 | main + 3 -> 40.chance { symcorner(1, 1) } 29 | loft -> squareTo(Random.nextInt(5, 8), Random.nextInt(5, 8)) 30 | } 31 | } 32 | return generator 33 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/image/Tga.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.image 2 | 3 | import com.zakgof.korender.PixelFormat 4 | import com.zakgof.korender.impl.buffer.NativeByteBuffer 5 | 6 | object Tga { 7 | 8 | fun encode(width: Int, height: Int, format: PixelFormat, bytes: NativeByteBuffer): ByteArray { 9 | 10 | val header = ByteArray(18) 11 | header[2] = 2 // Uncompressed RGB 12 | header[12] = (width and 0xFF).toByte() 13 | header[13] = ((width shr 8) and 0xFF).toByte() 14 | header[14] = (height and 0xFF).toByte() 15 | header[15] = ((height shr 8) and 0xFF).toByte() 16 | header[16] = 32 // 32 bits per pixel 17 | header[17] = 0x20 // Origin top-left (optional: 0x00 for bottom-left) 18 | 19 | val image = ByteArray(width * height * 4) 20 | 21 | var src = 0 22 | var dst = 0 23 | while (src < bytes.size()) { 24 | val r = bytes.byte(src) 25 | val g = bytes.byte(src + 1) 26 | val b = bytes.byte(src + 2) 27 | val a = bytes.byte(src + 3) 28 | image[dst] = b 29 | image[dst + 1] = g 30 | image[dst + 2] = r 31 | image[dst + 3] = a 32 | src += 4 33 | dst += 4 34 | } 35 | 36 | return header + image 37 | } 38 | } -------------------------------------------------------------------------------- /docs/light.md: -------------------------------------------------------------------------------- 1 | # Lights 2 | 3 | Korender supports 3 types of light sources: 4 | 5 | - ambient light 6 | - directional lights 7 | - point lights 8 | 9 | All types of lights can be declared dynamically in the Frame context: 10 | 11 | ````kotlin 12 | Frame { 13 | AmbientLight(white(0.25f)) 14 | PointLight(Vec3(100f, 20f, 100f), ColorRGB.Green) 15 | DirectionalLight(Vec3(1f, -1f, 2f), white(1.0f)) 16 | ```` 17 | 18 | # Shadows 19 | 20 | Shadows are supported for directional lights. Korender supports multiple cascades of shadow maps with automatic blending of maps within overlapping cascades. The supported mapping techniques are: 21 | 22 | - Hard shadows - straightforward shadow mapping with no shadow edge anti-aliasing. 23 | - Software PCF shadows - soft shadows with blurring filter using Vogel disk sampling 24 | - Hardware PCF shadows - percentage-close filtering on GPU provided by OpenGL implementation 25 | - VSM - variance shadow mapping 26 | 27 | ````kotlin 28 | Frame { 29 | DirectionalLight(Vec3(1f, -1f, 0.3f), white(5.0f)) { 30 | Cascade(mapSize = 1024, near = 4f, far = 12f, algorithm = softwarePcf(samples = 16, blurRadius = 0.01f)) 31 | Cascade(mapSize = 1024, near = 10f, far = 30f, algorithm = vsm(blurRadius = 0.01f)) 32 | Cascade(mapSize = 1024, near = 25f, far = 100f, algorithm = vsm(blurRadius = 0.02f)) 33 | } 34 | ```` -------------------------------------------------------------------------------- /korender-framework/baker/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.composeCompiler) 3 | alias(libs.plugins.kotlinMultiplatform) 4 | alias(libs.plugins.jetbrainsCompose) 5 | } 6 | 7 | compose.resources { 8 | publicResClass = true 9 | packageOfResClass = "com.zakgof.korender.baker.resources" 10 | generateResClass = auto 11 | } 12 | 13 | kotlin { 14 | 15 | jvm("desktop") 16 | 17 | sourceSets { 18 | val desktopMain by getting 19 | 20 | commonMain.dependencies { 21 | implementation(project(":korender")) 22 | implementation(compose.runtime) 23 | implementation(compose.foundation) 24 | implementation(compose.material) 25 | implementation(compose.ui) 26 | implementation(compose.components.resources) 27 | implementation(libs.commons.math3) 28 | implementation("com.github.haifengl:smile-core:4.4.0") 29 | } 30 | desktopMain.dependencies { 31 | implementation(compose.desktop.currentOs) 32 | } 33 | } 34 | } 35 | 36 | compose.desktop { 37 | application { 38 | mainClass = "com.zakgof.korender.baker.MainKt" 39 | jvmArgs("--add-exports", "java.desktop/sun.awt=ALL-UNNAMED", "-DprojectRoot=${project.projectDir.absolutePath}") 40 | nativeApplication { 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/kotlin/island/pixelmap/FloatPixelMap.kt: -------------------------------------------------------------------------------- 1 | package island.pixelmap 2 | 3 | import com.zakgof.korender.math.Vec2 4 | import java.awt.image.BufferedImage 5 | 6 | open class FloatPixelMap(side: Int) : PixelMap(side) { 7 | 8 | operator fun get(pt: Vec2): Float { 9 | if (pt.x < 0f || pt.x > 1f || pt.y < 0f || pt.y > 1f) 10 | return 0f 11 | val gridX = pt.x * side - 0.5f 12 | val gridY = pt.y * side - 0.5f 13 | val i = gridX.toInt().coerceIn(0, side - 1) 14 | val j = gridY.toInt().coerceIn(0, side - 1) 15 | val i1 = (i + 1).coerceIn(0, side - 1) 16 | val j1 = (j + 1).coerceIn(0, side - 1) 17 | val dx = gridX - i 18 | val dy = gridY - j 19 | val height00 = get(i, j) 20 | val height10 = get(i1, j) 21 | val height01 = get(i, j1) 22 | val height11 = get(i1, j1) 23 | val bottomInterpolation = height00 * (1f - dx) + height10 * dx 24 | val topInterpolation = height01 * (1f - dx) + height11 * dx 25 | return bottomInterpolation * (1f - dy) + topInterpolation * dy 26 | } 27 | 28 | override val imageType = BufferedImage.TYPE_BYTE_GRAY 29 | 30 | override val pixelChannels = 1 31 | 32 | override fun fillPixel(value: Float, pixel: IntArray) { 33 | pixel[0] = (value * 255f).toInt().coerceIn(0, 255) 34 | } 35 | } -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/kotlin/tree/Metaball.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.baker.tree 2 | 3 | import com.zakgof.korender.math.FloatMath 4 | import com.zakgof.korender.math.Vec3 5 | import kotlin.math.abs 6 | import kotlin.math.cos 7 | import kotlin.math.sin 8 | import kotlin.random.Random 9 | 10 | class Metaball( 11 | private val height: Float, 12 | private val radius: Float, 13 | private val sphereCount: Int = 4096, 14 | private val pointCount: Int = 64, 15 | private val shape: (Float) -> Float 16 | ) { 17 | 18 | val spheres: List 19 | val points: List 20 | 21 | init { 22 | val rnd = Random(1) 23 | spheres = (0 until sphereCount).flatMap { 24 | val phi = rnd.nextFloat() * 2f * FloatMath.PI 25 | val h = rnd.nextFloat() * height 26 | val r = rnd.nextFloat() * height 27 | if (abs(r - shape(h)) > 0.6f * radius) 28 | listOf() 29 | else 30 | listOf(Vec3(r * sin(phi), h, r * cos(phi))) 31 | }.map { 32 | Sphere(radius, it) 33 | } 34 | points = spheres.flatMap { s -> 35 | (0 until pointCount).map { 36 | val n = Vec3.random() 37 | Pt(s.pos + n * s.r, n) 38 | } 39 | } 40 | } 41 | 42 | class Sphere(val r: Float, val pos: Vec3) 43 | class Pt(val pos: Vec3, val n: Vec3) 44 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/island/city/CityStrategy.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples.island.city 2 | 3 | import kotlin.random.Random 4 | 5 | fun Int.chance(block: () -> Unit) { 6 | if (Random.nextInt(100) < this) block() 7 | } 8 | 9 | fun generateBuilding(generator: CityGenerator, xoffset: Int, yoffset: Int, xsize: Int, ysize: Int, seed: Int = 0) { 10 | 11 | val r = Random(seed) 12 | 13 | val h = 30 + r.nextInt(60) 14 | val base = h / 6 + r.nextInt(3) 15 | val main = 2 * h / 4 + r.nextInt(3) 16 | val loft = h - r.nextInt(3, 6) 17 | 18 | generator.building(xoffset, yoffset, xsize, ysize, h) { 19 | when (level) { 20 | 0 -> 40.chance { symcorner(r.nextInt(1, 3), r.nextInt(1, 3)) } 21 | base -> 30.chance { square(r.nextInt(1, 3), r.nextInt(1, 3)) } 22 | base -> 30.chance { symcorner(r.nextInt(1, 3), r.nextInt(1, 3)) } 23 | base + 1 -> 40.chance { symcorner(1, 1) } 24 | base + 3 -> 20.chance { 25 | symcorner( 26 | r.nextInt(1, 3), 27 | r.nextInt(1, 3) 28 | ) 29 | } 30 | main -> square(r.nextInt(1, 3), r.nextInt(1, 3)) 31 | main + 1 -> 40.chance { symcorner(1, 1) } 32 | main + 3 -> 40.chance { symcorner(1, 1) } 33 | loft -> squareTo(r.nextInt(5, 8), r.nextInt(5, 8)) 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/ObjFileExample.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples 2 | 3 | 4 | import androidx.compose.runtime.Composable 5 | import com.zakgof.app.resources.Res 6 | import com.zakgof.korender.Korender 7 | import com.zakgof.korender.examples.camera.OrbitCamera 8 | import com.zakgof.korender.math.ColorRGB.Companion.white 9 | import com.zakgof.korender.math.FloatMath.PIdiv2 10 | import com.zakgof.korender.math.Transform.Companion.scale 11 | import com.zakgof.korender.math.Vec3 12 | import com.zakgof.korender.math.y 13 | import com.zakgof.korender.math.z 14 | 15 | @Composable 16 | fun ObjFileExample() { 17 | Korender(appResourceLoader = { Res.readBytes(it) }) { 18 | val orbitCamera = OrbitCamera(20.z, 0.z) 19 | OnTouch { orbitCamera.touch(it) } 20 | Frame { 21 | DirectionalLight(Vec3(1.0f, -1.0f, -1.0f), white(3f)) 22 | camera = orbitCamera.run { camera() } 23 | Renderable( 24 | base(colorTexture = texture("model/head.jpg"), metallicFactor = 0.3f, roughnessFactor = 0.5f), 25 | mesh = obj("model/head.obj"), 26 | transform = scale(7.0f).rotate(1.y, -PIdiv2) 27 | ) 28 | Gui { 29 | Column { 30 | Filler() 31 | Text(id = "fps", text = "FPS ${frameInfo.avgFps.toInt()}") 32 | } 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /docs/env.md: -------------------------------------------------------------------------------- 1 | # Environment mapping 2 | 3 | Korender supports environment mapping (via cube maps). 4 | When enabled, rendered objects incorporate distant lighting from the environment map, following Korender’s physically-based rendering (PBR) model for realistic illumination. 5 | 6 | ## Cube map creation 7 | There a several ways to create a cube map: 8 | 9 | - from 6 textures images: 10 | 11 | ````kotlin 12 | Frame { 13 | val cubeMap = cubeTexture("env", mapOf( 14 | NX to "textures/env-nx.jpg", 15 | NY to "textures/env-ny.jpg", 16 | NZ to "textures/env-nz.jpg", 17 | PX to "textures/env-px.jpg", 18 | PY to "textures/env-py.jpg", 19 | PZ to "textures/env-pz.jpg" 20 | )) 21 | ```` 22 | 23 | - capture env probe from a scene: 24 | 25 | ````kotlin 26 | Frame { 27 | CaptureEnv("probe1", 1024) { 28 | // Render capture scene here 29 | } 30 | val cubeMap = cubeTextureProbe("probe1") 31 | ```` 32 | 33 | ## Environment rendering 34 | 35 | To render an object with environment mapping, add the `ibl` material modifier to a `Renderable` declaration: 36 | 37 | ````kotlin 38 | Frame { 39 | val cubeMap = ... 40 | Renderable( 41 | base(...), 42 | ibl(cubeMap), 43 | ```` 44 | 45 | It's also possible to use a sky material modifier as the ibl source: 46 | 47 | ````kotlin 48 | Frame { 49 | Renderable( 50 | base(...), 51 | ibl(fastCloudSky()), 52 | ```` 53 | 54 | 55 | -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/island/Terrain.kt: -------------------------------------------------------------------------------- 1 | import com.zakgof.korender.Image 2 | import com.zakgof.korender.Prefab 3 | import com.zakgof.korender.TextureFilter 4 | import com.zakgof.korender.context.FrameContext 5 | import com.zakgof.korender.examples.island.loadBinary 6 | import com.zakgof.korender.math.Vec2 7 | 8 | fun loadRunway(bytes: ByteArray): Pair = loadBinary(bytes) { 9 | val p1 = getVec2() 10 | val p2 = getVec2() 11 | p1 to p2 12 | } 13 | 14 | fun FrameContext.island(heightMap: Image, rwSeeds: Pair, terrain: Prefab) { 15 | Renderable( 16 | base(metallicFactor = 0.0f), 17 | plugin("normal", "!shader/plugin/normal.terrain.frag"), 18 | plugin("terrain", "island/terrain/shader/height.glsl"), 19 | plugin("albedo", "island/terrain/shader/albedo.glsl"), 20 | uniforms( 21 | "heightTexture" to texture("base-terrain", heightMap), 22 | "patchTexture" to texture("island/terrain/color.png"), 23 | "sdf" to texture("island/terrain/sdf.png", TextureFilter.Linear), 24 | "road" to texture("infcity/road.jpg"), 25 | "grassTexture" to texture("texture/grass.jpg"), 26 | "runwayTexture" to texture("island/terrain/runway.jpg"), 27 | "runwayP1" to rwSeeds.first, 28 | "runwayP2" to rwSeeds.second 29 | ), 30 | defs("NO_SHADOW_CAST"), 31 | prefab = terrain 32 | ) 33 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/PipeExample.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples 2 | 3 | import androidx.compose.runtime.Composable 4 | import com.zakgof.app.resources.Res 5 | import com.zakgof.korender.Korender 6 | import com.zakgof.korender.math.ColorRGBA 7 | import com.zakgof.korender.math.Transform.Companion.scale 8 | import com.zakgof.korender.math.Vec3 9 | import com.zakgof.korender.math.y 10 | import com.zakgof.korender.math.z 11 | 12 | @Composable 13 | fun PipeExample() = Korender(appResourceLoader = { Res.readBytes(it) }) { 14 | Frame { 15 | camera = camera((-10).z, 1.z, 1.y) 16 | projection = projection(3f * width / height, 3f, 3f, 100f) 17 | DirectionalLight(Vec3(1f, -1f, 0.1f)) 18 | Renderable( 19 | base(color = ColorRGBA.Blue), 20 | pipe(), 21 | mesh = pipeMesh("pipe", 7, false) { 22 | sequence { 23 | node(-2.y, 1.6f) 24 | node(6.y, 1.6f) 25 | } 26 | } 27 | ) 28 | Renderable( 29 | base(color = ColorRGBA.Red), 30 | mesh = cube(), 31 | transform = scale(7f, 1f, 7f).translate(-2.4f.y) 32 | ) 33 | Gui { 34 | Column { 35 | Filler() 36 | Text(id = "fps", text = "FPS ${frameInfo.avgFps.toInt()}", height = 40, color = ColorRGBA(0x66FF55A0)) 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/MultipleViewportsExample.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples 2 | 3 | import androidx.compose.foundation.layout.Arrangement 4 | import androidx.compose.foundation.layout.Box 5 | import androidx.compose.foundation.layout.Column 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.ui.Modifier 8 | import androidx.compose.ui.unit.dp 9 | import com.zakgof.app.resources.Res 10 | import com.zakgof.korender.Korender 11 | import com.zakgof.korender.math.ColorRGBA 12 | import com.zakgof.korender.math.Vec3 13 | 14 | @Composable 15 | fun MultipleViewportsExample() = Column( 16 | verticalArrangement = Arrangement.spacedBy(5.dp) 17 | ) { 18 | Box (modifier = Modifier.weight(1f)) { 19 | Korender(appResourceLoader = { Res.readBytes(it) }) { 20 | Frame { 21 | DirectionalLight(Vec3(1f, -1f, 0f)) 22 | Renderable( 23 | base(color = ColorRGBA.Red), 24 | mesh = sphere(1f) 25 | ) 26 | } 27 | } 28 | } 29 | Box (modifier = Modifier.weight(1f)) { 30 | Korender(appResourceLoader = { Res.readBytes(it) }) { 31 | Frame { 32 | DirectionalLight(Vec3(1f, -1f, 0f)) 33 | Renderable( 34 | base(color = ColorRGBA.Green), 35 | mesh = sphere(1f) 36 | ) 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/TransparencyExample.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples 2 | 3 | 4 | import androidx.compose.runtime.Composable 5 | import com.zakgof.app.resources.Res 6 | import com.zakgof.korender.Korender 7 | import com.zakgof.korender.examples.camera.OrbitCamera 8 | import com.zakgof.korender.math.ColorRGB 9 | import com.zakgof.korender.math.ColorRGBA 10 | import com.zakgof.korender.math.Transform.Companion.scale 11 | import com.zakgof.korender.math.Vec3 12 | import com.zakgof.korender.math.y 13 | import com.zakgof.korender.math.z 14 | 15 | @Composable 16 | fun TransparencyExample() { 17 | Korender(appResourceLoader = { Res.readBytes(it) }) { 18 | val orbitCamera = OrbitCamera(20.z, 0.y) 19 | OnTouch { orbitCamera.touch(it) } 20 | Frame { 21 | AmbientLight(ColorRGB.White) 22 | camera = orbitCamera.run { camera() } 23 | fun semitransparent(color: ColorRGBA, position: Vec3) = Renderable( 24 | base(color = color), 25 | mesh = cube(), 26 | transform = scale(5.0f, 5.0f, 0.1f).translate(position), 27 | transparent = true 28 | ) 29 | 30 | semitransparent(ColorRGBA(0.5f, 0.0f, 0.0f, 0.5f), Vec3(0f, 0f, 0f)) 31 | semitransparent(ColorRGBA(0.0f, 0.5f, 0.0f, 0.5f), Vec3(1f, 1f, 1f)) 32 | semitransparent(ColorRGBA(0.0f, 0.0f, 0.5f, 0.5f), Vec3(-1f, -1f, -1f)) 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/Resources.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl 2 | 3 | import com.zakgof.korender.KorenderException 4 | import com.zakgof.korender.ResourceLoader 5 | import com.zakgof.korender.impl.gl.GL.glGetError 6 | import com.zakgof.korender.resources.Res 7 | import kotlinx.coroutines.Deferred 8 | import kotlinx.coroutines.ExperimentalCoroutinesApi 9 | 10 | @OptIn(ExperimentalCoroutinesApi::class) 11 | internal fun Deferred.resultOrNull(): T? = if (this.isCompleted) this.getCompleted() else null 12 | 13 | internal suspend fun resourceBytes(appResourceLoader: ResourceLoader, resource: String): ByteArray { 14 | println("Loading resource [$resource]") 15 | if (resource.startsWith("!")) { 16 | return Res.readBytes("files/" + resource.substring(1)) 17 | } 18 | return appResourceLoader.invoke("files/$resource") 19 | } 20 | 21 | internal fun absolutizeResource(resource: String, referrer: String): String { 22 | if (resource.startsWith("data:")) 23 | return resource; 24 | return referrer.split("/").dropLast(1).joinToString("/") + "/" + resource; 25 | } 26 | 27 | internal fun ignoringGlError(block: () -> Unit) { 28 | block() 29 | @Suppress("ControlFlowWithEmptyBody") 30 | while (glGetError() != 0) { 31 | } 32 | } 33 | 34 | internal fun checkGlError(point: String) { 35 | val error = glGetError() 36 | if (error != 0) { 37 | throw KorenderException("GL error $error $point") 38 | } 39 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/font/Fonts.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.font 2 | 3 | import com.zakgof.korender.Platform 4 | import com.zakgof.korender.RetentionPolicy 5 | import com.zakgof.korender.impl.engine.Loader 6 | import com.zakgof.korender.impl.engine.Retentionable 7 | import com.zakgof.korender.impl.glgpu.GlGpuTexture 8 | import com.zakgof.korender.impl.image.InternalImage 9 | 10 | 11 | internal object Fonts { 12 | 13 | fun load(fontResource: String, loader: Loader): Font? = 14 | loader.safeBytes(fontResource) { 15 | loader.wait(fontResource) { Platform.loadFont(it) } 16 | }?.let { 17 | Font(GlGpuTexture(it.image), it.widths) 18 | } 19 | } 20 | 21 | internal class FontDef(val image: InternalImage, val widths: FloatArray) 22 | 23 | internal class Font(val gpuTexture: GlGpuTexture, val widths: FloatArray) : AutoCloseable { 24 | 25 | override fun close() = gpuTexture.close() 26 | 27 | fun textWidth(height: Int, text: String): Int = 28 | text.toCharArray() 29 | .map { widths[it.code] * height } 30 | .sum() 31 | .toInt() 32 | } 33 | 34 | internal class InternalFontDeclaration(val resource: String, override val retentionPolicy: RetentionPolicy) : Retentionable { 35 | override fun equals(other: Any?): Boolean = 36 | (other is InternalFontDeclaration && other.resource == resource) 37 | 38 | override fun hashCode(): Int = resource.hashCode() 39 | } -------------------------------------------------------------------------------- /docs/filters.md: -------------------------------------------------------------------------------- 1 | # Post-processing filters 2 | 3 | Korender supports post-processing effects that can be applied to the rendered scene. The post-processing pipeline operates as follows: 4 | 5 | - The scene is first rendered to a framebuffer, capturing both color and depth as target textures. 6 | - Each post-processing effect renders a full-screen quad using a dedicated shader, utilizing color and depth data from the original scene or the output of the previous effect. 7 | - The final post-processing effect renders directly to the screen. 8 | 9 | To define a post-processing effect in your frame, use the `PostProcess` function with one or more material modifiers that specify the effect’s shader. 10 | 11 | ````kotlin 12 | Frame { 13 | PostProcess(blurHorz(radius = 3.0f)) 14 | PostProcess(blurVert(radius = 3.0f)) 15 | ```` 16 | 17 | Korender includes the following built-in post-processing material modifiers: 18 | 19 | | Post-process filter | Description | 20 | |---------------------|--------------------------------------------| 21 | | blurHorz | Horizontal separable blur pass | 22 | | blurVert | Vertical separable blur pass | 23 | | adjust | Adjust brightness, contract and saturation | 24 | | water | Water effect | 25 | | fog | Fog | 26 | | fxaa | FXAA anti-aliasing filter | 27 | 28 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/plugin/vposition.skinning.vert: -------------------------------------------------------------------------------- 1 | layout(location = 3) in uvec4 joints; 2 | layout(location = 4) in vec4 weights; 3 | 4 | mat4 skinningMatrix; 5 | 6 | #ifdef INSTANCING 7 | uniform sampler2D jntTexture; 8 | #else 9 | #uniform mat4 jntMatrices[32]; 10 | #endif 11 | 12 | 13 | #ifdef INSTANCING 14 | mat4 fetchJointMatrix(uint jnt) { 15 | mat4 jointMatrix; 16 | jointMatrix[0] = texelFetch(jntTexture, ivec2(int(jnt) * 4 + 0, gl_InstanceID), 0); 17 | jointMatrix[1] = texelFetch(jntTexture, ivec2(int(jnt) * 4 + 1, gl_InstanceID), 0); 18 | jointMatrix[2] = texelFetch(jntTexture, ivec2(int(jnt) * 4 + 2, gl_InstanceID), 0); 19 | jointMatrix[3] = texelFetch(jntTexture, ivec2(int(jnt) * 4 + 3, gl_InstanceID), 0); 20 | return jointMatrix; 21 | } 22 | #endif 23 | 24 | vec4 pluginVPosition() { 25 | #ifdef INSTANCING 26 | skinningMatrix = 27 | weights.x * fetchJointMatrix(joints.x) + 28 | weights.y * fetchJointMatrix(joints.y) + 29 | weights.z * fetchJointMatrix(joints.z) + 30 | weights.w * fetchJointMatrix(joints.w); 31 | #else 32 | skinningMatrix = 33 | weights.x * jntMatrices[joints.x] + 34 | weights.y * jntMatrices[joints.y] + 35 | weights.z * jntMatrices[joints.z] + 36 | weights.w * jntMatrices[joints.w]; 37 | #endif 38 | return totalModel * (skinningMatrix * vec4(pos, 1.0)); 39 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/base.vert: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | 4 | layout(location = 0) in vec3 pos; 5 | layout(location = 1) in vec3 normal; 6 | layout(location = 2) in vec2 tex; 7 | #ifdef INSTANCING 8 | layout(location = 11) in vec4 instanceModel0; 9 | layout(location = 12) in vec4 instanceModel1; 10 | layout(location = 13) in vec4 instanceModel2; 11 | layout(location = 14) in vec4 instanceModel3; 12 | #endif 13 | 14 | out vec3 vpos; 15 | out vec3 vnormal; 16 | out vec2 vtex; 17 | 18 | #uniform mat4 model; 19 | #uniforms 20 | 21 | mat4 totalModel; 22 | 23 | #ifdef PLUGIN_VPOSITION 24 | #import "$vposition" 25 | #endif 26 | 27 | #ifdef PLUGIN_VNORMAL 28 | #import "$vnormal" 29 | #endif 30 | 31 | #import "$vprojection" 32 | 33 | void main() { 34 | 35 | totalModel = model; 36 | 37 | #ifdef INSTANCING 38 | totalModel = model * mat4(instanceModel0, instanceModel1, instanceModel2, instanceModel3); 39 | #endif 40 | 41 | #ifdef PLUGIN_VPOSITION 42 | vec4 worldPos = pluginVPosition(); 43 | #else 44 | vec4 worldPos = totalModel * vec4(pos, 1.0); 45 | #endif 46 | 47 | #ifdef PLUGIN_VNORMAL 48 | vnormal = pluginVNormal(); 49 | #else 50 | vnormal = mat3(transpose(inverse(totalModel))) * normal; 51 | #endif 52 | 53 | vpos = worldPos.xyz; 54 | vtex = tex; 55 | 56 | vec3 viewPos = (view * worldPos).xyz; 57 | gl_Position = pluginVProjection(viewPos); 58 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/impl/context/DefaultInstancedContext.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.impl.context 2 | 3 | import com.zakgof.korender.context.InstancedBillboardsContext 4 | import com.zakgof.korender.context.InstancedGltfContext 5 | import com.zakgof.korender.context.InstancedRenderablesContext 6 | import com.zakgof.korender.impl.engine.BillboardInstance 7 | import com.zakgof.korender.impl.engine.GltfInstance 8 | import com.zakgof.korender.impl.engine.MeshInstance 9 | import com.zakgof.korender.math.Transform 10 | import com.zakgof.korender.math.Vec2 11 | import com.zakgof.korender.math.Vec3 12 | 13 | internal class DefaultInstancedBillboardsContext internal constructor(private val instances: MutableList) : InstancedBillboardsContext { 14 | override fun Instance(pos: Vec3, scale: Vec2, rotation: Float) { 15 | instances.add(BillboardInstance(pos, scale, rotation)) 16 | } 17 | } 18 | 19 | internal class DefaultInstancedRenderablesContext internal constructor(private val instances: MutableList) : InstancedRenderablesContext { 20 | override fun Instance(transform: Transform) { 21 | instances.add(MeshInstance(transform, null)) 22 | } 23 | } 24 | 25 | internal class DefaultInstancedGltfContext internal constructor(private val instances: MutableList) : InstancedGltfContext { 26 | override fun Instance(transform: Transform, time: Float?, animation: Int?) { 27 | instances.add(GltfInstance(transform, time, animation)) 28 | } 29 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/SkyExample.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples 2 | 3 | 4 | import androidx.compose.runtime.Composable 5 | import com.zakgof.app.resources.Res 6 | import com.zakgof.korender.Korender 7 | import com.zakgof.korender.examples.camera.FreeCamera 8 | import com.zakgof.korender.math.ColorRGB 9 | import com.zakgof.korender.math.Transform.Companion.scale 10 | import com.zakgof.korender.math.Vec3 11 | import com.zakgof.korender.math.z 12 | import org.jetbrains.compose.resources.ExperimentalResourceApi 13 | 14 | @Composable 15 | fun SkyExample() { 16 | Korender(appResourceLoader = { Res.readBytes(it) }) { 17 | val freeCamera = FreeCamera(this, Vec3(0f, 4f, 20f), -1.z) 18 | OnTouch { freeCamera.touch(it) } 19 | Frame { 20 | AmbientLight(ColorRGB.White) 21 | camera = freeCamera.camera(projection, width, height, 0f) 22 | Sky(starrySky()) 23 | Renderable( 24 | base(colorTexture = texture("texture/asphalt-albedo.jpg"), metallicFactor = 0.2f, roughnessFactor = 0.9f), 25 | normalTexture(normalTexture = texture("texture/asphalt-normal.jpg")), 26 | triplanar(0.1f), 27 | mesh = cube(1f), 28 | transform = scale(2000f, 1f, 2000f) 29 | ) 30 | Gui { 31 | Column { 32 | Filler() 33 | Text(id = "fps", text = "FPS ${frameInfo.avgFps.toInt()}") 34 | } 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/caster.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | 4 | in vec3 vpos; 5 | in vec3 vnormal; 6 | in vec2 vtex; 7 | #ifdef VERTEX_COLOR 8 | in vec4 vcolor; 9 | #endif 10 | 11 | #uniform vec4 baseColor; 12 | #ifdef BASE_COLOR_MAP 13 | uniform sampler2D baseColorTexture; 14 | #endif 15 | 16 | #uniforms 17 | 18 | out vec4 fragColor; 19 | 20 | vec3 position; 21 | vec4 albedo; 22 | 23 | #ifdef PLUGIN_POSITION 24 | #import "$position" 25 | #endif 26 | 27 | #ifdef PLUGIN_TEXTURING 28 | #import "$texturing" 29 | #endif 30 | 31 | #ifdef PLUGIN_ALBEDO 32 | #import "$albedo" 33 | #endif 34 | 35 | void main() { 36 | 37 | albedo = baseColor; 38 | 39 | #ifdef VERTEX_COLOR 40 | albedo *= vcolor; 41 | #endif 42 | 43 | #ifdef PLUGIN_POSITION 44 | position = pluginPosition(); 45 | #else 46 | position = vpos; 47 | #endif 48 | 49 | #ifdef PLUGIN_TEXTURING 50 | albedo *= pluginTexturing(); 51 | #else 52 | #ifdef BASE_COLOR_MAP 53 | albedo *= texture(baseColorTexture, vtex); 54 | #endif 55 | #endif 56 | 57 | #ifdef PLUGIN_ALBEDO 58 | albedo = pluginAlbedo(); 59 | #endif 60 | 61 | if (albedo.a < 0.001) 62 | discard; 63 | 64 | 65 | #ifdef VSM_SHADOW 66 | float d = gl_FragCoord.z; 67 | float m1 = d * d; 68 | float dx = dFdx(m1); 69 | float dy = dFdy(m1); 70 | float m2 = m1 * m1 + 0.25 * (dx * dx + dy * dy); 71 | fragColor = vec4(m1, m2, 1.0, 1.0); 72 | #endif 73 | 74 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/pipe.vert: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | 4 | layout(location = 0) in vec3 pos; 5 | layout(location = 1) in vec3 normal; 6 | layout(location = 2) in vec2 tex; 7 | layout(location = 5) in vec2 scale; 8 | #ifdef INSTANCING 9 | layout(location = 11) in vec4 instanceModel0; 10 | layout(location = 12) in vec4 instanceModel1; 11 | layout(location = 13) in vec4 instanceModel2; 12 | layout(location = 14) in vec4 instanceModel3; 13 | #endif 14 | 15 | out vec3 vpos; 16 | out vec3 vnormal; 17 | out vec2 vtex; 18 | 19 | out vec3 vleft; 20 | out vec2 vscale; 21 | 22 | #uniform mat4 model; 23 | #uniforms 24 | 25 | #import "$vprojection" 26 | 27 | void main() { 28 | 29 | mat4 totalModel = model; 30 | 31 | #ifdef INSTANCING 32 | totalModel = model * mat4(instanceModel0, instanceModel1, instanceModel2, instanceModel3); 33 | #endif 34 | 35 | vec3 basepos = (totalModel * vec4(pos, 1.0)).xyz; 36 | vnormal = mat3(transpose(inverse(totalModel))) * normal; 37 | 38 | vec3 toEye = normalize(cameraPos - basepos); 39 | 40 | vleft = normalize(cross(toEye, vnormal)); 41 | float width = mix(scale.x, scale.y, tex.y); 42 | 43 | vec3 back = normalize(cross(vnormal, vleft)); 44 | 45 | vpos = basepos - vleft * (tex.x - 0.5) * 2.0 * width + vnormal * tex.y + back * width; 46 | vtex = tex; 47 | vscale = scale; 48 | 49 | vec4 worldPos = vec4(vpos, 1.0); 50 | 51 | vec3 viewPos = (view * worldPos).xyz; 52 | gl_Position = pluginVProjection(viewPos); 53 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/GltfCrowdExample.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples 2 | 3 | import androidx.compose.runtime.Composable 4 | import com.zakgof.app.resources.Res 5 | import com.zakgof.korender.Korender 6 | import com.zakgof.korender.examples.camera.OrbitCamera 7 | import com.zakgof.korender.math.ColorRGB.Companion.white 8 | import com.zakgof.korender.math.Transform.Companion.scale 9 | import com.zakgof.korender.math.Vec3 10 | import com.zakgof.korender.math.y 11 | import com.zakgof.korender.math.z 12 | 13 | @Composable 14 | fun GltfCrowdExample() = Korender(appResourceLoader = { Res.readBytes(it) }) { 15 | val orbitCamera = OrbitCamera(15.z, 0.y) 16 | OnTouch { orbitCamera.touch(it) } 17 | Frame { 18 | camera = orbitCamera.run { camera() } 19 | AmbientLight(white(0.6f)) 20 | DirectionalLight(Vec3(1.0f, -1.0f, -1.0f), white(3f)) 21 | Gltf( 22 | resource = "gltf/ai/swat.glb", 23 | instancing = gltfInstancing("crowd", 49, true) { 24 | (-3..3).forEach { x -> 25 | (-3..3).forEach { z -> 26 | Instance( 27 | time = (x + z * 31) * 100f + frameInfo.time, 28 | transform = scale(0.01f).translate(x.toFloat(), -2f, z.toFloat()) 29 | ) 30 | } 31 | } 32 | } 33 | ) 34 | Gui { 35 | Column { 36 | Filler() 37 | Text(id = "fps", text = "FPS ${frameInfo.avgFps.toInt()}") 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/desktopMain/kotlin/KeyMapping.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender 2 | 3 | import java.awt.event.KeyEvent.* 4 | 5 | internal val KEY_MAPPING = mapOf( 6 | VK_A to "A", 7 | VK_B to "B", 8 | VK_C to "C", 9 | VK_D to "D", 10 | VK_E to "E", 11 | VK_F to "F", 12 | VK_G to "G", 13 | VK_H to "H", 14 | VK_I to "I", 15 | VK_J to "J", 16 | VK_K to "K", 17 | VK_L to "L", 18 | VK_M to "M", 19 | VK_N to "N", 20 | VK_O to "O", 21 | VK_P to "P", 22 | VK_Q to "Q", 23 | VK_R to "R", 24 | VK_S to "S", 25 | VK_T to "T", 26 | VK_U to "U", 27 | VK_V to "V", 28 | VK_W to "W", 29 | VK_X to "X", 30 | VK_Y to "Y", 31 | VK_Z to "Z", 32 | VK_0 to "0", 33 | VK_1 to "1", 34 | VK_2 to "2", 35 | VK_3 to "3", 36 | VK_4 to "4", 37 | VK_5 to "5", 38 | VK_6 to "6", 39 | VK_7 to "7", 40 | VK_8 to "8", 41 | VK_9 to "9", 42 | VK_ESCAPE to "ESC", 43 | VK_F1 to "F1", 44 | VK_F2 to "F2", 45 | VK_F3 to "F3", 46 | VK_F4 to "F4", 47 | VK_F5 to "F5", 48 | VK_F6 to "F6", 49 | VK_F7 to "F7", 50 | VK_F8 to "F8", 51 | VK_F9 to "F9", 52 | VK_F10 to "F10", 53 | VK_F11 to "F11", 54 | VK_F12 to "F12", 55 | VK_PRINTSCREEN to "PRINTSCREEN", 56 | VK_DELETE to "DEL", 57 | VK_HOME to "HOME", 58 | VK_END to "END", 59 | VK_PAGE_UP to "PGUP", 60 | VK_PAGE_DOWN to "PGDOWN", 61 | VK_DEAD_TILDE to "~", 62 | VK_TAB to "TAB", 63 | VK_CAPS_LOCK to "CAPSLOCK", 64 | VK_UP to "UP", 65 | VK_DOWN to "DOWN", 66 | VK_LEFT to "LEFT", 67 | VK_RIGHT to "RIGHT", 68 | ) -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/kotlin/ltree/generator/SpruceTreeGenerator.kt: -------------------------------------------------------------------------------- 1 | package ltree.generator 2 | 3 | import com.zakgof.korender.math.y 4 | import ltree.floatIn 5 | import ltree.randomOrtho 6 | import kotlin.random.Random 7 | 8 | class SpruceTreeGenerator : SplitGrowTreeGenerator( 9 | maxAge = 16.0f, 10 | thicknessRatio = 1.14f, 11 | branchingStrategy = { branch: BranchDetail, r: Random -> 12 | if (branch.age < 1.6f) { 13 | listOf( 14 | (1.y.randomOrtho(r) * r.floatIn(0.01f, 0.06f) + 0.3f.y) to branch.age + 0.3f 15 | ) 16 | } else if (branch.age < 7f) { 17 | listOf( 18 | (1.y.randomOrtho(r) * r.floatIn(0.01f, 0.06f) + 0.3f.y) to branch.age + 0.3f, 19 | (1.y.randomOrtho(r) - branch.vector * 2.0f).normalize() * 1.0f to 10f + branch.age 20 | ) 21 | } else if (branch.vector.y < 0f) { 22 | val right = (1.y % branch.vector).normalize() * r.floatIn(0.5f, 1.0f) 23 | listOf( 24 | (branch.vector + right).normalize() to branch.age + 1f, 25 | (branch.vector - right).normalize() to branch.age + 1f, 26 | (branch.vector).normalize() * 1.3f to branch.age + 1.3f 27 | ) 28 | } else { 29 | listOf() 30 | } 31 | }, 32 | leafStrategy = { branch, r -> 33 | if (branch.age < 7f) 34 | listOf() 35 | else { 36 | (0 until 3).map { 37 | LTree.Leaf(branch.head, branch.vector, branch.vector.randomOrtho(r), 0.3f) 38 | } 39 | } 40 | 41 | } 42 | ) 43 | -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/kotlin/island/pixelmap/PixelMap.kt: -------------------------------------------------------------------------------- 1 | package island.pixelmap 2 | 3 | import com.zakgof.korender.math.Vec2 4 | import java.awt.image.BufferedImage 5 | import java.io.File 6 | import javax.imageio.ImageIO 7 | 8 | abstract class PixelMap

(val side: Int) { 9 | 10 | @Suppress("UNCHECKED_CAST") 11 | private val points: Array

= arrayOfNulls(side * side) as Array

12 | 13 | fun populate(function: (pt: Vec2) -> P) { 14 | for (xx in 0 until side) { 15 | for (zz in 0 until side) { 16 | points[xx + zz * side] = function(toVec2(xx, zz)) 17 | } 18 | } 19 | } 20 | 21 | fun toFl(pixel: Int): Float = (pixel + 0.5f) / side 22 | fun toPix(coord: Float): Int = (coord * side - 0.5f).toInt() 23 | fun toVec2(xx: Int, yy: Int): Vec2 = Vec2(toFl(xx), toFl(yy)) 24 | 25 | 26 | fun save(file: File) { 27 | val bi = BufferedImage(side, side, imageType) 28 | val raster = bi.raster 29 | val pixel = IntArray(pixelChannels) 30 | for (xx in 0 until side) { 31 | for (zz in 0 until side) { 32 | fillPixel(get(xx, zz), pixel) 33 | raster.setPixel(xx, zz, pixel) 34 | } 35 | } 36 | ImageIO.write(bi, "png", file) 37 | } 38 | 39 | fun set(xx: Int, zz: Int, value: P) { 40 | points[xx + zz * side] = value 41 | } 42 | 43 | fun get(xx: Int, zz: Int): P = points[xx + zz * side] 44 | 45 | abstract val imageType: Int 46 | 47 | abstract val pixelChannels: Int 48 | 49 | abstract fun fillPixel(value: P, pixel: IntArray) 50 | } 51 | 52 | -------------------------------------------------------------------------------- /korender-framework/baker/src/commonMain/kotlin/ltree/clusterizer/KMeans.kt: -------------------------------------------------------------------------------- 1 | package ltree.clusterizer 2 | 3 | import com.zakgof.korender.math.Vec3 4 | import com.zakgof.korender.math.x 5 | import ltree.generator.LTree 6 | import kotlin.math.abs 7 | 8 | class Plane(var center: Vec3, var normal: Vec3) { 9 | fun distanceTo(leaf: LTree.Leaf): Float { 10 | val planeDistance = (leaf.mount - center) * normal 11 | val projection = leaf.mount - normal * planeDistance 12 | return abs(planeDistance) + 0.1f * (projection - center).length() + 3.0f * (normal - leaf.normal).length() 13 | } 14 | } 15 | 16 | fun kMeans(leaves: List, initialPlanes: List): Map> { 17 | 18 | val planes = leaves.groupBy { leaf -> 19 | initialPlanes.minBy { plane -> plane.distanceTo(leaf) } 20 | }.toMutableMap() 21 | 22 | for (i in 0..128) { 23 | 24 | planes.forEach { 25 | val center = it.value.fold(0.x) { a, leaf -> a + leaf.mount } * (1f / it.value.size) 26 | val normal = it.value.fold(0.x) { a, leaf -> a + leaf.normal }.normalize() 27 | it.key.center = center 28 | it.key.normal = normal 29 | } 30 | 31 | val newPlanes = leaves.groupBy { leaf -> 32 | planes.keys.minBy { plane -> plane.distanceTo(leaf) } 33 | } 34 | planes.clear() 35 | planes += newPlanes 36 | 37 | val metric = planes.entries.sumOf { 38 | it.value.sumOf { l -> it.key.distanceTo(l).toDouble() } 39 | }.toFloat() 40 | 41 | println("KMeans iteration: $i metric: $metric") 42 | } 43 | return planes 44 | } 45 | 46 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/billboard.vert: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | #import "!shader/lib/ubo.glsl" 3 | 4 | layout(location = 2) in vec2 tex; 5 | #ifdef INSTANCING 6 | layout(location = 11) in vec3 instpos; 7 | layout(location = 12) in vec2 instscale; 8 | layout(location = 13) in float instrot; 9 | #endif 10 | 11 | #uniform mat4 model; 12 | 13 | #ifndef INSTANCING 14 | #uniform vec3 pos; 15 | #uniform vec2 scale; 16 | #uniform float rotation; 17 | #endif 18 | 19 | #uniforms 20 | 21 | out vec3 vcenter; 22 | out vec3 vpos; 23 | out vec2 vsize; 24 | out vec3 vnormal; 25 | out vec2 vtex; 26 | 27 | #import "$vprojection" 28 | 29 | void main() { 30 | 31 | #ifdef INSTANCING 32 | vec3 bpos = instpos; 33 | vec2 bscale = instscale; 34 | float brot = instrot; 35 | #else 36 | vec3 bpos = pos; 37 | vec2 bscale = scale; 38 | float brot = rotation; 39 | #endif 40 | 41 | vcenter = bpos; 42 | vec3 cameraRight = normalize(vec3(view[0][0], view[1][0], view[2][0])); 43 | vec3 cameraUp = normalize(vec3(view[0][1], view[1][1], view[2][1])); 44 | 45 | float right = ((tex.x - 0.5) * bscale.x); 46 | float up = ((tex.y - 0.5) * bscale.y); 47 | 48 | float l = sqrt(right * right + up * up); 49 | float angle = atan(up, right) + brot; 50 | 51 | vpos = vcenter + cameraRight * l * cos(angle) + cameraUp * l * sin(angle); 52 | vsize = bscale; 53 | vtex = vec2(tex.x, 1.0 - tex.y); 54 | vnormal = normalize(cameraPos - vcenter); 55 | 56 | vec3 viewPos = (view * vec4(vpos, 1.0)).xyz; 57 | gl_Position = pluginVProjection(viewPos); 58 | } -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/math/BoundingBox.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.math 2 | 3 | fun toAABB(points: List): Set { 4 | val xmin = points.minOf { it.x } 5 | val ymin = points.minOf { it.y } 6 | val zmin = points.minOf { it.z } 7 | val xmax = points.maxOf { it.x } 8 | val ymax = points.maxOf { it.y } 9 | val zmax = points.maxOf { it.z } 10 | return setOf( 11 | Vec3(xmin, ymin, zmin), 12 | Vec3(xmax, ymin, zmin), 13 | Vec3(xmin, ymax, zmin), 14 | Vec3(xmax, ymax, zmin), 15 | Vec3(xmin, ymin, zmax), 16 | Vec3(xmax, ymin, zmax), 17 | Vec3(xmin, ymax, zmax), 18 | Vec3(xmax, ymax, zmax) 19 | ) 20 | } 21 | 22 | class BoundingBox(val corners: Set) { 23 | 24 | constructor(points: List) : this(toAABB(points)) 25 | 26 | fun transform(transform: Transform): BoundingBox = 27 | BoundingBox(corners.map { transform.mat4 * it }) 28 | 29 | fun isIn(mat4: Mat4): Boolean { 30 | val screenSpaceCorners = corners.map { mat4.project(it) } 31 | return !(screenSpaceCorners.all { it.x < -1f } 32 | || screenSpaceCorners.all { it.x > 1f } 33 | || screenSpaceCorners.all { it.y < -1f } 34 | || screenSpaceCorners.all { it.y > 1f } 35 | || screenSpaceCorners.all { it.z < 0f } 36 | || screenSpaceCorners.all { it.z > 1f } 37 | ) 38 | } 39 | 40 | fun center(): Vec3 = Vec3( 41 | corners.sumOf { it.x.toDouble() }.toFloat(), 42 | corners.sumOf { it.y.toDouble() }.toFloat(), 43 | corners.sumOf { it.z.toDouble() }.toFloat() 44 | ) 45 | 46 | } 47 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/composeResources/files/shader/effect/kawase.frag: -------------------------------------------------------------------------------- 1 | #import "!shader/lib/header.glsl" 2 | 3 | in vec2 vtex; 4 | 5 | #uniforms 6 | 7 | #uniform float offset; 8 | uniform sampler2D colorInputTexture; 9 | #ifdef UPSAMPLE 10 | uniform sampler2D highResTexture; 11 | #uniform float highResolutionRatio; 12 | #endif 13 | 14 | uniform sampler2D depthInputTexture; 15 | 16 | out vec4 fragColor; 17 | 18 | void main() { 19 | 20 | #ifdef UPSAMPLE 21 | float centerWeight = 4.0; 22 | #else 23 | float centerWeight = 0.0; 24 | #endif 25 | 26 | vec2 off = offset / vec2(textureSize(colorInputTexture, 0)); 27 | vec2 t1 = vtex + off * vec2(-1.0, -1.0); 28 | vec2 t2 = vtex + off * vec2( 1.0, -1.0); 29 | vec2 t3 = vtex + off * vec2(-1.0, 1.0); 30 | vec2 t4 = vtex + off * vec2( 1.0, 1.0); 31 | vec3 c1 = texture(colorInputTexture, t1).rgb; 32 | vec3 c2 = texture(colorInputTexture, t2).rgb; 33 | vec3 c3 = texture(colorInputTexture, t3).rgb; 34 | vec3 c4 = texture(colorInputTexture, t4).rgb; 35 | vec3 c = texture(colorInputTexture, vtex).rgb; 36 | 37 | float d1 = texture(depthInputTexture, t1).r; 38 | float d2 = texture(depthInputTexture, t2).r; 39 | float d3 = texture(depthInputTexture, t3).r; 40 | float d4 = texture(depthInputTexture, t4).r; 41 | float d = texture(depthInputTexture, vtex).r; 42 | 43 | vec3 color = (c1 + c2 + c3 + c4 + centerWeight * c) / (centerWeight + 4.0); 44 | 45 | #ifdef UPSAMPLE 46 | vec3 highColor = texture(highResTexture, vtex).rgb; 47 | color += highColor * highResolutionRatio; 48 | #endif 49 | 50 | fragColor = vec4(color, 1.0); 51 | gl_FragDepth = min(d, min(min(d1, d2), min(d3, d4))); 52 | } -------------------------------------------------------------------------------- /korender-framework/examples/src/commonMain/kotlin/MetallicRoughnessExample.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.examples 2 | 3 | import androidx.compose.runtime.Composable 4 | import com.zakgof.app.resources.Res 5 | import com.zakgof.korender.CubeTextureSide 6 | import com.zakgof.korender.Korender 7 | import com.zakgof.korender.math.ColorRGB 8 | import com.zakgof.korender.math.ColorRGBA 9 | import com.zakgof.korender.math.Transform.Companion.translate 10 | import com.zakgof.korender.math.Vec3 11 | import com.zakgof.korender.math.y 12 | import com.zakgof.korender.math.z 13 | import kotlin.math.max 14 | 15 | @Composable 16 | fun MetallicRoughnessExample() = Korender(appResourceLoader = { Res.readBytes(it) }) { 17 | val env = cubeTexture(CubeTextureSide.entries.associateWith { "cube/room/${it.toString().lowercase()}.jpg" }) 18 | Frame { 19 | 20 | projection = projection(width = 3f * width / height, height = 3f, near = 3f, far = 1000f) 21 | camera = camera(18.z, -1.z, 1.y) 22 | Sky(cubeSky(env)) 23 | DirectionalLight(Vec3(1.0f, -1.0f, 0.0f), ColorRGB.white(3f)) 24 | AmbientLight(ColorRGB.Black) 25 | for (m in 0..4) { 26 | for (r in 0..4) { 27 | Renderable( 28 | base( 29 | color = ColorRGBA(0x80A0FFFF), 30 | metallicFactor = r / 4.0f, 31 | roughnessFactor = max(m / 4.0f, 0.05f) 32 | ), 33 | ibl(env), 34 | mesh = sphere(0.8f), 35 | transform = translate((m - 2) * 1.7f, (r - 2) * 1.7f, 8f) 36 | ) 37 | } 38 | } 39 | Gui { 40 | Column { 41 | Filler() 42 | Text(id = "fps", text = "FPS ${frameInfo.avgFps.toInt()}") 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /quickstart/composeApp/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /korender-framework/korender/src/commonMain/kotlin/math/Mat3.kt: -------------------------------------------------------------------------------- 1 | package com.zakgof.korender.math 2 | 3 | class Mat3( 4 | val m00: Float, 5 | val m01: Float, 6 | val m02: Float, 7 | val m10: Float, 8 | val m11: Float, 9 | val m12: Float, 10 | val m20: Float, 11 | val m21: Float, 12 | val m22: Float 13 | ) { 14 | companion object { 15 | val ZERO: Mat3 = Mat3(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f) 16 | val IDENTITY: Mat3 = Mat3(1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f) 17 | } 18 | 19 | operator fun times(a: Float): Mat3 { 20 | return Mat3( 21 | m00 * a, 22 | m01 * a, 23 | m02 * a, 24 | m10 * a, 25 | m11 * a, 26 | m12 * a, 27 | m20 * a, 28 | m21 * a, 29 | m22 * a 30 | ) 31 | } 32 | 33 | operator fun times(vec: Vec3): Vec3 { 34 | return Vec3( 35 | (m00 * vec.x + m01 * vec.y + m02 * vec.z), 36 | (m10 * vec.x + m11 * vec.y + m12 * vec.z), 37 | (m20 * vec.x + m21 * vec.y + m22 * vec.z) 38 | ) 39 | } 40 | 41 | fun asArray(): FloatArray = floatArrayOf( 42 | m00, m10, m20, 43 | m01, m11, m21, 44 | m02, m12, m22 45 | ) 46 | 47 | operator fun times(mat: Mat3): Mat3 = Mat3( 48 | m00 * mat.m00 + m01 * mat.m10 + m02 * mat.m20, 49 | m00 * mat.m01 + m01 * mat.m11 + m02 * mat.m21, 50 | m00 * mat.m02 + m01 * mat.m12 + m02 * mat.m22, 51 | 52 | m10 * mat.m00 + m11 * mat.m10 + m12 * mat.m20, 53 | m10 * mat.m01 + m11 * mat.m11 + m12 * mat.m21, 54 | m10 * mat.m02 + m11 * mat.m12 + m12 * mat.m22, 55 | 56 | m20 * mat.m00 + m21 * mat.m10 + m22 * mat.m20, 57 | m20 * mat.m01 + m21 * mat.m11 + m22 * mat.m21, 58 | m20 * mat.m02 + m21 * mat.m12 + m22 * mat.m22 59 | ) 60 | } --------------------------------------------------------------------------------