fix(lab_2): worked
All worked 2-nd lab
This commit is contained in:
parent
be5701e4de
commit
f18d6f1025
@ -21,18 +21,33 @@ dependencies {
|
|||||||
implementation("org.lwjgl:lwjgl")
|
implementation("org.lwjgl:lwjgl")
|
||||||
implementation("org.lwjgl:lwjgl-glfw")
|
implementation("org.lwjgl:lwjgl-glfw")
|
||||||
implementation("org.lwjgl:lwjgl-opengl")
|
implementation("org.lwjgl:lwjgl-opengl")
|
||||||
|
implementation("org.lwjgl:lwjgl-stb")
|
||||||
|
implementation("org.lwjgl:lwjgl-nanovg")
|
||||||
|
implementation("org.lwjgl:lwjgl-nfd")
|
||||||
|
implementation("org.lwjgl:lwjgl-openal")
|
||||||
|
|
||||||
runtimeOnly("org.lwjgl:lwjgl::$lwjglNatives")
|
runtimeOnly("org.lwjgl:lwjgl::$lwjglNatives")
|
||||||
runtimeOnly("org.lwjgl:lwjgl-glfw::$lwjglNatives")
|
runtimeOnly("org.lwjgl:lwjgl-glfw::$lwjglNatives")
|
||||||
runtimeOnly("org.lwjgl:lwjgl-opengl::$lwjglNatives")
|
runtimeOnly("org.lwjgl:lwjgl-opengl::$lwjglNatives")
|
||||||
|
runtimeOnly("org.lwjgl:lwjgl-stb::$lwjglNatives")
|
||||||
|
runtimeOnly("org.lwjgl:lwjgl-nanovg::$lwjglNatives")
|
||||||
|
runtimeOnly("org.lwjgl:lwjgl-nfd::$lwjglNatives")
|
||||||
|
runtimeOnly("org.lwjgl:lwjgl-openal::$lwjglNatives")
|
||||||
|
|
||||||
|
// JavaFX bindings
|
||||||
|
implementation("org.openjfx:javafx-controls:17")
|
||||||
|
implementation("org.openjfx:javafx-fxml:17")
|
||||||
|
implementation("org.openjfx:javafx-graphics:17")
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
mainClass.set("org.exampl.MainKt")
|
mainClass.set("org.exampl.MainKt")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.test {
|
tasks.test {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
jvmToolchain(21)
|
jvmToolchain(21)
|
||||||
}
|
}
|
@ -7,9 +7,9 @@ import javax.swing.filechooser.FileNameExtensionFilter
|
|||||||
|
|
||||||
class Form1 {
|
class Form1 {
|
||||||
private var loaded = false
|
private var loaded = false
|
||||||
private var currentLayer = 0
|
var currentLayer = 0
|
||||||
private val bin = Bin()
|
private val bin = Bin()
|
||||||
private val view = View()
|
val view = View()
|
||||||
|
|
||||||
private var minTF = -3000
|
private var minTF = -3000
|
||||||
private var widthTF = 2000
|
private var widthTF = 2000
|
||||||
@ -42,11 +42,14 @@ class Form1 {
|
|||||||
openFileDialog()
|
openFileDialog()
|
||||||
while (!glfwWindowShouldClose(window)) {
|
while (!glfwWindowShouldClose(window)) {
|
||||||
displayFPS()
|
displayFPS()
|
||||||
|
glfwPollEvents()
|
||||||
|
|
||||||
if (loaded) {
|
if (loaded) {
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
|
||||||
view.drawQuads(currentLayer)
|
view.drawQuads(currentLayer)
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwSwapBuffers(window)
|
glfwSwapBuffers(window)
|
||||||
glfwPollEvents()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,222 +1,8 @@
|
|||||||
package org.exampl
|
package org.exampl
|
||||||
|
|
||||||
/*import org.lwjgl.opengl.GL
|
|
||||||
import org.lwjgl.opengl.GL11.*
|
|
||||||
import org.lwjgl.opengl.GL15.*
|
|
||||||
import org.lwjgl.opengl.GL20.*
|
|
||||||
import org.lwjgl.opengl.GL30.*
|
|
||||||
import org.lwjgl.system.MemoryUtil
|
|
||||||
import org.lwjgl.glfw.GLFW.*
|
|
||||||
import java.io.File
|
|
||||||
import java.nio.ByteBuffer
|
|
||||||
import java.nio.ByteOrder
|
|
||||||
import kotlin.math.*
|
|
||||||
|
|
||||||
class CTVisualizer {
|
|
||||||
private var window: Long = 0
|
|
||||||
private var vao = 0
|
|
||||||
private var vbo = 0
|
|
||||||
private var textureID = 0
|
|
||||||
private var shaderProgram = 0
|
|
||||||
private var currentLayer = 0
|
|
||||||
private var minValue = 0
|
|
||||||
private var maxValue = 40961
|
|
||||||
private var windowWidth = 1600
|
|
||||||
private var windowHeight = 1000
|
|
||||||
private lateinit var volumeData: ShortArray
|
|
||||||
private var width = 256 // Фиксированный размер для примера
|
|
||||||
private var height = 256
|
|
||||||
private var depth = 256
|
|
||||||
|
|
||||||
fun run(binFilePath: String) {
|
|
||||||
initWindow()
|
|
||||||
initOpenGL()
|
|
||||||
loadVolumeData(binFilePath)
|
|
||||||
mainLoop()
|
|
||||||
cleanup()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initWindow() {
|
|
||||||
if (!glfwInit()) {
|
|
||||||
throw RuntimeException("Failed to initialize GLFW")
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3)
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3)
|
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)
|
|
||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE)
|
|
||||||
|
|
||||||
window = glfwCreateWindow(windowWidth, windowHeight, "КТ Визуализация (OpenTK/Kotlin)", 0, 0)
|
|
||||||
if (window == 0L) {
|
|
||||||
glfwTerminate()
|
|
||||||
throw RuntimeException("Failed to create GLFW window")
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwMakeContextCurrent(window)
|
|
||||||
glfwSwapInterval(1)
|
|
||||||
glfwShowWindow(window)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initOpenGL() {
|
|
||||||
GL.createCapabilities()
|
|
||||||
|
|
||||||
val vertexShader = """
|
|
||||||
#version 330 core
|
|
||||||
layout(location = 0) in vec2 position;
|
|
||||||
layout(location = 1) in vec2 texCoord;
|
|
||||||
out vec2 TexCoord;
|
|
||||||
void main() {
|
|
||||||
gl_Position = vec4(position, 0.0, 1.0);
|
|
||||||
TexCoord = texCoord;
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
|
|
||||||
val fragmentShader = """
|
|
||||||
#version 330 core
|
|
||||||
in vec2 TexCoord;
|
|
||||||
out vec4 FragColor;
|
|
||||||
uniform sampler2D ourTexture;
|
|
||||||
void main() {
|
|
||||||
FragColor = texture(ourTexture, TexCoord);
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
|
|
||||||
shaderProgram = createShaderProgram(vertexShader, fragmentShader)
|
|
||||||
|
|
||||||
vao = glGenVertexArrays()
|
|
||||||
vbo = glGenBuffers()
|
|
||||||
|
|
||||||
glBindVertexArray(vao)
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo)
|
|
||||||
|
|
||||||
val vertices = floatArrayOf(
|
|
||||||
-1.0f, -1.0f, 0.0f, 0.0f,
|
|
||||||
1.0f, -1.0f, 1.0f, 0.0f,
|
|
||||||
-1.0f, 1.0f, 0.0f, 1.0f,
|
|
||||||
1.0f, 1.0f, 1.0f, 1.0f
|
|
||||||
)
|
|
||||||
|
|
||||||
val vertexBuffer = MemoryUtil.memAllocFloat(vertices.size)
|
|
||||||
vertexBuffer.put(vertices).flip()
|
|
||||||
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, vertexBuffer, GL_STATIC_DRAW)
|
|
||||||
glVertexAttribPointer(0, 2, GL_FLOAT, false, 4 * 4, 0)
|
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, false, 4 * 4, 2 * 4)
|
|
||||||
glEnableVertexAttribArray(0)
|
|
||||||
glEnableVertexAttribArray(1)
|
|
||||||
|
|
||||||
MemoryUtil.memFree(vertexBuffer)
|
|
||||||
|
|
||||||
textureID = glGenTextures()
|
|
||||||
glBindTexture(GL_TEXTURE_2D, textureID)
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadVolumeData(binFilePath: String) {
|
|
||||||
val file = File(binFilePath)
|
|
||||||
if (!file.exists()) {
|
|
||||||
throw IllegalArgumentException("File $binFilePath not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
val buffer = ByteBuffer.wrap(file.readBytes())
|
|
||||||
.order(ByteOrder.LITTLE_ENDIAN)
|
|
||||||
.asShortBuffer()
|
|
||||||
|
|
||||||
volumeData = ShortArray(width * height * depth)
|
|
||||||
buffer.get(volumeData)
|
|
||||||
|
|
||||||
// Автоматическое определение min/max значений
|
|
||||||
minValue = volumeData.minOrNull()?.toInt() ?: 0
|
|
||||||
maxValue = volumeData.maxOrNull()?.toInt() ?: 4096
|
|
||||||
|
|
||||||
println("Loaded volume data: ${volumeData.size} voxels")
|
|
||||||
println("Value range: $minValue - $maxValue")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateTexture(layer: Int) {
|
|
||||||
val layerData = ByteBuffer.allocateDirect(width * height * 4)
|
|
||||||
|
|
||||||
for (y in 0 until height) {
|
|
||||||
for (x in 0 until width) {
|
|
||||||
val value = volumeData[x + y * width + layer * width * height].toInt()
|
|
||||||
val normalized = ((value - minValue).toFloat() / (maxValue - minValue).toFloat()).coerceIn(0f, 1f)
|
|
||||||
val color = (normalized * 255).toInt()
|
|
||||||
|
|
||||||
layerData.put(color.toByte())
|
|
||||||
layerData.put(color.toByte())
|
|
||||||
layerData.put(color.toByte())
|
|
||||||
layerData.put(255.toByte()) // Alpha
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
layerData.flip()
|
|
||||||
glBindTexture(GL_TEXTURE_2D, textureID)
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, layerData)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun mainLoop() {
|
|
||||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f)
|
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(window)) {
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT)
|
|
||||||
|
|
||||||
updateTexture(currentLayer)
|
|
||||||
|
|
||||||
glUseProgram(shaderProgram)
|
|
||||||
glBindVertexArray(vao)
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
|
|
||||||
|
|
||||||
glfwSwapBuffers(window)
|
|
||||||
glfwPollEvents()
|
|
||||||
|
|
||||||
if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
|
|
||||||
currentLayer = min(currentLayer + 1, depth - 1)
|
|
||||||
}
|
|
||||||
if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) {
|
|
||||||
currentLayer = max(currentLayer - 1, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createShaderProgram(vertexShaderSource: String, fragmentShaderSource: String): Int {
|
|
||||||
val vertexShader = glCreateShader(GL_VERTEX_SHADER)
|
|
||||||
glShaderSource(vertexShader, vertexShaderSource)
|
|
||||||
glCompileShader(vertexShader)
|
|
||||||
|
|
||||||
val fragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
|
|
||||||
glShaderSource(fragmentShader, fragmentShaderSource)
|
|
||||||
glCompileShader(fragmentShader)
|
|
||||||
|
|
||||||
val program = glCreateProgram()
|
|
||||||
glAttachShader(program, vertexShader)
|
|
||||||
glAttachShader(program, fragmentShader)
|
|
||||||
glLinkProgram(program)
|
|
||||||
|
|
||||||
glDeleteShader(vertexShader)
|
|
||||||
glDeleteShader(fragmentShader)
|
|
||||||
|
|
||||||
return program
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun cleanup() {
|
|
||||||
glDeleteVertexArrays(vao)
|
|
||||||
glDeleteBuffers(vbo)
|
|
||||||
glDeleteTextures(textureID)
|
|
||||||
glDeleteProgram(shaderProgram)
|
|
||||||
glfwTerminate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
// Укажите путь к вашему .bin файлу
|
|
||||||
val binFilePath = "./testdata.bin"
|
|
||||||
CTVisualizer().run(binFilePath)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
import org.lwjgl.glfw.GLFW.*
|
import org.lwjgl.glfw.GLFW.*
|
||||||
import org.lwjgl.opengl.GL
|
import org.lwjgl.opengl.GL
|
||||||
import org.lwjgl.opengl.GL11.glViewport
|
import org.lwjgl.opengl.GL11.*
|
||||||
import org.lwjgl.system.MemoryUtil.NULL
|
import org.lwjgl.system.MemoryUtil.NULL
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
@ -238,21 +24,35 @@ fun main() {
|
|||||||
glViewport(0, 0, width, height)
|
glViewport(0, 0, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val form1 = Form1()
|
||||||
|
|
||||||
|
glfwSetKeyCallback(window) { _: Long, key: Int, _: Int, action: Int, _: Int ->
|
||||||
|
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
|
||||||
|
when (key) {
|
||||||
|
GLFW_KEY_LEFT -> {
|
||||||
|
if (form1.currentLayer > 0) {
|
||||||
|
form1.currentLayer--
|
||||||
|
form1.view.needReload = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GLFW_KEY_RIGHT -> {
|
||||||
|
if (form1.currentLayer < Bin.Z - 1) {
|
||||||
|
form1.currentLayer++
|
||||||
|
form1.view.needReload = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glfwMakeContextCurrent(window)
|
glfwMakeContextCurrent(window)
|
||||||
glfwSwapInterval(1)
|
glfwSwapInterval(1)
|
||||||
glfwShowWindow(window)
|
glfwShowWindow(window)
|
||||||
|
|
||||||
GL.createCapabilities()
|
GL.createCapabilities()
|
||||||
|
|
||||||
val form1 = Form1()
|
|
||||||
form1.run(window)
|
form1.run(window)
|
||||||
|
|
||||||
glfwTerminate()
|
glfwTerminate()
|
||||||
exitProcess(0)
|
exitProcess(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@ import java.awt.image.BufferedImage
|
|||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
class View {
|
class View {
|
||||||
|
var needReload = false
|
||||||
|
|
||||||
fun setupView(width: Int, height: Int) {
|
fun setupView(width: Int, height: Int) {
|
||||||
glShadeModel(GL_SMOOTH)
|
glShadeModel(GL_SMOOTH)
|
||||||
glMatrixMode(GL_PROJECTION)
|
glMatrixMode(GL_PROJECTION)
|
||||||
@ -15,79 +17,12 @@ class View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun drawQuads(layerNumber: Int) {
|
fun drawQuads(layerNumber: Int) {
|
||||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
|
if (needReload) {
|
||||||
|
generateTextureImage(layerNumber)
|
||||||
glBegin(GL_QUADS)
|
load2DTexture()
|
||||||
|
needReload = false
|
||||||
for (x in 0 until Bin.X - 1) {
|
|
||||||
for (y in 0 until Bin.Y - 1) {
|
|
||||||
val value1 = Bin.array[x + y * Bin.X + layerNumber * Bin.X * Bin.Y]
|
|
||||||
val value2 = Bin.array[x + (y + 1) * Bin.X + layerNumber * Bin.X * Bin.Y]
|
|
||||||
val value3 = Bin.array[x + 1 + (y + 1) * Bin.X + layerNumber * Bin.X * Bin.Y]
|
|
||||||
val value4 = Bin.array[x + 1 + y * Bin.X + layerNumber * Bin.X * Bin.Y]
|
|
||||||
|
|
||||||
val color1 = TransferHelper.transferFunction(value1)
|
|
||||||
val color2 = TransferHelper.transferFunction(value2)
|
|
||||||
val color3 = TransferHelper.transferFunction(value3)
|
|
||||||
val color4 = TransferHelper.transferFunction(value4)
|
|
||||||
|
|
||||||
glColor3f(color1.red / 255.0f, color1.green / 255.0f, color1.blue / 255.0f)
|
|
||||||
glVertex2f(x.toFloat(), y.toFloat())
|
|
||||||
|
|
||||||
glColor3f(color2.red / 255.0f, color2.green / 255.0f, color2.blue / 255.0f)
|
|
||||||
glVertex2f(x.toFloat(), (y + 1).toFloat())
|
|
||||||
|
|
||||||
glColor3f(color3.red / 255.0f, color3.green / 255.0f, color3.blue / 255.0f)
|
|
||||||
glVertex2f((x + 1).toFloat(), (y + 1).toFloat())
|
|
||||||
|
|
||||||
glColor3f(color4.red / 255.0f, color4.green / 255.0f, color4.blue / 255.0f)
|
|
||||||
glVertex2f((x + 1).toFloat(), y.toFloat())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glEnd()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun drawQuadStrip(layerNumber: Int) {
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
|
|
||||||
|
|
||||||
for (x in 0 until Bin.X - 1) {
|
|
||||||
glBegin(GL_QUAD_STRIP)
|
|
||||||
|
|
||||||
for (y in 0 until Bin.Y) {
|
|
||||||
val value1 = Bin.array[x + y * Bin.X + layerNumber * Bin.X * Bin.Y]
|
|
||||||
val value2 = Bin.array[x + 1 + y * Bin.X + layerNumber * Bin.X * Bin.Y]
|
|
||||||
|
|
||||||
val color1 = TransferHelper.transferFunction(value1)
|
|
||||||
val color2 = TransferHelper.transferFunction(value2)
|
|
||||||
|
|
||||||
glColor3f(color1.red / 255.0f, color1.green / 255.0f, color1.blue / 255.0f)
|
|
||||||
glVertex2f(x.toFloat(), y.toFloat())
|
|
||||||
|
|
||||||
glColor3f(color2.red / 255.0f, color2.green / 255.0f, color2.blue / 255.0f)
|
|
||||||
glVertex2f((x + 1).toFloat(), y.toFloat())
|
|
||||||
}
|
|
||||||
|
|
||||||
glEnd()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var textureImage: BufferedImage
|
|
||||||
private var textureID: Int = 0
|
|
||||||
|
|
||||||
fun generateTextureImage(layerNumber: Int) {
|
|
||||||
textureImage = BufferedImage(Bin.X, Bin.Y, BufferedImage.TYPE_INT_ARGB)
|
|
||||||
|
|
||||||
for (x in 0 until Bin.X) {
|
|
||||||
for (y in 0 until Bin.Y) {
|
|
||||||
val pixelNumber = x + y * Bin.X + layerNumber * Bin.X * Bin.Y
|
|
||||||
val color = TransferHelper.transferFunction(Bin.array[pixelNumber])
|
|
||||||
textureImage.setRGB(x, y, color.rgb)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun drawTexture() {
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
|
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
|
||||||
glEnable(GL_TEXTURE_2D)
|
glEnable(GL_TEXTURE_2D)
|
||||||
glBindTexture(GL_TEXTURE_2D, textureID)
|
glBindTexture(GL_TEXTURE_2D, textureID)
|
||||||
@ -112,6 +47,21 @@ class View {
|
|||||||
glDisable(GL_TEXTURE_2D)
|
glDisable(GL_TEXTURE_2D)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private lateinit var textureImage: BufferedImage
|
||||||
|
private var textureID: Int = 0
|
||||||
|
|
||||||
|
fun generateTextureImage(layerNumber: Int) {
|
||||||
|
textureImage = BufferedImage(Bin.X, Bin.Y, BufferedImage.TYPE_INT_ARGB)
|
||||||
|
|
||||||
|
for (x in 0 until Bin.X) {
|
||||||
|
for (y in 0 until Bin.Y) {
|
||||||
|
val pixelNumber = x + y * Bin.X + layerNumber * Bin.X * Bin.Y
|
||||||
|
val color = TransferHelper.transferFunction(Bin.array[pixelNumber])
|
||||||
|
textureImage.setRGB(x, y, color.rgb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun load2DTexture() {
|
fun load2DTexture() {
|
||||||
textureID = glGenTextures()
|
textureID = glGenTextures()
|
||||||
glBindTexture(GL_TEXTURE_2D, textureID)
|
glBindTexture(GL_TEXTURE_2D, textureID)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user