changeset 375:2388119b2989

did: clenaup, fix: texture handling
author Sam <sam@basx.dev>
date Sun, 26 Nov 2023 19:52:42 +0700
parents ad2a7586f625
children fa38cd28f041
files src/semicongine/renderer.nim src/semicongine/scene.nim
diffstat 2 files changed, 21 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/src/semicongine/renderer.nim	Sun Nov 26 16:20:24 2023 +0700
+++ b/src/semicongine/renderer.nim	Sun Nov 26 19:52:42 2023 +0700
@@ -164,29 +164,7 @@
 
   renderer.checkSceneIntegrity(scene)
 
-  let
-    inputs = renderer.inputs(scene)
-
-  #[ 
-  # collect textures from mesh materials, add them to scenedata and upload to GPU
-  for mesh in scene.meshes:
-      for name, value in mesh.material.attributes.pairs:
-        if value.theType == TextureType:
-          if scene.shaderGlobals.contains(name) and scene.shaderGlobals[name].theType == TextureType:
-            warn &"Ignoring material texture '{name}' as scene-global textures with the same name have been defined"
-          else:
-            if not scenedata.textures.hasKey(name):
-              scenedata.textures[name] = @[]
-            scenedata.textures[name].add renderer.device.uploadTexture(getValue[Texture](value, 0))
-
-  # collect textures from shader globals, add them to scenedata and upload to GPU
-  for name, value in scene.shaderGlobals.pairs:
-    if value.theType == TextureType:
-      assert not scenedata.textures.contains(name) # should be handled by the above code
-      scenedata.textures[name] = @[]
-      for texture in getValues[Texture](value)[]:
-        scenedata.textures[name].add renderer.device.uploadTexture(texture)
-  ]#
+  let inputs = renderer.inputs(scene)
 
   # create index buffer if necessary
   var indicesBufferSize = 0
@@ -283,13 +261,12 @@
     scenedata.drawables.add (drawable, mesh)
 
   # setup uniforms and textures (anything descriptor)
+  var uploadedTextures: Table[Texture, VulkanTexture]
   for subpass_i in 0 ..< renderer.renderPass.subpasses.len:
     for (materialType, pipeline) in renderer.renderPass.subpasses[subpass_i].pipelines:
       if scene.usesMaterial(materialType):
-
         # gather textures
         scenedata.textures[pipeline.vk] = initTable[string, seq[VulkanTexture]]()
-        var uploadedTextures: Table[Texture, VulkanTexture]
         for texture in pipeline.samplers:
           scenedata.textures[pipeline.vk][texture.name] = newSeq[VulkanTexture]()
           if scene.shaderGlobals.contains(texture.name):
@@ -299,26 +276,21 @@
               scenedata.textures[pipeline.vk][texture.name].add uploadedTextures[textureValue]
           else:
             var foundTexture = false
-            var uploadedMaterials: seq[MaterialData]
-            for mesh in scene.meshes:
-              if not uploadedMaterials.contains(mesh.material):
-                for name, value in mesh.material.attributes.pairs:
-                  if name == texture.name:
-                    if not foundTexture:
-                      foundTexture = true
-                    assert value.theType == TextureType, &"Mesh material has attribute '{name}' which is expected to be of type 'Texture' but is of type {value.theType}"
-                    assert value.len == 1, &"Mesh material attribute '{name}' has texture-array, but only single textures are allowed"
-                    let textureValue = getValues[Texture](value)[][0]
-                    echo &"Mesh {mesh} -> Material {mesh.material} -> {name}: {textureValue}"
-                    if not uploadedTextures.contains(textureValue):
-                      uploadedTextures[textureValue] = renderer.device.uploadTexture(textureValue)
-                    scenedata.textures[pipeline.vk][texture.name].add uploadedTextures[textureValue]
-                    uploadedMaterials.add mesh.material
-              else:
-                foundTexture = true
-            assert foundTexture, "No texture found in shaderGlobals or materials for '{texture.name}'"
+            for material in scene.getMaterials(materialType):
+              for materialAttribName, value in material.attributes.pairs:
+                if materialAttribName == texture.name:
+                  if not foundTexture:
+                    foundTexture = true
+                  assert value.theType == TextureType, &"Mesh material has attribute '{materialAttribName}' which is expected to be of type 'Texture' but is of type {value.theType}"
+                  assert value.len == 1, &"Mesh material attribute '{materialAttribName}' has texture-array, but only single textures are allowed"
+                  let textureValue = getValues[Texture](value)[][0]
+                  if not uploadedTextures.contains(textureValue):
+                    uploadedTextures[textureValue] = renderer.device.uploadTexture(textureValue)
+                  scenedata.textures[pipeline.vk][texture.name].add uploadedTextures[textureValue]
+                  break
+            assert foundTexture, &"No texture found in shaderGlobals or materials for '{texture.name}'"
           let nTextures = scenedata.textures[pipeline.vk][texture.name].len
-          assert (texture.arrayCount == 0 and nTextures == 1) or texture.arrayCount == nTextures, &"Shader expected {texture.arrayCount} textures for '{texture.name}' but got {nTextures}"
+          assert (texture.arrayCount == 0 and nTextures == 1) or texture.arrayCount == nTextures, &"Shader assigned to render '{materialType}' expected {texture.arrayCount} textures for '{texture.name}' but got {nTextures}"
 
         # gather uniform sizes
         var uniformBufferSize = 0
--- a/src/semicongine/scene.nim	Sun Nov 26 16:20:24 2023 +0700
+++ b/src/semicongine/scene.nim	Sun Nov 26 19:52:42 2023 +0700
@@ -84,3 +84,8 @@
 
 func usesMaterial*(scene: Scene, materialType: MaterialType): bool =
   return scene.meshes.anyIt(it.material.theType == materialType)
+
+func getMaterials*(scene: Scene, materialType: MaterialType): seq[MaterialData] =
+  for mesh in scene.meshes:
+    if mesh.material.theType == materialType and (not result.contains(mesh.material)):
+      result.add mesh.material