Compilable WebGL program
This commit is contained in:
commit
92603d8faf
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/.idea/
|
||||||
|
/gradle/
|
||||||
|
/.gradle/
|
||||||
|
/build/
|
||||||
|
*.class
|
||||||
|
*.jar
|
||||||
|
/out/
|
||||||
|
/gradlew*
|
||||||
|
/.kotlin/
|
||||||
|
*.js
|
28
build.gradle.kts
Normal file
28
build.gradle.kts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("multiplatform") version "2.1.10"
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
js {
|
||||||
|
binaries.executable()
|
||||||
|
browser {
|
||||||
|
commonWebpackConfig {
|
||||||
|
outputFileName = "computer-graphics-1.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
jsMain {
|
||||||
|
dependencies {
|
||||||
|
implementation(kotlin("stdlib"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
gradle.properties
Normal file
1
gradle.properties
Normal file
@ -0,0 +1 @@
|
|||||||
|
kotlin.code.style=official
|
1
settings.gradle.kts
Normal file
1
settings.gradle.kts
Normal file
@ -0,0 +1 @@
|
|||||||
|
rootProject.name = "cg-js"
|
@ -0,0 +1,86 @@
|
|||||||
|
package ru.landgrafhomyak.bgtu.computer_graphics1
|
||||||
|
|
||||||
|
import kotlinx.browser.document
|
||||||
|
import kotlinx.browser.window
|
||||||
|
import org.khronos.webgl.Float32Array
|
||||||
|
import org.khronos.webgl.Int32Array
|
||||||
|
import org.khronos.webgl.WebGLRenderingContext
|
||||||
|
import org.w3c.dom.HTMLCanvasElement
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val canvas = document.getElementById("canvas")!! as HTMLCanvasElement
|
||||||
|
|
||||||
|
val gl: dynamic = canvas.getContext("webgl2")!! /*as WebGLRenderingContext*/
|
||||||
|
|
||||||
|
val modelVertexesBuffer = gl.createBuffer()
|
||||||
|
val textureVertexesBuffer = gl.createBuffer()
|
||||||
|
val textureTypesBuffer = gl.createBuffer()
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, modelVertexesBuffer)
|
||||||
|
gl.bufferData(
|
||||||
|
gl.ARRAY_BUFFER,
|
||||||
|
Float32Array(model.modelVertexes.toTypedArray()),
|
||||||
|
gl.STATIC_DRAW
|
||||||
|
)
|
||||||
|
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 3 * 4, 0)
|
||||||
|
gl.enableVertexAttribArray(0)
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, textureVertexesBuffer)
|
||||||
|
gl.bufferData(
|
||||||
|
gl.ARRAY_BUFFER,
|
||||||
|
Float32Array(model.textureVertexes.toTypedArray()),
|
||||||
|
gl.STATIC_DRAW
|
||||||
|
)
|
||||||
|
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 2 * 4, 0)
|
||||||
|
gl.enableVertexAttribArray(1)
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, textureTypesBuffer)
|
||||||
|
gl.bufferData(
|
||||||
|
gl.ARRAY_BUFFER,
|
||||||
|
Int32Array(model.textureTypes.map { t -> t.ordinal }.toTypedArray()),
|
||||||
|
gl.STATIC_DRAW
|
||||||
|
)
|
||||||
|
gl.vertexAttribIPointer(2, 2, gl.INT, false, 1 * 4, 0)
|
||||||
|
gl.enableVertexAttribArray(2)
|
||||||
|
|
||||||
|
val vertexShader = gl.createShader(gl.VERTEX_SHADER);
|
||||||
|
gl.shaderSource(vertexShader, vertexShaderSource)
|
||||||
|
gl.compileShader(vertexShader)
|
||||||
|
println("vertex shader compilation status: ${gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)}")
|
||||||
|
println("vertex shader compilation log: ${gl.getShaderInfoLog(vertexShader)}")
|
||||||
|
|
||||||
|
val fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
|
||||||
|
gl.shaderSource(fragmentShader, fragmentShaderSource)
|
||||||
|
gl.compileShader(fragmentShader)
|
||||||
|
println("fragment shader compilation status: ${gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)}")
|
||||||
|
println("fragment shader compilation log: ${gl.getShaderInfoLog(fragmentShader)}")
|
||||||
|
|
||||||
|
|
||||||
|
val shaderProgram = gl.createProgram()
|
||||||
|
gl.attachShader(shaderProgram, vertexShader)
|
||||||
|
gl.attachShader(shaderProgram, fragmentShader)
|
||||||
|
gl.linkProgram(shaderProgram)
|
||||||
|
println("program compilation log: ${gl.getProgramInfoLog(shaderProgram)}")
|
||||||
|
|
||||||
|
gl.useProgram(shaderProgram)
|
||||||
|
gl.clearColor(0f, 0f, 0f, 1f);
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
|
gl.drawArrays(gl.TRIANGLES, 0, model.textureTypes.size / 3)
|
||||||
|
|
||||||
|
window.onkeydown = { keyEvent ->
|
||||||
|
when (keyEvent.code) {
|
||||||
|
"ArrowDown" -> {
|
||||||
|
|
||||||
|
gl.clearColor(0f, 0f, 0f, 1f);
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
|
gl.drawArrays(gl.TRIANGLES, 0, model.textureTypes.size / 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
"ArrowUp" -> {}
|
||||||
|
"ArrowLeft" -> {}
|
||||||
|
"ArrowRight" -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,130 @@
|
|||||||
|
package ru.landgrafhomyak.bgtu.computer_graphics1
|
||||||
|
|
||||||
|
import kotlin.math.PI
|
||||||
|
import kotlin.math.cos
|
||||||
|
import kotlin.math.sin
|
||||||
|
import ru.landgrafhomyak.bgtu.computer_graphics1.model_builder.ModelTriangles
|
||||||
|
import ru.landgrafhomyak.bgtu.computer_graphics1.model_builder.Point2F
|
||||||
|
import ru.landgrafhomyak.bgtu.computer_graphics1.model_builder.Polygon
|
||||||
|
import ru.landgrafhomyak.bgtu.computer_graphics1.model_builder.TextureType
|
||||||
|
|
||||||
|
private fun rot_n(degrees: Int, length: Int): Point2F {
|
||||||
|
val radians = degrees.toLong().toDouble() * PI / 180;
|
||||||
|
return Point2F(
|
||||||
|
x = cos(radians).times(length).toFloat(),
|
||||||
|
y = sin(radians).times(length).toFloat()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val model = ModelTriangles.fromPolygons(
|
||||||
|
Polygon(
|
||||||
|
TextureType.HSV,
|
||||||
|
Polygon.PolygonVertex(0f, 1f, 1f, rot_n(0, 1)),
|
||||||
|
Polygon.PolygonVertex(1f, 1f, 0f, rot_n(240, 1)),
|
||||||
|
Polygon.PolygonVertex(1f, 0f, 1f, rot_n(120, 1))
|
||||||
|
),
|
||||||
|
|
||||||
|
Polygon(
|
||||||
|
TextureType.HSV,
|
||||||
|
Polygon.PolygonVertex(-1f, -1f, 1f, rot_n(60, 2)),
|
||||||
|
Polygon.PolygonVertex(-1f, 1f, 1f, rot_n(0, 2)),
|
||||||
|
Polygon.PolygonVertex(0f, 1f, 1f, rot_n(0, 1))
|
||||||
|
),
|
||||||
|
|
||||||
|
Polygon(
|
||||||
|
TextureType.HSV,
|
||||||
|
Polygon.PolygonVertex(-1f, -1f, 1f, rot_n(60, 2)),
|
||||||
|
Polygon.PolygonVertex(1f, 0f, 1f, rot_n(120, 1)),
|
||||||
|
Polygon.PolygonVertex(0f, 1f, 1f, rot_n(0, 1))
|
||||||
|
),
|
||||||
|
|
||||||
|
Polygon(
|
||||||
|
TextureType.HSV,
|
||||||
|
Polygon.PolygonVertex(-1f, -1f, 1f, rot_n(60, 2)),
|
||||||
|
Polygon.PolygonVertex(1f, 0f, 1f, rot_n(120, 1)),
|
||||||
|
Polygon.PolygonVertex(1f, -1f, 1f, rot_n(120, 1))
|
||||||
|
),
|
||||||
|
|
||||||
|
Polygon(
|
||||||
|
TextureType.HSV,
|
||||||
|
Polygon.PolygonVertex(1f, -1f, -1f, rot_n(180, 2)),
|
||||||
|
Polygon.PolygonVertex(1f, 1f, -1f, rot_n(240, 2)),
|
||||||
|
Polygon.PolygonVertex(1f, 1f, 0f, rot_n(240, 1))
|
||||||
|
),
|
||||||
|
|
||||||
|
Polygon(
|
||||||
|
TextureType.HSV,
|
||||||
|
Polygon.PolygonVertex(1f, -1f, -1f, rot_n(180, 2)),
|
||||||
|
Polygon.PolygonVertex(1f, 0f, 1f, rot_n(120, 1)),
|
||||||
|
Polygon.PolygonVertex(1f, 1f, 0f, rot_n(240, 1))
|
||||||
|
),
|
||||||
|
|
||||||
|
Polygon(
|
||||||
|
TextureType.HSV,
|
||||||
|
Polygon.PolygonVertex(1f, -1f, -1f, rot_n(180, 2)),
|
||||||
|
Polygon.PolygonVertex(1f, 0f, 1f, rot_n(120, 1)),
|
||||||
|
Polygon.PolygonVertex(1f, -1f, 1f, rot_n(120, 2))
|
||||||
|
),
|
||||||
|
|
||||||
|
Polygon(
|
||||||
|
TextureType.HSV,
|
||||||
|
Polygon.PolygonVertex(-1f, 1f, -1f, rot_n(300, 2)),
|
||||||
|
Polygon.PolygonVertex(1f, 1f, -1f, rot_n(240, 2)),
|
||||||
|
Polygon.PolygonVertex(1f, 1f, 0f, rot_n(240, 1))
|
||||||
|
),
|
||||||
|
|
||||||
|
Polygon(
|
||||||
|
TextureType.HSV,
|
||||||
|
Polygon.PolygonVertex(-1f, 1f, -1f, rot_n(300, 2)),
|
||||||
|
Polygon.PolygonVertex(0f, 1f, 1f, rot_n(0, 1)),
|
||||||
|
Polygon.PolygonVertex(1f, 1f, 0f, rot_n(240, 1))
|
||||||
|
),
|
||||||
|
|
||||||
|
Polygon(
|
||||||
|
TextureType.HSV,
|
||||||
|
Polygon.PolygonVertex(-1f, 1f, -1f, rot_n(300, 2)),
|
||||||
|
Polygon.PolygonVertex(0f, 1f, 1f, rot_n(0, 1)),
|
||||||
|
Polygon.PolygonVertex(-1f, 1f, 1f, rot_n(0, 2))
|
||||||
|
),
|
||||||
|
Polygon(
|
||||||
|
TextureType.WHITE_TRANSPARENCY,
|
||||||
|
Polygon.PolygonVertex(-1f, -1f, 1f, 0f, 0f),
|
||||||
|
Polygon.PolygonVertex(-1f, -1f, -1f, 0f, 1f),
|
||||||
|
Polygon.PolygonVertex(-1f, 1f, 1f, 1f, 0f)
|
||||||
|
),
|
||||||
|
|
||||||
|
Polygon(
|
||||||
|
TextureType.WHITE_TRANSPARENCY,
|
||||||
|
Polygon.PolygonVertex(-1f, 1f, -1f, 1f, 1f),
|
||||||
|
Polygon.PolygonVertex(-1f, -1f, -1f, 0f, 1f),
|
||||||
|
Polygon.PolygonVertex(-1f, 1f, 1f, 1f, 0f)
|
||||||
|
),
|
||||||
|
|
||||||
|
Polygon(
|
||||||
|
TextureType.WHITE_TRANSPARENCY,
|
||||||
|
Polygon.PolygonVertex(-1f, -1f, -1f, 0f, 0f),
|
||||||
|
Polygon.PolygonVertex(-1f, 1f, -1f, 0f, 1f),
|
||||||
|
Polygon.PolygonVertex(1f, 1f, -1f, 1f, 1f)
|
||||||
|
),
|
||||||
|
|
||||||
|
Polygon(
|
||||||
|
TextureType.WHITE_TRANSPARENCY,
|
||||||
|
Polygon.PolygonVertex(-1f, -1f, -1f, 0f, 0f),
|
||||||
|
Polygon.PolygonVertex(1f, -1f, -1f, 1f, 0f),
|
||||||
|
Polygon.PolygonVertex(1f, 1f, -1f, 1f, 1f)
|
||||||
|
),
|
||||||
|
|
||||||
|
Polygon(
|
||||||
|
TextureType.CHESS,
|
||||||
|
Polygon.PolygonVertex(1f, -1f, 1f, 0f, 0f),
|
||||||
|
Polygon.PolygonVertex(-1f, -1f, 1f, 0f, 1f),
|
||||||
|
Polygon.PolygonVertex(1f, -1f, -1f, 1f, 0f)
|
||||||
|
),
|
||||||
|
Polygon(
|
||||||
|
TextureType.CHESS,
|
||||||
|
Polygon.PolygonVertex(-1f, -1f, -1f, 1f, 1f),
|
||||||
|
Polygon.PolygonVertex(-1f, -1f, 1f, 0f, 1f),
|
||||||
|
Polygon.PolygonVertex(1f, -1f, -1f, 1f, 0f)
|
||||||
|
),
|
||||||
|
)
|
@ -0,0 +1,50 @@
|
|||||||
|
package ru.landgrafhomyak.bgtu.computer_graphics1.model_builder
|
||||||
|
|
||||||
|
|
||||||
|
class ModelTriangles(
|
||||||
|
val modelVertexes: FloatArray,
|
||||||
|
val textureVertexes: FloatArray,
|
||||||
|
val textureTypes: Array<TextureType>
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
private fun <T> MutableCollection<T>.addAll(vararg elems: T) {
|
||||||
|
this.addAll(elems)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromPolygons(vararg polygons: Polygon): ModelTriangles {
|
||||||
|
val modelVertexes = ArrayList<Float>()
|
||||||
|
val textureVertexes = ArrayList<Float>()
|
||||||
|
val textureTypes = ArrayList<TextureType>()
|
||||||
|
|
||||||
|
polygons@ for (polygon in polygons) {
|
||||||
|
val it = polygon.vertexes.iterator()
|
||||||
|
if (!it.hasNext()) continue@polygons
|
||||||
|
val root = it.next()
|
||||||
|
if (!it.hasNext()) continue@polygons
|
||||||
|
var prev = it.next()
|
||||||
|
for (curr in it) {
|
||||||
|
modelVertexes.addAll(
|
||||||
|
root.modelVertex.x, root.modelVertex.y, root.modelVertex.z,
|
||||||
|
prev.modelVertex.x, prev.modelVertex.y, prev.modelVertex.z,
|
||||||
|
curr.modelVertex.x, curr.modelVertex.y, curr.modelVertex.z,
|
||||||
|
)
|
||||||
|
textureVertexes.addAll(
|
||||||
|
root.textureVertex.x, root.textureVertex.y,
|
||||||
|
prev.textureVertex.x, prev.textureVertex.y,
|
||||||
|
curr.textureVertex.x, curr.textureVertex.y,
|
||||||
|
)
|
||||||
|
textureTypes.addAll(
|
||||||
|
polygon.textureType, polygon.textureType, polygon.textureType
|
||||||
|
)
|
||||||
|
|
||||||
|
prev = curr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ModelTriangles(
|
||||||
|
modelVertexes = modelVertexes.toTypedArray().toFloatArray(),
|
||||||
|
textureVertexes = textureVertexes.toTypedArray().toFloatArray(),
|
||||||
|
textureTypes = textureTypes.toTypedArray()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package ru.landgrafhomyak.bgtu.computer_graphics1.model_builder
|
||||||
|
|
||||||
|
class Point2F(
|
||||||
|
val x: Float,
|
||||||
|
val y: Float,
|
||||||
|
) {
|
||||||
|
operator fun component1(): Float = this.x
|
||||||
|
operator fun component2(): Float = this.y
|
||||||
|
|
||||||
|
override fun toString(): String =
|
||||||
|
"<point 2f x=${this.x} y=${this.y}>"
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package ru.landgrafhomyak.bgtu.computer_graphics1.model_builder
|
||||||
|
|
||||||
|
class Point3F(
|
||||||
|
val x: Float,
|
||||||
|
val y: Float,
|
||||||
|
val z: Float,
|
||||||
|
) {
|
||||||
|
operator fun component1(): Float = this.x
|
||||||
|
operator fun component2(): Float = this.y
|
||||||
|
operator fun component3(): Float = this.z
|
||||||
|
|
||||||
|
override fun toString(): String =
|
||||||
|
"<point 3f x=${this.x} y=${this.y} z=${this.z}>"
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package ru.landgrafhomyak.bgtu.computer_graphics1.model_builder
|
||||||
|
|
||||||
|
class Polygon(
|
||||||
|
val textureType: TextureType,
|
||||||
|
vararg val vertexes: PolygonVertex
|
||||||
|
) {
|
||||||
|
init {
|
||||||
|
require(this.vertexes.size >= 3) { "Polygon should has at least 3 vertexes" }
|
||||||
|
}
|
||||||
|
|
||||||
|
class PolygonVertex(
|
||||||
|
val modelVertex: Point3F,
|
||||||
|
val textureVertex: Point2F
|
||||||
|
) {
|
||||||
|
operator fun component1() = this.modelVertex
|
||||||
|
operator fun component2() = this.textureVertex
|
||||||
|
|
||||||
|
constructor(mx: Float, my: Float, mz: Float, tx: Float, ty: Float) :
|
||||||
|
this(Point3F(mx, my, mz), Point2F(tx, ty))
|
||||||
|
|
||||||
|
constructor(m: Point3F, tx: Float, ty: Float) :
|
||||||
|
this(m, Point2F(tx, ty))
|
||||||
|
|
||||||
|
constructor(mx: Float, my: Float, mz: Float, t: Point2F) :
|
||||||
|
this(Point3F(mx, my, mz), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package ru.landgrafhomyak.bgtu.computer_graphics1.model_builder
|
||||||
|
|
||||||
|
enum class TextureType {
|
||||||
|
CHESS,
|
||||||
|
HSV,
|
||||||
|
WHITE_TRANSPARENCY,
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package ru.landgrafhomyak.bgtu.computer_graphics1
|
||||||
|
|
||||||
|
import ru.landgrafhomyak.bgtu.computer_graphics1.model_builder.TextureType
|
||||||
|
|
||||||
|
internal val vertexShaderSource = """
|
||||||
|
#version 300 es
|
||||||
|
|
||||||
|
uniform mat4 transform;
|
||||||
|
layout(location = 0) in vec3 vertex_pos;
|
||||||
|
layout(location = 1) in vec2 texture_pos;
|
||||||
|
layout(location = 2) in int texture_type;
|
||||||
|
out vec2 texture_pos_v2f;
|
||||||
|
flat out int texture_type_v2f;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(vertex_pos.xyz, 1) * transform;
|
||||||
|
texture_pos_v2f = texture_pos;
|
||||||
|
texture_type_v2f = texture_type;
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
internal val fragmentShaderSource = """
|
||||||
|
#version 300 es
|
||||||
|
|
||||||
|
precision mediump float;
|
||||||
|
in vec2 texture_pos_v2f;
|
||||||
|
flat in int texture_type_v2f;
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
switch (texture_type_v2f) {
|
||||||
|
case ${TextureType.WHITE_TRANSPARENCY.ordinal}:
|
||||||
|
color = vec4(255, 255, 255, 127);
|
||||||
|
break;
|
||||||
|
case ${TextureType.CHESS.ordinal}:
|
||||||
|
if (int( round(floor(texture_pos_v2f.x / 0.1)) + round(floor(texture_pos_v2f.y / 0.1)) ) % 2 == 0) {
|
||||||
|
color = vec4(0, 0, 0, 255);
|
||||||
|
} else {
|
||||||
|
color = vec4(255, 255, 255, 255);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ${TextureType.HSV.ordinal}:
|
||||||
|
default:
|
||||||
|
color = vec4(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
12
src/jsMain/resources/index.html
Normal file
12
src/jsMain/resources/index.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas style="left: 0; top: 0; right: 0; bottom:0; position: fixed" id="canvas"></canvas>
|
||||||
|
<script src="computer-graphics-1.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user