changeset 145:a4e6e76128e6

add: upgrade all simple examples to new engine version
author Sam <sam@basx.dev>
date Wed, 26 Apr 2023 02:15:43 +0700
parents 01881f9296fa
children 253dd797e719
files examples/E01_hello_triangle.nim examples/E02_squares.nim examples/E03_hello_cube.nim examples/E04_input.nim examples/E10_pong.nim src/semicongine/engine.nim src/semicongine/platform/linux/xlib.nim src/semicongine/vulkan/renderpass.nim src/semicongine/vulkan/shader.nim
diffstat 9 files changed, 91 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/examples/E01_hello_triangle.nim	Tue Apr 25 18:32:23 2023 +0700
+++ b/examples/E01_hello_triangle.nim	Wed Apr 26 02:15:43 2023 +0700
@@ -38,8 +38,7 @@
 myengine.setRenderer(renderPass)
 myengine.addScene(triangle, vertexInput)
 
-while myengine.running and not myengine.keyWasPressed(Escape):
-  myengine.updateInputs()
+while myengine.updateInputs() == Running and not myengine.keyWasPressed(Escape):
   myengine.renderScene(triangle)
 
 myengine.destroy()
--- a/examples/E02_squares.nim	Tue Apr 25 18:32:23 2023 +0700
+++ b/examples/E02_squares.nim	Wed Apr 26 02:15:43 2023 +0700
@@ -93,8 +93,7 @@
   myengine.addScene(scene, vertexInput)
   var time = initShaderGlobal("time", 0.0'f32)
   scene.components.add time
-  while myengine.running and not myengine.keyWasPressed(Escape):
-    myengine.updateInputs()
+  while myengine.updateInputs() == Running and not myengine.keyWasPressed(Escape):
     setValue[float32](time.value, get[float32](time.value) + 0.0005)
     myengine.renderScene(scene)
 
--- a/examples/E03_hello_cube.nim	Tue Apr 25 18:32:23 2023 +0700
+++ b/examples/E03_hello_cube.nim	Wed Apr 26 02:15:43 2023 +0700
@@ -87,8 +87,7 @@
   myengine.addScene(cube, vertexInput)
 
   var t: float32 = cpuTime()
-  while myengine.running and not myengine.keyWasPressed(Escape):
-    myengine.updateInputs()
+  while myengine.updateInputs() == Running and not myengine.keyWasPressed(Escape):
     setValue[Mat4](model.value, translate3d(0'f32, 0'f32, 10'f32) * rotate3d(t, Yf32))
     setValue[Mat4](
       projection.value,
--- a/examples/E04_input.nim	Tue Apr 25 18:32:23 2023 +0700
+++ b/examples/E04_input.nim	Wed Apr 26 02:15:43 2023 +0700
@@ -56,6 +56,7 @@
     CtrlL, SuperL, AltL, Space, AltR, SuperR, CtrlR, Left, Down, Right
   ]
 
+# build keyboard and cursor meshes
 var
   scene: Entity
   keyvertexpos: seq[Vec3f]
@@ -91,7 +92,6 @@
   firstRow = false
 
 
-
 when isMainModule:
   var myengine = initEngine("Input")
 
@@ -106,41 +106,40 @@
   var positions = arrow
   for i in 0 ..< positions.len:
     positions[i] = cursorscale * newVec3f(positions[i].x, positions[i].y)
-  # cursor
-  var cursormesh = newMesh(
-    positions=positions,
-    colors=arrow_colors,
-    instanceCount=1,
-  )
 
-  # keyboard
-  var keyboardmesh = newMesh(
-    positions=keyvertexpos,
-    colors=keyvertexcolor,
-    indices=keymeshindices
-  )
-
-  # background
-  var backgroundmesh = newMesh(
-    positions= @[
-      newVec3f(0'f32, 0'f32),
-      newVec3f(1'f32, 0'f32),
-      newVec3f(1'f32, 1'f32),
-      newVec3f(0'f32, 1'f32),
-    ],
-    colors= @[
-      backgroundColor,
-      backgroundColor,
-      backgroundColor,
-      backgroundColor,
-    ],
-    indices= @[[0'u16, 1'u16, 2'u16], [2'u16, 3'u16, 0'u16]],
-  )
+  # define mesh objects
+  var
+    cursormesh = newMesh(
+      positions=positions,
+      colors=arrow_colors,
+      instanceCount=1,
+    )
+    keyboardmesh = newMesh(
+      positions=keyvertexpos,
+      colors=keyvertexcolor,
+      indices=keymeshindices
+    )
+    backgroundmesh = newMesh(
+      positions= @[
+        newVec3f(0'f32, 0'f32),
+        newVec3f(1'f32, 0'f32),
+        newVec3f(1'f32, 1'f32),
+        newVec3f(0'f32, 1'f32),
+      ],
+      colors= @[
+        backgroundColor,
+        backgroundColor,
+        backgroundColor,
+        backgroundColor,
+      ],
+      indices= @[[0'u16, 1'u16, 2'u16], [2'u16, 3'u16, 0'u16]],
+    )
 
   backgroundmesh.setInstanceData("transform", @[Unit4f32])
   keyboardmesh.setInstanceData("transform", @[Unit4f32])
   cursormesh.setInstanceData("transform", @[Unit4f32])
 
+  # define mesh objects
   scene = newEntity("scene")
   scene.add newEntity("background", backgroundmesh)
   let keyboard = newEntity("keyboard", keyboardmesh)
@@ -152,6 +151,7 @@
   scene.add newEntity("keyboard-center", keyboard)
   scene.add newEntity("cursor", cursormesh)
 
+  # shaders
   const
     vertexInput = @[
       attr[Vec3f]("position", memoryLocation=VRAM),
@@ -175,24 +175,29 @@
       outputs=fragOutput,
       main="color = vec4(outcolor, 1);"
     )
+
+  # set up rendering
   myengine.setRenderer(myengine.gpuDevice.simpleForwardRenderPass(vertexCode, fragmentCode, clearColor=newVec4f(0, 0, 0.5)))
   myengine.addScene(scene, vertexInput, transformAttribute="transform")
   var projection = initShaderGlobal("projection", Unit4f32)
   scene.add projection
-  while myengine.running and not myengine.keyWasPressed(Escape):
-    myengine.updateInputs()
-    setValue[Mat4](projection.value, ortho[float32](
-      0'f32, float32(myengine.getWindow().size[0]),
-      0'f32, float32(myengine.getWindow().size[1]),
-      0'f32, 1'f32,
-    ))
-    let
-      mousePos = translate3d(myengine.mousePosition().x + 20, myengine.mousePosition().y + 20, 0'f32)
-      winsize = myengine.getWindow().size
-      center = translate3d(float32(winsize[0]) / 2'f32, float32(winsize[1]) / 2'f32, 0.1'f32)
+
+  # mainloop
+  while myengine.updateInputs() == Running:
+    if myengine.windowWasResized():
+      setValue[Mat4](projection.value, ortho[float32](
+        0'f32, float32(myengine.getWindow().size[0]),
+        0'f32, float32(myengine.getWindow().size[1]),
+        0'f32, 1'f32,
+      ))
+      let
+        winsize = myengine.getWindow().size
+        center = translate3d(float32(winsize[0]) / 2'f32, float32(winsize[1]) / 2'f32, 0.1'f32)
+      scene.firstWithName("keyboard-center").transform = center
+      scene.firstWithName("background").transform = scale3d(float32(winsize[0]), float32(winsize[1]), 1'f32)
+
+    let mousePos = translate3d(myengine.mousePosition().x + 20, myengine.mousePosition().y + 20, 0'f32)
     scene.firstWithName("cursor").transform = mousePos
-    scene.firstWithName("keyboard-center").transform = center
-    scene.firstWithName("background").transform = scale3d(float32(winsize[0]), float32(winsize[1]), 1'f32)
 
     var mesh = Mesh(scene.firstWithName("keyboard").components[0])
     for (index, key) in enumerate(keyIndices):
--- a/examples/E10_pong.nim	Tue Apr 25 18:32:23 2023 +0700
+++ b/examples/E10_pong.nim	Wed Apr 26 02:15:43 2023 +0700
@@ -1,13 +1,5 @@
 import semicongine
 
-type
-  Vertex = object
-    position: PositionAttribute[Vec2]
-    color: ColorAttribute[Vec3]
-    transform: ModelTransformAttribute
-  Uniforms = object
-    view: ViewProjectionTransform
-
 const
   barcolor = RGBfromHex("5A3F00").gamma(2.2)
   barSize = 0.1'f
@@ -18,14 +10,11 @@
   backgroundColor = RGBAfromHex("FAC034").gamma(2.2)
   ballSpeed = 60'f
 
-echo RGBAfromHex("FAC034")
-echo RGBAfromHex("FAC034").gamma(2.2)
 var
-  uniforms = Uniforms()
-  pipeline: RenderPipeline[Vertex, Uniforms]
-  level: Thing
-  ballVelocity = Vec2([1'f, 1'f]).normalized * ballSpeed
+  level: Entity
+  ballVelocity = newVec2f(1, 1).normalized * ballSpeed
 
+#[
 proc globalUpdate(engine: var Engine; t, dt: float32) =
   var height = float32(engine.vulkan.frameSize.y) / float32(
       engine.vulkan.frameSize.x)
@@ -68,43 +57,30 @@
       ballBottom = ball.transform.col(3).y + ballSize/2
     if ballTop >= barTop and ballBottom <= barBottom:
       ballVelocity[0] = abs(ballVelocity[0])
-
+]#
 
 when isMainModule:
-  var myengine = igniteEngine("Pong")
-  myengine.maxFPS = 61
-  level = newThing("Level")
-  var playerbarmesh = quad[Vertex, Vec2, float32]()
+  var myengine = initEngine("Pong")
+  level = newEntity("Level")
+  var playerbarmesh = rect()
   playerbarmesh.vertexData.color.data = @[barcolor, barcolor, barcolor, barcolor]
-  playerbarmesh.vertexData.transform.data = @[Unit44]
-  var playerbar = newThing("playerbar", playerbarmesh)
-  playerbar.transform = scale3d(barWidth, barSize, 1'f) * translate3d(0.5'f,
-      0'f, 0'f)
-  var player = newThing("player", playerbar)
+  var playerbar = newEntity("playerbar", playerbarmesh)
+  playerbar.transform = scale3d(barWidth, barSize, 1'f) * translate3d(0.5'f, 0'f, 0'f)
+  var player = newEntity("player", playerbar)
   player.transform = translate3d(0'f, 0.3'f, 0'f)
   level.add player
 
-  var ballmesh = circle[Vertex, Vec2, float32]()
-  ballmesh.vertexData.color.data = newSeq[Vec3](
-      ballmesh.vertexData.position.data.len)
+  var ballmesh = circle()
+  ballmesh.vertexData.color.data = newSeq[Vec3](ballmesh.vertexData.position.data.len)
   for i in 0 ..< ballmesh.vertexData.color.data.len:
     ballmesh.vertexData.color.data[i] = ballcolor
   ballmesh.vertexData.transform.data = @[Unit44]
-  var ball = newThing("ball", ballmesh)
+  var ball = newEntity("ball", ballmesh)
   ball.transform = scale3d(ballSize, ballSize, 1'f) * translate3d(10'f, 10'f, 0'f)
   level.add ball
 
-  # upload data, prepare shaders, etc
-  const vertexShader = generateVertexShaderCode[Vertex, Uniforms]()
-  const fragmentShader = generateFragmentShaderCode[Vertex]()
-  pipeline = setupPipeline[Vertex, Uniforms, uint16](
-    myengine,
-    level,
-    vertexShader,
-    fragmentShader
-  )
   pipeline.clearColor = backgroundColor
   # show something
   myengine.run(pipeline, globalUpdate)
-  pipeline.trash()
-  myengine.trash()
+
+  myengine.destroy()
--- a/src/semicongine/engine.nim	Tue Apr 25 18:32:23 2023 +0700
+++ b/src/semicongine/engine.nim	Wed Apr 26 02:15:43 2023 +0700
@@ -16,6 +16,11 @@
 import ./math
 
 type
+  EngineState* = enum
+    Starting
+    Running
+    Shutdown
+    Destroyed
   Input = object
     keyIsDown: set[Key]
     keyWasPressed: set[Key]
@@ -27,7 +32,7 @@
     eventsProcessed: uint64
     windowWasResized: bool
   Engine* = object
-    running*: bool
+    state*: EngineState
     device: Device
     debugger: Debugger
     instance: Instance
@@ -47,7 +52,7 @@
     engine.debugger.destroy()
   engine.window.destroy()
   engine.instance.destroy()
-  engine.running = false
+  engine.state = Destroyed
 
 
 proc initEngine*(
@@ -57,7 +62,7 @@
   resizeHandler: proc(engine: var Engine) = nil,
   eventHandler: proc(engine: var Engine, event: Event) = nil
 ): Engine =
-  result.running = true
+  result.state = Starting
   result.exitHandler = exitHandler
   result.resizeHandler = resizeHandler
   result.eventHandler = eventHandler
@@ -87,27 +92,29 @@
   )
 
 proc setRenderer*(engine: var Engine, renderPass: RenderPass) =
+  assert engine.state != Destroyed
   engine.renderer = engine.device.initRenderer(renderPass)
 
 proc addScene*(engine: var Engine, scene: Entity, vertexInput: seq[ShaderAttribute], transformAttribute="") =
-  assert transformAttribute in map(vertexInput, proc(a: ShaderAttribute): string = a.name)
+  assert engine.state != Destroyed
+  assert transformAttribute == "" or transformAttribute in map(vertexInput, proc(a: ShaderAttribute): string = a.name)
   engine.renderer.setupDrawableBuffers(scene, vertexInput, transformAttribute=transformAttribute)
 
 proc renderScene*(engine: var Engine, scene: Entity) =
+  assert engine.state == Running
   assert engine.renderer.valid
-  if engine.running:
+  if engine.state == Running:
     engine.renderer.refreshMeshData(scene)
     engine.renderer.render(scene)
 
-proc updateInputs*(engine: var Engine) =
-  if not engine.running:
-    return
+proc updateInputs*(engine: var Engine): EngineState =
+  assert engine.state in [Starting, Running]
 
   engine.input.keyWasPressed = {}
   engine.input.keyWasReleased = {}
   engine.input.mouseWasPressed = {}
   engine.input.mouseWasReleased = {}
-  engine.input.windowWasResized = false
+  engine.input.windowWasResized = engine.state == Starting
 
   var killed = false
   for event in engine.window.pendingEvents():
@@ -133,12 +140,15 @@
         engine.input.mouseIsDown.excl event.button
       of MouseMoved:
         engine.input.mousePosition = newVec2(float32(event.x), float32(event.y))
+  if engine.state == Starting:
+    engine.state = Running
   if killed:
-    engine.running = false
+    engine.state = Shutdown
     if engine.exitHandler != nil:
       engine.exitHandler(engine)
   if engine.input.windowWasResized and engine.resizeHandler != nil:
     engine.resizeHandler(engine)
+  return engine.state
 
 func keyIsDown*(engine: Engine, key: Key): auto = key in engine.input.keyIsDown
 func keyWasPressed*(engine: Engine, key: Key): auto = key in engine.input.keyWasPressed
--- a/src/semicongine/platform/linux/xlib.nim	Tue Apr 25 18:32:23 2023 +0700
+++ b/src/semicongine/platform/linux/xlib.nim	Wed Apr 26 02:15:43 2023 +0700
@@ -113,7 +113,7 @@
     of MotionNotify:
       let motion = cast[PXMotionEvent](addr(event))
       result.add Event(eventType: MouseMoved, x: motion.x, y: motion.y)
-    of ConfigureNotify:
+    of ConfigureNotify, Expose:
       result.add Event(eventType: ResizedWindow)
     else:
       discard
--- a/src/semicongine/vulkan/renderpass.nim	Tue Apr 25 18:32:23 2023 +0700
+++ b/src/semicongine/vulkan/renderpass.nim	Wed Apr 26 02:15:43 2023 +0700
@@ -75,6 +75,7 @@
   clearColor=Vec4f([0.8'f32, 0.8'f32, 0.8'f32, 1'f32])
 ): RenderPass =
   assert device.vk.valid
+  assert fragmentCode.outputs.len == 1
   var theformat = format
   if theformat == VK_FORMAT_UNDEFINED:
     theformat = device.physicalDevice.getSurfaceFormats().filterSurfaceFormat().format
--- a/src/semicongine/vulkan/shader.nim	Tue Apr 25 18:32:23 2023 +0700
+++ b/src/semicongine/vulkan/shader.nim	Wed Apr 26 02:15:43 2023 +0700
@@ -24,9 +24,9 @@
     stage: VkShaderStageFlagBits
     entrypoint: string
     binary: seq[uint32]
-    inputs: seq[ShaderAttribute]
-    uniforms: seq[ShaderAttribute]
-    outputs: seq[ShaderAttribute]
+    inputs*: seq[ShaderAttribute]
+    uniforms*: seq[ShaderAttribute]
+    outputs*: seq[ShaderAttribute]
   Shader* = object
     device: Device
     vk*: VkShaderModule