) : 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 | }
--------------------------------------------------------------------------------